Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vis-violin): violin vis subcategories and proper facets #331

Merged
merged 100 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from 99 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
18b0f55
fixed hexbin plot
dvmoritzschoefl May 3, 2024
d4a9aba
unify plotaxis
dvdanielamoitzi May 3, 2024
6a357fa
fixed lasso
dvmoritzschoefl May 3, 2024
e8e542a
Merge branch 'mh/visinnovation' of github.com:datavisyn/visyn_core in…
dvmoritzschoefl May 3, 2024
60ee24c
hexbinplot: refactor labels, colors, axis
dvdanielamoitzi May 3, 2024
bb7fbc7
moved useZoom
dvmoritzschoefl May 6, 2024
016027b
changed opacity scale
dvmoritzschoefl May 6, 2024
37a6cb8
introduce color and size variables
dvdanielamoitzi May 6, 2024
8d58fd2
align axis / labels / legends / icons of heatmap
dvdanielamoitzi May 6, 2024
babc0be
small heatmap improvements
dvdanielamoitzi May 6, 2024
b1c0e2f
selection colors
dvdanielamoitzi May 6, 2024
72cad6c
fix label
dvdanielamoitzi May 6, 2024
69c18e2
remove raincloud plot
dvdanielamoitzi May 6, 2024
64c6238
use selection and grid colors
dvdanielamoitzi May 6, 2024
d95177a
use correct color
dvdanielamoitzi May 13, 2024
948ab3a
added legend to bar chart
dvmoritzschoefl May 13, 2024
93f8dbb
fix sort icons in barchart
dvdanielamoitzi May 14, 2024
ba0b103
barchart: grid color
dvdanielamoitzi May 14, 2024
bb194be
use rem everywhere
dvdanielamoitzi May 14, 2024
7a5f0ec
add sort icon component
dvdanielamoitzi May 16, 2024
eef9bc4
add priority sort, fix spacing, change default sort of heatmap to none
dvdanielamoitzi May 16, 2024
a01a451
Merge branch 'develop' into mh/visinnovation
dvmoritzschoefl May 22, 2024
15ca9bb
rotat categorical x-labels when too long in barchart
dvdanielamoitzi May 24, 2024
9e6ae8d
rotate labels
dvdanielamoitzi May 25, 2024
e629a0d
fix barchart axis rotation
dvdanielamoitzi May 25, 2024
b523ab4
fix x-label overflow
dvdanielamoitzi May 25, 2024
b8bcf5c
show error message if vis type is not selected
dvdanielamoitzi May 27, 2024
a2efdbd
fix initial label cut off in barchart
dvdanielamoitzi May 27, 2024
9b9e50a
hide grid lines in bar chart
dvdanielamoitzi May 29, 2024
0a1b071
fix barchart sorting
dvdanielamoitzi Jun 3, 2024
c828428
align colors across vis types
dvdanielamoitzi Jun 3, 2024
b24794e
unify unknown labels
dvdanielamoitzi Jun 3, 2024
dd85d86
fix legend height
dvdanielamoitzi Jun 3, 2024
ef7f957
Merge branch 'develop' into mh/visinnovation
dvdanielamoitzi Jun 4, 2024
48aea52
update imports and delete constants.tsx
dvdanielamoitzi Jun 4, 2024
7540199
manage hexbin selection colors
dvdanielamoitzi Jun 4, 2024
8c65df8
barchart: always consider legend height
dvdanielamoitzi Jun 4, 2024
756d828
unify behaviour of selections
dvdanielamoitzi Jun 4, 2024
4d7ab61
rename variable name
dvchristianbors Jun 5, 2024
8673035
use one color scale for hexbin plot
dvchristianbors Jun 5, 2024
395d2f1
implement proper grouping and strip overlay
dvmartinweigl Jun 5, 2024
1f03c91
Merge branch 'develop' into mh/visinnovation
dvdanielamoitzi Jun 6, 2024
547af55
fix: heatmap hover
dvdanielamoitzi Jun 6, 2024
22b7c80
fix: selecting the same vis type twice
dvdanielamoitzi Jun 6, 2024
b383810
remove test vis type from main
dvdanielamoitzi Jun 6, 2024
58fff14
change null label to unknown
dvchristianbors Jun 6, 2024
6eefd4b
improve violin style
dvmartinweigl Jun 6, 2024
9a35494
improve selection
dvmartinweigl Jun 6, 2024
57fd61f
hexbin plot: assign gray color to undefined or null values
dvdanielamoitzi Jun 6, 2024
2d497d3
add possibility to sync yaxis
dvmartinweigl Jun 6, 2024
cf9866e
add possibility to truncate from the middle
dvmartinweigl Jun 6, 2024
f6534a0
barchart: assign gray color to undefined or null values; fix tooltip …
dvdanielamoitzi Jun 6, 2024
726a5ca
add sort logic
dvmartinweigl Jun 6, 2024
945252f
Merge remote-tracking branch 'origin/mh/visinnovation' into mweigl/vi…
dvmartinweigl Jun 7, 2024
7d479b7
assign default color to unknown categories
dvdanielamoitzi Jun 7, 2024
e10b487
hexbin plot: deactivate legend interactiknos
dvdanielamoitzi Jun 7, 2024
5270bb6
Merge remote-tracking branch 'origin/mh/visinnovation' into mweigl/vi…
dvmartinweigl Jun 9, 2024
0843426
add legend group title
dvmartinweigl Jun 9, 2024
a853fdf
add category name to hoverinfo
dvmartinweigl Jun 10, 2024
3294192
refactor: reuse existing selection color variable
thinkh Jun 10, 2024
b023ac3
docs: add comments to constants
thinkh Jun 10, 2024
dced991
refactor: cast to string
thinkh Jun 10, 2024
87cf2d8
some layout improvements
dvmartinweigl Jun 10, 2024
1079366
add breast cancer dataset
dvmartinweigl Jun 10, 2024
c9dc8e9
Merge remote-tracking branch 'origin/mh/visinnovation' into mweigl/vi…
dvmartinweigl Jun 10, 2024
58b6b11
refactor: remove orphan code
thinkh Jun 10, 2024
e2ec2d0
refactor: cast to string
thinkh Jun 10, 2024
eb707fc
docs: convert comment to function comment
thinkh Jun 10, 2024
881137d
fix: remove unused mantine theme from sankey vis
thinkh Jun 10, 2024
657d729
sort icon and sort logic improvements
dvmartinweigl Jun 10, 2024
1490dcc
small sorting fix
dvmartinweigl Jun 10, 2024
c3a7ca7
add generic plotly sort icon create function
dvmartinweigl Jun 10, 2024
4be6b82
apply review feedback
dvdanielamoitzi Jun 11, 2024
e89033f
Merge branch 'develop' into mh/visinnovation
dvdanielamoitzi Jun 11, 2024
7866131
refactor: remove groupedIds
dvdanielamoitzi Jun 11, 2024
3b71fd0
add compact mode for sort icon
dvdanielamoitzi Jun 11, 2024
0a193cb
add sort icon for xaxis
dvmartinweigl Jun 11, 2024
05db48b
Merge remote-tracking branch 'origin/mh/visinnovation' into mweigl/vi…
dvmartinweigl Jun 11, 2024
f821777
switch to breatCancer data set in demo app
dvmartinweigl Jun 11, 2024
247d924
use neutral color for NAN_REPLACEMENT
dvmartinweigl Jun 11, 2024
11de579
move files
dvdanielamoitzi Jun 11, 2024
8637504
rename: I to identityMatrix
dvdanielamoitzi Jun 11, 2024
7ef28d8
rename I functions
dvdanielamoitzi Jun 11, 2024
c3e434a
rename files
dvdanielamoitzi Jun 11, 2024
2148b14
some minor improvements
dvmartinweigl Jun 11, 2024
234473b
Merge remote-tracking branch 'origin/mh/visinnovation' into mweigl/vi…
dvchristianbors Jun 11, 2024
3fd5d1b
Merge remote-tracking branch 'origin/develop' into mweigl/violin-vis-…
dvchristianbors Jun 11, 2024
2c018b7
add constant for traces color
dvchristianbors Jun 11, 2024
0cc24fd
reduce grid spacing
dvmartinweigl Jun 12, 2024
fe2c077
fix pointpos
dvmartinweigl Jun 12, 2024
0a07463
do not add sub category for y-value null
dvmartinweigl Jun 12, 2024
ea23ed5
set plotly legends to be enabled and disable legend click events
dvmartinweigl Jun 12, 2024
3934747
add dummy violin halfs
dvmartinweigl Jun 13, 2024
51edf34
improve grid layout
dvmartinweigl Jun 13, 2024
891beb7
pass separate categoryOrder array per subplot
dvmartinweigl Jun 13, 2024
f12b67b
add gene test data
dvchristianbors Jun 13, 2024
55c147c
Merge remote-tracking branch 'origin/mweigl/violin-vis-grouping' into…
dvchristianbors Jun 13, 2024
34f4527
remove gene test data
dvmartinweigl Jun 14, 2024
9700a12
fix wrong axis type
dvmartinweigl Jun 14, 2024
0aa2f96
add check for undefined data
dvchristianbors Jun 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 9 additions & 24 deletions src/demo/MainApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,16 @@ import {
IScatterConfig,
Vis,
} from '../vis';
import { fetchIrisData } from '../vis/stories/fetchIrisData';
import { iris } from '../vis/stories/irisData';
import { breastCancerData } from '../vis/stories/breastCancerData';
import { fetchBreastCancerData } from '../vis/stories/fetchBreastCancerData';
import { MyCategoricalScore, MyLinkScore, MyNumberScore, MySMILESScore, MyStringScore } from './scoresUtils';

