Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dev/dataSources.js
Original file line number Diff line number Diff line change
Expand Up @@ -1745,4 +1745,5 @@ export default {
],
'countries iso': ['AGO', 'ALB', 'ARE', 'ARG', 'ARM', 'AUS', 'AUT', 'AZE'],
states: ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'FL', 'GA'],
textpositions: ['bottom', 'bottom right', 'left', 'right', 'left'],
};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "react-chart-editor",
"description": "plotly.js chart editor react component UI",
"version": "0.35.1",
"version": "0.35.2",
"author": "Plotly, Inc.",
"bugs": {
"url": "https://github.com/plotly/react-chart-editor/issues"
Expand Down Expand Up @@ -126,4 +126,4 @@
"watch": "babel src --watch --out-dir lib --source-maps | node-sass -w src/styles/main.scss lib/react-chart-editor.css",
"watch-test": "jest --watch"
}
}
}
131 changes: 68 additions & 63 deletions scripts/translationKeys/combined-translation-keys.txt

Large diffs are not rendered by default.

131 changes: 68 additions & 63 deletions scripts/translationKeys/translation-keys.txt

Large diffs are not rendered by default.

105 changes: 105 additions & 0 deletions src/components/fields/TextPosition.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import Dropdown from './Dropdown';
import RadioBlocks from '../widgets/RadioBlocks';
import Field from './Field';
import PropTypes from 'prop-types';
import React, {Component, Fragment} from 'react';
import {connectToContainer} from 'lib';
import Info from './Info';
import DataSelector from './DataSelector';

export class UnconnectedTextPosition extends Component {
constructor(props) {
super(props);
this.state = {
posType: typeof props.fullValue === 'string' ? 'simple' : 'custom',
};
}

render() {
const _ = this.context.localize;
const radioOptions = [
{label: _('All'), value: 'simple'},
{label: _('Custom'), value: 'custom'},
];
const control =
this.state.posType === 'simple' ? (
<Fragment>
<Info>
{_(
'This will position all text values on the plot according to the selected position.'
)}
</Info>
<Dropdown options={this.props.options} attr="textposition" />
</Fragment>
) : (
<Fragment>
<Info>
<div>
{_(
'This will position text values individually, according to the provided data positions array. '
)}
</div>
</Info>
<DataSelector attr="textposition" />
<Info>
<div>{_('("Top", "Middle", "Bottom") + ("Left", "Center", "Right")')}</div>
</Info>
</Fragment>
);

return (
<Field {...this.props}>
<RadioBlocks
options={radioOptions}
activeOption={this.state.posType}
onOptionChange={value => {
this.setState({posType: value});
if (value === 'simple') {
this.props.updatePlot('middle center');
} else {
this.props.updateContainer({textpositionsrc: null});
}
}}
/>
{control}
</Field>
);
}
}

UnconnectedTextPosition.propTypes = {
...Field.propTypes,
options: PropTypes.array,
fullValue: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
};

UnconnectedTextPosition.contextTypes = {
localize: PropTypes.func,
};

export default connectToContainer(UnconnectedTextPosition, {
modifyPlotProps: (props, context, plotProps) => {
const {localize: _} = context;
let options = [
{label: _('Top Left'), value: 'top left'},
{label: _('Top Center'), value: 'top center'},
{label: _('Top Right'), value: 'top right'},
{label: _('Middle Left'), value: 'middle left'},
{label: _('Middle Center'), value: 'middle center'},
{label: _('Middle Right'), value: 'middle right'},
{label: _('Bottom Left'), value: 'bottom left'},
{label: _('Bottom Center'), value: 'bottom center'},
{label: _('Bottom Right'), value: 'bottom right'},
];
if (context.container.type === 'pie' || context.container.type === 'bar') {
options = [
{label: _('Inside'), value: 'inside'},
{label: _('Outside'), value: 'outside'},
{label: _('Auto'), value: 'auto'},
{label: _('None'), value: 'none'},
];
}
plotProps.options = options;
plotProps.clearable = false;
},
});
27 changes: 0 additions & 27 deletions src/components/fields/derived.js
Original file line number Diff line number Diff line change
Expand Up @@ -494,33 +494,6 @@ function computeAxesRefOptions(axes, propsAttr) {
return options;
}

export const TextPosition = connectToContainer(UnconnectedDropdown, {
modifyPlotProps: (props, context, plotProps) => {
const {localize: _} = context;
let options = [
{label: _('Top Left'), value: 'top left'},
{label: _('Top Center'), value: 'top center'},
{label: _('Top Right'), value: 'top right'},
{label: _('Middle Left'), value: 'middle left'},
{label: _('Middle Center'), value: 'middle center'},
{label: _('Middle Right'), value: 'middle right'},
{label: _('Bottom Left'), value: 'bottom left'},
{label: _('Bottom Center'), value: 'bottom center'},
{label: _('Bottom Right'), value: 'bottom right'},
];
if (context.container.type === 'pie' || context.container.type === 'bar') {
options = [
{label: _('Inside'), value: 'inside'},
{label: _('Outside'), value: 'outside'},
{label: _('Auto'), value: 'auto'},
{label: _('None'), value: 'none'},
];
}
plotProps.options = options;
plotProps.clearable = false;
},
});

