@pie-lib/graphing 2.6.1 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/lib/graph-with-controls.js +79 -17
- package/lib/graph-with-controls.js.map +1 -1
- package/lib/graph.js +2 -0
- package/lib/graph.js.map +1 -1
- package/lib/grid-setup.js +435 -0
- package/lib/grid-setup.js.map +1 -0
- package/lib/grid.js +0 -7
- package/lib/grid.js.map +1 -1
- package/lib/index.js +8 -0
- package/lib/index.js.map +1 -1
- package/package.json +3 -3
- package/src/graph-with-controls.jsx +90 -14
- package/src/graph.jsx +2 -0
- package/src/grid-setup.jsx +427 -0
- package/src/grid.jsx +0 -7
- package/src/index.js +2 -1
|
@@ -10,6 +10,13 @@ import ToolMenu from './tool-menu';
|
|
|
10
10
|
import Graph, { graphPropTypes } from './graph';
|
|
11
11
|
import UndoRedo from './undo-redo';
|
|
12
12
|
import { allTools, toolsArr } from './tools';
|
|
13
|
+
import {
|
|
14
|
+
ExpansionPanel,
|
|
15
|
+
ExpansionPanelDetails,
|
|
16
|
+
ExpansionPanelSummary,
|
|
17
|
+
Typography
|
|
18
|
+
} from '@material-ui/core';
|
|
19
|
+
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
13
20
|
|
|
14
21
|
export const setToolbarAvailability = toolbarTools =>
|
|
15
22
|
toolsArr.map(tA => ({ ...tA, toolbar: !!toolbarTools.find(t => t === tA.type) })) || [];
|
|
@@ -25,6 +32,28 @@ export const filterByValidToolTypes = backgroundMarks =>
|
|
|
25
32
|
export const filterByVisibleToolTypes = (toolbarTools, marks) =>
|
|
26
33
|
marks.filter(bM => !!toolbarTools.find(tool => tool === bM.type));
|
|
27
34
|
|
|
35
|
+
const getDefaultCurrentTool = toolType => toolsArr.find(tool => tool.type === toolType) || null;
|
|
36
|
+
|
|
37
|
+
const Collapsible = ({ classes, children, title }) => (
|
|
38
|
+
<ExpansionPanel
|
|
39
|
+
elevation={0}
|
|
40
|
+
className={classes.expansionPanel}
|
|
41
|
+
disabledGutters={true}
|
|
42
|
+
square={true}
|
|
43
|
+
>
|
|
44
|
+
<ExpansionPanelSummary
|
|
45
|
+
classes={{
|
|
46
|
+
root: classes.summaryRoot,
|
|
47
|
+
content: classes.summaryContent
|
|
48
|
+
}}
|
|
49
|
+
expandIcon={<ExpandMoreIcon />}
|
|
50
|
+
>
|
|
51
|
+
<Typography variant="subheading">{title}</Typography>
|
|
52
|
+
</ExpansionPanelSummary>
|
|
53
|
+
<ExpansionPanelDetails className={classes.details}>{children}</ExpansionPanelDetails>
|
|
54
|
+
</ExpansionPanel>
|
|
55
|
+
);
|
|
56
|
+
|
|
28
57
|
export class GraphWithControls extends React.Component {
|
|
29
58
|
static propTypes = {
|
|
30
59
|
...graphPropTypes,
|
|
@@ -34,9 +63,30 @@ export class GraphWithControls extends React.Component {
|
|
|
34
63
|
toolbarTools: PropTypes.arrayOf(PropTypes.string) // array of tool types that have to be displayed in the toolbar, same shape as 'allTools'
|
|
35
64
|
};
|
|
36
65
|
|
|
37
|
-
static defaultProps = {
|
|
66
|
+
static defaultProps = {
|
|
67
|
+
collapsibleToolbar: false,
|
|
68
|
+
collapsibleToolbarTitle: '',
|
|
69
|
+
toolbarTools: []
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
constructor(props) {
|
|
73
|
+
super(props);
|
|
74
|
+
|
|
75
|
+
this.state = {
|
|
76
|
+
currentTool: getDefaultCurrentTool(props.defaultTool),
|
|
77
|
+
labelModeEnabled: false
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
componentDidUpdate(prevProps) {
|
|
82
|
+
const { defaultTool } = this.props;
|
|
38
83
|
|
|
39
|
-
|
|
84
|
+
if (prevProps.defaultTool !== defaultTool) {
|
|
85
|
+
const currentTool = getDefaultCurrentTool(defaultTool);
|
|
86
|
+
|
|
87
|
+
this.setState({ currentTool });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
40
90
|
|
|
41
91
|
changeCurrentTool = (tool, tools) =>
|
|
42
92
|
this.setState({ currentTool: tools.find(t => t.type === tool) });
|
|
@@ -45,12 +95,13 @@ export class GraphWithControls extends React.Component {
|
|
|
45
95
|
|
|
46
96
|
render() {
|
|
47
97
|
let { currentTool, labelModeEnabled } = this.state;
|
|
48
|
-
|
|
49
98
|
const {
|
|
50
99
|
axesSettings,
|
|
51
100
|
classes,
|
|
52
101
|
className,
|
|
53
102
|
coordinatesOnHover,
|
|
103
|
+
collapsibleToolbar,
|
|
104
|
+
collapsibleToolbarTitle,
|
|
54
105
|
disabled,
|
|
55
106
|
domain,
|
|
56
107
|
labels,
|
|
@@ -62,7 +113,6 @@ export class GraphWithControls extends React.Component {
|
|
|
62
113
|
size,
|
|
63
114
|
title
|
|
64
115
|
} = this.props;
|
|
65
|
-
|
|
66
116
|
let { backgroundMarks, marks, toolbarTools } = this.props;
|
|
67
117
|
|
|
68
118
|
// make sure only valid tool types are kept (string) and without duplicates
|
|
@@ -81,19 +131,31 @@ export class GraphWithControls extends React.Component {
|
|
|
81
131
|
currentTool = getAvailableTool(tools);
|
|
82
132
|
}
|
|
83
133
|
|
|
134
|
+
const graphActions = (
|
|
135
|
+
<React.Fragment>
|
|
136
|
+
<ToolMenu
|
|
137
|
+
currentToolType={currentTool && currentTool.type}
|
|
138
|
+
disabled={!!disabled}
|
|
139
|
+
labelModeEnabled={labelModeEnabled}
|
|
140
|
+
onChange={tool => this.changeCurrentTool(tool, tools)}
|
|
141
|
+
onToggleLabelMode={this.toggleLabelMode}
|
|
142
|
+
toolbarTools={toolbarTools}
|
|
143
|
+
/>
|
|
144
|
+
|
|
145
|
+
{!disabled && <UndoRedo onUndo={onUndo} onRedo={onRedo} onReset={onReset} />}
|
|
146
|
+
</React.Fragment>
|
|
147
|
+
);
|
|
148
|
+
|
|
84
149
|
return (
|
|
85
150
|
<div className={classNames(classes.graphWithControls, className)}>
|
|
86
151
|
<div className={classes.controls}>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
/>
|
|
95
|
-
|
|
96
|
-
{!disabled && <UndoRedo onUndo={onUndo} onRedo={onRedo} onReset={onReset} />}
|
|
152
|
+
{collapsibleToolbar ? (
|
|
153
|
+
<Collapsible classes={classes} title={collapsibleToolbarTitle}>
|
|
154
|
+
{graphActions}
|
|
155
|
+
</Collapsible>
|
|
156
|
+
) : (
|
|
157
|
+
graphActions
|
|
158
|
+
)}
|
|
97
159
|
</div>
|
|
98
160
|
|
|
99
161
|
<div ref={r => (this.labelNode = r)} />
|
|
@@ -134,6 +196,20 @@ const styles = theme => ({
|
|
|
134
196
|
'& button': {
|
|
135
197
|
fontSize: theme.typography.fontSize
|
|
136
198
|
}
|
|
199
|
+
},
|
|
200
|
+
expansionPanel: {
|
|
201
|
+
backgroundColor: color.primaryLight()
|
|
202
|
+
},
|
|
203
|
+
summaryRoot: {
|
|
204
|
+
padding: `0 ${theme.spacing.unit}px`,
|
|
205
|
+
minHeight: '32px !important'
|
|
206
|
+
},
|
|
207
|
+
summaryContent: {
|
|
208
|
+
margin: '4px 0 !important'
|
|
209
|
+
},
|
|
210
|
+
details: {
|
|
211
|
+
padding: 0,
|
|
212
|
+
marginTop: theme.spacing.unit
|
|
137
213
|
}
|
|
138
214
|
});
|
|
139
215
|
|
package/src/graph.jsx
CHANGED
|
@@ -18,6 +18,8 @@ export const graphPropTypes = {
|
|
|
18
18
|
axesSettings: PropTypes.shape(AxisPropTypes),
|
|
19
19
|
backgroundMarks: PropTypes.array,
|
|
20
20
|
className: PropTypes.string,
|
|
21
|
+
collapsibleToolbar: PropTypes.bool,
|
|
22
|
+
collapsibleToolbarTitle: PropTypes.string,
|
|
21
23
|
domain: types.DomainType,
|
|
22
24
|
labels: PropTypes.shape(LabelType),
|
|
23
25
|
labelModeEnabled: PropTypes.bool,
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { color, InputContainer } from '@pie-lib/render-ui';
|
|
4
|
+
import { withStyles } from '@material-ui/core/styles';
|
|
5
|
+
import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
|
|
6
|
+
import Typography from '@material-ui/core/Typography';
|
|
7
|
+
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
|
|
8
|
+
import ExpansionPanel from '@material-ui/core/ExpansionPanel';
|
|
9
|
+
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
10
|
+
import { NumberTextFieldCustom, Toggle } from '@pie-lib/config-ui';
|
|
11
|
+
import EditableHTML from '@pie-lib/editable-html';
|
|
12
|
+
|
|
13
|
+
const GridConfig = props => {
|
|
14
|
+
const {
|
|
15
|
+
classes,
|
|
16
|
+
disabled,
|
|
17
|
+
displayedFields,
|
|
18
|
+
labelValue,
|
|
19
|
+
labelValues,
|
|
20
|
+
gridValue,
|
|
21
|
+
gridValues,
|
|
22
|
+
onChange
|
|
23
|
+
} = props;
|
|
24
|
+
const { labelStep = {}, step = {} } = displayedFields;
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div className={classes.columnView}>
|
|
28
|
+
{step && step.enabled && (
|
|
29
|
+
<NumberTextFieldCustom
|
|
30
|
+
className={classes.mediumTextField}
|
|
31
|
+
label={step.label || ''}
|
|
32
|
+
value={gridValue}
|
|
33
|
+
customValues={gridValues}
|
|
34
|
+
variant="outlined"
|
|
35
|
+
disabled={disabled}
|
|
36
|
+
onChange={(e, v) => onChange('step', v)}
|
|
37
|
+
/>
|
|
38
|
+
)}
|
|
39
|
+
{labelStep && labelStep.enabled && (
|
|
40
|
+
<NumberTextFieldCustom
|
|
41
|
+
className={classes.mediumTextField}
|
|
42
|
+
label={labelStep.label || ''}
|
|
43
|
+
value={labelValue}
|
|
44
|
+
customValues={labelValues}
|
|
45
|
+
variant="outlined"
|
|
46
|
+
disabled={disabled}
|
|
47
|
+
onChange={(e, v) => onChange('labelStep', v)}
|
|
48
|
+
/>
|
|
49
|
+
)}
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const AxisConfig = props => {
|
|
55
|
+
const {
|
|
56
|
+
classes,
|
|
57
|
+
disabled,
|
|
58
|
+
displayedFields,
|
|
59
|
+
displayHeader,
|
|
60
|
+
label,
|
|
61
|
+
maxValue,
|
|
62
|
+
minValue,
|
|
63
|
+
onChange,
|
|
64
|
+
type
|
|
65
|
+
} = props;
|
|
66
|
+
const { axisLabel = {}, min = {}, max = {} } = displayedFields;
|
|
67
|
+
const activePlugins = [
|
|
68
|
+
'bold',
|
|
69
|
+
'italic',
|
|
70
|
+
'underline',
|
|
71
|
+
'strikethrough'
|
|
72
|
+
// 'languageCharacters'
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div className={classes.columnView}>
|
|
77
|
+
{displayHeader && (
|
|
78
|
+
<Typography variant="subtitle2">
|
|
79
|
+
<i>{type === 'domain' ? 'x' : 'y'}</i>
|
|
80
|
+
-axis
|
|
81
|
+
</Typography>
|
|
82
|
+
)}
|
|
83
|
+
{min && min.enabled && (
|
|
84
|
+
<NumberTextFieldCustom
|
|
85
|
+
className={classes.mediumTextField}
|
|
86
|
+
label={min.label || ''}
|
|
87
|
+
value={minValue}
|
|
88
|
+
min={-10000}
|
|
89
|
+
max={maxValue - 0.01}
|
|
90
|
+
variant="outlined"
|
|
91
|
+
disabled={disabled}
|
|
92
|
+
onChange={(e, v) => onChange('min', v)}
|
|
93
|
+
/>
|
|
94
|
+
)}
|
|
95
|
+
{max && max.enabled && (
|
|
96
|
+
<NumberTextFieldCustom
|
|
97
|
+
className={classes.mediumTextField}
|
|
98
|
+
label={max.label || ''}
|
|
99
|
+
value={maxValue}
|
|
100
|
+
min={minValue + 0.01}
|
|
101
|
+
max={10000}
|
|
102
|
+
variant="outlined"
|
|
103
|
+
disabled={disabled}
|
|
104
|
+
onChange={(e, v) => onChange('max', v)}
|
|
105
|
+
/>
|
|
106
|
+
)}
|
|
107
|
+
{axisLabel && axisLabel.enabled && (
|
|
108
|
+
<InputContainer label={axisLabel.label || ''} className={classes.mediumTextField}>
|
|
109
|
+
<EditableHTML
|
|
110
|
+
className={classes.axisLabel}
|
|
111
|
+
onChange={value => onChange('axisLabel', value)}
|
|
112
|
+
markup={label || ''}
|
|
113
|
+
charactersLimit={5}
|
|
114
|
+
activePlugins={activePlugins}
|
|
115
|
+
/>
|
|
116
|
+
</InputContainer>
|
|
117
|
+
)}
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const GridSetup = props => {
|
|
123
|
+
const {
|
|
124
|
+
classes,
|
|
125
|
+
domain,
|
|
126
|
+
displayedFields = {},
|
|
127
|
+
gridValues = {},
|
|
128
|
+
includeAxes,
|
|
129
|
+
labelValues = {},
|
|
130
|
+
onChange,
|
|
131
|
+
range,
|
|
132
|
+
size,
|
|
133
|
+
sizeConstraints,
|
|
134
|
+
standardGrid
|
|
135
|
+
} = props;
|
|
136
|
+
const gridProps = { min: 2, max: 41 };
|
|
137
|
+
const {
|
|
138
|
+
axisLabel = {},
|
|
139
|
+
dimensionsEnabled,
|
|
140
|
+
includeAxesEnabled,
|
|
141
|
+
labelStep = {},
|
|
142
|
+
min = {},
|
|
143
|
+
max = {},
|
|
144
|
+
standardGridEnabled,
|
|
145
|
+
step = {}
|
|
146
|
+
} = displayedFields || {};
|
|
147
|
+
const displayAxisType =
|
|
148
|
+
min.enabled || max.enabled || axisLabel.enabled || step.enabled || labelStep.enabled;
|
|
149
|
+
const gridConfigFields = { step, labelStep };
|
|
150
|
+
const axisConfigFields = { min, max, axisLabel };
|
|
151
|
+
|
|
152
|
+
const onIncludeAxes = includeAxes => {
|
|
153
|
+
const noAxesConfig = type => {
|
|
154
|
+
const axis = type === 'domain' ? domain : range;
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
min: 1,
|
|
158
|
+
max: axis.max < gridProps.min || axis.max > gridProps.max ? 16 : axis.max,
|
|
159
|
+
step: 1,
|
|
160
|
+
labelStep: 0
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const updatedRange = {
|
|
165
|
+
...range,
|
|
166
|
+
...(includeAxes ? { labelStep: 1 } : noAxesConfig('range'))
|
|
167
|
+
};
|
|
168
|
+
const updatedDomain = {
|
|
169
|
+
...domain,
|
|
170
|
+
...(includeAxes ? { labelStep: 1 } : noAxesConfig('domain'))
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
onChange({ includeAxes, range: updatedRange, domain: updatedDomain });
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const onStandardGridChanged = value => {
|
|
177
|
+
onChange({
|
|
178
|
+
standardGrid: value,
|
|
179
|
+
range: {
|
|
180
|
+
...domain,
|
|
181
|
+
axisLabel: range.axisLabel
|
|
182
|
+
},
|
|
183
|
+
graph: {
|
|
184
|
+
...size,
|
|
185
|
+
height: size.width
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const onSizeChanged = (key, value) => {
|
|
191
|
+
const graph = { ...size, [key]: value };
|
|
192
|
+
|
|
193
|
+
if (standardGrid) {
|
|
194
|
+
graph.height = value;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
onChange({ graph });
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const onDomainChanged = (key, value) => {
|
|
201
|
+
domain[key] = value;
|
|
202
|
+
|
|
203
|
+
if (standardGrid && key !== 'axisLabel') {
|
|
204
|
+
range[key] = value;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
onChange({ domain, range });
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const onRangeChanged = (key, value) => {
|
|
211
|
+
range[key] = value;
|
|
212
|
+
|
|
213
|
+
onChange({ range });
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const axesConfig = (
|
|
217
|
+
<React.Fragment>
|
|
218
|
+
<div className={classes.rowView}>
|
|
219
|
+
<AxisConfig
|
|
220
|
+
classes={classes}
|
|
221
|
+
displayedFields={axisConfigFields}
|
|
222
|
+
displayHeader={displayAxisType}
|
|
223
|
+
type="domain"
|
|
224
|
+
minValue={domain.min}
|
|
225
|
+
maxValue={domain.max}
|
|
226
|
+
label={domain.axisLabel}
|
|
227
|
+
includeAxes={includeAxes}
|
|
228
|
+
onChange={onDomainChanged}
|
|
229
|
+
/>
|
|
230
|
+
<AxisConfig
|
|
231
|
+
classes={classes}
|
|
232
|
+
displayedFields={axisConfigFields}
|
|
233
|
+
displayHeader={displayAxisType}
|
|
234
|
+
type="range"
|
|
235
|
+
minValue={range.min}
|
|
236
|
+
maxValue={range.max}
|
|
237
|
+
label={range.axisLabel}
|
|
238
|
+
disabled={standardGrid}
|
|
239
|
+
includeAxes={includeAxes}
|
|
240
|
+
onChange={onRangeChanged}
|
|
241
|
+
/>
|
|
242
|
+
</div>
|
|
243
|
+
{(min.enabled || max.enabled) && (
|
|
244
|
+
<Typography className={classes.text}>
|
|
245
|
+
If you want the axis to be visible, use a zero or negative Min Value, and a positive Max
|
|
246
|
+
Value
|
|
247
|
+
</Typography>
|
|
248
|
+
)}
|
|
249
|
+
{(step.enabled || labelStep.enabled) && (
|
|
250
|
+
<div className={classes.rowView}>
|
|
251
|
+
<GridConfig
|
|
252
|
+
classes={classes}
|
|
253
|
+
displayedFields={gridConfigFields}
|
|
254
|
+
gridValue={domain.step}
|
|
255
|
+
labelValue={domain.labelStep}
|
|
256
|
+
gridValues={gridValues.domain || []}
|
|
257
|
+
labelValues={labelValues.domain || []}
|
|
258
|
+
onChange={onDomainChanged}
|
|
259
|
+
/>
|
|
260
|
+
<GridConfig
|
|
261
|
+
classes={classes}
|
|
262
|
+
disabled={standardGrid}
|
|
263
|
+
displayedFields={gridConfigFields}
|
|
264
|
+
gridValue={range.step}
|
|
265
|
+
labelValue={range.labelStep}
|
|
266
|
+
gridValues={gridValues.range || []}
|
|
267
|
+
labelValues={labelValues.range || []}
|
|
268
|
+
onChange={onRangeChanged}
|
|
269
|
+
/>
|
|
270
|
+
</div>
|
|
271
|
+
)}
|
|
272
|
+
{labelStep.enabled && (
|
|
273
|
+
<Typography className={classes.text}>
|
|
274
|
+
For unnumbered gridlines, enter a label interval of 0
|
|
275
|
+
</Typography>
|
|
276
|
+
)}
|
|
277
|
+
</React.Fragment>
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
const gridlinesConfig = max.enabled ? (
|
|
281
|
+
<div className={classes.columnView}>
|
|
282
|
+
<NumberTextFieldCustom
|
|
283
|
+
className={classes.largeTextField}
|
|
284
|
+
label="Number of Horizontal Gridlines"
|
|
285
|
+
value={domain.max}
|
|
286
|
+
min={!includeAxes && gridProps.min}
|
|
287
|
+
max={!includeAxes && gridProps.max}
|
|
288
|
+
variant="outlined"
|
|
289
|
+
onChange={(e, v) => onDomainChanged('max', v)}
|
|
290
|
+
/>
|
|
291
|
+
<NumberTextFieldCustom
|
|
292
|
+
className={classes.largeTextField}
|
|
293
|
+
label="Number of Vertical Gridlines"
|
|
294
|
+
value={range.max}
|
|
295
|
+
min={!includeAxes && gridProps.min}
|
|
296
|
+
max={!includeAxes && gridProps.max}
|
|
297
|
+
variant="outlined"
|
|
298
|
+
disabled={standardGrid}
|
|
299
|
+
onChange={(e, v) => onRangeChanged('max', v)}
|
|
300
|
+
/>
|
|
301
|
+
</div>
|
|
302
|
+
) : null;
|
|
303
|
+
|
|
304
|
+
return (
|
|
305
|
+
<div className={classes.wrapper}>
|
|
306
|
+
<ExpansionPanel>
|
|
307
|
+
<ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}>
|
|
308
|
+
<Typography variant="subtitle1">Customize Grid Setup</Typography>
|
|
309
|
+
</ExpansionPanelSummary>
|
|
310
|
+
<ExpansionPanelDetails>
|
|
311
|
+
<div className={classes.content}>
|
|
312
|
+
{includeAxesEnabled && (
|
|
313
|
+
<Toggle
|
|
314
|
+
label="Include axes and labels?"
|
|
315
|
+
toggle={onIncludeAxes}
|
|
316
|
+
checked={includeAxes}
|
|
317
|
+
/>
|
|
318
|
+
)}
|
|
319
|
+
{standardGridEnabled && (
|
|
320
|
+
<Toggle
|
|
321
|
+
label="Constrain to standard coordinate grid?"
|
|
322
|
+
toggle={onStandardGridChanged}
|
|
323
|
+
checked={standardGrid}
|
|
324
|
+
/>
|
|
325
|
+
)}
|
|
326
|
+
{includeAxes ? axesConfig : gridlinesConfig}
|
|
327
|
+
{dimensionsEnabled && (
|
|
328
|
+
<div className={classes.dimensions}>
|
|
329
|
+
<div>
|
|
330
|
+
<Typography>Dimensions(px)</Typography>
|
|
331
|
+
<Typography className={classes.disabled}>
|
|
332
|
+
Min {sizeConstraints.min}, Max {sizeConstraints.max}
|
|
333
|
+
</Typography>
|
|
334
|
+
</div>
|
|
335
|
+
<NumberTextFieldCustom
|
|
336
|
+
className={classes.textField}
|
|
337
|
+
label="Width"
|
|
338
|
+
value={size.width}
|
|
339
|
+
min={sizeConstraints.min}
|
|
340
|
+
max={sizeConstraints.max}
|
|
341
|
+
step={sizeConstraints.step}
|
|
342
|
+
variant="outlined"
|
|
343
|
+
onChange={(e, v) => onSizeChanged('width', v)}
|
|
344
|
+
/>
|
|
345
|
+
<NumberTextFieldCustom
|
|
346
|
+
className={classes.textField}
|
|
347
|
+
label="Height"
|
|
348
|
+
value={size.height}
|
|
349
|
+
min={sizeConstraints.min}
|
|
350
|
+
max={sizeConstraints.max}
|
|
351
|
+
step={sizeConstraints.step}
|
|
352
|
+
variant="outlined"
|
|
353
|
+
disabled={standardGrid}
|
|
354
|
+
onChange={(e, v) => onSizeChanged('height', v)}
|
|
355
|
+
/>
|
|
356
|
+
</div>
|
|
357
|
+
)}
|
|
358
|
+
</div>
|
|
359
|
+
</ExpansionPanelDetails>
|
|
360
|
+
</ExpansionPanel>
|
|
361
|
+
</div>
|
|
362
|
+
);
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
GridSetup.propTypes = {
|
|
366
|
+
classes: PropTypes.object,
|
|
367
|
+
domain: PropTypes.object,
|
|
368
|
+
displayedFields: PropTypes.object,
|
|
369
|
+
gridValues: PropTypes.object,
|
|
370
|
+
includeAxes: PropTypes.bool,
|
|
371
|
+
labelValues: PropTypes.object,
|
|
372
|
+
onChange: PropTypes.function,
|
|
373
|
+
range: PropTypes.object,
|
|
374
|
+
size: PropTypes.object,
|
|
375
|
+
sizeConstraints: PropTypes.object,
|
|
376
|
+
standardGrid: PropTypes.bool
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
const styles = theme => ({
|
|
380
|
+
wrapper: {
|
|
381
|
+
width: '450px'
|
|
382
|
+
},
|
|
383
|
+
content: {
|
|
384
|
+
display: 'flex',
|
|
385
|
+
flexDirection: 'column',
|
|
386
|
+
width: '100%'
|
|
387
|
+
},
|
|
388
|
+
columnView: {
|
|
389
|
+
display: 'flex',
|
|
390
|
+
flexDirection: 'column',
|
|
391
|
+
alignItems: 'center'
|
|
392
|
+
},
|
|
393
|
+
rowView: {
|
|
394
|
+
display: 'flex',
|
|
395
|
+
justifyContent: 'space-around',
|
|
396
|
+
alignItems: 'center'
|
|
397
|
+
},
|
|
398
|
+
textField: {
|
|
399
|
+
width: '130px',
|
|
400
|
+
margin: `${theme.spacing.unit}px ${theme.spacing.unit / 2}px`
|
|
401
|
+
},
|
|
402
|
+
mediumTextField: {
|
|
403
|
+
width: '160px',
|
|
404
|
+
margin: `${theme.spacing.unit}px ${theme.spacing.unit / 2}px`
|
|
405
|
+
},
|
|
406
|
+
largeTextField: {
|
|
407
|
+
width: '230px',
|
|
408
|
+
margin: `${theme.spacing.unit}px ${theme.spacing.unit / 2}px`
|
|
409
|
+
},
|
|
410
|
+
text: {
|
|
411
|
+
fontStyle: 'italic',
|
|
412
|
+
margin: `${theme.spacing.unit}px 0`
|
|
413
|
+
},
|
|
414
|
+
dimensions: {
|
|
415
|
+
display: 'flex',
|
|
416
|
+
justifyContent: 'space-between',
|
|
417
|
+
alignItems: 'center'
|
|
418
|
+
},
|
|
419
|
+
disabled: {
|
|
420
|
+
color: color.disabled()
|
|
421
|
+
},
|
|
422
|
+
axisLabel: {
|
|
423
|
+
paddingTop: theme.spacing.unit * 2
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
export default withStyles(styles)(GridSetup);
|
package/src/grid.jsx
CHANGED
|
@@ -14,13 +14,6 @@ export class Grid extends React.Component {
|
|
|
14
14
|
graphProps: types.GraphPropsType.isRequired
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
shouldComponentUpdate(nextProps) {
|
|
18
|
-
const { graphProps } = this.props;
|
|
19
|
-
const { graphProps: nextGraphProps } = nextProps;
|
|
20
|
-
|
|
21
|
-
return !utils.isDomainRangeEqual(graphProps, nextGraphProps);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
17
|
getAdditionalGridProps = (rowTickValues, columnTickValues) => {
|
|
25
18
|
const {
|
|
26
19
|
graphProps: {
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Graph from './graph';
|
|
2
2
|
import GraphContainer from './container';
|
|
3
|
+
import GridSetup from './grid-setup';
|
|
3
4
|
import * as tools from './tools';
|
|
4
5
|
import ToolMenu from './tool-menu';
|
|
5
6
|
|
|
6
|
-
export { Graph, GraphContainer, ToolMenu, tools };
|
|
7
|
+
export { Graph, GraphContainer, GridSetup, ToolMenu, tools };
|