From 924df0eb292c5cf21283f9e5145563b9fc8b8641 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Wed, 30 Jul 2025 15:43:58 -0400 Subject: [PATCH 01/10] save --- protocol-designer/package.json | 4 + .../FirstStepMoveLiquidTools.tsx | 126 + .../SecondStepsMoveLiquidTools.tsx | 286 ++- yarn.lock | 2218 ++++++++++++++++- 4 files changed, 2589 insertions(+), 45 deletions(-) diff --git a/protocol-designer/package.json b/protocol-designer/package.json index ad41ec23110..279d487bbac 100755 --- a/protocol-designer/package.json +++ b/protocol-designer/package.json @@ -27,6 +27,7 @@ "@opentrons/step-generation": "link:../step-generation", "@opentrons/shared-data": "link:../shared-data", "@sentry/react": "^9.12.0", + "@syncfusion/ej2-react-charts": "30.1.41", "@types/redux-actions": "2.6.1", "@types/styled-components": "^5.1.26", "@types/ua-parser-js": "0.7.36", @@ -41,6 +42,7 @@ "lodash": "4.17.21", "mixpanel-browser": "2.22.1", "query-string": "6.2.0", + "plotly.js": "3.1.0-rc.0", "react": "18.2.0", "react-color": "2.19.3", "react-dnd": "16.0.1", @@ -49,6 +51,7 @@ "react-error-boundary": "^4.0.10", "react-hook-form": "7.49.3", "react-i18next": "14.0.0", + "react-plotly.js": "2.6.0", "react-redux": "8.1.2", "redux": "5.0.1", "redux-actions": "2.2.1", @@ -68,6 +71,7 @@ "postcss-loader": "^4.0.4", "postcss-preset-env": "9.3.0", "postcss-color-mod-function": "3.0.3", + "victory": "37.1.1", "yup": "1.3.3" }, "devDependencies": { diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/FirstStepMoveLiquidTools.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/FirstStepMoveLiquidTools.tsx index a37dd98e4a7..3db0e66484d 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/FirstStepMoveLiquidTools.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/FirstStepMoveLiquidTools.tsx @@ -1,14 +1,35 @@ +import { useState } from 'react' +import { createPortal } from 'react-dom' import { useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' +import { registerLicense } from '@syncfusion/ej2-base' +import { + Category, + ChartComponent, + ColumnSeries, + DataEditing, + Inject, + Legend, + LineSeries, + SeriesCollectionDirective, + SeriesDirective, +} from '@syncfusion/ej2-react-charts' import { DIRECTION_COLUMN, Divider, Flex, + Modal, SPACING, StyledText, } from '@opentrons/components' +import { + getAllLiquidClassDefs, + getFlexNameConversion, + NONE_LIQUID_CLASS_NAME, +} from '@opentrons/shared-data' +import { getMainPagePortalEl } from '../../../../../../components/organisms' import { getEnablePartialTipSupport, getEnableReturnTip, @@ -32,9 +53,101 @@ import { WellSelectionField, } from '../../PipetteFields' +import type { LiquidHandlingPropertyByVolume } from '@opentrons/shared-data' import type { FormData } from '../../../../../../form-types' import type { FieldPropsByName } from '../../types' +const getByVolumeMappedToXY = ( + data: LiquidHandlingPropertyByVolume +): Array<{ x: number; y: number }> => { + return [ + { x: 0, y: data[0][1] }, + ...data.map(item => ({ + x: item[0], + y: item[1], + })), + ] +} + +function EditableLineChartModal(props: { + byVolume: LiquidHandlingPropertyByVolume + onClose: () => void +}): JSX.Element { + const { byVolume = [], onClose } = props + const onChartLoad = (): void => { + registerLicense( + 'Ngo9BigBOggjHTQxAR8/V1JEaF5cXmRCdkx0THxbf1x1ZFRHallVTnVdUiweQnxTdEBjXnxecXVQQmNbUkVzW0leYw==' + ) + let chart: Element = document.getElementById('charts') + chart.setAttribute('title', '') + } + + const data = getByVolumeMappedToXY(byVolume) + const maxFlowRate = 200 + return createPortal( + +
+
+ + + + + + +
+
+
, + getMainPagePortalEl() + ) +} + interface FirstStepMoveLiquidToolsProps { propsForFields: FieldPropsByName formData: FormData @@ -69,6 +182,19 @@ export function FirstStepMoveLiquidTools({ additionalEquipmentEntities[String(propsForFields.dispense_labware.value)] ?.name === 'trashBin' + const { spec: pipetteSpecs } = pipettes[String(formData.pipette)] + const byTipValues = getAllLiquidClassDefs() + [ + formData.liquidClass !== NONE_LIQUID_CLASS_NAME + ? formData.liquidClass + : 'waterV1' + ].byPipette.find( + ({ pipetteModel }) => pipetteModel === getFlexNameConversion(pipetteSpecs) + ) + ?.byTipType.find(({ tiprack }) => tiprack === formData.tipRack)?.aspirate + .flowRateByVolume + + const [showChart, setShowChart] = useState(false) return ( + setDataPoints: ( + dataPoints: Array<{ id: string; x: number; y: number }> + ) => void + byVolume: LiquidHandlingPropertyByVolume +}): JSX.Element { + const { dataPoints, setDataPoints } = props + + // Function to handle the relayout event (when shapes are dragged) + const handleRelayout = (eventData: any): void => { + // Loop through the existing data points + const updatedPoints = [...dataPoints] + let changed = false + + // Plotly's relayout event provides information about changes. + // For shapes, it's typically in the format 'shapes[index].x0', 'shapes[index].y0', etc. + // We need to iterate through possible shape indices to find what changed. + for (let i = 0; i < updatedPoints.length; i++) { + const xKey = `shapes[${i}].x0` + const yKey = `shapes[${i}].y0` + + if (eventData[xKey] !== undefined && eventData[yKey] !== undefined) { + // Adjust the x and y values for the center of the circle, + // as x0/y0 represent the top-left corner of the bounding box. + // Assuming a radius of 0.1 for the circles as in `getShapes`. + const newX = eventData[xKey] as number + const newY = eventData[yKey] as number + + if (updatedPoints[i].x !== newX || updatedPoints[i].y !== newY) { + updatedPoints[i] = { + ...updatedPoints[i], + // x: Math.max(newX, 0), + y: Math.max(newY, 0), + } + changed = true + } + } + } + + if (changed) { + setDataPoints(updatedPoints) + } + } + const getAnnotations = (): any => { + return dataPoints.map(point => ({ + xref: 'x', + yref: 'y', + x: point.x, + y: point.y, + text: `(${point.x.toFixed(2)}, ${point.y.toFixed(2)})`, + showarrow: false, + xanchor: 'center', + yanchor: 'bottom', + yshift: 15, + font: { + color: 'black', + size: 11, + }, + opacity: 1, // --- Simplified: Always visible now --- + })) + } + + // Helper function to generate shapes based on data points + const getShapes = (): any => { + return dataPoints.map((point, index) => ({ + type: 'circle', + xref: 'x', + yref: 'y', + // x0, y0, x1, y1 define the bounding box of the circle + // We'll make the circle radius 0.1 for visual clarity + x0: point.x - 5, + y0: point.y - 5, + x1: point.x + 5, + y1: point.y + 5, + fillcolor: COLORS.blue50, // Red, semi-transparent + line: { width: 0 }, + editable: false, // This makes the circle draggable + // A unique ID helps track the shape, though not directly used in this simple handler + name: point.id, + })) + } + + return ( +
+ p.x), + y: dataPoints.map(p => p.y), + mode: 'lines+markers', + type: 'scatter', + marker: { + size: 35, + opacity: 0, + }, + line: { width: 2 }, + showlegend: false, // Hide this trace from the legend + hoverinfo: 'none', + }, + ]} + layout={{ + width: 700, + height: 700, + title: { text: 'Flow rate (ul/s) vs Volume (ul)', editable: false }, + xaxis: { title: 'Volume (ul)', range: [0, 210] }, + yaxis: { title: 'Flow rate (ul/s)', range: [0, 210] }, + shapes: getShapes(), // Add the draggable shapes + hovermode: 'closest', // Improves hover experience + annotations: getAnnotations(), + }} + config={{ + editable: true, + displayModeBar: true, + modeBarButtonsToRemove: [ + 'zoom2d', // Remove the zoom box button + 'pan2d', // Remove the pan button + 'autoScale2d', // Remove the autoscale button + 'hoverClosestCartesian', // Remove hover tooltips + 'toImage', // Remove download image button + 'lasso2d', + 'select2d', + 'toggleHover', + 'zoomIn2d', + 'zoomOut2d', + ], + edits: { + titleText: false, // Disable title editing + axisTitleText: false, // Explicitly disable axis title editing + legendText: false, // Explicitly disable legend text editing + colorbarTitleText: false, // Explicitly disable colorbar title editing + shapePosition: true, // <-- Allow dragging shapes (this is the one we want true) + shapeEdit: false, // <-- Attempt to disable general shape editing (including resize) + }, + }} + onRelayout={handleRelayout} + /> +
+ ) +} + const addPrefix = (prefix: string) => (fieldName: string): StepFieldName => `${prefix}_${fieldName}` +const getByVolumeMappedToXY = ( + data: LiquidHandlingPropertyByVolume +): Array<{ x: number; y: number }> => { + return [ + { x: 0, y: data[0][1] }, + ...data.map(item => ({ + x: item[0], + y: item[1], + })), + ] +} + +function EditableLineChartModal(props: { + byVolume: LiquidHandlingPropertyByVolume + onClose: () => void + setFlowRates: Dispatch> + defaultFlowRates: LiquidHandlingPropertyByVolume + setIsFlowRatesUpdated: Dispatch> +}): JSX.Element { + const { + byVolume = [], + onClose, + setFlowRates, + defaultFlowRates, + setIsFlowRatesUpdated, + } = props + const defaultDataPoints = getByVolumeMappedToXY(byVolume) + const [dataPoints, setDataPoints] = useState(defaultDataPoints) + + return createPortal( + + + + { + setDataPoints(getByVolumeMappedToXY(defaultFlowRates)) + }} + > + Reset curve + + { + setFlowRates(dataPoints.map(p => [p.x, p.y])) + onClose() + setIsFlowRatesUpdated(true) + }} + > + Save + + + , + getMainPagePortalEl() + ) +} + interface SecondStepsMoveLiquidToolsProps { propsForFields: FieldPropsByName formData: FormData @@ -76,10 +300,27 @@ export const SecondStepsMoveLiquidTools = ({ const { trashBinEntities, wasteChuteEntities } = useSelector( getInvariantContext ) + const { spec: pipetteSpecs } = pipetteEntities[String(formData.pipette)] + const byTipValues = getAllLiquidClassDefs() + [ + formData.liquidClass !== NONE_LIQUID_CLASS_NAME + ? formData.liquidClass + : 'waterV1' + ].byPipette.find( + ({ pipetteModel }) => pipetteModel === getFlexNameConversion(pipetteSpecs) + ) + ?.byTipType.find(({ tiprack }) => tiprack === formData.tipRack)?.aspirate + .flowRateByVolume + const robotType = useSelector(getRobotType) const pipetteSpec = useSelector(getPipetteEntities)[formData.pipette]?.spec const [showResetModal, setShowResetModal] = useState(false) - + const [showChart, setShowChart] = useState(false) + const [flowRates, setFlowRates] = useState( + byTipValues ?? [] + ) + // need presaved logic here + const [isFlowRatesUpdated, setIsFlowRatesUpdated] = useState(false) const addFieldNamePrefix = addPrefix(tab) const isWasteChuteSelected = propsForFields.dispense_labware?.value != null @@ -281,19 +522,38 @@ export const SecondStepsMoveLiquidTools = ({
- + {byTipValues != null ? ( + + { + setShowChart(true) + }} + > + Flow rate builder + + {isFlowRatesUpdated ? ( + + ) : null} + {showChart ? ( + { + setShowChart(false) + }} + setFlowRates={setFlowRates} + defaultFlowRates={byTipValues ?? []} + setIsFlowRatesUpdated={setIsFlowRatesUpdated} + /> + ) : null} + + ) : null} + {hideWellOrderField ? null : ( <> - = 2.1.2 < 3" -iconv-lite@0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -14180,7 +15364,7 @@ ieee754@1.1.13: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== -ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: +ieee754@^1.1.12, ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -14304,6 +15488,11 @@ ini@^1.3.2, ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +ini@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.3.tgz#4c359675a6071a46985eb39b14e4a2c0ec98a795" + integrity sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg== + inline-style-parser@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.3.tgz#e35c5fb45f3a83ed7849fe487336eb7efa25971c" @@ -14333,6 +15522,11 @@ internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + interpret@^1.0.0, interpret@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" @@ -14496,6 +15690,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-browser@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-browser/-/is-browser-2.1.0.tgz#fc084d59a5fced307d6708c59356bad7007371a9" + integrity sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ== + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -14551,6 +15750,13 @@ is-core-module@^2.12.1, is-core-module@^2.13.0, is-core-module@^2.13.1, is-core- dependencies: hasown "^2.0.0" +is-core-module@^2.16.0: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + is-data-descriptor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz#2109164426166d32ea38c405c1e0945d9e6a4eeb" @@ -14637,11 +15843,16 @@ is-finalizationregistry@^1.0.2: dependencies: call-bind "^1.0.2" -is-finite@^1.0.0: +is-finite@^1.0.0, is-finite@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== +is-firefox@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-firefox/-/is-firefox-1.0.3.tgz#2a2a1567783a417f6e158323108f3861b0918562" + integrity sha512-6Q9ITjvWIm0Xdqv+5U12wgOKEM2KoBw4Y926m0OFkvlCxnbG94HKAsVz8w3fWcfAS5YA2fJORXX1dLrkprCCxA== + is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" @@ -14688,6 +15899,11 @@ is-hexadecimal@^2.0.0: resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz#86b5bf668fca307498d319dfc03289d781a90027" integrity sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg== +is-iexplorer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-iexplorer/-/is-iexplorer-1.0.0.tgz#1d72bc66d3fe22eaf6170dda8cf10943248cfc76" + integrity sha512-YeLzceuwg3K6O0MLM3UyUUjKAlyULetwryFp1mHy1I5PfArK0AEqlfa+MR4gkJjcbuJXoDJCvXbyqZVf5CR2Sg== + is-immutable-type@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/is-immutable-type/-/is-immutable-type-5.0.1.tgz#bfc2a10d995891b4205a448710b4f4c8260986fa" @@ -14727,6 +15943,11 @@ is-map@^2.0.3: resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== +is-mobile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-mobile/-/is-mobile-4.0.0.tgz#bba396eb9656e2739afde3053d7191da310fc758" + integrity sha512-mlcHZA84t1qLSuWkt2v0I2l61PYdyQDt4aG1mLIXF5FDMm4+haBCxCPYSr/uwqQNRk1MiTizn0ypEuRAOLRAew== + is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" @@ -14907,6 +16128,11 @@ is-stream@^3.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== +is-string-blank@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-string-blank/-/is-string-blank-1.0.1.tgz#866dca066d41d2894ebdfd2d8fe93e586e583a03" + integrity sha512-9H+ZBCVs3L9OYqv8nuUAzpcT9OTgMD1yAWrG7ihlnibdkbtB850heAmYWxHuXc4CHy4lKeK69tN+ny1K7gBIrw== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -14914,6 +16140,11 @@ is-string@^1.0.5, is-string@^1.0.7: dependencies: has-tostringtag "^1.0.0" +is-svg-path@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-svg-path/-/is-svg-path-1.0.2.tgz#77ab590c12b3d20348e5c7a13d0040c87784dda0" + integrity sha512-Lj4vePmqpPR1ZnRctHv8ltSh1OrSxHkhUkd7wi+VQdcdP15/KvQFyk7LhNuM7ZW0EVbJz8kZLVmL9quLrfq4Kg== + is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" @@ -15012,7 +16243,7 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== -isarray@^2.0.5: +isarray@^2.0.1, isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== @@ -15032,6 +16263,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isexe@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d" + integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ== + isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -15366,6 +16602,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stringify-pretty-compact@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz#cf4844770bddee3cb89a6170fe4b00eee5dbf1d4" + integrity sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q== + json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -15464,6 +16705,16 @@ jszip@^3.1.0: readable-stream "~2.3.6" setimmediate "^1.0.5" +kdbush@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-3.0.0.tgz#f8484794d47004cc2d85ed3a79353dbe0abc2bf0" + integrity sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew== + +kdbush@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-4.0.2.tgz#2f7b7246328b4657dd122b6c7f025fbc2c868e39" + integrity sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA== + keyboardevent-from-electron-accelerator@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/keyboardevent-from-electron-accelerator/-/keyboardevent-from-electron-accelerator-2.0.0.tgz#ace21b1aa4e47148815d160057f9edb66567c50c" @@ -16038,6 +17289,13 @@ map-cache@^0.2.2: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== +map-limit@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/map-limit/-/map-limit-0.0.1.tgz#eb7961031c0f0e8d001bf2d56fab685d58822f38" + integrity sha512-pJpcfLPnIF/Sk3taPW21G/RQsEEirGaFpCW3oXRwH9dnFHPHNGjNyvh++rdmC2fNqEaTw2MhYJraoJWAHx8kEg== + dependencies: + once "~1.3.0" + map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" @@ -16065,6 +17323,38 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +maplibre-gl@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/maplibre-gl/-/maplibre-gl-4.7.1.tgz#06a524438ee2aafbe8bcd91002a4e01468ea5486" + integrity sha512-lgL7XpIwsgICiL82ITplfS7IGwrB1OJIw/pCvprDp2dhmSSEBgmPzYRvwYYYvJGJD7fxUv1Tvpih4nZ6VrLuaA== + dependencies: + "@mapbox/geojson-rewind" "^0.5.2" + "@mapbox/jsonlint-lines-primitives" "^2.0.2" + "@mapbox/point-geometry" "^0.1.0" + "@mapbox/tiny-sdf" "^2.0.6" + "@mapbox/unitbezier" "^0.0.1" + "@mapbox/vector-tile" "^1.3.1" + "@mapbox/whoots-js" "^3.1.0" + "@maplibre/maplibre-gl-style-spec" "^20.3.1" + "@types/geojson" "^7946.0.14" + "@types/geojson-vt" "3.2.5" + "@types/mapbox__point-geometry" "^0.1.4" + "@types/mapbox__vector-tile" "^1.3.4" + "@types/pbf" "^3.0.5" + "@types/supercluster" "^7.1.3" + earcut "^3.0.0" + geojson-vt "^4.0.2" + gl-matrix "^3.4.3" + global-prefix "^4.0.0" + kdbush "^4.0.2" + murmurhash-js "^1.0.0" + pbf "^3.3.0" + potpack "^2.0.0" + quickselect "^3.0.0" + supercluster "^8.0.1" + tinyqueue "^3.0.0" + vt-pbf "^3.1.3" + markdown-escapes@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" @@ -16100,6 +17390,11 @@ material-colors@^1.2.1: resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46" integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg== +math-log2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/math-log2/-/math-log2-1.0.1.tgz#fb8941be5f5ebe8979e718e6273b178e58694565" + integrity sha512-9W0yGtkaMAkf74XGYVy4Dqw3YUMnTNB2eeiw9aQbUl4A3KmuCEHTt2DgAB07ENzOYAjsYSAYufkAq0Zd+jU7zA== + mathml-tag-names@^2.1.0: version "2.1.3" resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" @@ -16941,6 +18236,32 @@ module-lookup-amd@^6.1.0: requirejs "^2.3.5" requirejs-config-file "^3.1.1" +mouse-change@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/mouse-change/-/mouse-change-1.4.0.tgz#c2b77e5bfa34a43ce1445c8157a4e4dc9895c14f" + integrity sha512-vpN0s+zLL2ykyyUDh+fayu9Xkor5v/zRD9jhSqjRS1cJTGS0+oakVZzNm5n19JvvEj0you+MXlYTpNxUDQUjkQ== + dependencies: + mouse-event "^1.0.0" + +mouse-event-offset@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/mouse-event-offset/-/mouse-event-offset-3.0.2.tgz#dfd86a6e248c6ba8cad53b905d5037a2063e9984" + integrity sha512-s9sqOs5B1Ykox3Xo8b3Ss2IQju4UwlW6LSR+Q5FXWpprJ5fzMLefIIItr3PH8RwzfGy6gxs/4GAmiNuZScE25w== + +mouse-event@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/mouse-event/-/mouse-event-1.0.5.tgz#b3789edb7109997d5a932d1d01daa1543a501732" + integrity sha512-ItUxtL2IkeSKSp9cyaX2JLUuKk2uMoxBg4bbOWVd29+CskYJR9BGsUqtXenNzKbnDshvupjUewDIYVrOB6NmGw== + +mouse-wheel@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mouse-wheel/-/mouse-wheel-1.2.0.tgz#6d2903b1ea8fb48e61f1b53b9036773f042cdb5c" + integrity sha512-+OfYBiUOCTWcTECES49neZwL5AoGkXE+lFjIvzwNCnYRlso+EnfvovcBxGoyQ0yQt806eSPjS675K0EwWknXmw== + dependencies: + right-now "^1.0.0" + signum "^1.0.0" + to-px "^1.0.1" + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -17032,6 +18353,11 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" +murmurhash-js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/murmurhash-js/-/murmurhash-js-1.0.0.tgz#b06278e21fc6c37fa5313732b0412bcb6ae15f51" + integrity sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw== + mutexify@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/mutexify/-/mutexify-1.4.0.tgz#b7f4ac0273c81824b840887c6a6e0bfab14bbe94" @@ -17093,11 +18419,25 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +native-promise-only@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" + integrity sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +needle@^2.5.2: + version "2.9.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.9.1.tgz#22d1dffbe3490c2b83e301f7709b6736cd8f2684" + integrity sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + negotiator@0.6.3, negotiator@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -17113,6 +18453,11 @@ netmask@2.0.2: resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -17303,6 +18648,18 @@ normalize-selector@^0.2.0: resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" integrity sha512-dxvWdI8gw6eAvk9BlPffgEoGfM7AdijoCwOEJge3e3ulT2XLgmU7KvvxprOaCu05Q1uGRHmOhHe1r6emZoKyFw== +normalize-svg-path@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz#0e614eca23c39f0cffe821d6be6cd17e569a766c" + integrity sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg== + dependencies: + svg-arc-to-cubic-bezier "^3.0.0" + +normalize-svg-path@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/normalize-svg-path/-/normalize-svg-path-0.1.0.tgz#456360e60ece75fbef7b5d7e160480e7ffd16fe5" + integrity sha512-1/kmYej2iedi5+ROxkRESL/pI02pkg0OBnaR4hJkSIX6+ORzepwbuUXfrdZaPjysTsJInj0Rj5NuX027+dMBvA== + normalize-url@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" @@ -17385,6 +18742,13 @@ number-allocator@^1.0.9: debug "^4.3.1" js-sdsl "4.3.0" +number-is-integer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-integer/-/number-is-integer-1.0.1.tgz#e59bca172ffed27318e79c7ceb6cb72c095b2152" + integrity sha512-Dq3iuiFBkrbmuQjGFFF3zckXNCQoSD37/SdSbgcBailUx6knDvDwb5CympBgcoWHy36sfS12u74MHYkXyHq6bg== + dependencies: + is-finite "^1.0.1" + nwsapi@^2.2.16: version "2.2.20" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.20.tgz#22e53253c61e7b0e7e93cef42c891154bcca11ef" @@ -17572,6 +18936,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +once@~1.3.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" + integrity sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w== + dependencies: + wrappy "1" + one-time@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" @@ -17816,6 +19187,11 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parenthesis@^3.1.5: + version "3.1.8" + resolved "https://registry.yarnpkg.com/parenthesis/-/parenthesis-3.1.8.tgz#3457fccb8f05db27572b841dad9d2630b912f125" + integrity sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw== + parse-asn1@^5.0.0, parse-asn1@^5.1.7: version "5.1.7" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.7.tgz#73cdaaa822125f9647165625eb45f8a051d2df06" @@ -17889,6 +19265,23 @@ parse-passwd@^1.0.0: resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== +parse-rect@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/parse-rect/-/parse-rect-1.2.0.tgz#e0a5b0dbaaaee637a0a1eb9779969e19399d8dec" + integrity sha512-4QZ6KYbnE6RTwg9E0HpLchUM9EZt6DnDxajFZZDSV4p/12ZJEvPO702DZpGvRYEPo00yKDys7jASi+/w7aO8LA== + dependencies: + pick-by-alias "^1.2.0" + +parse-svg-path@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/parse-svg-path/-/parse-svg-path-0.1.2.tgz#7a7ec0d1eb06fa5325c7d3e009b859a09b5d49eb" + integrity sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ== + +parse-unit@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-unit/-/parse-unit-1.0.1.tgz#7e1bb6d5bef3874c28e392526a2541170291eecf" + integrity sha512-hrqldJHokR3Qj88EIlV/kAyAi/G5R2+R56TBANxNMy0uPlYcttx0jnMW6Yx5KsKPSbC3KddM/7qQm3+0wEXKxg== + parse5@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" @@ -18032,6 +19425,14 @@ pathval@^2.0.0: resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== +pbf@^3.2.1, pbf@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/pbf/-/pbf-3.3.0.tgz#1790f3d99118333cc7f498de816028a346ef367f" + integrity sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q== + dependencies: + ieee754 "^1.1.12" + resolve-protobuf-schema "^2.1.0" + pbkdf2@^3.0.3, pbkdf2@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" @@ -18067,6 +19468,11 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== +pick-by-alias@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pick-by-alias/-/pick-by-alias-1.2.0.tgz#5f7cb2b1f21a6e1e884a0c87855aa4a37361107b" + integrity sha512-ESj2+eBxhGrcA1azgHs7lARG5+5iLakc/6nlfbpjcLl00HuuUOIuORhYXN4D1HfvMSKuVtFQjAlnwi1JHEeDIw== + picocolors@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" @@ -18175,11 +19581,72 @@ plist@3.1.0, plist@^3.0.4, plist@^3.0.5, plist@^3.1.0: base64-js "^1.5.1" xmlbuilder "^15.1.1" +plotly.js@1.0.6: + version "3.1.0-rc.0" + resolved "https://registry.yarnpkg.com/plotly.js/-/plotly.js-3.1.0-rc.0.tgz#f23c746c87485fe36e2183b8fce3ff59beca03a3" + integrity sha512-7yOQs7cHBpc/aA8MV39EjPNLPYb5F4+w0kMgUWgIlDQ7TzWUtfuD8rM70KjzLgsZmBcP7O8sZ27ugezbllcftg== + dependencies: + "@plotly/d3" "3.8.2" + "@plotly/d3-sankey" "0.7.2" + "@plotly/d3-sankey-circular" "0.33.1" + "@plotly/mapbox-gl" "1.13.4" + "@plotly/regl" "^2.1.2" + "@turf/area" "^7.1.0" + "@turf/bbox" "^7.1.0" + "@turf/centroid" "^7.1.0" + base64-arraybuffer "^1.0.2" + canvas-fit "^1.5.0" + color-alpha "1.0.4" + color-normalize "1.5.0" + color-parse "2.0.0" + color-rgba "3.0.0" + country-regex "^1.1.0" + d3-force "^1.2.1" + d3-format "^1.4.5" + d3-geo "^1.12.1" + d3-geo-projection "^2.9.0" + d3-hierarchy "^1.1.9" + d3-interpolate "^3.0.1" + d3-time "^1.1.0" + d3-time-format "^2.2.3" + fast-isnumeric "^1.1.4" + gl-mat4 "^1.2.0" + gl-text "^1.4.0" + has-hover "^1.0.1" + has-passive-events "^1.0.0" + is-mobile "^4.0.0" + maplibre-gl "^4.7.1" + mouse-change "^1.4.0" + mouse-event-offset "^3.0.2" + mouse-wheel "^1.2.0" + native-promise-only "^0.8.1" + parse-svg-path "^0.1.2" + point-in-polygon "^1.1.0" + polybooljs "^1.2.2" + probe-image-size "^7.2.3" + regl-error2d "^2.0.12" + regl-line2d "^3.1.3" + regl-scatter2d "^3.3.1" + regl-splom "^1.0.14" + strongly-connected-components "^1.0.1" + superscript-text "^1.0.0" + svg-path-sdf "^1.1.3" + tinycolor2 "^1.4.2" + to-px "1.0.1" + topojson-client "^3.1.0" + webgl-context "^2.2.0" + world-calendars "^1.0.4" + pluralize@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== +point-in-polygon@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/point-in-polygon/-/point-in-polygon-1.1.0.tgz#b0af2616c01bdee341cbf2894df643387ca03357" + integrity sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw== + polished@^4.2.2: version "4.3.1" resolved "https://registry.yarnpkg.com/polished/-/polished-4.3.1.tgz#5a00ae32715609f83d89f6f31d0f0261c6170548" @@ -18187,6 +19654,11 @@ polished@^4.2.2: dependencies: "@babel/runtime" "^7.17.8" +polybooljs@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/polybooljs/-/polybooljs-1.2.2.tgz#c7127b014a63e1d00c70608abbd8dc0967ffeea3" + integrity sha512-ziHW/02J0XuNuUtmidBc6GXE8YohYydp3DWPWXYsd7O721TjcmN+k6ezjdwkDqep+gnWnFY+yqZHvzElra2oCg== + popper.js@^1.14.1: version "1.16.1" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" @@ -18962,6 +20434,16 @@ postcss@^8.4.43: picocolors "^1.1.1" source-map-js "^1.2.1" +potpack@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.2.tgz#23b99e64eb74f5741ffe7656b5b5c4ddce8dfc14" + integrity sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ== + +potpack@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/potpack/-/potpack-2.1.0.tgz#fe548e2f9061e9937f17191c1ab6dd98ca30e02f" + integrity sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ== + preact@^10.25.1: version "10.25.1" resolved "https://registry.yarnpkg.com/preact/-/preact-10.25.1.tgz#1c4b84253c42dee874bfbf6a92bdce45e3662665" @@ -19054,6 +20536,15 @@ pretty-ms@^7.0.0: dependencies: parse-ms "^2.1.0" +probe-image-size@^7.2.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/probe-image-size/-/probe-image-size-7.2.3.tgz#d49c64be540ec8edea538f6f585f65a9b3ab4309" + integrity sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w== + dependencies: + lodash.merge "^4.6.2" + needle "^2.5.2" + stream-parser "~0.3.1" + proc-log@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.1.tgz#8f3f69a1f608de27878f91f5c688b225391cb685" @@ -19128,6 +20619,11 @@ property-information@^6.0.0: resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig== +protocol-buffers-schema@^3.3.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz#77bc75a48b2ff142c1ad5b5b90c94cd0fa2efd03" + integrity sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw== + proxy-addr@~2.0.4, proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -19351,6 +20847,23 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== +quickselect@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-2.0.0.tgz#f19680a486a5eefb581303e023e98faaf25dd018" + integrity sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw== + +quickselect@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-3.0.0.tgz#a37fc953867d56f095a20ac71c6d27063d2de603" + integrity sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g== + +raf@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" + integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== + dependencies: + performance-now "^2.1.0" + ramda@0.29.0: version "0.29.0" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.29.0.tgz#fbbb67a740a754c8a4cbb41e2a6e0eb8507f55fb" @@ -19497,6 +21010,11 @@ react-fast-compare@^2.0.1: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== +react-fast-compare@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" + integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== + react-hook-form@7.49.3: version "7.49.3" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.49.3.tgz#576a4567f8a774830812f4855e89f5da5830435c" @@ -19572,6 +21090,13 @@ react-markdown@9.0.3: unist-util-visit "^5.0.0" vfile "^6.0.0" +react-plotly.js@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/react-plotly.js/-/react-plotly.js-2.6.0.tgz#ad6b68ee64f1b5cfa142ee92c59687f9c2c09209" + integrity sha512-g93xcyhAVCSt9kV1svqG1clAEdL6k3U+jjuSzfTV7owaSU9Go6Ph8bl25J+jKfKvIGAEYpe4qj++WHJuc9IaeA== + dependencies: + prop-types "^15.8.1" + react-popper@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.0.0.tgz#b99452144e8fe4acc77fa3d959a8c79e07a65084" @@ -19848,6 +21373,16 @@ readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stre string_decoder "^1.1.1" util-deprecate "^1.0.1" +"readable-stream@>=1.0.33-1 <1.1.0-0": + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readable-stream@^4.5.2: version "4.5.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09" @@ -20040,6 +21575,76 @@ regjsparser@^0.9.1: dependencies: jsesc "~0.5.0" +regl-error2d@^2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/regl-error2d/-/regl-error2d-2.0.12.tgz#3b976e13fe641d5242a154fcacc80aecfa0a9881" + integrity sha512-r7BUprZoPO9AbyqM5qlJesrSRkl+hZnVKWKsVp7YhOl/3RIpi4UDGASGJY0puQ96u5fBYw/OlqV24IGcgJ0McA== + dependencies: + array-bounds "^1.0.1" + color-normalize "^1.5.0" + flatten-vertex-data "^1.0.2" + object-assign "^4.1.1" + pick-by-alias "^1.2.0" + to-float32 "^1.1.0" + update-diff "^1.1.0" + +regl-line2d@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/regl-line2d/-/regl-line2d-3.1.3.tgz#03669c676a9e3a06973d34c68ada2400792724a4" + integrity sha512-fkgzW+tTn4QUQLpFKsUIE0sgWdCmXAM3ctXcCgoGBZTSX5FE2A0M7aynz7nrZT5baaftLrk9te54B+MEq4QcSA== + dependencies: + array-bounds "^1.0.1" + array-find-index "^1.0.2" + array-normalize "^1.1.4" + color-normalize "^1.5.0" + earcut "^2.1.5" + es6-weak-map "^2.0.3" + flatten-vertex-data "^1.0.2" + object-assign "^4.1.1" + parse-rect "^1.2.0" + pick-by-alias "^1.2.0" + to-float32 "^1.1.0" + +regl-scatter2d@^3.2.3, regl-scatter2d@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/regl-scatter2d/-/regl-scatter2d-3.3.1.tgz#0956952901ab30743dbdfb4c67fd358075e9b939" + integrity sha512-seOmMIVwaCwemSYz/y4WE0dbSO9svNFSqtTh5RE57I7PjGo3tcUYKtH0MTSoshcAsreoqN8HoCtnn8wfHXXfKQ== + dependencies: + "@plotly/point-cluster" "^3.1.9" + array-range "^1.0.1" + array-rearrange "^2.2.2" + clamp "^1.0.1" + color-id "^1.1.0" + color-normalize "^1.5.0" + color-rgba "^2.1.1" + flatten-vertex-data "^1.0.2" + glslify "^7.0.0" + is-iexplorer "^1.0.0" + object-assign "^4.1.1" + parse-rect "^1.2.0" + pick-by-alias "^1.2.0" + to-float32 "^1.1.0" + update-diff "^1.1.0" + +regl-splom@^1.0.14: + version "1.0.14" + resolved "https://registry.yarnpkg.com/regl-splom/-/regl-splom-1.0.14.tgz#58800b7bbd7576aa323499a1966868a6c9ea1456" + integrity sha512-OiLqjmPRYbd7kDlHC6/zDf6L8lxgDC65BhC8JirhP4ykrK4x22ZyS+BnY8EUinXKDeMgmpRwCvUmk7BK4Nweuw== + dependencies: + array-bounds "^1.0.1" + array-range "^1.0.1" + color-alpha "^1.0.4" + flatten-vertex-data "^1.0.2" + parse-rect "^1.2.0" + pick-by-alias "^1.2.0" + raf "^3.4.1" + regl-scatter2d "^3.2.3" + +regl@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/regl/-/regl-2.1.1.tgz#fb3eecbc684031ec6172f68aaab2cbe9c3aa3148" + integrity sha512-+IOGrxl3FZ8ZM9ixCWQZzFRiRn7Rzn9bu3iFHwg/yz4tlOUQgbO4PHLgG+1ZT60zcIV8tief6Qrmyl8qcoJP0g== + rehype-parse@^6.0.0: version "6.0.2" resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-6.0.2.tgz#aeb3fdd68085f9f796f1d3137ae2b85a98406964" @@ -20364,11 +21969,32 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== +resolve-protobuf-schema@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758" + integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ== + dependencies: + protocol-buffers-schema "^3.3.1" + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== +resolve@^0.6.1: + version "0.6.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46" + integrity sha512-UHBY3viPlJKf85YijDUcikKX6tmF4SokIDp518ZDVT92JNDcG5uKIthaT/owt3Sar0lwtOafsQuwrg22/v2Dwg== + +resolve@^1.0.0, resolve@^1.1.10, resolve@^1.1.5: + version "1.22.10" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" + integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== + dependencies: + is-core-module "^2.16.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.2, resolve@^1.22.4: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" @@ -20439,6 +22065,11 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg== +right-now@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/right-now/-/right-now-1.0.0.tgz#6e89609deebd7dcdaf8daecc9aea39cf585a0918" + integrity sha512-DA8+YS+sMIVpbsuKgy+Z67L9Lxb1p05mNxRpDPNksPDEFir4vmBlUtuN9jkTGn9YMMdlBuK7XQgFiz6ws+yhSg== + right-pad@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/right-pad/-/right-pad-1.0.1.tgz#8ca08c2cbb5b55e74dafa96bf7fd1a27d568c8d0" @@ -20586,6 +22217,11 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" +rw@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== + rxjs@^6.5.1, rxjs@^6.5.5: version "6.6.7" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" @@ -20977,6 +22613,11 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" +shallow-copy@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" + integrity sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw== + shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" @@ -21053,6 +22694,11 @@ signal-exit@^4.0.1, signal-exit@^4.1.0: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +signum@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/signum/-/signum-1.0.0.tgz#74a7d2bf2a20b40eba16a92b152124f1d559fa77" + integrity sha512-yodFGwcyt59XRh7w5W3jPcIQb3Bwi21suEfT7MAWnBX3iCdklJpgDgvGT9o04UonglZN5SNMfJFkHIR/jO8GHw== + simple-git@^3.15.1: version "3.24.0" resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-3.24.0.tgz#33a8c88dc6fa74e53eaf3d6bfc27d0182a49ec00" @@ -21421,6 +23067,11 @@ stable@0.1.8, stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-trace@0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695" + integrity sha512-vjUc6sfgtgY0dxCdnc40mK6Oftjo9+2K8H/NG81TMhgL392FtiPA9tn9RLyTxXmTLPJPjF3VyzFp6bsWFLisMQ== + stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" @@ -21446,6 +23097,13 @@ state-toggle@^1.0.0: resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== +static-eval@^2.0.5: + version "2.1.1" + resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.1.1.tgz#71ac6a13aa32b9e14c5b5f063c362176b0d584ba" + integrity sha512-MgWpQ/ZjGieSVB3eOJVs4OA2LT/q1vx98KPCTTQPzq/aLr0YUXTsgryTXr4SLfR0ZfUUCiedM9n/ABeDIyy4mA== + dependencies: + escodegen "^2.1.0" + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -21530,6 +23188,13 @@ stream-http@^2.7.2: to-arraybuffer "^1.0.0" xtend "^4.0.0" +stream-parser@~0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/stream-parser/-/stream-parser-0.3.1.tgz#1618548694420021a1182ff0af1911c129761773" + integrity sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ== + dependencies: + debug "2" + stream-shift@^1.0.0, stream-shift@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" @@ -21550,12 +23215,19 @@ strict-uri-encode@^2.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== +string-split-by@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string-split-by/-/string-split-by-1.0.0.tgz#53895fb3397ebc60adab1f1e3a131f5372586812" + integrity sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A== + dependencies: + parenthesis "^3.1.5" + string-ts@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/string-ts/-/string-ts-2.2.1.tgz#9cf9a93d210f778080a9db86ca37cba37f55e44c" integrity sha512-Q2u0gko67PLLhbte5HmPfdOjNvUKbKQM+mCNQae6jE91DmoFHY6HH9GcdqCeNx87DZ2KKjiFxmA0R/42OneGWw== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -21573,6 +23245,15 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -21685,7 +23366,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -21706,6 +23387,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -21795,6 +23483,11 @@ strnum@^1.0.5: resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== +strongly-connected-components@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strongly-connected-components/-/strongly-connected-components-1.0.1.tgz#0920e2b4df67c8eaee96c6b6234fe29e873dba99" + integrity sha512-i0TFx4wPcO0FwX+4RkLJi1MxmcTv90jNZgxMu9XRnMXMeFUY1VJlIoXpZunPUvUUqbCT1pg5PEkFqqpcaElNaA== + style-loader@^1.1.3: version "1.3.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" @@ -21948,6 +23641,25 @@ sumchecker@^3.0.1: dependencies: debug "^4.1.0" +supercluster@^7.1.0: + version "7.1.5" + resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-7.1.5.tgz#65a6ce4a037a972767740614c19051b64b8be5a3" + integrity sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg== + dependencies: + kdbush "^3.0.0" + +supercluster@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-8.0.1.tgz#9946ba123538e9e9ab15de472531f604e7372df5" + integrity sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ== + dependencies: + kdbush "^4.0.2" + +superscript-text@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/superscript-text/-/superscript-text-1.0.0.tgz#e7cb2752567360df50beb0610ce8df3d71d8dfd8" + integrity sha512-gwu8l5MtRZ6koO0icVTlmN5pm7Dhh1+Xpe9O4x6ObMAsW+3jPbW14d1DsBq1F4wiI+WOFjXF35pslgec/G8yCQ== + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -21986,6 +23698,32 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +svg-arc-to-cubic-bezier@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz#390c450035ae1c4a0104d90650304c3bc814abe6" + integrity sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g== + +svg-path-bounds@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/svg-path-bounds/-/svg-path-bounds-1.0.2.tgz#00312f672b08afc432a66ddfbd06db40cec8d0d0" + integrity sha512-H4/uAgLWrppIC0kHsb2/dWUYSmb4GE5UqH06uqWBcg6LBjX2fu0A8+JrO2/FJPZiSsNOKZAhyFFgsLTdYUvSqQ== + dependencies: + abs-svg-path "^0.1.1" + is-svg-path "^1.0.1" + normalize-svg-path "^1.0.0" + parse-svg-path "^0.1.2" + +svg-path-sdf@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/svg-path-sdf/-/svg-path-sdf-1.1.3.tgz#92957a31784c0eaf68945472c8dc6bf9e6d126fc" + integrity sha512-vJJjVq/R5lSr2KLfVXVAStktfcfa1pNFjFOgyJnzZFXlO/fDZ5DmM8FpnSKKzLPfEYTVeXuVBTHF296TpxuJVg== + dependencies: + bitmap-sdf "^1.0.0" + draw-svg-path "^1.0.0" + is-svg-path "^1.0.1" + parse-svg-path "^0.1.2" + svg-path-bounds "^1.0.1" + svg-tags@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" @@ -22211,7 +23949,15 @@ throttleit@^1.0.0: resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.1.tgz#304ec51631c3b770c65c6c6f76938b384000f4d5" integrity sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ== -through2@^2.0.0, through2@^2.0.3: +through2@^0.6.3: + version "0.6.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" + integrity sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg== + dependencies: + readable-stream ">=1.0.33-1 <1.1.0-0" + xtend ">=4.0.0 <4.1.0-0" + +through2@^2.0.0, through2@^2.0.1, through2@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== @@ -22285,7 +24031,7 @@ tinybench@^2.9.0: resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== -tinycolor2@^1.4.1: +tinycolor2@^1.4.1, tinycolor2@^1.4.2: version "1.6.0" resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw== @@ -22300,6 +24046,16 @@ tinypool@^1.0.1: resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.2.tgz#706193cc532f4c100f66aa00b01c42173d9051b2" integrity sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA== +tinyqueue@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-2.0.3.tgz#64d8492ebf39e7801d7bd34062e29b45b2035f08" + integrity sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA== + +tinyqueue@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-3.0.0.tgz#101ea761ccc81f979e29200929e78f1556e3661e" + integrity sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g== + tinyrainbow@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" @@ -22354,6 +24110,11 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== +to-float32@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/to-float32/-/to-float32-1.1.0.tgz#39bd3b11eadccd490c08f5f9171da5127b6f3946" + integrity sha512-keDnAusn/vc+R3iEiSDw8TOF7gPiTLdK1ArvWtYbJQiVfmRg6i/CAvbKq3uIS0vWroAC7ZecN3DjQKw3aSklUg== + to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" @@ -22361,6 +24122,20 @@ to-object-path@^0.3.0: dependencies: kind-of "^3.0.2" +to-px@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-px/-/to-px-1.0.1.tgz#5bbaed5e5d4f76445bcc903c293a2307dd324646" + integrity sha512-2y3LjBeIZYL19e5gczp14/uRWFDtDUErJPVN3VU9a7SJO+RjGRtYR47aMN2bZgGlxvW4ZcEz2ddUPVHXcMfuXw== + dependencies: + parse-unit "^1.0.1" + +to-px@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/to-px/-/to-px-1.1.0.tgz#b6b269ed5db0cc9aefc15272a4c8bcb2ca1e99ca" + integrity sha512-bfg3GLYrGoEzrGoE05TAL/Uw+H/qrf2ptr9V3W7U0lkjjyYnIfgxmVLUfhQ1hZpIQwin81uxhDjvUkDYsC0xWw== + dependencies: + parse-unit "^1.0.1" + to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" @@ -22396,6 +24171,13 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +topojson-client@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/topojson-client/-/topojson-client-3.1.0.tgz#22e8b1ed08a2b922feeb4af6f53b6ef09a467b99" + integrity sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw== + dependencies: + commander "2" + toposort@^1.0.0: version "1.0.7" resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" @@ -22564,6 +24346,11 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== +tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tsutils@^3.17.1, tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -22658,6 +24445,11 @@ type-is@^1.6.4, type-is@~1.6.16, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +type@^2.7.2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.3.tgz#436981652129285cc3ba94f392886c2637ea0486" + integrity sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== + typed-array-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" @@ -22707,6 +24499,14 @@ typed-styles@^0.0.5: resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.5.tgz#a60df245d482a9b1adf9c06c078d0f06085ed1cf" integrity sha512-ht+rEe5UsdEBAa3gr64+QjUOqjOLJfWLvl5HZR5Ev9uo/OnD3p43wPeFSB1hNFc13GXQF/JU1Bn0YHLUqBRIlw== +typedarray-pool@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/typedarray-pool/-/typedarray-pool-1.2.0.tgz#e7e90720144ba02b9ed660438af6f3aacfe33ac3" + integrity sha512-YTSQbzX43yvtpfRtIDAYygoYtgT+Rpjuxy9iOpczrjpXLgGoyG7aS5USJXV2d3nn8uHTeb9rXDvzS27zUg5KYQ== + dependencies: + bit-twiddle "^1.0.0" + dup "^1.0.0" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -23088,7 +24888,7 @@ unplugin@^1.3.1: webpack-sources "^3.2.3" webpack-virtual-modules "^0.6.1" -unquote@~1.1.1: +unquote@^1.1.0, unquote@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" integrity sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg== @@ -23144,6 +24944,11 @@ update-browserslist-db@^1.1.1: escalade "^3.2.0" picocolors "^1.1.0" +update-diff@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-diff/-/update-diff-1.1.0.tgz#f510182d81ee819fb82c3a6b22b62bbdeda7808f" + integrity sha512-rCiBPiHxZwT4+sBhEbChzpO5hYHjm91kScWgdHf4Qeafs6Ba7MBl+d9GlGv72bcTZQO0sLmtQS1pHSWoCLtN/A== + upper-case@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" @@ -23443,6 +25248,306 @@ vfile@^6.0.0: unist-util-stringify-position "^4.0.0" vfile-message "^4.0.0" +victory-area@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-area/-/victory-area-37.1.1.tgz#bc4ec36b70353d3327176f3ba62fe3edd5401d3f" + integrity sha512-9OVILTIT5DW/BsMksZ1xCjmNrT0iIhsHnumeNJDvvfzWUeqLyYPwmqp8e2wRraj1VRhRAAgZGXAHi7XA3rJkgQ== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + victory-vendor "37.1.1" + +victory-axis@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-axis/-/victory-axis-37.1.1.tgz#35ccf75dd6f40c485754dc032a388e3cc88101f6" + integrity sha512-LqlXoAHNxvS/GdAKR6YSHZf0I9egMZf84kqUb7dG3NNLE8M1XnaEkYlfIOJsL+vsZJqm4kqoe67yI56eqIY5Hw== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + +victory-bar@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-bar/-/victory-bar-37.1.1.tgz#ff581e402b8613e0be156d9e557def994c02b35e" + integrity sha512-1e1QtVDMgFRwXZDrt9nT1Fqv57yHL9Z9ssA2mgyzV/wi/HRneuUXE958Q/t59z4cTEkRYwNrUE3dODBCpxXMKw== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + victory-vendor "37.1.1" + +victory-box-plot@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-box-plot/-/victory-box-plot-37.1.1.tgz#c8b4c223e12baccdf772a4fc2e9baf5d1d9a8404" + integrity sha512-cdmAxg1Sqt/c2lbPJdD8+4qBNj8UMav8fLtsGd/uCNHWYzv52+0g9B8ToE6ImsKyBFRGnW+c0BD5vKbtyW6tJw== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + victory-vendor "37.1.1" + +victory-brush-container@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-brush-container/-/victory-brush-container-37.1.1.tgz#d0ff9224ddf1ef6c611b7ae8fe61e459c313728e" + integrity sha512-iZkp/r7uzkc7UN3EgAWe4aDDEFHe7BQs0nv/mmyFeFYIXG5e2uiKs28OsZnfgp6CDIHDqUoV8DAGOccotUbUaQ== + dependencies: + lodash "^4.17.19" + react-fast-compare "^3.2.0" + victory-core "37.1.1" + +victory-brush-line@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-brush-line/-/victory-brush-line-37.1.1.tgz#22c678eae56673ece6b56fb3f41134a0ec4b8a54" + integrity sha512-nsuJW7VFYFO2R+i0wveC4nizOhLj/UcTHwv98J6PYt3c0LQXa04YMFOfrRuKV/+Qsrj4DOVO3/GU6/PSUwozlQ== + dependencies: + lodash "^4.17.19" + react-fast-compare "^3.2.0" + victory-core "37.1.1" + +victory-candlestick@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-candlestick/-/victory-candlestick-37.1.1.tgz#a49586cf25d9339ad401871d41d9bb7e47099ed2" + integrity sha512-M5ftMbFi8HM9QYLrPb1DfrHOYKCwnDkxe8ct8MjE2ibsnKNCxUrwjJbkh0QXPa4ndk5y4jl98T9FmJS1Q14nPg== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + +victory-canvas@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-canvas/-/victory-canvas-37.1.1.tgz#973b1fa284cadbf75d457ff7ab4e73b8bd9eee01" + integrity sha512-nq+du3x2D8sdRfNNg2idieElJbwq7vI2DO5FoFyFyowX6plXjOXoJZAOX/+7GTBQ4FP7tktNka5AQ9z8u5Sxbw== + dependencies: + lodash "^4.17.19" + victory-bar "37.1.1" + victory-core "37.1.1" + +victory-chart@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-chart/-/victory-chart-37.1.1.tgz#3f0877439a5fa13bb32205ad337420cdaa2c4f52" + integrity sha512-p//04lKzUX1ocXmp9RWmQMOsQUcP7m1CsrYkBOvqzD1sjgMhDzTqZdn38rMUzW0bpbCs0Tl6wbOzxMN+/PA8fQ== + dependencies: + lodash "^4.17.19" + react-fast-compare "^3.2.0" + victory-axis "37.1.1" + victory-core "37.1.1" + victory-polar-axis "37.1.1" + victory-shared-events "37.1.1" + +victory-core@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-core/-/victory-core-37.1.1.tgz#1ac00415055a40b3cffb19c2ec70efcaf578adc1" + integrity sha512-4UK1S1+9CFBn1Nwu18JsOf2EtaTI/DOE4Eoi5byLd6kFO8/luSbaLvc7BDPxiLpSj0BGiX/Hbqs12T2gPaEnAA== + dependencies: + lodash "^4.17.21" + react-fast-compare "^3.2.0" + victory-vendor "37.1.1" + +victory-create-container@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-create-container/-/victory-create-container-37.1.1.tgz#d6c1997e0eaa7ee34adb460157fb734cf2b9e7f3" + integrity sha512-t/soXK97TcP4yxHYwvfCWJW9jGlRyYS4zdhjLe9Q2iETY0ngiVk+bpETZVPMgubPxq3JPaogMQKgd+1hDWjBMg== + dependencies: + lodash "^4.17.19" + victory-brush-container "37.1.1" + victory-core "37.1.1" + victory-cursor-container "37.1.1" + victory-selection-container "37.1.1" + victory-voronoi-container "37.1.1" + victory-zoom-container "37.1.1" + +victory-cursor-container@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-cursor-container/-/victory-cursor-container-37.1.1.tgz#3dbfdf986cbb8f0660e0ff707bc79f48f8f1ca37" + integrity sha512-m2YS7nmAcGHatVhuqjuJW7jXRXutI0e1pBz9PbHm692HNAJbMfFTJAKtgPXUj5wYVae4OAr6f0551/ekkcL7xQ== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + +victory-errorbar@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-errorbar/-/victory-errorbar-37.1.1.tgz#133abc0a74c49ac627b1cb34c998c85304d8b8e8" + integrity sha512-1nDaa6zT/OaA99DYwznwEwbD3lHfsnBV0UbUlQn91Hv99sg0Rvyk9cZinQWTZ0nNf8cNBYOzZlpFxY35XbQVSA== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + +victory-group@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-group/-/victory-group-37.1.1.tgz#4d4a313631d49e84a6910d45b2bfda2729b27b53" + integrity sha512-170CnQ6+doT8VUPZzcq6IIluSMSYqactT9J0ANSDEwHsO/+r0tFwez44FtA4/DgdDh5ObWQ6VfQx330urMG5bA== + dependencies: + lodash "^4.17.19" + react-fast-compare "^3.2.0" + victory-core "37.1.1" + victory-shared-events "37.1.1" + +victory-histogram@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-histogram/-/victory-histogram-37.1.1.tgz#1ce1c2c53c0ac951507e1b649f2ad1c1134dd1ab" + integrity sha512-2KnfdQYaO+MELM/PB3saPHcUf+tHg0SwbaLHKRk+Im7+aQRUlprlHH7sHZJM/TYXCkJdqbQQNoW6R9VK/kQiGg== + dependencies: + lodash "^4.17.19" + react-fast-compare "^3.2.0" + victory-bar "37.1.1" + victory-core "37.1.1" + victory-vendor "37.1.1" + +victory-legend@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-legend/-/victory-legend-37.1.1.tgz#521df42846088abefe5f94d961d1112e75b36219" + integrity sha512-8F51DbYzG+jkMJoGp2Ulqqxgoq00TWgvQcBTZptdrN2PFlc2b1Ug7z3lbK1ziUCunrVbHQpAhge0onDoRyn1Vg== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + +victory-line@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-line/-/victory-line-37.1.1.tgz#443edf833501d5c548252fe3bf4d03e3321bd482" + integrity sha512-YLR9/i7BwN3taBvHCfmc5hA0po16QFQuFnO61NPNCBZtv8kNf39m3BpDTDYMeuEgEBCnMw0znR0C1NASZcJDWQ== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + victory-vendor "37.1.1" + +victory-pie@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-pie/-/victory-pie-37.1.1.tgz#9f01bd0d283c37474df17b1b861aed5616be2c65" + integrity sha512-GWHR4prUq6ZNeMd0IEywHvvWn3dkn7vS3fkLMVTKitpbMIRPGlFxo5gLTkAQv3nnA/762GLSyELbcFgFQXOQUA== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + victory-vendor "37.1.1" + +victory-polar-axis@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-polar-axis/-/victory-polar-axis-37.1.1.tgz#688fb86c891eaef3e38699b0c21825e4b2dcd359" + integrity sha512-I9okmw1MauiucV6WxylHDOZtW5mgrozYmfglOSR6fnQ9gcxPoXSgBNxo801kyV2/pu8BP6dD07Uz1QLbCh3KSA== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + +victory-scatter@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-scatter/-/victory-scatter-37.1.1.tgz#735c1bf11c95a3edc861e92d8e51cea03ec6683e" + integrity sha512-2jt0HgYnLngw8oVAY5Tcq2MEHVc3FDo47gMQf7LysFvsuCtBLvgkaDuRPnF+8Ty3hP/7qwjV9tgM7Ui2cSfZSg== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + +victory-selection-container@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-selection-container/-/victory-selection-container-37.1.1.tgz#fc359f3c454d5e962360a94a0d66de8099661ace" + integrity sha512-5FYlMQNt7uV+EfndtCTYkE5/yjnHo243ZnBiUzXmvXU+IBCjzXmcOeyqyn7IY7+p1fvA2Hc698mDLGydd8QJrA== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + +victory-shared-events@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-shared-events/-/victory-shared-events-37.1.1.tgz#e91b59d916912b9b66fe2f36aa812a70e6aa6785" + integrity sha512-hMZI4GMLNWoIQ/Yso/tiTKpx5wUgNi2iwozrxWDesr11I5uqwutkBeHpIBMBwsGRWy6plkMyBp9lCf2Etkxm4A== + dependencies: + json-stringify-safe "^5.0.1" + lodash "^4.17.19" + react-fast-compare "^3.2.0" + victory-core "37.1.1" + +victory-stack@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-stack/-/victory-stack-37.1.1.tgz#7996186ffa0347933d63cb344746ffa789a9f2a6" + integrity sha512-jIHV7xRZW8jEuOGjrEreIh/u1mddDix98NmIJnd2+qMk1EuWIHngC2neCKQ0iF3wc8eAMuaK8gGr6ksSkpsqPA== + dependencies: + lodash "^4.17.19" + react-fast-compare "^3.2.0" + victory-core "37.1.1" + victory-shared-events "37.1.1" + +victory-tooltip@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-tooltip/-/victory-tooltip-37.1.1.tgz#c2908d7079c40e41f5bec25e62f7af900c6405ff" + integrity sha512-n5TTR92jIDaeXSADV+edevcMcNLz1iPwzQr7CNX38vWU6RWf/FRcdiBlBNg3v4rNh41+sO8jjMQhjOpDti6Rvw== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + +victory-vendor@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-vendor/-/victory-vendor-37.1.1.tgz#ba5651157a623f4112234c7368c920422a2b9165" + integrity sha512-WDnoGOSqmgyFgY/+7v4i40Vc/I/iOqc9JpUniWO9TvLCWAVEmwAjKxrorBlxEv+vQxQuhxGKOf3PcJqfjZqA9g== + dependencies: + "@types/d3-array" "^3.0.3" + "@types/d3-ease" "^3.0.0" + "@types/d3-interpolate" "^3.0.1" + "@types/d3-scale" "^4.0.2" + "@types/d3-shape" "^3.1.0" + "@types/d3-time" "^3.0.0" + "@types/d3-timer" "^3.0.0" + d3-array "^3.1.6" + d3-ease "^3.0.1" + d3-interpolate "^3.0.1" + d3-scale "^4.0.2" + d3-shape "^3.1.0" + d3-time "^3.0.0" + d3-timer "^3.0.1" + +victory-voronoi-container@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-voronoi-container/-/victory-voronoi-container-37.1.1.tgz#65c0175efa4b4b6fe0244631a3355f4978486b60" + integrity sha512-OIiT/KroQCvPaITEGcZfPd7B5Byw2vjo52RiUfzdg5WfCvqxuOURnvXsv6lh8nTNS/VI9uWaxHYdATXqXtNgfA== + dependencies: + delaunay-find "0.0.6" + lodash "^4.17.19" + react-fast-compare "^3.2.0" + victory-core "37.1.1" + victory-tooltip "37.1.1" + +victory-voronoi@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-voronoi/-/victory-voronoi-37.1.1.tgz#1573f1e2fa66112cb25dfef4219dcebefbb75cdb" + integrity sha512-LIGT4JLP+9GxzvA1rka3W8iHXx8TXvGDzcgDhj3E14dSjkDkYaX0/tyBBirHo7T3IFHThAO6GNPsfMrCzz8Z9w== + dependencies: + d3-voronoi "^1.1.4" + lodash "^4.17.19" + victory-core "37.1.1" + +victory-zoom-container@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory-zoom-container/-/victory-zoom-container-37.1.1.tgz#f8a706294754fe9ac1c20e0972838033ffa5dc36" + integrity sha512-pBW64iT9zlFqmo468+MXkqNwJuuM+Q/+5/llFCKBoMA6wE1SwpkgHQ8RITWQUDCY9dR3y/bJFLEQg2aqoFB8/g== + dependencies: + lodash "^4.17.19" + victory-core "37.1.1" + +victory@37.1.1: + version "37.1.1" + resolved "https://registry.yarnpkg.com/victory/-/victory-37.1.1.tgz#1a3efcab84fc7cdaf21782ba4d34d3f8b666b590" + integrity sha512-3tyIZ79YVd9bxS3KocGa6UuQdCA4Kenqzh3Th7QBB7Am96MHXVyePsYwhg0KorOmKqocQxYgLShGIjEHT1Qv+w== + dependencies: + victory-area "37.1.1" + victory-axis "37.1.1" + victory-bar "37.1.1" + victory-box-plot "37.1.1" + victory-brush-container "37.1.1" + victory-brush-line "37.1.1" + victory-candlestick "37.1.1" + victory-canvas "37.1.1" + victory-chart "37.1.1" + victory-core "37.1.1" + victory-create-container "37.1.1" + victory-cursor-container "37.1.1" + victory-errorbar "37.1.1" + victory-group "37.1.1" + victory-histogram "37.1.1" + victory-legend "37.1.1" + victory-line "37.1.1" + victory-pie "37.1.1" + victory-polar-axis "37.1.1" + victory-scatter "37.1.1" + victory-selection-container "37.1.1" + victory-shared-events "37.1.1" + victory-stack "37.1.1" + victory-tooltip "37.1.1" + victory-voronoi "37.1.1" + victory-voronoi-container "37.1.1" + victory-zoom-container "37.1.1" + vite-node@2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.8.tgz#9495ca17652f6f7f95ca7c4b568a235e0c8dbac5" @@ -23561,6 +25666,15 @@ vscode-uri@^3.0.3: resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f" integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw== +vt-pbf@^3.1.1, vt-pbf@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/vt-pbf/-/vt-pbf-3.1.3.tgz#68fd150756465e2edae1cc5c048e063916dcfaac" + integrity sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA== + dependencies: + "@mapbox/point-geometry" "0.1.0" + "@mapbox/vector-tile" "^1.3.1" + pbf "^3.2.1" + w3c-xmlserializer@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" @@ -23639,11 +25753,23 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +weak-map@^1.0.5: + version "1.0.8" + resolved "https://registry.yarnpkg.com/weak-map/-/weak-map-1.0.8.tgz#394c18a9e8262e790544ed8b55c6a4ddad1cb1a3" + integrity sha512-lNR9aAefbGPpHO7AEnY0hCFjz1eTkWCXYvkTRrTHs9qv8zJp+SkVYpzfLIFXQQiG3tVvbNFQgVg2bQS8YGgxyw== + web-namespaces@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== +webgl-context@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/webgl-context/-/webgl-context-2.2.0.tgz#8f37d7257cf6df1cd0a49e6a7b1b721b94cc86a0" + integrity sha512-q/fGIivtqTT7PEoF07axFIlHNk/XCPaYpq64btnepopSWvKNFkoORlQYgqDigBIuGA1ExnFd/GnSUnBNEPQY7Q== + dependencies: + get-canvas-context "^1.0.1" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -23933,6 +26059,13 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" +which@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a" + integrity sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg== + dependencies: + isexe "^3.1.1" + why-is-node-running@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" @@ -23996,7 +26129,14 @@ worker-plugin@^5.0.0: dependencies: loader-utils "^1.1.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +world-calendars@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/world-calendars/-/world-calendars-1.0.4.tgz#2a12bcbd796b6c99aef2e52f281229faad8fa96c" + integrity sha512-VGRnLJS+xJmGDPodgJRnGIDwGu0s+Cr9V2HB3EzlDZ5n0qb8h5SJtGUEkjrphZYAglEiXZ6kiXdmk0H/h/uu/w== + dependencies: + object-assign "^4.1.0" + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -24023,6 +26163,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -24133,11 +26282,16 @@ xregexp@^4.2.4: dependencies: "@babel/runtime-corejs3" "^7.12.1" -xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: +"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +xtend@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.2.0.tgz#eef6b1f198c1c8deafad8b1765a04dad4a01c5a9" + integrity sha512-SLt5uylT+4aoXxXuwtQp5ZnMMzhDb1Xkg4pEqc00WUJCQifPfV9Ub1VrNhp9kXkrjZD2I2Hl8WnjP37jzZLPZw== + y18n@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" From 84711346ff22d378faf7c9a9801df9a59dc95600 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 31 Jul 2025 13:45:12 -0400 Subject: [PATCH 02/10] remove sycnfusion --- protocol-designer/package.json | 1 - yarn.lock | 150 +-------------------------------- 2 files changed, 1 insertion(+), 150 deletions(-) diff --git a/protocol-designer/package.json b/protocol-designer/package.json index 279d487bbac..4728a659ca5 100755 --- a/protocol-designer/package.json +++ b/protocol-designer/package.json @@ -27,7 +27,6 @@ "@opentrons/step-generation": "link:../step-generation", "@opentrons/shared-data": "link:../shared-data", "@sentry/react": "^9.12.0", - "@syncfusion/ej2-react-charts": "30.1.41", "@types/redux-actions": "2.6.1", "@types/styled-components": "^5.1.26", "@types/ua-parser-js": "0.7.36", diff --git a/yarn.lock b/yarn.lock index a9f351df01e..62909149292 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6008,154 +6008,6 @@ "@types/express" "^4.7.0" file-system-cache "2.3.0" -"@syncfusion/ej2-base@~30.1.37", "@syncfusion/ej2-base@~30.1.38", "@syncfusion/ej2-base@~30.1.42": - version "30.1.42" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-base/-/ej2-base-30.1.42.tgz#918909e8b78860b38f2a0b110045f92be8abf91d" - integrity sha512-PQm14uiirN2vdlbygyYb960+ELRy/f92lxC4E9GWpVSnOt/18C5ZZJSMmC1sjE2axqhHWM8JS9gFQ7OXB5FHIw== - dependencies: - "@syncfusion/ej2-icons" "~30.1.37" - -"@syncfusion/ej2-buttons@~30.1.37": - version "30.1.37" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-buttons/-/ej2-buttons-30.1.37.tgz#f60ee9d00212c91e1e950a72a2bdca50b470bb9d" - integrity sha512-31dPIDSkraFlR8+sCz2NtM1tg9TSBN2YRHC7mBZGDWX6B26ie4zbe63S22l0ytaoMDt3XHqExsk7MLlnG3LR8g== - dependencies: - "@syncfusion/ej2-base" "~30.1.37" - -"@syncfusion/ej2-calendars@~30.1.37": - version "30.1.37" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-calendars/-/ej2-calendars-30.1.37.tgz#058c24099e9b46ce1c35c76c450b8ec695717d58" - integrity sha512-9g41zBRizXilbRJWHJgqRYJPpX0WJF5qJwGNpgvsBnyYdolYQy///x6c3oYo9W6YG28N0QDavdbOaxwprj4ghg== - dependencies: - "@syncfusion/ej2-base" "~30.1.37" - "@syncfusion/ej2-buttons" "~30.1.37" - "@syncfusion/ej2-inputs" "~30.1.37" - "@syncfusion/ej2-lists" "~30.1.37" - "@syncfusion/ej2-popups" "~30.1.37" - -"@syncfusion/ej2-charts@30.1.41": - version "30.1.41" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-charts/-/ej2-charts-30.1.41.tgz#f31686b655f13af893abeb7ae7478f178a5e333f" - integrity sha512-dbTfuZBHCE7xLhgQniRmY5h0Nuq9ovKgBha0VuXUaDJOYKTS6wK8D7EFflos7Xh/7cxDSdL3DYbF8IAB6GZweA== - dependencies: - "@syncfusion/ej2-base" "~30.1.38" - "@syncfusion/ej2-calendars" "~30.1.37" - "@syncfusion/ej2-data" "~30.1.40" - "@syncfusion/ej2-excel-export" "~30.1.37" - "@syncfusion/ej2-navigations" "~30.1.41" - "@syncfusion/ej2-pdf-export" "~30.1.41" - "@syncfusion/ej2-svg-base" "~30.1.37" - -"@syncfusion/ej2-compression@~30.1.37": - version "30.1.37" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-compression/-/ej2-compression-30.1.37.tgz#48103d442a11adcd593c3eac624564e5cc8199e6" - integrity sha512-QA5oAJZDaAONO12zwVCc1IqYTmiwthSoWaMoE0jgQR+mpYR8XmlMi1VOvP8Jtu+HlfQMaEGcMQ++UM5UeZW4+g== - dependencies: - "@syncfusion/ej2-file-utils" "~30.1.37" - -"@syncfusion/ej2-data@~30.1.40": - version "30.1.40" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-data/-/ej2-data-30.1.40.tgz#a430e5f1a73b998b6435fafb47aff78d3198c294" - integrity sha512-jxQll5rn3yailAP/wcCnIw96ROfafwFzMJ6BIcI5FTn+/mk3hLQTp/GiZ/In7uDGgXQll2yQeolPJcOkILtWkw== - dependencies: - "@syncfusion/ej2-base" "~30.1.38" - -"@syncfusion/ej2-excel-export@~30.1.37": - version "30.1.37" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-excel-export/-/ej2-excel-export-30.1.37.tgz#a47fe56df679a41dfb198bce698dabf0f302cddc" - integrity sha512-AMOTpy/uzb6QzKHgQdofA2P0Ec1KLmfT9vDXPzmF3npsPbqL0a+6K73MaZZKjW8rBrwohnbJV2R+acotpW/Seg== - dependencies: - "@syncfusion/ej2-base" "~30.1.37" - "@syncfusion/ej2-compression" "~30.1.37" - -"@syncfusion/ej2-file-utils@~30.1.37": - version "30.1.37" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-file-utils/-/ej2-file-utils-30.1.37.tgz#2ec85e400480976b3536ab3ec93dcf15735c1aed" - integrity sha512-1r0rWrXEsXsRJhG0yOs8Hp2nGARLsBCD4u602R4IxLDrockIPVJv4gz0rIw4dDtFW7bpAa8J+yWXtr6fW29Bhw== - -"@syncfusion/ej2-icons@~30.1.37": - version "30.1.37" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-icons/-/ej2-icons-30.1.37.tgz#75493418efa8bc0bf094b2f39f01451a6a7f1cc6" - integrity sha512-bgPklX0jiaLESbWJDNx8f8PqVexwbRJHoz4kDgOJR4VN4JoOtC7Zw47Wb+eFwj13Ped1lTfuPfmU8sI1s5INeQ== - -"@syncfusion/ej2-inputs@~30.1.37", "@syncfusion/ej2-inputs@~30.1.40": - version "30.1.40" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-inputs/-/ej2-inputs-30.1.40.tgz#d3b9ee1e79ab617bd08d46ce15b79333e213a337" - integrity sha512-qMbwX8x6s+pS4C9BKz6Dy9z7t+GYCSDvbJXVykvqmdpU54EjmIwb8l7LV9P2B4ooiXQ4QgkFf/CtGjP3z3H1yg== - dependencies: - "@syncfusion/ej2-base" "~30.1.38" - "@syncfusion/ej2-buttons" "~30.1.37" - "@syncfusion/ej2-popups" "~30.1.40" - "@syncfusion/ej2-splitbuttons" "~30.1.39" - -"@syncfusion/ej2-lists@~30.1.37", "@syncfusion/ej2-lists@~30.1.42": - version "30.1.42" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-lists/-/ej2-lists-30.1.42.tgz#5f80b6db425b9acd30b8824269e9da7aa1cda0f2" - integrity sha512-rGRU3d6duWGPZ5wNqNEbg5RXMPmLcFgS/1+DpElpHgDxJrwckPF+KJVbysCDQDAwknn6S28Dtaezd9ffFQrp7w== - dependencies: - "@syncfusion/ej2-base" "~30.1.42" - "@syncfusion/ej2-buttons" "~30.1.37" - "@syncfusion/ej2-data" "~30.1.40" - "@syncfusion/ej2-popups" "~30.1.42" - -"@syncfusion/ej2-navigations@~30.1.41": - version "30.1.42" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-navigations/-/ej2-navigations-30.1.42.tgz#dddd7225cf72e20ed25ee482c46025cc9fae7ba2" - integrity sha512-vIOSsvvR1s1Wf2/7TPheqkhMekH2rvynS6L+OTmlQmsDvaUYdfeuht3wAY/0MPJHHDYrjq5gHLvqVehAY7UuqA== - dependencies: - "@syncfusion/ej2-base" "~30.1.42" - "@syncfusion/ej2-buttons" "~30.1.37" - "@syncfusion/ej2-data" "~30.1.40" - "@syncfusion/ej2-inputs" "~30.1.40" - "@syncfusion/ej2-lists" "~30.1.42" - "@syncfusion/ej2-popups" "~30.1.42" - -"@syncfusion/ej2-pdf-export@~30.1.41": - version "30.1.42" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-pdf-export/-/ej2-pdf-export-30.1.42.tgz#0017ce207ba63bdac252620b9ebe8329ddf36da6" - integrity sha512-+mSVSOf1b3VKtZcl8DM6o6HKnkM7zG1lJb+b++NXR+8VcosODw3JKXiUXrn9v8pqXtY97ZubGKPCd7Uef5/ZOg== - dependencies: - "@syncfusion/ej2-compression" "~30.1.37" - -"@syncfusion/ej2-popups@~30.1.37", "@syncfusion/ej2-popups@~30.1.40", "@syncfusion/ej2-popups@~30.1.42": - version "30.1.42" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-popups/-/ej2-popups-30.1.42.tgz#ad309c1428b87352019a1591170f5735864c1c30" - integrity sha512-lqaaaMfWH4gWy6aaEWHQx8NkGAN2VyYCu2BYxqox/PfaHIS1gI1zKOzNxAWZyF0OUvwG2dCGwvWOBdoWHNwAhg== - dependencies: - "@syncfusion/ej2-base" "~30.1.42" - "@syncfusion/ej2-buttons" "~30.1.37" - -"@syncfusion/ej2-react-base@~30.1.37": - version "30.1.37" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-react-base/-/ej2-react-base-30.1.37.tgz#371e12e8f63e76eeb0059cac60b283cd0628a4cc" - integrity sha512-9Mr+gGR9fb9ywlvXLU/sROH7qcQl/rnITR9wVndKtLP0kCULIAl0QVjaBP4krVIrV5rKIqpL4dEXOJhNVXwgNQ== - dependencies: - "@syncfusion/ej2-base" "~30.1.37" - -"@syncfusion/ej2-react-charts@30.1.41": - version "30.1.41" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-react-charts/-/ej2-react-charts-30.1.41.tgz#4f200a38c7e13cfefd9fee3b28ee059a65c94c5b" - integrity sha512-p+vb1jwq35Ojgq1EyARHXqIqzWVP9IQjOpKLIlj0YXjxvMb6Fp/4AU1lJdY1It7BqMwLSYY1bVxTuaw3j7au2A== - dependencies: - "@syncfusion/ej2-base" "~30.1.38" - "@syncfusion/ej2-charts" "30.1.41" - "@syncfusion/ej2-react-base" "~30.1.37" - -"@syncfusion/ej2-splitbuttons@~30.1.39": - version "30.1.41" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-splitbuttons/-/ej2-splitbuttons-30.1.41.tgz#df504f1512e195f32499587639d96805b5cec6b0" - integrity sha512-PV8oiXHUmTliEY3Lmr6+ecYc6JUhBYwxfA3VhQI750awlbtUDoesXM1mtzZ91uM+0a0Cogw1G3NNCsm3Q6l77g== - dependencies: - "@syncfusion/ej2-base" "~30.1.38" - "@syncfusion/ej2-popups" "~30.1.37" - -"@syncfusion/ej2-svg-base@~30.1.37": - version "30.1.37" - resolved "https://registry.yarnpkg.com/@syncfusion/ej2-svg-base/-/ej2-svg-base-30.1.37.tgz#a36bc6d7842c61c8d9a9aacd1f0b95e21fe9160d" - integrity sha512-5T4XxwWqcqxEDelOvPArUCnoNu/LeTp9s4sy+5qnNvACNW7wYWV+0Qu1s0UEOx0/N9T5Lq1zFcggOckNR7hW4A== - dependencies: - "@syncfusion/ej2-base" "~30.1.37" - "@szmarczak/http-timer@^4.0.5": version "4.0.6" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" @@ -19581,7 +19433,7 @@ plist@3.1.0, plist@^3.0.4, plist@^3.0.5, plist@^3.1.0: base64-js "^1.5.1" xmlbuilder "^15.1.1" -plotly.js@1.0.6: +plotly.js@3.1.0-rc.0: version "3.1.0-rc.0" resolved "https://registry.yarnpkg.com/plotly.js/-/plotly.js-3.1.0-rc.0.tgz#f23c746c87485fe36e2183b8fce3ff59beca03a3" integrity sha512-7yOQs7cHBpc/aA8MV39EjPNLPYb5F4+w0kMgUWgIlDQ7TzWUtfuD8rM70KjzLgsZmBcP7O8sZ27ugezbllcftg== From 62c89bad4d60ee830939c923eff7504144a185d8 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 31 Jul 2025 14:55:07 -0400 Subject: [PATCH 03/10] fix dependencies --- .../FirstStepMoveLiquidTools.tsx | 126 ------------------ .../SecondStepsMoveLiquidTools.tsx | 98 +++++++++----- protocol-designer/typings/react-plotly.d.ts | 5 + protocol-designer/vite.config.mts | 1 + 4 files changed, 68 insertions(+), 162 deletions(-) create mode 100644 protocol-designer/typings/react-plotly.d.ts diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/FirstStepMoveLiquidTools.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/FirstStepMoveLiquidTools.tsx index 3db0e66484d..a37dd98e4a7 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/FirstStepMoveLiquidTools.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/FirstStepMoveLiquidTools.tsx @@ -1,35 +1,14 @@ -import { useState } from 'react' -import { createPortal } from 'react-dom' import { useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' -import { registerLicense } from '@syncfusion/ej2-base' -import { - Category, - ChartComponent, - ColumnSeries, - DataEditing, - Inject, - Legend, - LineSeries, - SeriesCollectionDirective, - SeriesDirective, -} from '@syncfusion/ej2-react-charts' import { DIRECTION_COLUMN, Divider, Flex, - Modal, SPACING, StyledText, } from '@opentrons/components' -import { - getAllLiquidClassDefs, - getFlexNameConversion, - NONE_LIQUID_CLASS_NAME, -} from '@opentrons/shared-data' -import { getMainPagePortalEl } from '../../../../../../components/organisms' import { getEnablePartialTipSupport, getEnableReturnTip, @@ -53,101 +32,9 @@ import { WellSelectionField, } from '../../PipetteFields' -import type { LiquidHandlingPropertyByVolume } from '@opentrons/shared-data' import type { FormData } from '../../../../../../form-types' import type { FieldPropsByName } from '../../types' -const getByVolumeMappedToXY = ( - data: LiquidHandlingPropertyByVolume -): Array<{ x: number; y: number }> => { - return [ - { x: 0, y: data[0][1] }, - ...data.map(item => ({ - x: item[0], - y: item[1], - })), - ] -} - -function EditableLineChartModal(props: { - byVolume: LiquidHandlingPropertyByVolume - onClose: () => void -}): JSX.Element { - const { byVolume = [], onClose } = props - const onChartLoad = (): void => { - registerLicense( - 'Ngo9BigBOggjHTQxAR8/V1JEaF5cXmRCdkx0THxbf1x1ZFRHallVTnVdUiweQnxTdEBjXnxecXVQQmNbUkVzW0leYw==' - ) - let chart: Element = document.getElementById('charts') - chart.setAttribute('title', '') - } - - const data = getByVolumeMappedToXY(byVolume) - const maxFlowRate = 200 - return createPortal( - -
-
- - - - - - -
-
-
, - getMainPagePortalEl() - ) -} - interface FirstStepMoveLiquidToolsProps { propsForFields: FieldPropsByName formData: FormData @@ -182,19 +69,6 @@ export function FirstStepMoveLiquidTools({ additionalEquipmentEntities[String(propsForFields.dispense_labware.value)] ?.name === 'trashBin' - const { spec: pipetteSpecs } = pipettes[String(formData.pipette)] - const byTipValues = getAllLiquidClassDefs() - [ - formData.liquidClass !== NONE_LIQUID_CLASS_NAME - ? formData.liquidClass - : 'waterV1' - ].byPipette.find( - ({ pipetteModel }) => pipetteModel === getFlexNameConversion(pipetteSpecs) - ) - ?.byTipType.find(({ tiprack }) => tiprack === formData.tipRack)?.aspirate - .flowRateByVolume - - const [showChart, setShowChart] = useState(false) return ( - setDataPoints: ( - dataPoints: Array<{ id: string; x: number; y: number }> - ) => void + dataPoints: DataPoint[] + setDataPoints: (dataPoints: DataPoint[]) => void byVolume: LiquidHandlingPropertyByVolume }): JSX.Element { const { dataPoints, setDataPoints } = props // Function to handle the relayout event (when shapes are dragged) const handleRelayout = (eventData: any): void => { - // Loop through the existing data points const updatedPoints = [...dataPoints] let changed = false - // Plotly's relayout event provides information about changes. - // For shapes, it's typically in the format 'shapes[index].x0', 'shapes[index].y0', etc. - // We need to iterate through possible shape indices to find what changed. for (let i = 0; i < updatedPoints.length; i++) { const xKey = `shapes[${i}].x0` const yKey = `shapes[${i}].y0` if (eventData[xKey] !== undefined && eventData[yKey] !== undefined) { - // Adjust the x and y values for the center of the circle, - // as x0/y0 represent the top-left corner of the bounding box. - // Assuming a radius of 0.1 for the circles as in `getShapes`. const newX = eventData[xKey] as number const newY = eventData[yKey] as number if (updatedPoints[i].x !== newX || updatedPoints[i].y !== newY) { updatedPoints[i] = { ...updatedPoints[i], - // x: Math.max(newX, 0), y: Math.max(newY, 0), } changed = true @@ -108,9 +102,29 @@ function DraggableLineChart(props: { } if (changed) { - setDataPoints(updatedPoints) + const sortedPoints = updatedPoints.sort((a, b) => a.x - b.x) + setDataPoints(sortedPoints) + } + } + + // Function to handle a click on the invisible "click" trace + const handlePlotClick = (eventData: any): void => { + // This event handler is triggered by clicking on the invisible trace's line. + // The `eventData.points` array will contain information about the clicked point. + if (eventData && eventData.points && eventData.points.length > 0) { + const point = eventData.points[0] + const newPoint: DataPoint = { + x: point.x, + y: point.y, + } + + const updatedPoints = [...dataPoints, newPoint] + const sortedPoints = updatedPoints.sort((a, b) => a.x - b.x) + setDataPoints(sortedPoints) } } + + // Helper function to generate annotations const getAnnotations = (): any => { return dataPoints.map(point => ({ xref: 'x', @@ -126,7 +140,7 @@ function DraggableLineChart(props: { color: 'black', size: 11, }, - opacity: 1, // --- Simplified: Always visible now --- + opacity: 1, })) } @@ -136,17 +150,14 @@ function DraggableLineChart(props: { type: 'circle', xref: 'x', yref: 'y', - // x0, y0, x1, y1 define the bounding box of the circle - // We'll make the circle radius 0.1 for visual clarity x0: point.x - 5, y0: point.y - 5, x1: point.x + 5, y1: point.y + 5, - fillcolor: COLORS.blue50, // Red, semi-transparent + fillcolor: COLORS.blue50, line: { width: 0 }, - editable: false, // This makes the circle draggable - // A unique ID helps track the shape, though not directly used in this simple handler - name: point.id, + editable: true, + name: String(point.x), })) } @@ -164,8 +175,22 @@ function DraggableLineChart(props: { opacity: 0, }, line: { width: 2 }, - showlegend: false, // Hide this trace from the legend + showlegend: false, + hoverinfo: 'none', + }, + // This is the invisible, "clickable" trace. + { + x: dataPoints.map(p => p.x), + y: dataPoints.map(p => p.y), + mode: 'lines', + type: 'scatter', + line: { + width: 20, + color: 'rgba(0,0,0,0)', // Completely transparent + }, hoverinfo: 'none', + showlegend: false, + name: 'click-trace', }, ]} layout={{ @@ -174,19 +199,19 @@ function DraggableLineChart(props: { title: { text: 'Flow rate (ul/s) vs Volume (ul)', editable: false }, xaxis: { title: 'Volume (ul)', range: [0, 210] }, yaxis: { title: 'Flow rate (ul/s)', range: [0, 210] }, - shapes: getShapes(), // Add the draggable shapes - hovermode: 'closest', // Improves hover experience + shapes: getShapes(), + hovermode: 'closest', annotations: getAnnotations(), }} config={{ editable: true, displayModeBar: true, modeBarButtonsToRemove: [ - 'zoom2d', // Remove the zoom box button - 'pan2d', // Remove the pan button - 'autoScale2d', // Remove the autoscale button - 'hoverClosestCartesian', // Remove hover tooltips - 'toImage', // Remove download image button + 'zoom2d', + 'pan2d', + 'autoScale2d', + 'hoverClosestCartesian', + 'toImage', 'lasso2d', 'select2d', 'toggleHover', @@ -194,15 +219,16 @@ function DraggableLineChart(props: { 'zoomOut2d', ], edits: { - titleText: false, // Disable title editing - axisTitleText: false, // Explicitly disable axis title editing - legendText: false, // Explicitly disable legend text editing - colorbarTitleText: false, // Explicitly disable colorbar title editing - shapePosition: true, // <-- Allow dragging shapes (this is the one we want true) - shapeEdit: false, // <-- Attempt to disable general shape editing (including resize) + titleText: false, + axisTitleText: false, + legendText: false, + colorbarTitleText: false, + shapePosition: true, + shapeEdit: false, }, }} onRelayout={handleRelayout} + onClick={handlePlotClick} /> ) diff --git a/protocol-designer/typings/react-plotly.d.ts b/protocol-designer/typings/react-plotly.d.ts new file mode 100644 index 00000000000..f1674ee5c7b --- /dev/null +++ b/protocol-designer/typings/react-plotly.d.ts @@ -0,0 +1,5 @@ +declare module 'react-plotly' { + const Plot: any + // eslint-disable-next-line import/no-default-export + export default Plot +} diff --git a/protocol-designer/vite.config.mts b/protocol-designer/vite.config.mts index c3a00897caf..a2c3ae9c0de 100644 --- a/protocol-designer/vite.config.mts +++ b/protocol-designer/vite.config.mts @@ -88,6 +88,7 @@ export default defineConfig( '@opentrons/step-generation': path.resolve( '../step-generation/src/index.ts' ), + 'react-plotly': 'react-plotly.js', }, }, server: { From 17706c60778ecf45bf592aeacf185c836493e82c Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Mon, 4 Aug 2025 12:06:20 -0400 Subject: [PATCH 04/10] refine organization of byVolume builder, add calculator and add point functionality --- .../localization/en/by_volume_builder.json | 26 ++ .../assets/localization/en/feature_flags.json | 4 + .../src/assets/localization/en/index.ts | 2 + .../localization/en/protocol_steps.json | 1 + .../src/feature-flags/reducers.ts | 2 + .../src/feature-flags/selectors.ts | 4 + protocol-designer/src/feature-flags/types.ts | 2 + .../ByVolumeBuilderModal/ByVolumeBuilder.tsx | 133 ++++++++ .../ByVolumeBuilderModal.tsx | 106 +++++++ .../ByVolumeCalculator.tsx | 82 +++++ .../ByVolumeBuilderModal/constants.ts | 58 ++++ .../StepTools/ByVolumeBuilderModal/types.ts | 8 + .../StepTools/ByVolumeBuilderModal/utils.ts | 54 ++++ .../SecondStepsMoveLiquidTools.tsx | 287 ++---------------- protocol-designer/typings/react-plotly.d.ts | 2 +- protocol-designer/vite.config.mts | 1 - 16 files changed, 516 insertions(+), 256 deletions(-) create mode 100644 protocol-designer/src/assets/localization/en/by_volume_builder.json create mode 100644 protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx create mode 100644 protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilderModal.tsx create mode 100644 protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeCalculator.tsx create mode 100644 protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/constants.ts create mode 100644 protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/types.ts create mode 100644 protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/utils.ts diff --git a/protocol-designer/src/assets/localization/en/by_volume_builder.json b/protocol-designer/src/assets/localization/en/by_volume_builder.json new file mode 100644 index 00000000000..fe75b645bd9 --- /dev/null +++ b/protocol-designer/src/assets/localization/en/by_volume_builder.json @@ -0,0 +1,26 @@ +{ + "add_point": "Add point", + "calculator": { + "calculate": "Calculate", + "interpolated_value": "Interpolated {{type}}", + "volume_to_calculate": "Input volume" + }, + "flowRate": { + "axes": { + "x": { + "label": "Volume ({{units}})", + "units": "µl" + }, + "y": { + "label": "Flow Rate ({{units}})", + "units": "µl/s" + } + }, + "title": "Flow Rate Builder" + }, + "instructions": "Drag the points to adjust the curve.", + "reset": "Reset curve", + "type": { + "flowRate": "flow rate" + } +} diff --git a/protocol-designer/src/assets/localization/en/feature_flags.json b/protocol-designer/src/assets/localization/en/feature_flags.json index b280526c16a..809f0cfd4a8 100644 --- a/protocol-designer/src/assets/localization/en/feature_flags.json +++ b/protocol-designer/src/assets/localization/en/feature_flags.json @@ -46,5 +46,9 @@ "OT_PD_ENABLE_JSON_EXPORT": { "title": "Enable exporting JSON", "description": "Enables the ability to export JSON for internal usages only" + }, + "OT_PD_ENABLE_BY_VOLUME_BUILDER": { + "title": "Enable by-volume builder", + "description": "Enables the ability to build by-volume curves" } } diff --git a/protocol-designer/src/assets/localization/en/index.ts b/protocol-designer/src/assets/localization/en/index.ts index 5233c6751fb..45ee652ae75 100644 --- a/protocol-designer/src/assets/localization/en/index.ts +++ b/protocol-designer/src/assets/localization/en/index.ts @@ -1,6 +1,7 @@ import alert from './alert.json' import application from './application.json' import button from './button.json' +import by_volume_builder from './by_volume_builder.json' import card from './card.json' import context_menu from './context_menu.json' import deck_configuration from './deck_configuration.json' @@ -23,6 +24,7 @@ export const en = { alert, application, button, + by_volume_builder, card, context_menu, deck, diff --git a/protocol-designer/src/assets/localization/en/protocol_steps.json b/protocol-designer/src/assets/localization/en/protocol_steps.json index a145af595d9..4205d783b50 100644 --- a/protocol-designer/src/assets/localization/en/protocol_steps.json +++ b/protocol-designer/src/assets/localization/en/protocol_steps.json @@ -63,6 +63,7 @@ "edit_step": "Edit step", "ending_deck": "Ending deck", "engage_height": "Engage height", + "flow_rate_builder": "Flow rate builder", "flow_type_title": "{{type}} flow rate", "from": "from", "heater_shaker": { diff --git a/protocol-designer/src/feature-flags/reducers.ts b/protocol-designer/src/feature-flags/reducers.ts index e90d549d125..e78d12a0fad 100644 --- a/protocol-designer/src/feature-flags/reducers.ts +++ b/protocol-designer/src/feature-flags/reducers.ts @@ -40,6 +40,8 @@ const initialFlags: Flags = { OT_PD_ENABLE_STACKING: process.env.OT_PD_ENABLE_STACKING === '1' || false, OT_PD_ENABLE_JSON_EXPORT: process.env.OT_PD_ENABLE_JSON_EXPORT === '1' || false, + OT_PD_ENABLE_BY_VOLUME_BUILDER: + process.env.OT_PD_ENABLE_BY_VOLUME_BUILDER === '1' || false, } // @ts-expect-error(sa, 2021-6-10): cannot use string literals as action type // TODO IMMEDIATELY: refactor this to the old fashioned way if we cannot have type safety: https://github.com/redux-utilities/redux-actions/issues/282#issuecomment-595163081 diff --git a/protocol-designer/src/feature-flags/selectors.ts b/protocol-designer/src/feature-flags/selectors.ts index d72f2cc2648..9dd170fe995 100644 --- a/protocol-designer/src/feature-flags/selectors.ts +++ b/protocol-designer/src/feature-flags/selectors.ts @@ -63,3 +63,7 @@ export const getEnableJsonExport: Selector = createSelector( getFeatureFlagData, flags => flags.OT_PD_ENABLE_JSON_EXPORT ?? false ) +export const getEnableByVolumeBuilder: Selector = createSelector( + getFeatureFlagData, + flags => flags.OT_PD_ENABLE_BY_VOLUME_BUILDER ?? false +) diff --git a/protocol-designer/src/feature-flags/types.ts b/protocol-designer/src/feature-flags/types.ts index 43afb9db40d..6338bfcab66 100644 --- a/protocol-designer/src/feature-flags/types.ts +++ b/protocol-designer/src/feature-flags/types.ts @@ -44,6 +44,7 @@ export type FlagTypes = | 'OT_PD_ENABLE_STACKING' // this feature is for internal purposes, users should never export JSON | 'OT_PD_ENABLE_JSON_EXPORT' + | 'OT_PD_ENABLE_BY_VOLUME_BUILDER' // flags that are not in this list only show in prerelease mode export const userFacingFlags: FlagTypes[] = [ 'OT_PD_DISABLE_MODULE_RESTRICTIONS', @@ -61,5 +62,6 @@ export const allFlags: FlagTypes[] = [ 'OT_PD_ENABLE_PARTIAL_TIP_SUPPORT', 'OT_PD_ENABLE_STACKING', 'OT_PD_ENABLE_JSON_EXPORT', + 'OT_PD_ENABLE_BY_VOLUME_BUILDER', ] export type Flags = Partial> diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx new file mode 100644 index 00000000000..cc8d6de05b6 --- /dev/null +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx @@ -0,0 +1,133 @@ +import { useTranslation } from 'react-i18next' +import Plot from 'react-plotly.js' + +import { + AXIS_OFFSET_PERCENTAGE, + BASE_DATA, + BASE_LAYOUT, + CONFIG, +} from './constants' +import { getAnnotations, getShapes } from './utils' + +import type { LiquidHandlingPropertyByVolume } from '@opentrons/shared-data' +import type { ByVolumeType, DataPoint } from './types' + +export function ByVolumeBuilder(props: { + type: ByVolumeType + dataPoints: DataPoint[] + setDataPoints: (dataPoints: DataPoint[]) => void + byVolume: LiquidHandlingPropertyByVolume + maxVolume: number +}): JSX.Element { + const { type, dataPoints, setDataPoints, maxVolume } = props + + const { t } = useTranslation(['by_volume_builder']) + + const handleRelayout = (eventData: any): void => { + const updatedPoints = [...dataPoints] + let changed = false + + // Handle shape-based editing (when shapes are moved) + for (let i = 0; i < updatedPoints.length; i++) { + const shapeX0Key = `shapes[${i}].x0` + const shapeY0Key = `shapes[${i}].y0` + const shapeX1Key = `shapes[${i}].x1` + const shapeY1Key = `shapes[${i}].y1` + + if ( + eventData[shapeX0Key] !== undefined && + eventData[shapeY0Key] !== undefined && + eventData[shapeX1Key] !== undefined && + eventData[shapeY1Key] !== undefined + ) { + // Calculate center point from shape bounds + const newX = (eventData[shapeX0Key] + eventData[shapeX1Key]) / 2 + const newY = (eventData[shapeY0Key] + eventData[shapeY1Key]) / 2 + + if (updatedPoints[i].x !== newX || updatedPoints[i].y !== newY) { + updatedPoints[i] = { + ...updatedPoints[i], + x: Math.min(Math.max(newX, 0), maxVolume), + y: Math.min(Math.max(newY, 0), maxVolume), + } + changed = true + } + } + } + + // Handle data-based editing (when data points are moved directly) + const xEventData = eventData['data[0].x'] + const yEventData = eventData['data[0].y'] + if (xEventData != null && yEventData != null) { + const newXValues = xEventData as number[] + const newYValues = yEventData as number[] + + for (let i = 0; i < updatedPoints.length; i++) { + const newX = newXValues[i] + const newY = newYValues[i] + + if (updatedPoints[i].x !== newX || updatedPoints[i].y !== newY) { + updatedPoints[i] = { + ...updatedPoints[i], + x: Math.max(newX, 0), + y: Math.max(newY, 0), + } + changed = true + } + } + } + + if (changed) { + const sortedPoints = updatedPoints.sort((a, b) => a.x - b.x) + setDataPoints(sortedPoints) + } + } + const axisOffset = maxVolume * AXIS_OFFSET_PERCENTAGE + return ( +
+ p.x), maxVolume], + y: [ + dataPoints[0].y, + ...dataPoints.map(p => p.y), + dataPoints[dataPoints.length - 1].y, + ], + }, + ]} + layout={{ + ...BASE_LAYOUT, + title: { + text: t(`by_volume_builder:instructions`), + xanchor: 'right', + }, + xaxis: { + title: { + text: t(`by_volume_builder:${type}.axes.x.label`, { + units: t(`by_volume_builder:${type}.axes.x.units`), + }), + editable: false, + }, + range: [-1 * axisOffset, maxVolume + axisOffset], + }, + yaxis: { + title: { + text: t(`by_volume_builder:${type}.axes.y.label`, { + units: t(`by_volume_builder:${type}.axes.y.units`), + }), + editable: false, + }, + range: [-1 * axisOffset, maxVolume + axisOffset], + }, + shapes: getShapes(dataPoints, maxVolume), + annotations: getAnnotations(dataPoints), + }} + config={CONFIG} + onRelayout={handleRelayout} + /> +
+ ) +} diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilderModal.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilderModal.tsx new file mode 100644 index 00000000000..225af6a2973 --- /dev/null +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilderModal.tsx @@ -0,0 +1,106 @@ +import { useState } from 'react' +import { createPortal } from 'react-dom' +import { useTranslation } from 'react-i18next' + +import { + DIRECTION_COLUMN, + Flex, + FLEX_MIN_CONTENT, + JUSTIFY_FLEX_END, + Modal, + PrimaryButton, + SecondaryButton, + SPACING, +} from '@opentrons/components' +import { linearInterpolate } from '@opentrons/shared-data' + +import { getMainPagePortalEl } from '../../../../../../components/organisms' +import { ByVolumeBuilder } from './ByVolumeBuilder' +import { ByVolumeCalculator } from './ByVolumeCalculator' +import { getByVolumeMappedToXY } from './utils' + +import type { Dispatch, SetStateAction } from 'react' +import type { LiquidHandlingPropertyByVolume } from '@opentrons/shared-data' +import type { ByVolumeType } from './types' + +export function ByVolumeBuilderModal(props: { + byVolume: LiquidHandlingPropertyByVolume + setByVolume: Dispatch> + type: ByVolumeType + onClose: () => void + defaultFlowRates: LiquidHandlingPropertyByVolume + maxVolume: number +}): JSX.Element { + const { + byVolume = [], + type, + onClose, + setByVolume, + defaultFlowRates, + maxVolume, + } = props + + const { t } = useTranslation(['shared', 'by_volume_builder']) + + const defaultDataPoints = getByVolumeMappedToXY(byVolume) + const [dataPoints, setDataPoints] = useState(defaultDataPoints) + + // adds a new point to the center x value at the interpolated y value + const handleAddPoint = (): void => { + const newXValue = maxVolume / 2 + const newYValue = linearInterpolate( + newXValue, + dataPoints.map(p => [p.x, p.y]) + ) + if (newYValue != null) { + const newPoints = [...dataPoints, { x: newXValue, y: newYValue }] + const newPointsSorted = newPoints.sort((a, b) => a.x - b.x) + setDataPoints(newPointsSorted) + } + } + + return createPortal( + + + + [p.x, p.y])} + /> + + { + setDataPoints(getByVolumeMappedToXY(defaultFlowRates)) + }} + > + {t(`by_volume_builder:reset`)} + + + + {t('by_volume_builder:add_point')} + + { + setByVolume(dataPoints.map(p => [p.x, p.y])) + onClose() + }} + > + {t('shared:save')} + + + + , + getMainPagePortalEl() + ) +} diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeCalculator.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeCalculator.tsx new file mode 100644 index 00000000000..dd11674518f --- /dev/null +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeCalculator.tsx @@ -0,0 +1,82 @@ +import { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { round } from 'lodash' + +import { + ALIGN_CENTER, + DIRECTION_COLUMN, + Flex, + FLEX_MIN_CONTENT, + InputField, + PrimaryButton, + SPACING, +} from '@opentrons/components' +import { linearInterpolate } from '@opentrons/shared-data' + +import { maskToFloat } from '../../../../../../steplist/fieldLevel/processing' + +import type { ByVolumeType } from './types' + +export function ByVolumeCalculator(props: { + type: ByVolumeType + points: Array<[number, number]> +}): JSX.Element { + const { type, points } = props + const [volumeToInterpolate, setVolumeToInterpolate] = useState( + null + ) + const [interpolatedValue, setInterpolatedValue] = useState( + null + ) + const [canInterpolate, setCanInterpolate] = useState( + volumeToInterpolate != null + ) + const { t } = useTranslation(['by_volume_builder']) + useEffect(() => { + if (volumeToInterpolate != null) { + setCanInterpolate(true) + } + }, [volumeToInterpolate, points]) + return ( + + + { + setVolumeToInterpolate(Number(e.target.value)) + }} + units={t(`by_volume_builder:${type}.axes.x.units`)} + type="number" + /> + + + { + if (volumeToInterpolate != null) { + setInterpolatedValue(linearInterpolate(volumeToInterpolate, points)) + setCanInterpolate(false) + } + }} + disabled={!canInterpolate} + width="100%" + > + {t('by_volume_builder:calculator.calculate')} + + + ) +} diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/constants.ts b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/constants.ts new file mode 100644 index 00000000000..87fe81819bc --- /dev/null +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/constants.ts @@ -0,0 +1,58 @@ +const MODE_BAR_BUTTONS_TO_REMOVE = [ + 'zoom2d', + 'pan2d', + 'autoScale2d', + 'hoverClosestCartesian', + 'toImage', + 'lasso2d', + 'select2d', + 'toggleHover', + 'zoomIn2d', + 'zoomOut2d', +] + +const CONFIG_EDITS = { + titleText: false, + axisTitleText: false, + legendText: false, + colorbarTitleText: false, + shapePosition: true, + shapeEdit: false, + annotationText: false, + annotationPosition: false, +} + +const WIDTH_PX = 600 +const HEIGHT_PX = 600 + +const MARKER_SIZE = 35 +const MARKER_OPACITY = 0 +const LINE_WIDTH = 2 + +export const AXIS_OFFSET_PERCENTAGE = 0.05 + +export const CONFIG = { + editable: true, + displayModeBar: true, + modeBarButtonsToRemove: MODE_BAR_BUTTONS_TO_REMOVE, + edits: CONFIG_EDITS, +} + +export const BASE_LAYOUT = { + width: WIDTH_PX, + height: HEIGHT_PX, + hovermode: 'closest', + dragmode: false, +} + +export const BASE_DATA = { + mode: 'lines+markers', + type: 'scatter', + marker: { + size: MARKER_SIZE, + opacity: MARKER_OPACITY, + }, + line: { width: LINE_WIDTH }, + showlegend: false, + hoverinfo: 'none', +} diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/types.ts b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/types.ts new file mode 100644 index 00000000000..e78a5c6c938 --- /dev/null +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/types.ts @@ -0,0 +1,8 @@ +export const FLOW_RATE = 'flowRate' + +export type ByVolumeType = typeof FLOW_RATE + +export interface DataPoint { + x: number + y: number +} diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/utils.ts b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/utils.ts new file mode 100644 index 00000000000..7066ec284b3 --- /dev/null +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/utils.ts @@ -0,0 +1,54 @@ +import { COLORS, TYPOGRAPHY } from '@opentrons/components' + +import type { LiquidHandlingPropertyByVolume } from '@opentrons/shared-data' +import type { DataPoint } from './types' + +export const getByVolumeMappedToXY = ( + data: LiquidHandlingPropertyByVolume +): Array<{ x: number; y: number }> => + data.map(item => ({ + x: item[0], + y: item[1], + })) + +export const getAnnotations = ( + dataPoints: DataPoint[], + decimalPlaces: number = 1 +): any => { + return dataPoints.map(point => ({ + xref: 'x', + yref: 'y', + x: point.x, + y: point.y, + text: `(${point.x.toFixed(decimalPlaces)}, ${point.y.toFixed( + decimalPlaces + )})`, + showarrow: false, + xanchor: 'center', + yanchor: 'bottom', + yshift: 15, + font: { + color: COLORS.black90, + size: TYPOGRAPHY.fontSize20, + }, + opacity: 1, + editable: false, + })) +} + +export const getShapes = (dataPoints: DataPoint[], axisRange: number): any => { + const shapeRadius = axisRange / 50 / 2 + return dataPoints.map(point => ({ + type: 'circle', + xref: 'x', + yref: 'y', + x0: point.x - shapeRadius, + y0: point.y - shapeRadius, + x1: point.x + shapeRadius, + y1: point.y + shapeRadius, + fillcolor: COLORS.blue50, + line: { width: 0 }, + editable: true, + name: String(point.x), + })) +} diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx index 810860eed9e..cabab0ddb62 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx @@ -1,22 +1,14 @@ import { useMemo, useRef, useState } from 'react' -import { createPortal } from 'react-dom' import { useTranslation } from 'react-i18next' -import Plot from 'react-plotly' import { useSelector } from 'react-redux' import { round } from 'lodash' import { ALIGN_CENTER, - Chip, - COLORS, DIRECTION_COLUMN, Divider, Flex, - FLEX_MIN_CONTENT, - JUSTIFY_FLEX_END, - Modal, PrimaryButton, - SecondaryButton, SPACING, StyledText, Tabs, @@ -28,15 +20,18 @@ import { getMinXYDimension, NONE_LIQUID_CLASS_NAME, } from '@opentrons/shared-data' -import { getTrashOrLabware } from '@opentrons/step-generation' +import { + getPipetteWithTipMaxVol, + getTrashOrLabware, +} from '@opentrons/step-generation' import { CheckboxExpandStepFormField, InputStepFormField, ToggleStepFormField, } from '../../../../../../components/molecules' -import { getMainPagePortalEl } from '../../../../../../components/organisms' import { ResetSettingsModal } from '../../../../../../components/organisms/ResetSettingsModal' +import { getEnableByVolumeBuilder } from '../../../../../../feature-flags/selectors' import { getRobotType } from '../../../../../../file-data/selectors' import { getAdditionalEquipmentEntities, @@ -57,6 +52,8 @@ import { getBlowoutLocationOptionsForForm, getLabwareFieldForPositioningField, } from '../../utils' +import { ByVolumeBuilderModal } from '../ByVolumeBuilderModal/ByVolumeBuilderModal' +import { FLOW_RATE } from '../ByVolumeBuilderModal/types' import { MultiInputField } from './MultiInputField' import { ResetSettingsField } from './ResetSettingsField' @@ -66,241 +63,9 @@ import type { FormData, StepFieldName } from '../../../../../../form-types' import type { FieldPropsByName, LiquidHandlingTab } from '../../types' import type { StepInputFieldProps } from './MultiInputField' -interface DataPoint { - x: number - y: number -} - -function DraggableLineChart(props: { - dataPoints: DataPoint[] - setDataPoints: (dataPoints: DataPoint[]) => void - byVolume: LiquidHandlingPropertyByVolume -}): JSX.Element { - const { dataPoints, setDataPoints } = props - - // Function to handle the relayout event (when shapes are dragged) - const handleRelayout = (eventData: any): void => { - const updatedPoints = [...dataPoints] - let changed = false - - for (let i = 0; i < updatedPoints.length; i++) { - const xKey = `shapes[${i}].x0` - const yKey = `shapes[${i}].y0` - - if (eventData[xKey] !== undefined && eventData[yKey] !== undefined) { - const newX = eventData[xKey] as number - const newY = eventData[yKey] as number - - if (updatedPoints[i].x !== newX || updatedPoints[i].y !== newY) { - updatedPoints[i] = { - ...updatedPoints[i], - y: Math.max(newY, 0), - } - changed = true - } - } - } - - if (changed) { - const sortedPoints = updatedPoints.sort((a, b) => a.x - b.x) - setDataPoints(sortedPoints) - } - } - - // Function to handle a click on the invisible "click" trace - const handlePlotClick = (eventData: any): void => { - // This event handler is triggered by clicking on the invisible trace's line. - // The `eventData.points` array will contain information about the clicked point. - if (eventData && eventData.points && eventData.points.length > 0) { - const point = eventData.points[0] - const newPoint: DataPoint = { - x: point.x, - y: point.y, - } - - const updatedPoints = [...dataPoints, newPoint] - const sortedPoints = updatedPoints.sort((a, b) => a.x - b.x) - setDataPoints(sortedPoints) - } - } - - // Helper function to generate annotations - const getAnnotations = (): any => { - return dataPoints.map(point => ({ - xref: 'x', - yref: 'y', - x: point.x, - y: point.y, - text: `(${point.x.toFixed(2)}, ${point.y.toFixed(2)})`, - showarrow: false, - xanchor: 'center', - yanchor: 'bottom', - yshift: 15, - font: { - color: 'black', - size: 11, - }, - opacity: 1, - })) - } - - // Helper function to generate shapes based on data points - const getShapes = (): any => { - return dataPoints.map((point, index) => ({ - type: 'circle', - xref: 'x', - yref: 'y', - x0: point.x - 5, - y0: point.y - 5, - x1: point.x + 5, - y1: point.y + 5, - fillcolor: COLORS.blue50, - line: { width: 0 }, - editable: true, - name: String(point.x), - })) - } - - return ( -
- p.x), - y: dataPoints.map(p => p.y), - mode: 'lines+markers', - type: 'scatter', - marker: { - size: 35, - opacity: 0, - }, - line: { width: 2 }, - showlegend: false, - hoverinfo: 'none', - }, - // This is the invisible, "clickable" trace. - { - x: dataPoints.map(p => p.x), - y: dataPoints.map(p => p.y), - mode: 'lines', - type: 'scatter', - line: { - width: 20, - color: 'rgba(0,0,0,0)', // Completely transparent - }, - hoverinfo: 'none', - showlegend: false, - name: 'click-trace', - }, - ]} - layout={{ - width: 700, - height: 700, - title: { text: 'Flow rate (ul/s) vs Volume (ul)', editable: false }, - xaxis: { title: 'Volume (ul)', range: [0, 210] }, - yaxis: { title: 'Flow rate (ul/s)', range: [0, 210] }, - shapes: getShapes(), - hovermode: 'closest', - annotations: getAnnotations(), - }} - config={{ - editable: true, - displayModeBar: true, - modeBarButtonsToRemove: [ - 'zoom2d', - 'pan2d', - 'autoScale2d', - 'hoverClosestCartesian', - 'toImage', - 'lasso2d', - 'select2d', - 'toggleHover', - 'zoomIn2d', - 'zoomOut2d', - ], - edits: { - titleText: false, - axisTitleText: false, - legendText: false, - colorbarTitleText: false, - shapePosition: true, - shapeEdit: false, - }, - }} - onRelayout={handleRelayout} - onClick={handlePlotClick} - /> -
- ) -} - const addPrefix = (prefix: string) => (fieldName: string): StepFieldName => `${prefix}_${fieldName}` -const getByVolumeMappedToXY = ( - data: LiquidHandlingPropertyByVolume -): Array<{ x: number; y: number }> => { - return [ - { x: 0, y: data[0][1] }, - ...data.map(item => ({ - x: item[0], - y: item[1], - })), - ] -} - -function EditableLineChartModal(props: { - byVolume: LiquidHandlingPropertyByVolume - onClose: () => void - setFlowRates: Dispatch> - defaultFlowRates: LiquidHandlingPropertyByVolume - setIsFlowRatesUpdated: Dispatch> -}): JSX.Element { - const { - byVolume = [], - onClose, - setFlowRates, - defaultFlowRates, - setIsFlowRatesUpdated, - } = props - const defaultDataPoints = getByVolumeMappedToXY(byVolume) - const [dataPoints, setDataPoints] = useState(defaultDataPoints) - - return createPortal( - - - - { - setDataPoints(getByVolumeMappedToXY(defaultFlowRates)) - }} - > - Reset curve - - { - setFlowRates(dataPoints.map(p => [p.x, p.y])) - onClose() - setIsFlowRatesUpdated(true) - }} - > - Save - - - , - getMainPagePortalEl() - ) -} - interface SecondStepsMoveLiquidToolsProps { propsForFields: FieldPropsByName formData: FormData @@ -326,7 +91,14 @@ export const SecondStepsMoveLiquidTools = ({ const { trashBinEntities, wasteChuteEntities } = useSelector( getInvariantContext ) + const enableByVolumeBuilder = useSelector(getEnableByVolumeBuilder) const { spec: pipetteSpecs } = pipetteEntities[String(formData.pipette)] + const invariantContext = useSelector(getInvariantContext) + const maxVolume = getPipetteWithTipMaxVol( + formData.pipette as string, + invariantContext, + formData.tipRack as string + ) const byTipValues = getAllLiquidClassDefs() [ formData.liquidClass !== NONE_LIQUID_CLASS_NAME @@ -345,8 +117,7 @@ export const SecondStepsMoveLiquidTools = ({ const [flowRates, setFlowRates] = useState( byTipValues ?? [] ) - // need presaved logic here - const [isFlowRatesUpdated, setIsFlowRatesUpdated] = useState(false) + // need presaved and deep equality check logic here const addFieldNamePrefix = addPrefix(tab) const isWasteChuteSelected = propsForFields.dispense_labware?.value != null @@ -548,7 +319,7 @@ export const SecondStepsMoveLiquidTools = ({
- {byTipValues != null ? ( + {enableByVolumeBuilder && byTipValues != null ? ( - Flow rate builder + {t('protocol_steps:flow_rate_builder')} - {isFlowRatesUpdated ? ( - - ) : null} {showChart ? ( - { setShowChart(false) }} - setFlowRates={setFlowRates} + type={FLOW_RATE} + setByVolume={setFlowRates} defaultFlowRates={byTipValues ?? []} - setIsFlowRatesUpdated={setIsFlowRatesUpdated} + maxVolume={maxVolume} /> ) : null} - ) : null} - + ) : ( + + )} {hideWellOrderField ? null : ( <> Date: Mon, 4 Aug 2025 13:44:43 -0400 Subject: [PATCH 05/10] comment --- .../StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx index cabab0ddb62..fa2f2322956 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx @@ -114,6 +114,9 @@ export const SecondStepsMoveLiquidTools = ({ const pipetteSpec = useSelector(getPipetteEntities)[formData.pipette]?.spec const [showResetModal, setShowResetModal] = useState(false) const [showChart, setShowChart] = useState(false) + + // TODO: replace this state/setter with propsForFields value/updateValue + // should remove the need for byTipValues (handled in form change utils) const [flowRates, setFlowRates] = useState( byTipValues ?? [] ) From 4077f8d5b393d4fb0e3ed0397bfae01d49327393 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 7 Aug 2025 10:49:35 -0400 Subject: [PATCH 06/10] fix tests --- .../StepForm/StepTools/MixTools/__tests__/MixTools.test.tsx | 3 +++ .../MoveLiquidTools/__tests__/MoveLiquidTools.test.tsx | 3 +++ .../Designer/ProtocolSteps/__tests__/ProtocolSteps.test.tsx | 3 +++ .../src/pages/Designer/__tests__/Designer.test.tsx | 3 +++ 4 files changed, 12 insertions(+) diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MixTools/__tests__/MixTools.test.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MixTools/__tests__/MixTools.test.tsx index 722e9c6233b..1e82edd38b3 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MixTools/__tests__/MixTools.test.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MixTools/__tests__/MixTools.test.tsx @@ -35,6 +35,9 @@ vi.mock('../FirstStepMixTools') vi.mock('../SecondStepMixTools') vi.mock('../../MoveLiquidTools/LiquidClassesStepTools') vi.mock('../../MoveLiquidTools/hooks/useAssignLiquidClass') +vi.mock('react-plotly.js', () => ({ + default: () =>
Mock Plotly Chart
, +})) const labwareId = 'mockLabwareId' const pipetteId = 'mockPipetteId' diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/__tests__/MoveLiquidTools.test.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/__tests__/MoveLiquidTools.test.tsx index 5c301a7e849..8115d8dcf7f 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/__tests__/MoveLiquidTools.test.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/__tests__/MoveLiquidTools.test.tsx @@ -22,6 +22,9 @@ vi.mock('../SecondStepsMoveLiquidTools') vi.mock('../LiquidClassesStepTools') vi.mock('../hooks/useAssignLiquidClass') vi.mock('../hooks/useSupportedLiquidClassOptions') +vi.mock('react-plotly.js', () => ({ + default: () =>
Mock Plotly Chart
, +})) const render = (props: ComponentProps) => { return renderWithProviders() diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/__tests__/ProtocolSteps.test.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/__tests__/ProtocolSteps.test.tsx index 4eeaf8f876b..c0b19895791 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/__tests__/ProtocolSteps.test.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/__tests__/ProtocolSteps.test.tsx @@ -44,6 +44,9 @@ vi.mock('../../../../top-selectors/labware-locations') vi.mock('../Timeline/utils') vi.mock('../../../../components/organisms/StepSummary') vi.mock('../../../../resources/hooks') +vi.mock('react-plotly.js', () => ({ + default: () =>
Mock Plotly Chart
, +})) const render = () => { return renderWithProviders( diff --git a/protocol-designer/src/pages/Designer/__tests__/Designer.test.tsx b/protocol-designer/src/pages/Designer/__tests__/Designer.test.tsx index ed16bdf73f8..061cd9ace5c 100644 --- a/protocol-designer/src/pages/Designer/__tests__/Designer.test.tsx +++ b/protocol-designer/src/pages/Designer/__tests__/Designer.test.tsx @@ -24,6 +24,9 @@ vi.mock('../../../components/organisms/LiquidsOverflowMenu') vi.mock('../DeckSetup') vi.mock('../../../file-data/selectors') vi.mock('../../../top-selectors/labware-locations') +vi.mock('react-plotly.js', () => ({ + default: () =>
Mock Plotly Chart
, +})) vi.mock('react-router-dom', async importOriginal => { const actual = await importOriginal() return { From 7d425841cd8093e9f78818519dfbad448c7882a6 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 7 Aug 2025 10:59:43 -0400 Subject: [PATCH 07/10] update yarn.lock --- yarn.lock | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6d2cbc2a0f8..8e7e68335d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15706,11 +15706,6 @@ is-mobile@^4.0.0: resolved "https://registry.yarnpkg.com/is-mobile/-/is-mobile-4.0.0.tgz#bba396eb9656e2739afde3053d7191da310fc758" integrity sha512-mlcHZA84t1qLSuWkt2v0I2l61PYdyQDt4aG1mLIXF5FDMm4+haBCxCPYSr/uwqQNRk1MiTizn0ypEuRAOLRAew== -is-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" - integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== - is-nan@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" @@ -21730,7 +21725,7 @@ resolve@^1.0.0, resolve@^1.1.10, resolve@^1.1.5: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.2, resolve@^1.22.4: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11.1, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.2, resolve@^1.22.4: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== From c21f9c79dadda7e01b50be82b7465c58563e4dc7 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 7 Aug 2025 12:02:34 -0400 Subject: [PATCH 08/10] refine logic for byVolume axes --- .../StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx index fa2f2322956..45e8fb76ee7 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx @@ -94,7 +94,7 @@ export const SecondStepsMoveLiquidTools = ({ const enableByVolumeBuilder = useSelector(getEnableByVolumeBuilder) const { spec: pipetteSpecs } = pipetteEntities[String(formData.pipette)] const invariantContext = useSelector(getInvariantContext) - const maxVolume = getPipetteWithTipMaxVol( + const pipetteWithTipMaxVol = getPipetteWithTipMaxVol( formData.pipette as string, invariantContext, formData.tipRack as string @@ -109,6 +109,8 @@ export const SecondStepsMoveLiquidTools = ({ ) ?.byTipType.find(({ tiprack }) => tiprack === formData.tipRack)?.aspirate .flowRateByVolume + const highestY = Math.max(...(byTipValues?.map(point => point[1]) ?? [])) + const maxVolume = Math.max(pipetteWithTipMaxVol, highestY) const robotType = useSelector(getRobotType) const pipetteSpec = useSelector(getPipetteEntities)[formData.pipette]?.spec From b69443d376759766e7cebdaad4310999bf74b761 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 7 Aug 2025 13:28:34 -0400 Subject: [PATCH 09/10] split axis ranges and shape x- and y-radii --- .../ByVolumeBuilderModal/ByVolumeBuilder.tsx | 20 ++++++++++--------- .../ByVolumeBuilderModal.tsx | 11 ++++++---- .../StepTools/ByVolumeBuilderModal/utils.ts | 19 ++++++++++++------ .../SecondStepsMoveLiquidTools.tsx | 5 +++-- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx index cc8d6de05b6..586ef32d05e 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx @@ -17,9 +17,10 @@ export function ByVolumeBuilder(props: { dataPoints: DataPoint[] setDataPoints: (dataPoints: DataPoint[]) => void byVolume: LiquidHandlingPropertyByVolume - maxVolume: number + maxX: number + maxY: number }): JSX.Element { - const { type, dataPoints, setDataPoints, maxVolume } = props + const { type, dataPoints, setDataPoints, maxX, maxY } = props const { t } = useTranslation(['by_volume_builder']) @@ -47,8 +48,8 @@ export function ByVolumeBuilder(props: { if (updatedPoints[i].x !== newX || updatedPoints[i].y !== newY) { updatedPoints[i] = { ...updatedPoints[i], - x: Math.min(Math.max(newX, 0), maxVolume), - y: Math.min(Math.max(newY, 0), maxVolume), + x: Math.min(Math.max(newX, 0), maxX), + y: Math.min(Math.max(newY, 0), maxY), } changed = true } @@ -82,7 +83,8 @@ export function ByVolumeBuilder(props: { setDataPoints(sortedPoints) } } - const axisOffset = maxVolume * AXIS_OFFSET_PERCENTAGE + const axisOffsetX = maxX * AXIS_OFFSET_PERCENTAGE + const axisOffsetY = maxY * AXIS_OFFSET_PERCENTAGE return (
p.x), maxVolume], + x: [0, ...dataPoints.map(p => p.x), maxX], y: [ dataPoints[0].y, ...dataPoints.map(p => p.y), @@ -111,7 +113,7 @@ export function ByVolumeBuilder(props: { }), editable: false, }, - range: [-1 * axisOffset, maxVolume + axisOffset], + range: [-1 * axisOffsetX, maxX + axisOffsetX], }, yaxis: { title: { @@ -120,9 +122,9 @@ export function ByVolumeBuilder(props: { }), editable: false, }, - range: [-1 * axisOffset, maxVolume + axisOffset], + range: [-1 * axisOffsetY, maxY + axisOffsetY], }, - shapes: getShapes(dataPoints, maxVolume), + shapes: getShapes(dataPoints, maxX, maxY), annotations: getAnnotations(dataPoints), }} config={CONFIG} diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilderModal.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilderModal.tsx index 225af6a2973..570d0a26d21 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilderModal.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilderModal.tsx @@ -29,7 +29,8 @@ export function ByVolumeBuilderModal(props: { type: ByVolumeType onClose: () => void defaultFlowRates: LiquidHandlingPropertyByVolume - maxVolume: number + maxX: number + maxY: number }): JSX.Element { const { byVolume = [], @@ -37,7 +38,8 @@ export function ByVolumeBuilderModal(props: { onClose, setByVolume, defaultFlowRates, - maxVolume, + maxX, + maxY, } = props const { t } = useTranslation(['shared', 'by_volume_builder']) @@ -47,7 +49,7 @@ export function ByVolumeBuilderModal(props: { // adds a new point to the center x value at the interpolated y value const handleAddPoint = (): void => { - const newXValue = maxVolume / 2 + const newXValue = maxX / 2 const newYValue = linearInterpolate( newXValue, dataPoints.map(p => [p.x, p.y]) @@ -72,7 +74,8 @@ export function ByVolumeBuilderModal(props: { dataPoints={dataPoints} setDataPoints={setDataPoints} byVolume={byVolume} - maxVolume={maxVolume} + maxX={maxX} + maxY={maxY} /> { - const shapeRadius = axisRange / 50 / 2 +const POINT_SCALAR = 0.02 + +export const getShapes = ( + dataPoints: DataPoint[], + axisRangeX: number, + axisRangeY: number +): any => { + const shapeXRadius = (axisRangeX * POINT_SCALAR) / 2 + const shapeYRadius = (axisRangeY * POINT_SCALAR) / 2 return dataPoints.map(point => ({ type: 'circle', xref: 'x', yref: 'y', - x0: point.x - shapeRadius, - y0: point.y - shapeRadius, - x1: point.x + shapeRadius, - y1: point.y + shapeRadius, + x0: point.x - shapeXRadius, + y0: point.y - shapeYRadius, + x1: point.x + shapeXRadius, + y1: point.y + shapeYRadius, fillcolor: COLORS.blue50, line: { width: 0 }, editable: true, diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx index 45e8fb76ee7..bcdfd46a2d8 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/MoveLiquidTools/SecondStepsMoveLiquidTools.tsx @@ -110,7 +110,7 @@ export const SecondStepsMoveLiquidTools = ({ ?.byTipType.find(({ tiprack }) => tiprack === formData.tipRack)?.aspirate .flowRateByVolume const highestY = Math.max(...(byTipValues?.map(point => point[1]) ?? [])) - const maxVolume = Math.max(pipetteWithTipMaxVol, highestY) + const maxY = Math.max(pipetteWithTipMaxVol, highestY) const robotType = useSelector(getRobotType) const pipetteSpec = useSelector(getPipetteEntities)[formData.pipette]?.spec @@ -346,7 +346,8 @@ export const SecondStepsMoveLiquidTools = ({ type={FLOW_RATE} setByVolume={setFlowRates} defaultFlowRates={byTipValues ?? []} - maxVolume={maxVolume} + maxX={pipetteWithTipMaxVol} + maxY={maxY} /> ) : null} From 801cecc538bb2c76c636d6150d5050078598258a Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 7 Aug 2025 13:34:41 -0400 Subject: [PATCH 10/10] refactor shape size function and scalars --- .../StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx | 4 +++- .../StepForm/StepTools/ByVolumeBuilderModal/constants.ts | 1 + .../StepForm/StepTools/ByVolumeBuilderModal/utils.ts | 8 ++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx index 586ef32d05e..1cb675cc887 100644 --- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx +++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ByVolumeBuilderModal/ByVolumeBuilder.tsx @@ -85,6 +85,8 @@ export function ByVolumeBuilder(props: { } const axisOffsetX = maxX * AXIS_OFFSET_PERCENTAGE const axisOffsetY = maxY * AXIS_OFFSET_PERCENTAGE + const axisRangeX = maxX + 2 * axisOffsetX + const axisRangeY = maxY + 2 * axisOffsetY return (
{ - const shapeXRadius = (axisRangeX * POINT_SCALAR) / 2 - const shapeYRadius = (axisRangeY * POINT_SCALAR) / 2 + const shapeXRadius = (axisRangeX * POINT_DIAMETER_SCALAR) / 2 + const shapeYRadius = (axisRangeY * POINT_DIAMETER_SCALAR) / 2 return dataPoints.map(point => ({ type: 'circle', xref: 'x',