Skip to content

Commit d118796

Browse files
committed
remove visibility computations from modifyPlotProps, do it higher up
1 parent 235916a commit d118796

File tree

8 files changed

+65
-85
lines changed

8 files changed

+65
-85
lines changed

src/components/containers/PlotlySection.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import React, {Component} from 'react';
22
import PropTypes from 'prop-types';
3-
import {containerConnectedContextTypes, unpackPlotProps} from '../../lib';
3+
import {
4+
containerConnectedContextTypes,
5+
unpackPlotProps,
6+
validateVisibilityWithCustomConfig,
7+
} from '../../lib';
48

59
export class Section extends Component {
610
constructor() {
@@ -45,7 +49,7 @@ export default class PlotlySection extends Section {
4549

4650
determineVisibility(nextProps, nextContext) {
4751
const {isVisible} = unpackPlotProps(nextProps, nextContext);
48-
this.sectionVisible = Boolean(isVisible);
52+
this.sectionVisible = validateVisibilityWithCustomConfig(isVisible, nextProps, nextContext);
4953

5054
React.Children.forEach(nextProps.children, child => {
5155
if (!child || this.sectionVisible) {
@@ -57,7 +61,13 @@ export default class PlotlySection extends Section {
5761
if (child.type.modifyPlotProps) {
5862
child.type.modifyPlotProps(child.props, nextContext, plotProps);
5963
}
60-
this.sectionVisible = this.sectionVisible || plotProps.isVisible;
64+
65+
this.sectionVisible = validateVisibilityWithCustomConfig(
66+
this.sectionVisible || plotProps.isVisible,
67+
child.props,
68+
nextContext,
69+
child.type && child.type.displayName ? child.type.displayName : null
70+
);
6171
return;
6272
}
6373

src/components/fields/HoverLabelNameLength.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, {Component} from 'react';
22
import PropTypes from 'prop-types';
3-
import {connectToContainer, hasValidCustomConfigVisibilityRules} from 'lib';
3+
import {connectToContainer} from 'lib';
44
import Field from './Field';
55
import RadioBlocks from '../widgets/RadioBlocks';
66
import NumericInput from '../widgets/NumericInput';
@@ -86,11 +86,8 @@ UnconnectedHoverLabelNameLength.displayName = 'UnconnectedHoverLabelNameLength';
8686
export default connectToContainer(UnconnectedHoverLabelNameLength, {
8787
modifyPlotProps: (props, context, plotProps) => {
8888
const {container} = plotProps;
89-
const baseRule =
89+
plotProps.isVisible =
9090
(container.hoverinfo && container.hoverinfo.includes('name')) ||
9191
(container.hovertemplate || container.hovertemplate === ' ');
92-
plotProps.isVisible = hasValidCustomConfigVisibilityRules(context.customConfig)
93-
? plotProps.isVisible && baseRule
94-
: baseRule;
9592
},
9693
});

src/components/fields/LocationSelector.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import React, {Component} from 'react';
22
import PropTypes from 'prop-types';
3-
import {
4-
connectToContainer,
5-
hasValidCustomConfigVisibilityRules,
6-
computeCustomConfigVisibility,
7-
} from 'lib';
3+
import {connectToContainer} from 'lib';
84
import Field from './Field';
95
import Radio from './Radio';
106
import {UnconnectedDropdown} from './Dropdown';
@@ -14,9 +10,7 @@ const LocationmodeVisible = connectToContainer(UnconnectedDropdown, {
1410
modifyPlotProps: (props, context, plotProps) => {
1511
if (!plotProps.fullValue) {
1612
plotProps.fullValue = plotProps.container.locationmode;
17-
plotProps.isVisible = hasValidCustomConfigVisibilityRules(context.customConfig)
18-
? computeCustomConfigVisibility(props, plotProps.fullValue, context.customConfig)
19-
: true;
13+
plotProps.isVisible = true;
2014

2115
return;
2216
}

src/components/fields/derived.js

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,7 @@ import Info from './Info';
1111
import {UnconnectedColorPicker} from './ColorPicker';
1212
import {UnconnectedTextEditor} from './TextEditor';
1313
import {UnconnectedVisibilitySelect} from './VisibilitySelect';
14-
import {
15-
computeCustomConfigVisibility,
16-
connectToContainer,
17-
getAllAxes,
18-
getAxisTitle,
19-
axisIdToAxisName,
20-
hasValidCustomConfigVisibilityRules,
21-
} from 'lib';
14+
import {connectToContainer, getAllAxes, getAxisTitle, axisIdToAxisName} from 'lib';
2215

2316
export const AxisAnchorDropdown = connectToContainer(UnconnectedDropdown, {
2417
modifyPlotProps: (props, context, plotProps) => {
@@ -87,9 +80,7 @@ export const RangesliderVisible = connectToContainer(UnconnectedRadio, {
8780
if (!plotProps.fullValue) {
8881
plotProps.fullValue = false;
8982
plotProps.visible = false;
90-
plotProps.isVisible = hasValidCustomConfigVisibilityRules(context.customConfig)
91-
? computeCustomConfigVisibility(props, plotProps.fullValue, context.customConfig)
92-
: true;
83+
plotProps.isVisible = true;
9384
return;
9485
}
9586
},
@@ -171,10 +162,7 @@ export const TickFormat = connectToContainer(UnconnectedDropdownCustom, {
171162
export const ShowInLegend = connectToContainer(UnconnectedVisibilitySelect, {
172163
modifyPlotProps: (props, context, plotProps) => {
173164
if (context.container.type && context.container.type !== 'sunburst') {
174-
const baseRule = context.fullLayout.showlegend;
175-
plotProps.isVisible = hasValidCustomConfigVisibilityRules(context.customConfig)
176-
? plotProps.isVisible && baseRule
177-
: baseRule;
165+
plotProps.isVisible = context.fullLayout.showlegend;
178166
}
179167

180168
return plotProps;
@@ -183,32 +171,23 @@ export const ShowInLegend = connectToContainer(UnconnectedVisibilitySelect, {
183171

184172
export const HistogramInfoVertical = connectToContainer(Info, {
185173
modifyPlotProps: (props, context, plotProps) => {
186-
const baseRule =
174+
plotProps.isVisible =
187175
context.fullContainer.type === 'histogram' && context.fullContainer.orientation === 'v';
188-
plotProps.isVisible = hasValidCustomConfigVisibilityRules(context.customConfig)
189-
? plotProps.isVisible && baseRule
190-
: baseRule;
191176
return plotProps;
192177
},
193178
});
194179

195180
export const HistogramInfoHorizontal = connectToContainer(Info, {
196181
modifyPlotProps: (props, context, plotProps) => {
197-
const baseRule =
182+
plotProps.isVisible =
198183
context.fullContainer.type === 'histogram' && context.fullContainer.orientation === 'h';
199-
plotProps.isVisible = hasValidCustomConfigVisibilityRules(context.customConfig)
200-
? plotProps.isVisible && baseRule
201-
: baseRule;
202184
return plotProps;
203185
},
204186
});
205187

206188
export const Histogram2d = connectToContainer(Info, {
207189
modifyPlotProps: (props, context, plotProps) => {
208-
const baseRule = context.fullContainer.type === 'histogram2d';
209-
plotProps.isVisible = hasValidCustomConfigVisibilityRules(context.customConfig)
210-
? plotProps.isVisible && baseRule
211-
: baseRule;
190+
plotProps.isVisible = context.fullContainer.type === 'histogram2d';
212191
return plotProps;
213192
},
214193
});
@@ -729,10 +708,7 @@ export const HovermodeDropdown = connectToContainer(UnconnectedVisibilitySelect,
729708

730709
export const HoverColor = connectToContainer(UnconnectedColorPicker, {
731710
modifyPlotProps: (props, context, plotProps) => {
732-
const baseRule = Boolean(context.fullLayout.hovermode);
733-
plotProps.isVisible = hasValidCustomConfigVisibilityRules(context.customConfig)
734-
? plotProps.isVisible && baseRule
735-
: baseRule;
711+
plotProps.isVisible = Boolean(context.fullLayout.hovermode);
736712
return plotProps;
737713
},
738714
});
@@ -742,9 +718,7 @@ export const LevelRendered = connectToContainer(UnconnectedDropdown, {
742718
const _ = context.localize;
743719

744720
if (context.container.ids && context.container.ids.length) {
745-
plotProps.isVisible = hasValidCustomConfigVisibilityRules(context.customConfig)
746-
? plotProps.isVisible
747-
: true;
721+
plotProps.isVisible = true;
748722
plotProps.options = [{label: _('Root'), value: ''}].concat(
749723
context.container.ids.map(i => ({label: i, value: i}))
750724
);

src/lib/__tests__/unpackPlotProps-test.js

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,11 @@
11
import {computeCustomConfigVisibility} from '../index';
2-
import {Component} from 'react';
32

4-
class ColorscalePicker extends Component {
5-
render() {
6-
return null;
7-
}
8-
}
9-
ColorscalePicker.displayName = 'ColorscalePicker';
10-
11-
class AnotherPicker extends Component {
12-
render() {
13-
return null;
14-
}
15-
}
16-
AnotherPicker.displayName = 'AnotherPicker';
17-
18-
const validate = (string, expected, config, wrappedComponent) => {
19-
const isVisible = computeCustomConfigVisibility({attr: string}, 'red', config, wrappedComponent);
3+
const validate = (string, expected, config, wrappedComponentDisplayName) => {
4+
const isVisible = computeCustomConfigVisibility(
5+
{attr: string},
6+
config,
7+
wrappedComponentDisplayName
8+
);
209
expect(isVisible).toBe(expected[string]);
2110
};
2211

@@ -93,7 +82,7 @@ describe('computeCustomConfigVisibility', () => {
9382

9483
const case1 = {'marker.color': false};
9584
const case2 = {'marker.color': true};
96-
Object.keys(case1).forEach(c => validate(c, case1, config, ColorscalePicker));
97-
Object.keys(case2).forEach(c => validate(c, case2, config, AnotherPicker));
85+
Object.keys(case1).forEach(c => validate(c, case1, config, 'ColorscalePicker'));
86+
Object.keys(case2).forEach(c => validate(c, case2, config, 'AnotherPicker'));
9887
});
9988
});

src/lib/connectToContainer.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, {Component} from 'react';
22
import PropTypes from 'prop-types';
3-
import unpackPlotProps from './unpackPlotProps';
3+
import unpackPlotProps, {validateVisibilityWithCustomConfig} from './unpackPlotProps';
44
import {getDisplayName} from '../lib';
55

66
export const containerConnectedContextTypes = {
@@ -63,7 +63,17 @@ export default function connectToContainer(WrappedComponent, config = {}) {
6363
// is also wrapped by a component that `unpackPlotProps`. That way inner
6464
// component can skip computation as it can see plotProps is already defined.
6565
const {plotProps = this.plotProps, ...props} = Object.assign({}, this.plotProps, this.props);
66-
if (props.isVisible) {
66+
const wrappedComponentDisplayName =
67+
WrappedComponent && WrappedComponent.displayName ? WrappedComponent.displayName : null;
68+
69+
if (
70+
validateVisibilityWithCustomConfig(
71+
props.isVisible,
72+
props,
73+
this.context,
74+
wrappedComponentDisplayName
75+
)
76+
) {
6777
return <WrappedComponent {...props} plotProps={plotProps} />;
6878
}
6979

src/lib/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import tinyColor from 'tinycolor2';
2626
import unpackPlotProps, {
2727
computeCustomConfigVisibility,
2828
hasValidCustomConfigVisibilityRules,
29+
validateVisibilityWithCustomConfig,
2930
} from './unpackPlotProps';
3031
import walkObject, {isPlainObject} from './walkObject';
3132
import {traceTypeToPlotlyInitFigure, plotlyTraceToCustomTrace} from './customTraceType';
@@ -265,5 +266,6 @@ export {
265266
transpose,
266267
unpackPlotProps,
267268
upperCase,
269+
validateVisibilityWithCustomConfig,
268270
walkObject,
269271
};

src/lib/unpackPlotProps.js

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,11 @@ export function hasValidCustomConfigVisibilityRules(customConfig) {
6262
return false;
6363
}
6464

65-
export function computeCustomConfigVisibility(props, fullValue, customConfig, wrappedComponent) {
65+
export function computeCustomConfigVisibility(props, customConfig, wrappedComponentDisplayName) {
6666
let isVisible;
6767

6868
const isRegexMatch = rule => {
69-
const stringToTest =
70-
rule.type === 'attrName'
71-
? props.attr
72-
: wrappedComponent && wrappedComponent.displayName
73-
? wrappedComponent.displayName
74-
: '';
75-
69+
const stringToTest = rule.type === 'attrName' ? props.attr : wrappedComponentDisplayName;
7670
return RegExp(rule.regex_match).test(stringToTest);
7771
};
7872

@@ -97,8 +91,21 @@ export function computeCustomConfigVisibility(props, fullValue, customConfig, wr
9791
return isVisible;
9892
}
9993

100-
export default function unpackPlotProps(props, context, wrappedComponent) {
101-
const {container, getValObject, defaultContainer, updateContainer, customConfig} = context;
94+
export function validateVisibilityWithCustomConfig(
95+
initial,
96+
nextProps,
97+
nextContext,
98+
componentDisplayName
99+
) {
100+
let show = initial;
101+
if (show && hasValidCustomConfigVisibilityRules(nextContext.customConfig)) {
102+
show = computeCustomConfigVisibility(nextProps, nextContext.customConfig, componentDisplayName);
103+
}
104+
return show;
105+
}
106+
107+
export default function unpackPlotProps(props, context) {
108+
const {container, getValObject, defaultContainer, updateContainer} = context;
102109

103110
if (!props.attr) {
104111
return {};
@@ -123,10 +130,7 @@ export default function unpackPlotProps(props, context, wrappedComponent) {
123130
multiValued = true;
124131
}
125132

126-
let isVisible = Boolean(hasFullValue(fullValue) || props.show);
127-
if (isVisible && hasValidCustomConfigVisibilityRules(customConfig)) {
128-
isVisible = computeCustomConfigVisibility(props, fullValue, customConfig, wrappedComponent);
129-
}
133+
const isVisible = Boolean(hasFullValue(fullValue) || props.show);
130134

131135
let defaultValue = props.defaultValue;
132136
if (defaultValue === void 0 && defaultContainer) {

0 commit comments

Comments
 (0)