export function MainApp() {
const { user } = useVisynAppContext();
const [visConfig, setVisConfig] = React.useState<BaseVisConfig>({
type: ESupportedPlotlyVis.SCATTER,
numColumnsSelected: [
{
description: '',
id: 'sepalLength',
name: 'Sepal Length',
},
{
description: '',
id: 'sepalWidth',
name: 'Sepal Width',
},
],
color: {
description: '',
id: 'species',
name: 'Species',
},
numColumnsSelected: [],
color: null,
numColorScaleType: ENumericalColorScaleType.SEQUENTIAL,
shape: null,
dragMode: EScatterSelectSettings.RECTANGLE,
Expand All @@ -49,10 +34,10 @@ export function MainApp() {
showStats: true,
},
} as IScatterConfig);
const columns = React.useMemo(() => (user ? fetchIrisData() : []), [user]);
const [selection, setSelection] = React.useState<typeof iris>([]);
const columns = React.useMemo(() => (user ? fetchBreastCancerData() : []), [user]);
const [selection, setSelection] = React.useState<typeof breastCancerData>([]);

const visSelection = React.useMemo(() => selection.map((s) => `${iris.indexOf(s)}`), [selection]);
const visSelection = React.useMemo(() => selection.map((s) => `${breastCancerData.indexOf(s)}`), [selection]);
const [loading, setLoading] = React.useState(false);
const lineupRef = React.useRef<DatavisynTaggle>();

Expand Down Expand Up @@ -111,7 +96,7 @@ export function MainApp() {
/>

<VisynRanking
data={iris}
data={breastCancerData}
selection={selection}
setSelection={setSelection}
getBuilder={({ data }) => defaultBuilder({ data, smilesOptions: { setDynamicHeight: true } })}
Expand All @@ -130,7 +115,7 @@ export function MainApp() {
selected={visSelection}
selectionCallback={(s) => {
if (s) {
setSelection(s.map((i) => iris[+i]));
setSelection(s.map((i) => breastCancerData[+i]));
}
}}
filterCallback={(f) => {
Expand Down
64 changes: 61 additions & 3 deletions src/vis/general/SortIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import * as React from 'react';
import { Tooltip, ActionIcon, Text, Group } from '@mantine/core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { VIS_LABEL_COLOR } from './constants';
import { ActionIcon, Group, Text, Tooltip } from '@mantine/core';
import * as d3v7 from 'd3v7';
import * as React from 'react';
import { dvSort, dvSortAsc, dvSortDesc } from '../../icons';
import { selectionColorDark } from '../../utils';
import { VIS_LABEL_COLOR } from './constants';

export enum ESortStates {
NONE = 'none',
Expand Down Expand Up @@ -53,3 +54,60 @@ export function SortIcon({
</Group>
);
}

export function createPlotlySortIcon({
sortState,
axis,
axisLabel,
onToggleSort,
}: {
sortState: { col: string; state: ESortStates };
axis: string;
axisLabel: string;
onToggleSort: (col: string) => void;
}) {
const icon = sortState?.col === axisLabel ? (sortState.state === ESortStates.ASC ? dvSortAsc.icon[4] : dvSortDesc.icon[4]) : dvSort.icon[4];
const color = sortState?.col === axisLabel ? selectionColorDark : VIS_LABEL_COLOR;

const isYAxis = axis.includes('y');
const titleElement = d3v7.select(`g .${axis}title`);

if (titleElement.node()) {
// @ts-ignore
const bounds = titleElement.node().getBoundingClientRect();
const yOffset = isYAxis ? bounds.height / 2 + 30 : bounds.height - 5;
const xOffset = isYAxis ? bounds.width / 2 : -(bounds.width / 2 + 15);
const y = Number.parseInt(titleElement.attr('y'), 10) - yOffset;
const x = Number.parseInt(titleElement.attr('x'), 10) - xOffset;
if (d3v7.select(`g .g-${axis}title`).select('svg').empty()) {
const title = d3v7.select(`g .g-${axis}title`);

title
.style('pointer-events', 'all')
.append('svg')
.attr('width', 14)
.attr('height', 16)
.attr('x', x)
.attr('y', y)
.attr('viewBox', '0 0 512 472')
.attr('xmlns', 'http://www.w3.org/2000/svg')
.attr('fill', color)
.append('path')
.style('stroke-width', '1')
.attr('d', icon)
.attr('transform', `${isYAxis ? 'rotate(-90, 256, 236)' : ''}`);

title
.append('foreignObject')
.attr('width', 16)
.attr('height', 18)
.attr('x', x)
.attr('y', y)
.html(`<div></div>`)
.style('cursor', 'pointer')
.on('click', () => {
onToggleSort(axisLabel);
});
}
}
}
5 changes: 5 additions & 0 deletions src/vis/general/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ export const VIS_GRID_COLOR = '#E9ECEF';
*/
export const VIS_NEUTRAL_COLOR = '#71787E';

/**
* Trace color (e.g., Dot labels in scatter plot)
*/
export const VIS_TRACES_COLOR = '#7f7f7f';

/**
* Color for unselected items. It is the VIS_NEUTRAL_COLOR but with 0.3 opacity.
*/
Expand Down
91 changes: 69 additions & 22 deletions src/vis/general/layoutUtils.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
import { ColumnInfo, PlotlyInfo, VisColumn } from '../interfaces';
import { PlotlyTypes } from '../../plotly';
import { VIS_AXIS_LABEL_SIZE, VIS_AXIS_LABEL_SIZE_SMALL, VIS_GRID_COLOR, VIS_LABEL_COLOR, VIS_TICK_LABEL_SIZE, VIS_TICK_LABEL_SIZE_SMALL } from './constants';
import { ColumnInfo, PlotlyInfo, VisColumn } from '../interfaces';
import {
VIS_AXIS_LABEL_SIZE,
VIS_AXIS_LABEL_SIZE_SMALL,
VIS_GRID_COLOR,
VIS_LABEL_COLOR,
VIS_TICK_LABEL_SIZE,
VIS_TICK_LABEL_SIZE_SMALL,
VIS_TRACES_COLOR,
} from './constants';

/**
*
* @param alpha Alpha value from 0-1 to convert to hex representation
* @returns Hex representation of the given alpha value
*/
export const alphaToHex = (alpha: number) => {
const alphaInt = Math.round(alpha * 255);
const alphaHex = alphaInt.toString(16).toUpperCase();
return alphaHex.padStart(2, '0');
};

/**
* Truncate long texts (e.g., to use as axes title)
* @param text Input text to be truncated
* @param middle If true, truncate from the middle (default: false)
* @param maxLength Maximum text length (default: 50)
*/
export function truncateText(text: string, maxLength = 50) {
return text?.length > maxLength ? `${text.substring(0, maxLength)}\u2026` : text;
export function truncateText(text: string, middle: boolean = false, maxLength = 50) {
const half = maxLength / 2;
return text?.length > maxLength
? middle
? `${text.substring(0, half)}\u2026${text.substring(text.length - half)}`
: `${text.substring(0, maxLength)}\u2026`
: text;
}

export function columnNameWithDescription(col: ColumnInfo) {
Expand All @@ -21,9 +46,22 @@ export function columnNameWithDescription(col: ColumnInfo) {
* @param layout the current layout to be changed. Typed to any because the plotly types complain.p
* @returns the changed layout
*/
export function beautifyLayout(traces: PlotlyInfo, layout: Partial<PlotlyTypes.Layout>, oldLayout: Partial<PlotlyTypes.Layout>, automargin = true) {
export function beautifyLayout(
traces: PlotlyInfo,
layout: Partial<PlotlyTypes.Layout>,
oldLayout: Partial<PlotlyTypes.Layout>,
categoryOrder: Map<number, string[]> = null,
automargin = true,
autorange = true,
) {
layout.annotations = [];
const titlePlots = traces.plots.filter((value, index, self) => {

// Sometimes we have multiple traces that share the same axis. For layout changes we only need to consider one per axis.
const sharedAxisTraces = traces.plots.filter((value, index, self) => {
return self.findIndex((v) => v.data.xaxis === value.data.xaxis && v.data.yaxis === value.data.yaxis) === index;
});

const titleTraces = sharedAxisTraces.filter((value, index, self) => {
return value.title && self.findIndex((v) => v.title === value.title) === index;
});

Expand All @@ -34,73 +72,82 @@ export function beautifyLayout(traces: PlotlyInfo, layout: Partial<PlotlyTypes.L

// We should stop using plotly for a component like this one which wants a lot of unique functionality, and does not require complex rendering logic (like a canvas)

titlePlots.forEach((t) => {
titleTraces.forEach((t) => {
if (t.title) {
layout.annotations.push({
text: t.title,
text: truncateText(t.title, true, 30),
showarrow: false,
x: 0.5,
y: 1.1,
// @ts-ignore
xref: `${t.data.xaxis} domain`,
// @ts-ignore
yref: `${t.data.yaxis} domain`,
y: 1.0,
yshift: 5,
xref: `${t.data.xaxis} domain` as Plotly.XAxisName,
yref: `${t.data.yaxis} domain` as Plotly.YAxisName,
font: {
size: 13.4,
color: VIS_TRACES_COLOR,
},
});
}
});

traces.plots.forEach((t, i) => {
sharedAxisTraces.forEach((t, i) => {
const axisX = t.data.xaxis?.replace('x', 'xaxis') || 'xaxis';
layout[axisX] = {
range: t.xDomain ? t.xDomain : null,
...oldLayout?.[`xaxis${i > 0 ? i + 1 : ''}`],
range: t.xDomain ? t.xDomain : null,
color: VIS_LABEL_COLOR,
gridcolor: VIS_GRID_COLOR,
zerolinecolor: VIS_GRID_COLOR,
automargin,
tickvals: t.xTicks,
ticktext: t.xTickLabels,
tickfont: {
size: traces.plots.length > 1 ? VIS_TICK_LABEL_SIZE_SMALL : VIS_TICK_LABEL_SIZE,
size: sharedAxisTraces.length > 1 ? VIS_TICK_LABEL_SIZE_SMALL : VIS_TICK_LABEL_SIZE,
},
type: typeof t.data.x[0] === 'string' ? 'category' : null,
ticks: 'none',
text: t.xTicks,
showspikes: false,
spikedash: 'dash',
categoryarray: categoryOrder?.get(i + 1) || null,
categoryorder: categoryOrder?.get(i + 1) ? 'array' : null,

title: {
standoff: 5,
text: traces.plots.length > 1 ? truncateText(t.xLabel, 20) : truncateText(t.xLabel, 55),
text: sharedAxisTraces.length > 1 ? truncateText(t.xLabel, false, 20) : truncateText(t.xLabel, true, 55),
font: {
family: 'Roboto, sans-serif',
size: traces.plots.length > 1 ? VIS_AXIS_LABEL_SIZE_SMALL : VIS_AXIS_LABEL_SIZE,
size: sharedAxisTraces.length > 1 ? VIS_AXIS_LABEL_SIZE_SMALL : VIS_AXIS_LABEL_SIZE,
color: VIS_LABEL_COLOR,
},
},
};

const axisY = t.data.yaxis?.replace('y', 'yaxis') || 'yaxis';
layout[axisY] = {
range: t.yDomain ? t.yDomain : null,
...oldLayout?.[`yaxis${i > 0 ? i + 1 : ''}`],
range: t.yDomain ? t.yDomain : null,
automargin,
autorange,
color: VIS_LABEL_COLOR,
gridcolor: VIS_GRID_COLOR,
zerolinecolor: VIS_GRID_COLOR,
tickvals: t.yTicks,
ticktext: t.yTickLabels,
tickfont: {
size: traces.plots.length > 1 ? VIS_TICK_LABEL_SIZE_SMALL : VIS_TICK_LABEL_SIZE,
size: sharedAxisTraces.length > 1 ? VIS_TICK_LABEL_SIZE_SMALL : VIS_TICK_LABEL_SIZE,
},
type: typeof t.data.y[0] === 'string' ? 'category' : null,
ticks: 'none',
text: t.yTicks,
showspikes: false,
spikedash: 'dash',
title: {
standoff: 5,
text: traces.plots.length > 1 ? truncateText(t.yLabel, 20) : truncateText(t.yLabel, 55),
text: sharedAxisTraces.length > 1 ? truncateText(t.yLabel, false, 20) : truncateText(t.yLabel, true, 55),
font: {
family: 'Roboto, sans-serif',
size: traces.plots.length > 1 ? VIS_AXIS_LABEL_SIZE_SMALL : VIS_AXIS_LABEL_SIZE,
size: sharedAxisTraces.length > 1 ? VIS_AXIS_LABEL_SIZE_SMALL : VIS_AXIS_LABEL_SIZE,
color: VIS_LABEL_COLOR,
weight: 'bold',
},
Expand Down
1 change: 1 addition & 0 deletions src/vis/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export interface VisNumericalColumn extends VisCommonColumn {
export interface VisCategoricalColumn extends VisCommonColumn {
type: EColumnTypes.CATEGORICAL;
color?: Record<string, string>;
domain?: string[];
}

export type VisColumn = VisNumericalColumn | VisCategoricalColumn;
Expand Down
11 changes: 8 additions & 3 deletions src/vis/scatter/ScatterVis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { BrushOptionButtons } from '../sidebar/BrushOptionButtons';
import { fitRegressionLine } from './Regression';
import { ELabelingOptions, ERegressionLineType, IRegressionResult, IScatterConfig } from './interfaces';
import { createScatterTraces, defaultRegressionLineStyle } from './utils';
import { VIS_TRACES_COLOR } from '../general/constants';

const formatPValue = (pValue: number) => {
if (pValue === null) {
Expand Down Expand Up @@ -181,7 +182,7 @@ export function ScatterVis({
showarrow: false,
font: {
size: 16,
color: '#7f7f7f',
color: VIS_TRACES_COLOR,
},
}),
);
Expand Down Expand Up @@ -220,11 +221,11 @@ export function ScatterVis({
b: 50,
},
shapes: [],
grid: { rows: traces.rows, columns: traces.cols, xgap: 0.3, pattern: 'independent' },
grid: { rows: traces.rows, columns: traces.cols, xgap: 0.15, ygap: config.facets ? 0.2 : 0.15, pattern: 'independent' },
dragmode: config.dragMode,
};

setLayout({ ...layout, ...beautifyLayout(traces, innerLayout, layout, false) });
setLayout({ ...layout, ...beautifyLayout(traces, innerLayout, layout, null, false) });
// WARNING: Do not update when layout changes, that would be an infinite loop.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [traces, config.dragMode, showLegend]);
Expand Down Expand Up @@ -349,6 +350,10 @@ export function ScatterVis({
selectionCallback([...selectedList, clickedId]);
}
}}
onLegendClick={() => false}
onDoubleClick={() => {
selectionCallback([]);
}}
onInitialized={() => {
d3.select(id).selectAll('.legend').selectAll('.traces').style('opacity', 1);
}}
Expand Down
Loading
Loading