diff --git a/package.json b/package.json index 100e58f56..95ff2be4f 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "fs": "^0.0.1-security", "gl": "^4.0.4", "glob": "^7.1.2", - "jest": "^23.5.0", + "jest": "^23.6.0", "jest-cli": "^23.5.0", "mkdirp": "^0.5.1", "node-sass": "^4.7.2", @@ -63,12 +63,13 @@ "postcss-combine-duplicated-selectors": "^6.0.2", "postcss-custom-properties": "^6.3.1", "postcss-remove-root": "^0.0.2", - "prettier": "1.14.2", - "react": "^16.0.0", + "prettier": "^1.14.2", + "react": "^16.6.0", "react-ace": "^6.1.4", - "react-dom": "^16.0.0", - "react-hot-loader": "^4.0.0-beta.21", + "react-dom": "^16.6.0", + "react-hot-loader": "^4.3.12", "react-inspector": "^2.2.2", + "react-percy": "^0.3.0", "react-test-renderer": "^16.2.0", "rimraf": "2.6.2", "sass-loader": "^7.1.0", @@ -77,8 +78,8 @@ "webpack-dev-server": "^2.11.1" }, "peerDependencies": { - "react": ">15", - "react-dom": ">15" + "react": ">16.6.0", + "react-dom": ">16.6.0" }, "homepage": "https://plotly.github.io/react-chart-editor/", "jest": { diff --git a/src/DefaultEditor.js b/src/DefaultEditor.js index 9ef3fb2bb..7434d8159 100644 --- a/src/DefaultEditor.js +++ b/src/DefaultEditor.js @@ -19,6 +19,7 @@ import { import {traceHasColorbar} from './default_panels/StyleColorbarsPanel'; import Logo from './components/widgets/Logo'; import {TRANSFORMABLE_TRACES} from './lib/constants'; +import {EditorControlsContext} from './context'; class DefaultEditor extends Component { constructor(props, context) { @@ -98,11 +99,6 @@ DefaultEditor.propTypes = { menuPanelOrder: PropTypes.array, }; -DefaultEditor.contextTypes = { - localize: PropTypes.func, - fullData: PropTypes.array, - fullLayout: PropTypes.object, - layout: PropTypes.object, -}; +DefaultEditor.contextType = EditorControlsContext; export default DefaultEditor; diff --git a/src/EditorControls.js b/src/EditorControls.js index b8de22231..3cb2d064f 100644 --- a/src/EditorControls.js +++ b/src/EditorControls.js @@ -18,6 +18,7 @@ import nestedProperty from 'plotly.js/src/lib/nested_property'; import {categoryLayout, traceTypes} from 'lib/traceTypes'; import {ModalProvider} from 'components/containers'; import {DEFAULT_FONTS} from 'lib/constants'; +import {EditorControlsContext} from './context'; class EditorControls extends Component { constructor(props, context) { @@ -62,6 +63,37 @@ class EditorControls extends Component { }; } + provideValue() { + const gd = this.props.graphDiv || {}; + return { + advancedTraceTypeSelector: this.props.advancedTraceTypeSelector, + config: gd._context, + srcConverters: this.props.srcConverters, + data: gd.data, + dataSources: this.props.dataSources, + dataSourceOptions: this.props.dataSourceOptions, + dataSourceValueRenderer: this.props.dataSourceValueRenderer, + dataSourceOptionRenderer: this.props.dataSourceOptionRenderer, + dictionaries: this.props.dictionaries || {}, + localize: this.localize, + frames: gd._transitionData ? gd._transitionData._frames : [], + fullData: gd._fullData, + fullLayout: gd._fullLayout, + graphDiv: gd, + layout: gd.layout, + locale: this.props.locale, + onUpdate: this.handleUpdate.bind(this), + plotSchema: this.plotSchema, + plotly: this.props.plotly, + traceTypesConfig: this.props.traceTypesConfig, + showFieldTooltips: this.props.showFieldTooltips, + glByDefault: this.props.glByDefault, + mapBoxAccess: this.props.mapBoxAccess, + fontOptions: this.props.fontOptions, + chartHelp: this.props.chartHelp, + }; + } + handleUpdate({type, payload}) { const {graphDiv} = this.props; @@ -295,19 +327,21 @@ class EditorControls extends Component { render() { return ( -
- - {this.props.graphDiv && - this.props.graphDiv._fullLayout && - (this.props.children ? this.props.children : )} - -
+ +
+ + {this.props.graphDiv && + this.props.graphDiv._fullLayout && + (this.props.children ? this.props.children : )} + +
+
); } } diff --git a/src/components/PanelMenuWrapper.js b/src/components/PanelMenuWrapper.js index c23f50695..3f704acfe 100644 --- a/src/components/PanelMenuWrapper.js +++ b/src/components/PanelMenuWrapper.js @@ -3,6 +3,7 @@ import React, {cloneElement, Component} from 'react'; import SidebarGroup from './sidebar/SidebarGroup'; import {bem} from 'lib'; import sortMenu from 'lib/sortMenu'; +import {PanelMenuWrapperContext} from '../context'; class PanelsWithSidebar extends Component { constructor(props) { @@ -30,6 +31,12 @@ class PanelsWithSidebar extends Component { }; } + provideValue() { + return { + setPanel: this.setPanel, + }; + } + renderSection(section, i) { if (section.type && (section.type.plotly_editor_traits || {}).sidebar_element) { return cloneElement(section, {key: i}); @@ -89,18 +96,20 @@ class PanelsWithSidebar extends Component { const menuOpts = this.computeMenuOptions(this.props); return ( -
-
{menuOpts.map(this.renderSection)}
- {React.Children.map( - this.props.children, - (child, i) => - child === null || - this.state.group !== child.props.group || - this.state.panel !== child.props.name - ? null - : cloneElement(child, {key: i}) - )} -
+ +
+
{menuOpts.map(this.renderSection)}
+ {React.Children.map( + this.props.children, + (child, i) => + child === null || + this.state.group !== child.props.group || + this.state.panel !== child.props.name + ? null + : cloneElement(child, {key: i}) + )} +
+
); } } diff --git a/src/components/containers/AnnotationAccordion.js b/src/components/containers/AnnotationAccordion.js index 0db622967..bba399ce1 100644 --- a/src/components/containers/AnnotationAccordion.js +++ b/src/components/containers/AnnotationAccordion.js @@ -4,6 +4,7 @@ import {PanelMessage} from './PanelEmpty'; import PropTypes from 'prop-types'; import React, {Component} from 'react'; import {connectAnnotationToLayout} from 'lib'; +import {EditorControlsContext} from '../../context'; const AnnotationFold = connectAnnotationToLayout(PlotlyFold); @@ -61,10 +62,7 @@ class AnnotationAccordion extends Component { } } -AnnotationAccordion.contextTypes = { - layout: PropTypes.object, - localize: PropTypes.func, -}; +AnnotationAccordion.contextType = EditorControlsContext; AnnotationAccordion.propTypes = { children: PropTypes.node, diff --git a/src/components/containers/ImageAccordion.js b/src/components/containers/ImageAccordion.js index e9a9c488c..5b8a33c0f 100644 --- a/src/components/containers/ImageAccordion.js +++ b/src/components/containers/ImageAccordion.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; import React, {Component} from 'react'; import {connectImageToLayout} from 'lib'; import {PanelMessage} from './PanelEmpty'; +import {EditorControlsContext} from '../../context'; const ImageFold = connectImageToLayout(PlotlyFold); @@ -66,10 +67,7 @@ class ImageAccordion extends Component { } } -ImageAccordion.contextTypes = { - layout: PropTypes.object, - localize: PropTypes.func, -}; +ImageAccordion.contextType = EditorControlsContext; ImageAccordion.propTypes = { children: PropTypes.node, diff --git a/src/components/containers/Modal.js b/src/components/containers/Modal.js index 356842dc4..268304cc9 100644 --- a/src/components/containers/Modal.js +++ b/src/components/containers/Modal.js @@ -1,6 +1,7 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; import {CloseIcon} from 'plotly-icons'; +import {ModalProviderContext} from '../../context'; const ModalHeader = ({title, handleClose}) => (
@@ -68,10 +69,7 @@ Modal.propTypes = { title: PropTypes.node, }; -Modal.contextTypes = { - handleClose: PropTypes.func, - isAnimatingOut: PropTypes.bool, -}; +Modal.contextType = ModalProviderContext; export default Modal; diff --git a/src/components/containers/ModalProvider.js b/src/components/containers/ModalProvider.js index 6cbb13958..a2fabc5bb 100644 --- a/src/components/containers/ModalProvider.js +++ b/src/components/containers/ModalProvider.js @@ -1,5 +1,6 @@ import React, {Fragment} from 'react'; import PropTypes from 'prop-types'; +import {ModalProviderContext} from '../../context'; class ModalProvider extends React.Component { constructor(props) { @@ -70,13 +71,26 @@ class ModalProvider extends React.Component { }; } + provideValue() { + return { + openModal: (c, p) => this.openModal(c, p), + closeModal: () => this.closeModal(), + handleClose: () => this.handleClose(), + isAnimatingOut: this.state.isAnimatingOut, + }; + } + render() { const {component: Component, componentProps, isAnimatingOut} = this.state; return ( - - {this.props.children} - {this.state.open ? : null} - + + + {this.props.children} + {this.state.open ? ( + + ) : null} + + ); } } diff --git a/src/components/containers/PlotlyFold.js b/src/components/containers/PlotlyFold.js index 87a500778..0c167d48f 100644 --- a/src/components/containers/PlotlyFold.js +++ b/src/components/containers/PlotlyFold.js @@ -4,6 +4,7 @@ import React, {Component} from 'react'; import classnames from 'classnames'; import {CloseIcon, AngleDownIcon} from 'plotly-icons'; import {unpackPlotProps, containerConnectedContextTypes, striptags} from 'lib'; +import {PlotlyFoldContext} from '../../context'; export class Fold extends Component { constructor() { @@ -17,9 +18,15 @@ export class Fold extends Component { }; } + provideValue() { + return { + foldInfo: this.props.foldInfo ? this.props.foldInfo : null, + }; + } + render() { if (!this.foldVisible && !this.props.messageIfEmpty) { - return null; + return ; } const {deleteContainer} = this.context; const { @@ -97,10 +104,12 @@ export class Fold extends Component { const classes = className ? ' ' + className : ''; return ( -
- {foldHeader} - {foldContent} -
+ +
+ {foldHeader} + {foldContent} +
+
); } } diff --git a/src/components/containers/PlotlyPanel.js b/src/components/containers/PlotlyPanel.js index 2281dd718..7a22588db 100644 --- a/src/components/containers/PlotlyPanel.js +++ b/src/components/containers/PlotlyPanel.js @@ -5,6 +5,7 @@ import React, {Component, cloneElement} from 'react'; import update from 'immutability-helper'; import {bem} from 'lib'; import {EmbedIconIcon} from 'plotly-icons'; +import {PlotlyPanelContext} from '../../context'; class PanelErrorImpl extends Component { render() { @@ -41,6 +42,12 @@ export class Panel extends Component { }; } + provideValue() { + return { + deleteContainer: this.props.deleteAction ? this.props.deleteAction : null, + }; + } + componentDidCatch() { this.setState({hasError: true}); } @@ -88,7 +95,11 @@ export class Panel extends Component { const {individualFoldStates, hasError} = this.state; if (hasError) { - return ; + return ( + + + + ); } const newChildren = React.Children.map(this.props.children, (child, index) => { @@ -103,15 +114,17 @@ export class Panel extends Component { }); return ( -
- 1} - toggleFolds={this.toggleFolds} - hasOpen={individualFoldStates.some(s => s === false)} - /> -
{newChildren}
-
+ +
+ 1} + toggleFolds={this.toggleFolds} + hasOpen={individualFoldStates.some(s => s === false)} + /> +
{newChildren}
+
+
); } } diff --git a/src/components/containers/RangeSelectorAccordion.js b/src/components/containers/RangeSelectorAccordion.js index 940799ec1..2f188550c 100644 --- a/src/components/containers/RangeSelectorAccordion.js +++ b/src/components/containers/RangeSelectorAccordion.js @@ -3,6 +3,7 @@ import PlotlyPanel from './PlotlyPanel'; import PropTypes from 'prop-types'; import React, {Component} from 'react'; import {connectRangeSelectorToAxis} from 'lib'; +import {EditorControlsContext} from '../../context'; const RangeSelectorFold = connectRangeSelectorToAxis(PlotlyFold); @@ -54,10 +55,7 @@ class RangeSelectorAccordion extends Component { } } -RangeSelectorAccordion.contextTypes = { - fullContainer: PropTypes.object, - localize: PropTypes.func, -}; +RangeSelectorAccordion.contextType = EditorControlsContext; RangeSelectorAccordion.propTypes = { children: PropTypes.node, diff --git a/src/components/containers/ShapeAccordion.js b/src/components/containers/ShapeAccordion.js index a321eb643..fa22a3ffb 100644 --- a/src/components/containers/ShapeAccordion.js +++ b/src/components/containers/ShapeAccordion.js @@ -5,6 +5,7 @@ import React, {Component} from 'react'; import {connectShapeToLayout} from 'lib'; import {COLORS} from 'lib/constants'; import {PanelMessage} from './PanelEmpty'; +import {EditorControlsContext} from '../../context'; const ShapeFold = connectShapeToLayout(PlotlyFold); @@ -66,10 +67,7 @@ class ShapeAccordion extends Component { } } -ShapeAccordion.contextTypes = { - layout: PropTypes.object, - localize: PropTypes.func, -}; +ShapeAccordion.contextType = EditorControlsContext; ShapeAccordion.propTypes = { children: PropTypes.node, diff --git a/src/components/containers/SliderAccordion.js b/src/components/containers/SliderAccordion.js index ef87cbb1f..e87b47e34 100644 --- a/src/components/containers/SliderAccordion.js +++ b/src/components/containers/SliderAccordion.js @@ -3,6 +3,7 @@ import TraceRequiredPanel from './TraceRequiredPanel'; import PropTypes from 'prop-types'; import React, {Component} from 'react'; import {connectSliderToLayout} from 'lib'; +import {EditorControlsContext} from '../../context'; const SliderFold = connectSliderToLayout(PlotlyFold); @@ -26,10 +27,7 @@ class SliderAccordion extends Component { } } -SliderAccordion.contextTypes = { - layout: PropTypes.object, - localize: PropTypes.func, -}; +SliderAccordion.contextType = EditorControlsContext; SliderAccordion.propTypes = { children: PropTypes.node, diff --git a/src/components/containers/SubplotAccordion.js b/src/components/containers/SubplotAccordion.js index e7f3924fd..f2e5326ab 100644 --- a/src/components/containers/SubplotAccordion.js +++ b/src/components/containers/SubplotAccordion.js @@ -9,6 +9,7 @@ import { getSubplotTitle, } from 'lib'; import {TRACE_TO_AXIS, SUBPLOT_TO_ATTR} from 'lib/constants'; +import {EditorControlsContext} from '../../context'; const TraceFold = connectTraceToPlot(PlotlyFold); const NonCartesianSubplotFold = connectNonCartesianSubplotToLayout(PlotlyFold); @@ -143,12 +144,7 @@ class SubplotAccordion extends Component { } } -SubplotAccordion.contextTypes = { - fullData: PropTypes.array, - data: PropTypes.array, - layout: PropTypes.object, - localize: PropTypes.func, -}; +SubplotAccordion.contextType = EditorControlsContext; SubplotAccordion.propTypes = { children: PropTypes.node, diff --git a/src/components/containers/TraceAccordion.js b/src/components/containers/TraceAccordion.js index 062523521..ca52b8bf4 100644 --- a/src/components/containers/TraceAccordion.js +++ b/src/components/containers/TraceAccordion.js @@ -8,6 +8,7 @@ import {connectTraceToPlot, plotlyTraceToCustomTrace} from 'lib'; import {Tab, Tabs, TabList, TabPanel} from 'react-tabs'; import {traceTypes} from 'lib/traceTypes'; import {PanelMessage} from './PanelEmpty'; +import {EditorControlsContext} from '../../context'; const TraceFold = connectTraceToPlot(PlotlyFold); @@ -181,11 +182,7 @@ class TraceAccordion extends Component { } } -TraceAccordion.contextTypes = { - fullData: PropTypes.array, - data: PropTypes.array, - localize: PropTypes.func, -}; +TraceAccordion.contextType = EditorControlsContext; TraceAccordion.propTypes = { canAdd: PropTypes.bool, diff --git a/src/components/containers/TraceRequiredPanel.js b/src/components/containers/TraceRequiredPanel.js index e5f538e3b..745062e0e 100644 --- a/src/components/containers/TraceRequiredPanel.js +++ b/src/components/containers/TraceRequiredPanel.js @@ -2,6 +2,7 @@ import PanelEmpty from './PanelEmpty'; import PropTypes from 'prop-types'; import React, {Component} from 'react'; import {LayoutPanel} from './derived'; +import {EditorControlsContext, ModalProviderContext} from '../../context'; class TraceRequiredPanel extends Component { hasTrace() { @@ -19,13 +20,17 @@ class TraceRequiredPanel extends Component { return this.hasTrace() ? ( {children} ) : ( - -

- {_('Go to the ')} - this.context.setPanel('Structure', 'Traces')}>{_('Traces')} - {_(' panel under Structure to define traces.')} -

-
+ + {({setPanel}) => ( + +

+ {_('Go to the ')} + setPanel('Structure', 'Traces')}>{_('Traces')} + {_(' panel under Structure to define traces.')} +

+
+ )} +
); } } @@ -39,10 +44,6 @@ TraceRequiredPanel.defaultProps = { visible: true, }; -TraceRequiredPanel.contextTypes = { - fullData: PropTypes.array, - localize: PropTypes.func, - setPanel: PropTypes.func, -}; +TraceRequiredPanel.contextType = EditorControlsContext; export default TraceRequiredPanel; diff --git a/src/components/containers/UpdateMenuAccordion.js b/src/components/containers/UpdateMenuAccordion.js index 735c1e9fb..84e7c7339 100644 --- a/src/components/containers/UpdateMenuAccordion.js +++ b/src/components/containers/UpdateMenuAccordion.js @@ -3,6 +3,7 @@ import TraceRequiredPanel from './TraceRequiredPanel'; import PropTypes from 'prop-types'; import React, {Component} from 'react'; import {connectUpdateMenuToLayout} from 'lib'; +import {EditorControlsContext} from '../../context'; const UpdateMenuFold = connectUpdateMenuToLayout(PlotlyFold); @@ -36,10 +37,7 @@ class UpdateMenuAccordion extends Component { } } -UpdateMenuAccordion.contextTypes = { - fullLayout: PropTypes.object, - localize: PropTypes.func, -}; +UpdateMenuAccordion.contextType = EditorControlsContext; UpdateMenuAccordion.propTypes = { children: PropTypes.node, diff --git a/src/components/fields/AxesCreator.js b/src/components/fields/AxesCreator.js index 13e19d816..a1d8b09ee 100644 --- a/src/components/fields/AxesCreator.js +++ b/src/components/fields/AxesCreator.js @@ -7,6 +7,7 @@ import Button from '../widgets/Button'; import {PlusIcon} from 'plotly-icons'; import {connectToContainer, traceTypeToAxisType, getAxisTitle, axisIdToAxisName} from 'lib'; import {PlotlySection} from 'components'; +import {EditorControlsContext, ModalProviderContext} from '../../context'; class UnconnectedAxisCreator extends Component { canAddAxis() { @@ -104,12 +105,7 @@ UnconnectedAxisCreator.propTypes = { updateContainer: PropTypes.func, }; -UnconnectedAxisCreator.contextTypes = { - fullLayout: PropTypes.object, - data: PropTypes.array, - fullData: PropTypes.array, - onUpdate: PropTypes.func, -}; +UnconnectedAxisCreator.contextType = EditorControlsContext; const AxisCreator = connectToContainer(UnconnectedAxisCreator); @@ -149,11 +145,15 @@ class UnconnectedAxesCreator extends Component { return ( {controls} - - {_('You can style and position your axes in the ')} - this.context.setPanel('Structure', 'Subplots')}>{_('Subplots')} - {_(' panel.')} - + + {({setPanel}) => ( + + {_('You can style and position your axes in the ')} + setPanel('Structure', 'Subplots')}>{_('Subplots')} + {_(' panel.')} + + )} + ); } @@ -164,13 +164,7 @@ UnconnectedAxesCreator.propTypes = { fullContainer: PropTypes.object, }; -UnconnectedAxesCreator.contextTypes = { - data: PropTypes.array, - fullData: PropTypes.array, - fullLayout: PropTypes.object, - localize: PropTypes.func, - setPanel: PropTypes.func, -}; +UnconnectedAxesCreator.contextType = EditorControlsContext; export default connectToContainer(UnconnectedAxesCreator, { modifyPlotProps: (props, context, plotProps) => { diff --git a/src/components/fields/ErrorBars.js b/src/components/fields/ErrorBars.js index 9095851c2..b630cd871 100644 --- a/src/components/fields/ErrorBars.js +++ b/src/components/fields/ErrorBars.js @@ -4,6 +4,7 @@ import {DataSelector, Radio, Numeric, MultiColorPicker} from '../index'; import RadioBlocks from '../widgets/RadioBlocks'; import Field from './Field'; import {connectToContainer} from 'lib'; +import {EditorControlsContext} from '../../context'; class ErrorBars extends Component { constructor(props, context) { @@ -158,6 +159,7 @@ class ErrorBars extends Component { render() { return ( + Field {this.renderModeSelector()} {this.renderErrorBarControls()} @@ -171,8 +173,6 @@ ErrorBars.propTypes = { updatePlot: PropTypes.func, }; -ErrorBars.contextTypes = { - localize: PropTypes.func, -}; +ErrorBars.contextType = EditorControlsContext; export default connectToContainer(ErrorBars); diff --git a/src/components/fields/GroupCreator.js b/src/components/fields/GroupCreator.js index e7fb7ff25..c4a279679 100644 --- a/src/components/fields/GroupCreator.js +++ b/src/components/fields/GroupCreator.js @@ -6,6 +6,7 @@ import PropTypes from 'prop-types'; import Button from '../widgets/Button'; import {PlusIcon} from 'plotly-icons'; import {MULTI_VALUED} from 'lib/constants'; +import {EditorControlsContext} from '../../context'; class UnconnectedGroupCreator extends Component { getAllGroups() { @@ -75,10 +76,6 @@ UnconnectedGroupCreator.propTypes = { ...Field.propTypes, }; -UnconnectedGroupCreator.contextTypes = { - localize: PropTypes.func, - data: PropTypes.array, - fullData: PropTypes.array, -}; +UnconnectedGroupCreator.contextType = EditorControlsContext; export default connectToContainer(UnconnectedGroupCreator); diff --git a/src/components/fields/SubplotCreator.js b/src/components/fields/SubplotCreator.js index 45e4bd186..09e87b1cb 100644 --- a/src/components/fields/SubplotCreator.js +++ b/src/components/fields/SubplotCreator.js @@ -7,6 +7,7 @@ import Button from '../widgets/Button'; import {PlusIcon} from 'plotly-icons'; import {connectToContainer, traceTypeToAxisType, getSubplotTitle} from 'lib'; import {PlotlySection} from 'components'; +import {EditorControlsContext, ModalProviderContext} from '../../context'; class UnconnectedSingleSubplotCreator extends Component { canAddSubplot() { @@ -91,12 +92,7 @@ UnconnectedSingleSubplotCreator.propTypes = { updateContainer: PropTypes.func, }; -UnconnectedSingleSubplotCreator.contextTypes = { - fullLayout: PropTypes.object, - data: PropTypes.array, - fullData: PropTypes.array, - onUpdate: PropTypes.func, -}; +UnconnectedSingleSubplotCreator.contextType = EditorControlsContext; const SingleSubplotCreator = connectToContainer(UnconnectedSingleSubplotCreator); @@ -130,11 +126,15 @@ class UnconnectedSubplotCreator extends Component { label={SUBPLOT_TO_ATTR[subplotType].layout} options={getOptions(subplotType)} /> - - {_('You can style and position your subplots in the ')} - this.context.setPanel('Structure', 'Subplots')}>{_('Subplots')} - {_(' panel.')} - + + {({setPanel}) => ( + + {_('You can style and position your subplots in the ')} + setPanel('Structure', 'Subplots')}>{_('Subplots')} + {_(' panel.')} + + )} + ); } @@ -145,13 +145,7 @@ UnconnectedSubplotCreator.propTypes = { fullContainer: PropTypes.object, }; -UnconnectedSubplotCreator.contextTypes = { - data: PropTypes.array, - fullData: PropTypes.array, - fullLayout: PropTypes.object, - localize: PropTypes.func, - setPanel: PropTypes.func, -}; +UnconnectedSubplotCreator.contextType = EditorControlsContext; export default connectToContainer(UnconnectedSubplotCreator, { modifyPlotProps: (props, context, plotProps) => { diff --git a/src/components/fields/TextEditor.js b/src/components/fields/TextEditor.js index a85008401..4231c245b 100644 --- a/src/components/fields/TextEditor.js +++ b/src/components/fields/TextEditor.js @@ -6,6 +6,7 @@ import LaTeX from '../widgets/text_editors/LaTeX'; import RichText from '../widgets/text_editors/RichText'; import MultiFormat from '../widgets/text_editors/MultiFormat'; import HTML from '../widgets/text_editors/HTML'; +import {EditorControlsContext} from '../../context'; class UnconnectedTextEditor extends Component { render() { @@ -60,9 +61,7 @@ UnconnectedTextEditor.propTypes = { updatePlot: PropTypes.func, }; -UnconnectedTextEditor.contextTypes = { - localize: PropTypes.func, -}; +UnconnectedTextEditor.contextType = EditorControlsContext; export default connectToContainer(UnconnectedTextEditor, { modifyPlotProps: (props, context, plotProps) => { diff --git a/src/components/fields/TraceSelector.js b/src/components/fields/TraceSelector.js index 00270429c..e40298842 100644 --- a/src/components/fields/TraceSelector.js +++ b/src/components/fields/TraceSelector.js @@ -11,11 +11,11 @@ import {TRACES_WITH_GL} from 'lib/constants'; import {TraceTypeSelector, TraceTypeSelectorButton, RadioBlocks} from 'components/widgets'; import Field from './Field'; import {CogIcon} from 'plotly-icons'; +import {EditorControlsContext, ModalProviderContext} from '../../context'; class TraceSelector extends Component { constructor(props, context) { super(props, context); - this.updatePlot = this.updatePlot.bind(this); this.setGl = this.setGl.bind(this); this.glEnabled = this.glEnabled.bind(this); @@ -112,17 +112,21 @@ class TraceSelector extends Component { alignItems: 'center', }} > - - this.context.openModal(TraceTypeSelector, { - ...props, - traceTypesConfig: this.context.traceTypesConfig, - glByDefault: this.context.glByDefault, - }) - } - /> + + {({openModal}) => ( + + openModal(TraceTypeSelector, { + ...props, + traceTypesConfig: this.context.traceTypesConfig, + glByDefault: this.context.glByDefault, + }) + } + /> + )} + {!TRACES_WITH_GL.includes(this.props.container.type) ? ( '' ) : ( @@ -149,15 +153,7 @@ class TraceSelector extends Component { } } -TraceSelector.contextTypes = { - openModal: PropTypes.func, - advancedTraceTypeSelector: PropTypes.bool, - traceTypesConfig: PropTypes.object, - plotSchema: PropTypes.object, - config: PropTypes.object, - localize: PropTypes.func, - glByDefault: PropTypes.bool, -}; +TraceSelector.contextType = EditorControlsContext; TraceSelector.propTypes = { container: PropTypes.object.isRequired, diff --git a/src/components/fields/UpdateMenuButtons.js b/src/components/fields/UpdateMenuButtons.js index 3edf503b5..1682242f7 100644 --- a/src/components/fields/UpdateMenuButtons.js +++ b/src/components/fields/UpdateMenuButtons.js @@ -3,6 +3,7 @@ import React, {Component} from 'react'; import {Dropdown, TextEditor} from '../index'; import Field from './Field'; import {connectToContainer} from 'lib'; +import {EditorControlsContext} from '../../context'; class UpdateMenuButtons extends Component { constructor(props, context) { @@ -45,8 +46,6 @@ UpdateMenuButtons.propTypes = { updatePlot: PropTypes.func, }; -UpdateMenuButtons.contextTypes = { - localize: PropTypes.func, -}; +UpdateMenuButtons.contextType = EditorControlsContext; export default connectToContainer(UpdateMenuButtons); diff --git a/src/components/widgets/ColorscalePicker.js b/src/components/widgets/ColorscalePicker.js index 5d40b917b..5255aac96 100644 --- a/src/components/widgets/ColorscalePicker.js +++ b/src/components/widgets/ColorscalePicker.js @@ -3,6 +3,7 @@ import Dropdown from './Dropdown'; import Info from '../fields/Info'; import PropTypes from 'prop-types'; import React, {Component, Fragment} from 'react'; +import {EditorControlsContext} from '../../context'; class Scale extends Component { constructor(props) { @@ -81,8 +82,6 @@ Scale.propTypes = { initialCategory: PropTypes.string, }; -Scale.contextTypes = { - localize: PropTypes.func, -}; +Scale.contextType = EditorControlsContext; export default Scale; diff --git a/src/components/widgets/Dropdown.js b/src/components/widgets/Dropdown.js index 3de20f193..2b1a49eec 100644 --- a/src/components/widgets/Dropdown.js +++ b/src/components/widgets/Dropdown.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types'; import React, {Component} from 'react'; import Select from 'react-select'; import classnames from 'classnames'; +import {EditorControlsContext} from '../../context'; class Dropdown extends Component { constructor(props) { @@ -111,8 +112,6 @@ Dropdown.propTypes = { width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), }; -Dropdown.contextTypes = { - localize: PropTypes.func, -}; +Dropdown.contextType = EditorControlsContext; export default Dropdown; diff --git a/src/components/widgets/Dropzone.js b/src/components/widgets/Dropzone.js index 4fa9da2ae..9fac8d18f 100644 --- a/src/components/widgets/Dropzone.js +++ b/src/components/widgets/Dropzone.js @@ -1,6 +1,7 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; import Drop from 'react-dropzone'; +import {EditorControlsContext} from '../../context'; class Dropzone extends Component { constructor(props, context) { @@ -154,8 +155,6 @@ Dropzone.propTypes = { value: PropTypes.any, }; -Dropzone.contextTypes = { - localize: PropTypes.func, -}; +Dropzone.contextType = EditorControlsContext; export default Dropzone; diff --git a/src/components/widgets/TraceTypeSelector.js b/src/components/widgets/TraceTypeSelector.js index d249d19b2..e69a99e77 100644 --- a/src/components/widgets/TraceTypeSelector.js +++ b/src/components/widgets/TraceTypeSelector.js @@ -4,6 +4,7 @@ import {SearchIcon, ThumnailViewIcon, GraphIcon} from 'plotly-icons'; import Modal from 'components/containers/Modal'; import {traceTypeToPlotlyInitFigure, renderTraceIcon, plotlyTraceToCustomTrace} from 'lib'; import {TRACES_WITH_GL} from 'lib/constants'; +import {EditorControlsContext} from '../../context'; const renderActionItems = (actionItems, item) => actionItems @@ -60,9 +61,7 @@ Item.propTypes = { actions: PropTypes.func, showActions: PropTypes.bool, }; -Item.contextTypes = { - localize: PropTypes.func, -}; +Item.contextType = EditorControlsContext; class TraceTypeSelector extends Component { constructor(props) { @@ -269,8 +268,6 @@ TraceTypeSelectorButton.propTypes = { container: PropTypes.object, traceTypesConfig: PropTypes.object.isRequired, }; -TraceTypeSelectorButton.contextTypes = { - localize: PropTypes.func, -}; +TraceTypeSelectorButton.contextType = EditorControlsContext; export default TraceTypeSelector; diff --git a/src/components/widgets/text_editors/MultiFormat.js b/src/components/widgets/text_editors/MultiFormat.js index 9b02f354e..ac265dd76 100644 --- a/src/components/widgets/text_editors/MultiFormat.js +++ b/src/components/widgets/text_editors/MultiFormat.js @@ -6,6 +6,7 @@ import RichTextEditor from './RichText'; import {isLaTeXExpr, htmlToLaTeX, laTeXToHTML, hasTextExpression} from './convertFormats'; import classnames from 'classnames'; import Button from 'components/widgets/Button'; +import {EditorControlsContext} from '../../../context'; class MultiFormatTextEditor extends Component { constructor(props, context) { @@ -278,8 +279,6 @@ MultiFormatTextEditor.defaultProps = { value: '', }; -MultiFormatTextEditor.contextTypes = { - localize: PropTypes.func, -}; +MultiFormatTextEditor.contextType = EditorControlsContext; export default MultiFormatTextEditor; diff --git a/src/components/widgets/text_editors/RichText/LinkEditor.js b/src/components/widgets/text_editors/RichText/LinkEditor.js index 6b0b2cebd..bf1956a9b 100644 --- a/src/components/widgets/text_editors/RichText/LinkEditor.js +++ b/src/components/widgets/text_editors/RichText/LinkEditor.js @@ -7,6 +7,7 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; import {RETURN_KEY, ESCAPE_KEY} from 'lib/constants'; import {findDOMNode} from 'react-dom'; +import {EditorControlsContext} from '../../../../context'; class LinkEditor extends Component { constructor(props) { @@ -128,8 +129,6 @@ LinkEditor.defaultProps = { }, }; -LinkEditor.contextTypes = { - localize: PropTypes.func.isRequired, -}; +LinkEditor.contextType = EditorControlsContext; export default LinkEditor; diff --git a/src/context/index.js b/src/context/index.js new file mode 100644 index 000000000..312d60220 --- /dev/null +++ b/src/context/index.js @@ -0,0 +1,42 @@ +import {createContext} from 'react'; +const EditorControlsContext = createContext({}); +const PanelMenuWrapperContext = createContext({}); +const ModalProviderContext = createContext({}); +const PlotlyFoldContext = createContext({}); +const PlotlyPanelContext = createContext({}); +// const ConnectAggregationToTransformContext = createContext({}); +// const ConnectAnnotationToLayoutContext = createContext({}); +// const ConnectAxesToLayoutContext = createContext({}); +// const ConnectCartesianSubplotToLayoutContext = createContext({}); +// const ConnectImageToLayoutContext = createContext({}); +// const ConnectLayoutToPlotContext = createContext({}); +// const ConnectNonCartesianSubplotToLayoutContext = createContext({}); +// const ConnectRangeSelectorToAxisContext = createContext({}); +// const ConnectShapeToLayoutContext = createContext({}); +// const ConnectSliderToLayoutContext = createContext({}); +// const ConnectToContainerContext = createContext({}); +const ConnectTraceToPlotContext = createContext({}); +// const ConnectTransformToTraceContext = createContext({}); +// const ConnectUpdateMenuToLayoutContext = createContext({}); + +export { + EditorControlsContext, + PanelMenuWrapperContext, + ModalProviderContext, + PlotlyFoldContext, + PlotlyPanelContext, + // ConnectAggregationToTransformContext, + // ConnectAnnotationToLayoutContext, + // ConnectAxesToLayoutContext, + // ConnectCartesianSubplotToLayoutContext, + // ConnectImageToLayoutContext, + // ConnectLayoutToPlotContext, + // ConnectNonCartesianSubplotToLayoutContext, + // ConnectRangeSelectorToAxisContext, + // ConnectShapeToLayoutContext, + // ConnectSliderToLayoutContext, + // ConnectToContainerContext, + ConnectTraceToPlotContext, + // ConnectTransformToTraceContext, + // ConnectUpdateMenuToLayoutContext, +}; diff --git a/src/default_panels/GraphCreatePanel.js b/src/default_panels/GraphCreatePanel.js index 6cfd2df5a..320bebea8 100644 --- a/src/default_panels/GraphCreatePanel.js +++ b/src/default_panels/GraphCreatePanel.js @@ -1,5 +1,5 @@ import React from 'react'; -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import { DataSelector, Dropdown, @@ -17,148 +17,163 @@ import { HistogramInfoHorizontal, Histogram2d, } from '../components/fields/derived'; +import {EditorControlsContext, ModalProviderContext} from '../context'; -const GraphCreatePanel = (props, {localize: _, setPanel}) => { +const GraphCreatePanel = () => { return ( - - !(t.transforms && t.transforms.some(tr => ['fit', 'moving-average'].includes(tr.type))) - } - > - + + {({localize: _}) => ( + + {({setPanel}) => ( + + !( + t.transforms && + t.transforms.some(tr => ['fit', 'moving-average'].includes(tr.type)) + ) + } + > + - + - - + + - - - - - - {_( - 'Note: in vertical orientation, X values are used for binning. If Y values are provided, they are used as inputs to the histogram function which you can configure in the ' - )} - setPanel('Style', 'Traces')}>{_('Traces')} - {_( - ' panel under Style. If Y values are omitted, the histogram function defaults to Count.' - )} - - - {_( - 'Note: in horizontal orientation, Y values are used for binning. If X values are provided, they are used as inputs to the histogram function which you can configure in the ' - )} - setPanel('Style', 'Traces')}>{_('Traces')} - {_( - ' under Style panel. If X values are omitted, the histogram function defaults to Count.' - )} - - - {_( - 'Note: X and Y Values are used for binning. If Z values are provided, they are used as inputs to the histogram function which you can configure in the ' - )} - setPanel('Style', 'Traces')}>{_('Traces')} - {_( - ' under Style panel. If Z values are omitted, the histogram function defaults to Count.' - )} - - - - - - - - - - - - - - - - - - - + + + + + + {_( + 'Note: in vertical orientation, X values are used for binning. If Y values are provided, they are used as inputs to the histogram function which you can configure in the ' + )} + setPanel('Style', 'Traces')}>{_('Traces')} + {_( + ' panel under Style. If Y values are omitted, the histogram function defaults to Count.' + )} + + + {_( + 'Note: in horizontal orientation, Y values are used for binning. If X values are provided, they are used as inputs to the histogram function which you can configure in the ' + )} + setPanel('Style', 'Traces')}>{_('Traces')} + {_( + ' under Style panel. If X values are omitted, the histogram function defaults to Count.' + )} + + + {_( + 'Note: X and Y Values are used for binning. If Z values are provided, they are used as inputs to the histogram function which you can configure in the ' + )} + setPanel('Style', 'Traces')}>{_('Traces')} + {_( + ' under Style panel. If Z values are omitted, the histogram function defaults to Count.' + )} + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - - + + + + + + + + )} + + )} + ); }; export default GraphCreatePanel; -GraphCreatePanel.contextTypes = { - localize: PropTypes.func, - setPanel: PropTypes.func, -}; +// GraphCreatePanel.contextTypes = { +// localize: PropTypes.func, +// setPanel: PropTypes.func, +// }; diff --git a/src/default_panels/GraphSubplotsPanel.js b/src/default_panels/GraphSubplotsPanel.js index 473ac788d..09a7f471c 100644 --- a/src/default_panels/GraphSubplotsPanel.js +++ b/src/default_panels/GraphSubplotsPanel.js @@ -1,5 +1,5 @@ import React from 'react'; -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import { SubplotAccordion, RectanglePositioner, @@ -16,220 +16,228 @@ import { NumericFraction, } from '../components'; import {TRACE_TO_AXIS} from '../lib/constants'; +import {EditorControlsContext} from '../context'; -const GraphSubplotsPanel = (props, {localize: _}) => ( - - - - - +const GraphSubplotsPanel = () => ( + + {({localize: _}) => ( + + + + + - - + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - - - - - - - - + + + + + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - + + + - - - - - - + + + + + + + )} + ); -GraphSubplotsPanel.contextTypes = { - localize: PropTypes.func, -}; +// GraphSubplotsPanel.contextTypes = { +// localize: PropTypes.func, +// }; export default GraphSubplotsPanel; diff --git a/src/default_panels/GraphTransformsPanel.js b/src/default_panels/GraphTransformsPanel.js index 38592174e..717dceed5 100644 --- a/src/default_panels/GraphTransformsPanel.js +++ b/src/default_panels/GraphTransformsPanel.js @@ -14,6 +14,7 @@ import {connectAggregationToTransform} from '../lib'; import {TRANSFORMABLE_TRACES} from 'lib/constants'; const AggregationSection = connectAggregationToTransform(PlotlySection); +import {EditorControlsContext} from '../context'; export class Aggregations extends Component { render() { @@ -64,37 +65,41 @@ Aggregations.contextTypes = { localize: PropTypes.func, }; -const GraphTransformsPanel = (props, {localize: _}) => { +const GraphTransformsPanel = () => { return ( - TRANSFORMABLE_TRACES.includes(t.type)}> - - + + {({localize: _}) => ( + TRANSFORMABLE_TRACES.includes(t.type)}> + + - + - - - + + + - + - - - + + + + )} + ); }; -GraphTransformsPanel.contextTypes = { - localize: PropTypes.func, -}; +// GraphTransformsPanel.contextTypes = { +// localize: PropTypes.func, +// }; export default GraphTransformsPanel; diff --git a/src/default_panels/StyleColorbarsPanel.js b/src/default_panels/StyleColorbarsPanel.js index ae3527834..b0196f168 100644 --- a/src/default_panels/StyleColorbarsPanel.js +++ b/src/default_panels/StyleColorbarsPanel.js @@ -1,5 +1,5 @@ import React from 'react'; -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import { Radio, @@ -15,256 +15,291 @@ import { ColorPicker, VisibilitySelect, } from '../components'; +import {EditorControlsContext} from '../context'; export const traceHasColorbar = (trace, fullTrace) => (fullTrace.marker && fullTrace.marker.showscale !== undefined) || // eslint-disable-line no-undefined fullTrace.showscale !== undefined; // eslint-disable-line no-undefined -const StyleColorBarsPanel = (props, {localize: _}) => { +const StyleColorBarsPanel = () => { return ( - - {['', 'marker.'].map(prefix => { - return ( - - - - + + {({localize: _}) => ( + + {['', 'marker.'].map(prefix => { + return ( + + + + - - - - - - - - + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - ); - })} - + + + + + + + + + + + + + + + + + + + ); + })} + + )} + ); }; -StyleColorBarsPanel.contextTypes = { - localize: PropTypes.func, -}; +// StyleColorBarsPanel.contextTypes = { +// localize: PropTypes.func, +// }; export default StyleColorBarsPanel; diff --git a/src/default_panels/StyleImagesPanel.js b/src/default_panels/StyleImagesPanel.js index e7feae8be..915cf164f 100644 --- a/src/default_panels/StyleImagesPanel.js +++ b/src/default_panels/StyleImagesPanel.js @@ -1,5 +1,5 @@ import React from 'react'; -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import { ImageAccordion, Radio, @@ -9,67 +9,72 @@ import { PositioningRef, Dropdown, } from '../components'; +import {EditorControlsContext} from '../context'; -const StyleImagesPanel = (props, {localize: _}) => ( - - +const StyleImagesPanel = () => ( + + {({localize: _}) => ( + + - + - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + + )} + ); -StyleImagesPanel.contextTypes = { - localize: PropTypes.func, -}; +// StyleImagesPanel.contextTypes = { +// localize: PropTypes.func, +// }; export default StyleImagesPanel; diff --git a/src/default_panels/StyleLayoutPanel.js b/src/default_panels/StyleLayoutPanel.js index 403abe56d..0ed7207d5 100644 --- a/src/default_panels/StyleLayoutPanel.js +++ b/src/default_panels/StyleLayoutPanel.js @@ -1,5 +1,5 @@ import React from 'react'; -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import { ColorPicker, ColorwayPicker, @@ -16,132 +16,137 @@ import { Radio, } from '../components'; import {HoverColor} from '../components/fields/derived'; +import {EditorControlsContext} from '../context'; -const StyleLayoutPanel = (props, {localize: _}) => ( - - - - - - - - - - +const StyleLayoutPanel = () => ( + + {({localize: _}) => ( + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + )} + ); -StyleLayoutPanel.contextTypes = { - localize: PropTypes.func, -}; +// StyleLayoutPanel.contextTypes = { +// localize: PropTypes.func, +// }; export default StyleLayoutPanel; diff --git a/src/default_panels/StyleLegendPanel.js b/src/default_panels/StyleLegendPanel.js index b650789f0..2780084b3 100644 --- a/src/default_panels/StyleLegendPanel.js +++ b/src/default_panels/StyleLegendPanel.js @@ -1,5 +1,5 @@ import React from 'react'; -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import { ColorPicker, FontSelector, @@ -10,76 +10,81 @@ import { Dropdown, TraceRequiredPanel, } from '../components'; +import {EditorControlsContext} from '../context'; -const StyleLegendPanel = (props, {localize: _}) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const StyleLegendPanel = () => ( + + {({localize: _}) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + )} + ); -StyleLegendPanel.contextTypes = { - localize: PropTypes.func, -}; +// StyleLegendPanel.contextTypes = { +// localize: PropTypes.func, +// }; export default StyleLegendPanel; diff --git a/src/default_panels/StyleNotesPanel.js b/src/default_panels/StyleNotesPanel.js index 1eef7af10..83eb24c50 100644 --- a/src/default_panels/StyleNotesPanel.js +++ b/src/default_panels/StyleNotesPanel.js @@ -1,5 +1,5 @@ import React from 'react'; -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import { AnnotationArrowRef, AnnotationRef, @@ -14,65 +14,70 @@ import { TextEditor, PlotlySection, } from '../components'; +import {EditorControlsContext} from '../context'; -const StyleNotesPanel = (props, {localize: _}) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const StyleNotesPanel = () => ( + + {({localize: _}) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + )} + ); -StyleNotesPanel.contextTypes = { - localize: PropTypes.func, -}; +// StyleNotesPanel.contextTypes = { +// localize: PropTypes.func, +// }; export default StyleNotesPanel; diff --git a/src/default_panels/StyleShapesPanel.js b/src/default_panels/StyleShapesPanel.js index ff6ca1335..b8b74c23c 100644 --- a/src/default_panels/StyleShapesPanel.js +++ b/src/default_panels/StyleShapesPanel.js @@ -1,5 +1,5 @@ import React from 'react'; -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import { ShapeAccordion, Radio, @@ -11,47 +11,52 @@ import { ColorPicker, LineDashSelector, } from '../components'; +import {EditorControlsContext} from '../context'; -const StyleShapesPanel = (props, {localize: _}) => ( - - - +const StyleShapesPanel = () => ( + + {({localize: _}) => ( + + + - - - - - + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + )} + ); -StyleShapesPanel.contextTypes = { - localize: PropTypes.func, -}; +// StyleShapesPanel.contextTypes = { +// localize: PropTypes.func, +// }; export default StyleShapesPanel; diff --git a/src/default_panels/StyleSlidersPanel.js b/src/default_panels/StyleSlidersPanel.js index 1791acb02..19a5490d3 100644 --- a/src/default_panels/StyleSlidersPanel.js +++ b/src/default_panels/StyleSlidersPanel.js @@ -1,5 +1,5 @@ import React from 'react'; -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import { ColorPicker, FontSelector, @@ -9,77 +9,82 @@ import { Dropdown, SliderAccordion, } from '../components'; +import {EditorControlsContext} from '../context'; -const StyleSlidersPanel = (props, {localize: _}) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const StyleSlidersPanel = () => ( + + {({localize: _}) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + )} + ); -StyleSlidersPanel.contextTypes = { - localize: PropTypes.func, -}; +// StyleSlidersPanel.contextTypes = { +// localize: PropTypes.func, +// }; export default StyleSlidersPanel; diff --git a/src/default_panels/StyleTracesPanel.js b/src/default_panels/StyleTracesPanel.js index c42329f05..ece23680f 100644 --- a/src/default_panels/StyleTracesPanel.js +++ b/src/default_panels/StyleTracesPanel.js @@ -1,5 +1,5 @@ import React from 'react'; -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import { Flaglist, @@ -39,622 +39,636 @@ import { TextInfo, HoveronDropdown, } from '../components/fields/derived'; +import {EditorControlsContext} from '../context'; -const StyleTracesPanel = (props, {localize: _}) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const StyleTracesPanel = () => ( + + {({localize: _}) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + + )} + ); -StyleTracesPanel.contextTypes = { - localize: PropTypes.func, -}; +// StyleTracesPanel.contextTypes = { +// localize: PropTypes.func, +// }; export default StyleTracesPanel; diff --git a/src/default_panels/StyleUpdateMenusPanel.js b/src/default_panels/StyleUpdateMenusPanel.js index f8d1bb00d..311f3cfd1 100644 --- a/src/default_panels/StyleUpdateMenusPanel.js +++ b/src/default_panels/StyleUpdateMenusPanel.js @@ -1,5 +1,5 @@ import React from 'react'; -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import { ColorPicker, FontSelector, @@ -10,67 +10,72 @@ import { VisibilitySelect, Radio, } from '../components'; +import {EditorControlsContext} from '../context'; -const StyleUpdateMenusPanel = (props, {localize: _}) => ( - - - - - - - - - - - - - - - - - +const StyleUpdateMenusPanel = () => ( + + {({localize: _}) => ( + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + )} + ); -StyleUpdateMenusPanel.contextTypes = { - localize: PropTypes.func, -}; +// StyleUpdateMenusPanel.contextTypes = { +// localize: PropTypes.func, +// }; export default StyleUpdateMenusPanel; diff --git a/src/index.js b/src/index.js index f53cee550..a29cbca25 100644 --- a/src/index.js +++ b/src/index.js @@ -20,6 +20,13 @@ import { walkObject, } from './lib'; import {EDITOR_ACTIONS} from './lib/constants'; +import { + EditorControlsContext, + PanelMenuWrapperContext, + ModalProviderContext, + PlotlyFoldContext, + PlotlyPanelContext, +} from './context'; import { AnnotationAccordion, @@ -179,6 +186,11 @@ export { EditorControls, DefaultEditor, RectanglePositioner, + EditorControlsContext, + PanelMenuWrapperContext, + ModalProviderContext, + PlotlyFoldContext, + PlotlyPanelContext, }; export default PlotlyEditor; diff --git a/src/lib/connectAggregationToTransform.js b/src/lib/connectAggregationToTransform.js index 9a1df3de8..3aab86b0e 100644 --- a/src/lib/connectAggregationToTransform.js +++ b/src/lib/connectAggregationToTransform.js @@ -35,6 +35,16 @@ export default function connectAggregationToTransform(WrappedComponent) { }; } + provideValue() { + return { + getValObject: attr => + !this.context.getValObject ? null : this.context.getValObject(`aggregations[].${attr}`), + updateContainer: this.updateAggregation, + container: this.container, + fullContainer: this.fullContainer, + }; + } + updateAggregation(update) { const newUpdate = {}; const path = `aggregations[${this.props.aggregationIndex}]`; diff --git a/src/lib/connectAnnotationToLayout.js b/src/lib/connectAnnotationToLayout.js index ea3f282be..b87a0889d 100644 --- a/src/lib/connectAnnotationToLayout.js +++ b/src/lib/connectAnnotationToLayout.js @@ -38,6 +38,17 @@ export default function connectAnnotationToLayout(WrappedComponent) { }; } + provideValue() { + return { + getValObject: attr => + !this.context.getValObject ? null : this.context.getValObject(`annotations[].${attr}`), + updateContainer: this.updateAnnotation, + deleteContainer: this.deleteAnnotation, + container: this.container, + fullContainer: this.fullContainer, + }; + } + updateAnnotation(update) { const newUpdate = {}; const {annotationIndex} = this.props; diff --git a/src/lib/connectAxesToLayout.js b/src/lib/connectAxesToLayout.js index f60e52d1f..c1dd4c1f4 100644 --- a/src/lib/connectAxesToLayout.js +++ b/src/lib/connectAxesToLayout.js @@ -104,6 +104,22 @@ export default function connectAxesToLayout(WrappedComponent) { }; } + provideValue() { + return { + getValObject: attr => + !this.context.getValObject + ? null + : this.context.getValObject(`${this.state.axesTarget}.${attr}`), + axesOptions: this.axesOptions, + axesTarget: this.state.axesTarget, + axesTargetHandler: this.axesTargetHandler, + container: this.container, + defaultContainer: this.defaultContainer, + fullContainer: this.fullContainer, + updateContainer: this.updateContainer, + }; + } + axesTargetHandler(axesTarget) { this.setState({axesTarget}); } diff --git a/src/lib/connectCartesianSubplotToLayout.js b/src/lib/connectCartesianSubplotToLayout.js index eab68ddb1..0fb56e022 100644 --- a/src/lib/connectCartesianSubplotToLayout.js +++ b/src/lib/connectCartesianSubplotToLayout.js @@ -52,6 +52,21 @@ export default function connectCartesianSubplotToLayout(WrappedComponent) { }; } + provideValue() { + return { + getValObject: attr => + !this.context.getValObject + ? null + : this.context.getValObject( + attr.replace('xaxis', this.props.xaxis).replace('yaxis', this.props.yaxis) + ), + updateContainer: this.updateSubplot, + deleteContainer: this.deleteSubplot, + container: this.container, + fullContainer: this.fullContainer, + }; + } + updateSubplot(update) { const newUpdate = {}; for (const key in update) { diff --git a/src/lib/connectImageToLayout.js b/src/lib/connectImageToLayout.js index f2517a15f..a68b00ea8 100644 --- a/src/lib/connectImageToLayout.js +++ b/src/lib/connectImageToLayout.js @@ -38,6 +38,17 @@ export default function connectImageToLayout(WrappedComponent) { }; } + provideValue() { + return { + getValObject: attr => + !this.context.getValObject ? null : this.context.getValObject(`images[].${attr}`), + updateContainer: this.updateImage, + deleteContainer: this.deleteImage, + container: this.container, + fullContainer: this.fullContainer, + }; + } + updateImage(update) { const newUpdate = {}; const {imageIndex} = this.props; diff --git a/src/lib/connectLayoutToPlot.js b/src/lib/connectLayoutToPlot.js index 276f2ddde..0296c2015 100644 --- a/src/lib/connectLayoutToPlot.js +++ b/src/lib/connectLayoutToPlot.js @@ -32,6 +32,32 @@ export default function connectLayoutToPlot(WrappedComponent) { }; } + provideValue() { + const {layout, fullLayout, plotly, onUpdate} = this.context; + + const updateContainer = update => { + if (!onUpdate) { + return; + } + onUpdate({ + type: EDITOR_ACTIONS.UPDATE_LAYOUT, + payload: { + update, + }, + }); + }; + + return { + getValObject: attr => + !plotly + ? null + : plotly.PlotSchema.getLayoutValObject(fullLayout, nestedProperty({}, attr).parts), + updateContainer, + container: layout, + fullContainer: fullLayout, + }; + } + render() { return ; } diff --git a/src/lib/connectNonCartesianSubplotToLayout.js b/src/lib/connectNonCartesianSubplotToLayout.js index db29cb198..f1c91630d 100644 --- a/src/lib/connectNonCartesianSubplotToLayout.js +++ b/src/lib/connectNonCartesianSubplotToLayout.js @@ -43,6 +43,18 @@ export default function connectNonCartesianSubplotToLayout(WrappedComponent) { }; } + provideValue() { + return { + getValObject: attr => + !this.context.getValObject + ? null + : this.context.getValObject(`${this.props.subplot}.${attr}`), + updateContainer: this.updateSubplot, + container: this.container, + fullContainer: this.fullContainer, + }; + } + updateSubplot(update) { const newUpdate = {}; for (const key in update) { diff --git a/src/lib/connectRangeSelectorToAxis.js b/src/lib/connectRangeSelectorToAxis.js index 977a84de9..8e891c9f3 100644 --- a/src/lib/connectRangeSelectorToAxis.js +++ b/src/lib/connectRangeSelectorToAxis.js @@ -42,6 +42,19 @@ export default function connectRangeSelectorToAxis(WrappedComponent) { }; } + provideValue() { + return { + getValObject: attr => + !this.context.getValObject + ? null + : this.context.getValObject(`rangeselector.buttons[].${attr}`), + updateContainer: this.updateRangeselector, + deleteContainer: this.deleteRangeselector, + container: this.container, + fullContainer: this.fullContainer, + }; + } + updateRangeselector(update) { const newUpdate = {}; const {rangeselectorIndex} = this.props; diff --git a/src/lib/connectShapeToLayout.js b/src/lib/connectShapeToLayout.js index d093686a9..441ffe7a8 100644 --- a/src/lib/connectShapeToLayout.js +++ b/src/lib/connectShapeToLayout.js @@ -38,6 +38,17 @@ export default function connectShapeToLayout(WrappedComponent) { }; } + provideValue() { + return { + getValObject: attr => + !this.context.getValObject ? null : this.context.getValObject(`shapes[].${attr}`), + updateContainer: this.updateShape, + deleteContainer: this.deleteShape, + container: this.container, + fullContainer: this.fullContainer, + }; + } + updateShape(update) { const newUpdate = {}; const {shapeIndex} = this.props; diff --git a/src/lib/connectSliderToLayout.js b/src/lib/connectSliderToLayout.js index d42a7bde3..4c1d582b2 100644 --- a/src/lib/connectSliderToLayout.js +++ b/src/lib/connectSliderToLayout.js @@ -34,6 +34,16 @@ export default function connectSliderToLayout(WrappedComponent) { }; } + provideValue() { + return { + getValObject: attr => + !this.context.getValObject ? null : this.context.getValObject(`sliders[].${attr}`), + updateContainer: this.updateSlider, + container: this.container, + fullContainer: this.fullContainer, + }; + } + updateSlider(update) { const newUpdate = {}; const {sliderIndex} = this.props; diff --git a/src/lib/connectToContainer.js b/src/lib/connectToContainer.js index 0a5fedee5..51ee0322b 100644 --- a/src/lib/connectToContainer.js +++ b/src/lib/connectToContainer.js @@ -56,6 +56,13 @@ export default function connectToContainer(WrappedComponent, config = {}) { }; } + provideValue() { + return { + description: this.plotProps.description, + attr: this.attr, + }; + } + render() { // Merge plotprops onto props so leaf components only need worry about // props. However pass plotProps as a specific prop in case inner component diff --git a/src/lib/connectTraceToPlot.js b/src/lib/connectTraceToPlot.js index af621122c..4d58ef80e 100644 --- a/src/lib/connectTraceToPlot.js +++ b/src/lib/connectTraceToPlot.js @@ -76,6 +76,10 @@ export default function connectTraceToPlot(WrappedComponent) { return this.childContext; } + provideValue() { + return this.childContext; + } + updateTrace(update) { if (this.context.onUpdate) { const splitTraceGroup = this.props.fullDataArrayPosition diff --git a/src/lib/connectTransformToTrace.js b/src/lib/connectTransformToTrace.js index a24b16b41..10a7d9372 100644 --- a/src/lib/connectTransformToTrace.js +++ b/src/lib/connectTransformToTrace.js @@ -38,6 +38,17 @@ export default function connectTransformToTrace(WrappedComponent) { }; } + provideValue() { + return { + getValObject: attr => + !this.context.getValObject ? null : this.context.getValObject(`transforms[].${attr}`), + updateContainer: this.updateTransform, + deleteContainer: this.deleteTransform, + container: this.container, + fullContainer: this.fullContainer, + }; + } + updateTransform(update) { const newUpdate = {}; const {transformIndex} = this.props; diff --git a/src/lib/connectUpdateMenuToLayout.js b/src/lib/connectUpdateMenuToLayout.js index 9b1229dd7..05adffe73 100644 --- a/src/lib/connectUpdateMenuToLayout.js +++ b/src/lib/connectUpdateMenuToLayout.js @@ -34,6 +34,16 @@ export default function connectUpdateMenuToLayout(WrappedComponent) { }; } + provideValue() { + return { + getValObject: attr => + !this.context.getValObject ? null : this.context.getValObject(`updatemenus[].${attr}`), + updateContainer: this.updateUpdateMenu, + container: this.container, + fullContainer: this.fullContainer, + }; + } + updateUpdateMenu(update) { const newUpdate = {}; const {updateMenuIndex} = this.props;