export const TextInfo = connectToContainer(UnconnectedFlaglist, {
modifyPlotProps: (props, context, plotProps) => {
const {localize: _, container} = context;
Expand Down
2 changes: 1 addition & 1 deletion src/components/fields/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import RectanglePositioner from './RectanglePositioner';
import LocationSelector from './LocationSelector';
import AxisInterval from './AxisInterval';
import DateTimePicker from './DateTimePicker';
import TextPosition from './TextPosition';

import {
AnnotationArrowRef,
Expand All @@ -57,7 +58,6 @@ import {
TraceOrientation,
AxisOverlayDropdown,
AxisSide,
TextPosition,
ShowInLegend,
HoveronDropdown,
HovermodeDropdown,
Expand Down
2 changes: 1 addition & 1 deletion src/default_panels/StyleAxesPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ class StyleAxesPanel extends Component {
attr="exponentformat"
clearable={false}
options={[
{label: _('None'), value: '000'},
{label: _('None'), value: 'none'},
{label: _('e+6'), value: 'e'},
{label: _('E+6'), value: 'E'},
{label: _('x10^6'), value: 'power'},
Expand Down
25 changes: 14 additions & 11 deletions src/default_panels/StyleLayoutPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,17 +174,20 @@ const StyleLayoutPanel = (props, {localize: _}) => (
{_(
'You can refer to the items in this column in any text fields of the editor like so: '
)}
<span
style={{
lineHeight: '20px',
backgroundColor: '#eadef7',
borderRadius: '2px',
fontStyle: 'italic',
}}
>
{'%{meta[0]}'}
</span>
{' .'}
<div>
<span
style={{
lineHeight: '20px',
backgroundColor: '#eadef7',
borderRadius: '2px',
fontStyle: 'italic',
letterSpacing: '1px',
}}
>
{'%{meta[0]}'}
</span>
{' .'}
</div>
</p>
{_('Note: item count starts at 0.')}
</Info>
Expand Down
21 changes: 21 additions & 0 deletions src/default_panels/StyleNotesPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,28 @@ const StyleNotesPanel = (props, {localize: _}) => (
<Numeric label={_('Font Size')} attr="font.size" units="px" />
<ColorPicker label={_('Font Color')} attr="font.color" />
<Numeric label={_('Angle')} attr="textangle" units="°" />
<Dropdown
label={_('Horizontal Alignment')}
clearable={false}
attr="align"
options={[
{label: _('Left'), value: 'left'},
{label: _('Center'), value: 'center'},
{label: _('Right'), value: 'right'},
]}
/>
<Dropdown
label={_('Vertical Alignment')}
clearable={false}
attr="valign"
options={[
{label: _('Left'), value: 'left'},
{label: _('Center'), value: 'center'},
{label: _('Right'), value: 'right'},
]}
/>
</PlotlySection>

<PlotlySection name={_('Arrow')}>
<Radio
attr="showarrow"
Expand Down
10 changes: 10 additions & 0 deletions src/lib/__tests__/dereference-test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import dereference from '../dereference';

/* eslint-disable no-magic-numbers */
describe('dereference', () => {
it('does not search into data arrays', () => {
Expand Down Expand Up @@ -65,4 +66,13 @@ describe('dereference', () => {
expect(container[0].z[2][0]).toBe(3);
expect(container[0].z[2][1]).toBe(2);
});

// TO DO: dereference all of layout
it('can dereference top level layout keys', () => {
const container = {metasrc: 'x1', xaxis: {ticktext: 'x2'}};
dereference(container, {x1: ['yes!'], x2: ['some', 'text']});

expect(Array.isArray(container.meta)).toBe(true);
expect(container.meta[0]).toBe('yes!');
});
});
28 changes: 19 additions & 9 deletions src/lib/dereference.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export default function dereference(container, dataSources, config = {deleteKeys
}

const dataKey = key.replace(SRC_ATTR_PATTERN, '');
const traceType = parent.type;

let srcRef = config.toSrc ? config.toSrc(parent[key]) : parent[key];

Expand All @@ -19,7 +18,7 @@ export default function dereference(container, dataSources, config = {deleteKeys
srcRef = [srcRef];
}

let data = srcRef.map(ref => {
let dereferencedData = srcRef.map(ref => {
if (config.deleteKeys && !(ref in dataSources)) {
delete parent[dataKey];
}
Expand All @@ -28,18 +27,29 @@ export default function dereference(container, dataSources, config = {deleteKeys

// remove extra data wrapping
if (srcRef.length === 1) {
data = data[0];
dereferencedData = dereferencedData[0];
}

if (!Array.isArray(data)) {
if (!Array.isArray(dereferencedData)) {
return;
}

parent[dataKey] = maybeTransposeData(data, srcPath, traceType);
if (Array.isArray(container)) {
// Case where we were originally given data to dereference
const traceType = parent.type;
parent[dataKey] = maybeTransposeData(dereferencedData, srcPath, traceType);
} else {
// This means we're dereferencing layout
parent[dataKey] = dereferencedData;
}
};

walkObject(container, replacer, {
walkArraysMatchingKeys: ['data', 'transforms'],
pathType: 'nestedProperty',
});
if (Array.isArray(container)) {
walkObject(container, replacer, {
walkArraysMatchingKeys: ['data', 'transforms'],
pathType: 'nestedProperty',
});
} else {
walkObject(container, replacer, {pathType: 'nestedProperty'});
}
}