GithubHelp home page GithubHelp logo

plotly / react-chart-editor Goto Github PK

View Code? Open in Web Editor NEW
496.0 496.0 100.0 26.94 MB

Customizable React-based editor panel for Plotly charts

Home Page: https://plotly.github.io/react-chart-editor/

License: MIT License

JavaScript 89.39% CSS 0.04% HTML 0.05% SCSS 10.52%

react-chart-editor's Introduction

react-chart-editor

React component for creating & editing D3 charts. Sponsor an addition to this project

master

Demo & Screenshots

Check out the live demo here.

gif

Quick start

Check out the demo of the latest release of the DefaultEditor at https://plotly.github.io/react-chart-editor/ or run it locally with:

git clone [this repo]
cd react-chart-editor
cd examples/demo
yarn install
yarn watch

See more examples here.

Overview

This module's entry point is a React component called <PlotlyEditor /> which connects an instance of <EditorControls /> to a plotly.js-powered <Plot /> component care of react-plotly.js. <PlotlyEditor /> accepts as children React components whose descendents are input elements wrapped via connectToContainer() calls so as to bind them to the <Plot />'s figure's values. If no children are passed to the <PlotlyEditor />, the <DefaultEditor /> is used. This module also exposes the building block components that comprise the <DefaultEditor /> so that developers can create their own customized editors.

Styling the <DefaultEditor /> and the built-in components

  • Import editor styles with import 'react-chart-editor/lib/react-chart-editor.min.css'
  • Interested in theming?
  • Need to support IE11? import the IE css instead: import 'react-chart-editor/lib/react-chart-editor.ie.min.css'

Development Setup

This repo contains a dev app that depends on the components locally and is configured for hot reloading, for easy local development. A jest-based test suite is also included.

cp accessTokens.tpl.js accessTokens.js # and edit to taste
yarn install
yarn watch
# hacking happens here
yarn test

Built-in Components

This module provides a number of nestable containers which are intended to contain fields that render widgets that have been connected to individual values in the figure via connector functions. Containers can also be connected to parts of the figure tree (e.g. layout or specific traces in data) such that their child fields map to the appropriate leaf values. A field must have a connected container as an ancestor in order to be bound to the figure. The <PlotlyEditor /> and connector functions use the React context API to push configuration information to child components.

At a pseudo-code level it looks like this:

<PlotlyEditor {...etc}>
  <ConnectedContainer {...etc}>
    <Field attr="path.to.figure.value" {...etc} />
  </ConnectedContainer>
</PlotlyEditor>

The custom editor example shows how to build a custom editor, and shows off all of the general-purpose containers and fields listed below.

General-purpose Containers

  • <PanelMenuWrapper />: renders as a sidebar selector menu for <Panel />s
  • <PlotlyPanel />: renders as a generic rectangular container with special handling for collapsing/expanding child <Fold />s and optionally an 'add' button for creating them, has special visibility rules that depend on plotly figure
  • <PlotlyFold />: collapsable container within a <Panel />, has special visibility rules that depend on plotly figure
  • <PlotlySection />: uncollapsable container within a <Panel /> or <Fold />, has special visibility rules that depend on plotly figure
  • <Panel/>, <Fold/>, <Section/>: same as PlotlyPanel, PlotlyFold, PlotlySection, but there are no special visibility rules, those containers always show, and always show their children, but Fold does not have the canDelete functionality as its context related
  • <SingleSidebarItem/>: wraps any item you would like to see appear in the sidebar menu.

General-purpose Fields

All Fields except <Info /> accept an attr property to bind them to a key in the figure (see https://plot.ly/javascript/reference/ for exhaustive documentation of figure keys). This property can be a .-delimited path to a leaf, starting at the context-appropriate point in the figure for the parent container (see connector functions below).

  • <Info />: renders its children as HTML, useful for displaying help text
  • <Numeric />: renders as a text field with arrows and units, useful for numeric values
  • <Radio />: renders as a button group, useful for mutually-exclusive low-cardinality enumerable values
  • <Dropdown />: renders as a dropdown menu useful for mutually-exclusive high-cardinality enumerable values
  • <Dropzone/>: renders a dropzone component to drag and drop files to load
  • <ColorPicker />: renders as a popup color-picker, useful for CSS color hex value strings
  • <ColorscalePicker />: npm module react-colorscales
  • <Flaglist />: renders as a list of checkboxes, useful for +-joined flag lists like data[].mode
  • <TextEditor />: renders as a WYSIWYG editor, useful for text like layout.title, takes props: latexOnly, richTextOnly, htmlOnly if no format props given, defaults to the MultiFormat text editor (latex && richText && html)

Components

Widgets

Simple component that takes in props and renders.

  • <Button/>: simple button component, useful when combined with <SingleSidebarItem/> to add as menu item

Special-Purpose Containers

  • <TraceAccordion />: <Panel /> whose children are replicated into <Folds /> connected to traces via connectTraceToPlot().
  • <LayoutPanel />: <Panel /> whose children are connected to the layout figure key
  • <LayoutSection />: <Section /> whose children are connected to the layout figure key
  • <TraceRequiredPanel />: <LayoutPanel /> renders <PanelEmpty /> if no trace data is set, can add extra conditions (i.e. an array of functions that will be run) with the extraConditions prop and a matching array with extraEmptyPanelMessages to show when those conditions are not met.
  • <AnnotationAccordion />: <Panel /> whose children are replicated into <Folds /> connected to annotations via connectAnnotationToLayout(). For use in a <LayoutPanel />.
  • <ShapeAccordion />: <Panel /> whose children are replicated into <Folds /> connected to shapes via connectShapeToLayout(). For use in a <LayoutPanel />.
  • <ImageAccordion />: <Panel /> whose children are replicated into <Folds /> connected to images via connectImageToLayout(). For use in a <LayoutPanel />.
  • <AxesFold />: <Fold /> whose children are bound to axis-specific keys. For use in a <LayoutPanel />; and automatically contains an <AxesSelector /> (see below).
  • <TraceMarkerSection />: <Section /> with trace-specific name handling. For use in containers bound to traces e.g. as children of <TraceAccordion />.

Special-Purpose Fields

For use in containers bound to traces e.g. as children of <TraceAccordion />:

  • <DataSelector />: renders as a <Dropdown /> coupled to data[].*src etc, triggers onUpdateTraces when changed
  • <TraceSelector />: renders as a <Dropdown /> useful for data[].type
  • <LineDashSelector />: renders as a <Dropdown /> useful for data[].line.dash
  • <LineShapeSelector />: renders as a <Dropdown /> useful for data[].line.shape
  • <SymbolSelector />: renders as a <Dropdown /> useful for data[].marker.symbol
  • <PositioningRef />: renders as a <Dropdown /> useful for layout.*.xref/yref where the allowable values are paper|[axis]
  • <ErrorBars/>: renders a set of controls that control a trace's error bars (visibility, type, value, valueminus, array, arrayminus)

For use in containers bound to layout:

  • <FontSelector />: renders as a <Dropdown /> whose options are rendered in the selected font
  • <CanvasSize />: renders as a <Numeric /> with visibility coupled to layout.autosize

For use in containers bound to axes:

  • <AxesSelector />: renders as a <Radio /> to select one or all axes. Must be in a container bound to a figure via connectAxesToPlot() and sets that container's context such that its children are bound to either all axes or just the selected one. <AxesFold>s automatically contain this component.
  • <AxesRange />: numeric with visibility coupled to layout.*axis.autorange

For use in containers bound to annotations e.g. as children of <AnnotationAccordion />:

  • <AnnotationRef />: renders as a <Dropdown /> useful for layout.annotations[].xref, layout.annotations[].yref
  • <AnnotationArrowRef />: renders as a <Dropdown /> useful for layout.annotations[].axref, layout.annotations[].ayref
  • <ArrowSelector />: renders as a <Dropdown /> useful for layout.annotations[].arrowhead

Connector functions

  • connectToContainer( Component ): returns a field component that can be bound to a figure value via the attr prop.
  • connectTraceToPlot( Container ): returns a wrapped container component that can be bound to a figure trace such that its children are bound to that trace's figure entry under the data key, e.g. <TraceAccordion /> above.
  • connectLayoutToPlot( Container ): returns a wrapped container component that can be bound to a figure such that its children are bound to that figure's layout under the layout key.
  • connectAxesToLayout( Container ): returns a wrapped container component that should contain an <AxesSelector /> field (see above) and can be bound to a figure such that its children are bound to that figure's axes entries under the layout.*axis keys.
  • connectAnnotationToLayout( Container ): returns a wrapped container component that can be bound to a figure annotation such that its children are bound to that annotation's figure entry under the layout.annotations key, e.g. the <Fold>s in <AnnotationAccordion /> above.
  • connectShapeToLayout( Container ): returns a wrapped container component that can be bound to a shape such that its children are bound to that shape's figure entry under the layout.shapes key, e.g. the <Fold>s in <ShapeAccordion /> above.
  • connectImagesToLayout( Container ): returns a wrapped container component that can be bound to an image such that its children are bound to that image's figure entry under the layout.image key, e.g. the <Fold>s in <ImageAccordion /> above.

Mapbox Access Tokens

To use Satellite Maps in the Editor, Mapbox access tokens are required.

Once you have your tokens, you can provide it as a config prop to the <PlotlyEditor /> component: <PlotlyEditor config={{mapboxAccessToken: 'your token'}}/>

See also

License

© 2019 Plotly, Inc. MIT License.

react-chart-editor's People

Contributors

alexcjohnson avatar ankoh avatar aulneau avatar bhogan-mitre avatar bpostlethwaite avatar dmt0 avatar gvwilson avatar jackparmer avatar nicolaskruchten avatar oprstchn avatar renovate-bot avatar rreusser avatar verazab avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-chart-editor's Issues

Reference Issues

It looks like the latest commit added a lib folder to the lib folder which threw off all the references to common in the components. Also, the PlotlyReactEditor.js file changed from plotly.js-react-editor which broke the reference in index.js

But after fixing all those references, I get the following run-time error:
TypeError: Super expression must either be null or a function, not undefined index.js:35134:113

Transpile *all* src files

Only transpiling the entry point breaks everything. For an exported component, all source files must be transpiled into lib.

Title and Fonts: Typeface

Text editor to change title content and font.

Depends upon: font selector menu, possibly rich text editor from streambed.

Fill color - Default and custom

Plotly to provide their color picker as a default; built in a way that it can be updated later.

This feature requires the color picker to work, which is mainly dependent upon #9.

Title and fonts: Size

Font size menu. (To check: Is this a regular select menu? Part of the rich text editor? Both?)

Canvas size: display in inches

Similar to photoshop, it would be nice to have a linked editor in which you can specify inches and get pixels. That requires some conversion factor like 72 dpi that's just not as relevant in 2017 as it used to be, but so that we can provide intuitive units for people to work with and since it affects things like font sizes, the photoshop editor is probably a good way to approach it.

screen shot 2017-10-16 at 10 41 35

Add SCSS build process

So far I've been sticking with plain CSS. It's the main barrier preventing the color selector from working, so it seems that the time has come to pull in scss from streambed and get a proper scss pipeline hooked up.

i18n

Opening this for a discussion of i18n, both for this and for the public plotly.js repo.

There are a few different ways to accomplish this. In semi-pseudocode, the i18n function fundamentally looks like:

function _( key ) {
  if (key in dictionary) {
    return dictionary[key]
  } else {
    return key
  }
}

The input is the string itself, which has pros and cons. The dictionary looks like:

{
  "es": {
    "Trace": "Rastro",
    "Click to toggle visibility": "Haga clic para activar la visibilidad",
    ...etc
  },
  "ru": {
    ...
  }
}

You'd use this like:

_("Trace")

The downside is that "Trace" (nominative) and "Trace" (accusative) have different translations in some languages. If this were the case, you could be more explicit and make nontrivial use of an english dictionary to use keys instead of the strings themselves.

{
  "en": {
    "Trace label in style panel": "Trace"
  },
  "es": {
    "Trace label in style panel": "Rastro",
    "Click to toggle visibility": "Haga clic para activar la visibilidad",
    ...etc
  },
  "ru": {
    ...
  }
}
_("Trace label in the style panel")

Or maybe panels.style.trace or whatever you prefer. It's a bit free-form.

At any rate, you'd pass in a dictionary which would get deep-merged into whatever default dictionaries plotly.js has built in. The fallback is builtin dictionary values or just a pass-through i18n function.

For plotly, the dictionary would be passed through config as, e.g. {"es": {...}} and the desired language would be specified as, e.g "language": "es". As in:

Plotly.plot(gd, {
  data: {...},
  config: {
    language: "es",
    dictionary: {
      es: {
        key: value
      }
    }
  }
})

(locale instead of language? dictionaries, plural? I at least like the idea of being able to pass multiple dictionaries in one parameter so that changing the language would be possible.)

For plotly.js it could also be possible to use Plotly.Register. As in:

Plotly.Register(require('plotly.js/dictionaries/en.json'))
Plotly.Register(require('plotly.js/dictionaries/es.json'))

Plotly.plot(gd, {config: {language: 'es'}})

For react components, the editor would probably receive a dictionary and expose it through context. All components would inherit from a base component that makes the dictionary available so that it's not global and so that the dictionary doesn't need to trickle down through props explicitly. Then instead of importing _, you'd inherit from the base component and have this._(...) automatically available.

/cc @bpostlethwaite @alexcjohnson @etpinard

Remove `bem` function

We now have nested CSS so the bem function isn't as useful. It also requires a number of extra function calls when it's fairly trivial to hardcode strings. Hardcoded strings are easier to search the src code for as well. Searching for CSS strings in src code happens fairly often when debugging an application.

Select Controls are Broken

After the most recent updates, the select controls for selecting trace x, y, and plot type no longer function. clicking and holding one shows the options, but they disappear when you release the mouse so you can't select one. I tried to see if the same behavior happens in the react-lab example, but it no longer compiles because of new referencing issues.

Scope all css selectors

I've been taking a sort of extended BEM approach to the CSS selectors. That is, BEM but prefixed with plotly-editor. The reason is so that you can include the editor on any page and expect it not to conflict with your existing CSS. With SCSS/LESS, the prefix could be centralized into one location, but at the moment this seems adequate.

TO DO: I took a few shortcuts just leaving streambed component class names as-is. They should also be prefixed.

<TraceSelector> should compute all Plotly.js traces

Right now <DefaultEditor> computes all the Plotly.js traces and passes those down to <TraceSelector>

Now that we are standardizing on the idea of one-stop shop components that handle all their own craziness we should move the traceOptions handling from DefaultEditor to TraceSelector.

npm start fails

Error: Cannot find module '../../src/plotly.js-react-editor.jsx' from '/home/ben/plotly/react-plotly.js-editor/example/src'

Bar & Pie charts

Add selector for bar and pie chart types. The menu is not yet graphical, and not yet addressed is the way that the workspace has a fairly loose mapping between chart types displayed in the selector and internal trace types. That is, there is no "area" chart, but the workspace shows an "area" chart type for convenience.

Minimize unnecessary plotprops computation

When application logic changes unpackPlotProps is run on every rendered attribute Field. Investigate a way to prevent this from happening. Probably worth starting with the Editor revision number ++

nest icon classes

Split the actual icon class definitions into their own file that can be nested in the main.scss and remove their plotlyjs_editor prefixes.

I think @fontface still needs to be global scope so that will need to be included in a fonts. Does it need to be global? It didn't work when I tried nesting the whole of _icons.scss but I didn't do much investigation.

Hide sections with no valid properties

The presence or lack of an attribute value in fullData is enough to hide or show the corresponding field automatically. Visibility of the section headings isn't free. It might be necessary to traverse the config and hide/show them accordingly, depending on whether any specific fields are present or not.

screen shot 2017-10-13 at 15 14 32

Section visibility nuances

see #54 (comment)

Right now <Section> will hide itself when all of its attr children are not visible. Currently if you put non attr children in a <Section> it will show. However you could make the case that <Info> (for example) should not by default force <Section> to show since it is <Info> about non applicable (and hidden) fields.

We might be able to extend this argument to <MenuPanel> (CogMenu) as well. If CogMenu is always (or almost always) an advanced settings of the base fields in <Section> then it may not make sense to show it.

To resolve this we need to look at all the CogMenus in the workspace and figure out sane defaults.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.