@pie-lib/graphing 2.7.0 → 2.9.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 +30 -0
- package/lib/axis/arrow.js +15 -25
- package/lib/axis/arrow.js.map +1 -1
- package/lib/axis/axes.js +41 -73
- package/lib/axis/axes.js.map +1 -1
- package/lib/axis/index.js +1 -1
- package/lib/bg.js +20 -31
- package/lib/bg.js.map +1 -1
- package/lib/container/index.js +27 -41
- package/lib/container/index.js.map +1 -1
- package/lib/container/reducer.js +2 -2
- package/lib/container/reducer.js.map +1 -1
- package/lib/coordinates-label.js +5 -5
- package/lib/coordinates-label.js.map +1 -1
- package/lib/graph-with-controls.js +53 -38
- package/lib/graph-with-controls.js.map +1 -1
- package/lib/graph.js +68 -75
- package/lib/graph.js.map +1 -1
- package/lib/grid-setup.js +6 -6
- package/lib/grid-setup.js.map +1 -1
- package/lib/grid.js +28 -46
- package/lib/grid.js.map +1 -1
- package/lib/index.js +3 -3
- package/lib/index.js.map +1 -1
- package/lib/labels.js +107 -57
- package/lib/labels.js.map +1 -1
- package/lib/mark-label.js +10 -20
- package/lib/mark-label.js.map +1 -1
- package/lib/toggle-bar.js +177 -45
- package/lib/toggle-bar.js.map +1 -1
- package/lib/tool-menu.js +49 -32
- package/lib/tool-menu.js.map +1 -1
- package/lib/tools/circle/bg-circle.js +27 -38
- package/lib/tools/circle/bg-circle.js.map +1 -1
- package/lib/tools/circle/component.js +36 -54
- package/lib/tools/circle/component.js.map +1 -1
- package/lib/tools/circle/index.js +5 -5
- package/lib/tools/circle/index.js.map +1 -1
- package/lib/tools/line/component.js +11 -25
- package/lib/tools/line/component.js.map +1 -1
- package/lib/tools/line/index.js +2 -2
- package/lib/tools/line/index.js.map +1 -1
- package/lib/tools/parabola/component.js +2 -2
- package/lib/tools/parabola/component.js.map +1 -1
- package/lib/tools/parabola/index.js +5 -5
- package/lib/tools/parabola/index.js.map +1 -1
- package/lib/tools/point/component.js +30 -47
- package/lib/tools/point/component.js.map +1 -1
- package/lib/tools/point/index.js +5 -5
- package/lib/tools/point/index.js.map +1 -1
- package/lib/tools/polygon/component.js +59 -107
- package/lib/tools/polygon/component.js.map +1 -1
- package/lib/tools/polygon/index.js +9 -19
- package/lib/tools/polygon/index.js.map +1 -1
- package/lib/tools/polygon/line.js +28 -41
- package/lib/tools/polygon/line.js.map +1 -1
- package/lib/tools/polygon/polygon.js +28 -42
- package/lib/tools/polygon/polygon.js.map +1 -1
- package/lib/tools/ray/component.js +11 -25
- package/lib/tools/ray/component.js.map +1 -1
- package/lib/tools/ray/index.js +2 -2
- package/lib/tools/ray/index.js.map +1 -1
- package/lib/tools/segment/component.js +8 -11
- package/lib/tools/segment/component.js.map +1 -1
- package/lib/tools/segment/index.js +2 -2
- package/lib/tools/segment/index.js.map +1 -1
- package/lib/tools/shared/arrow-head.js +2 -2
- package/lib/tools/shared/arrow-head.js.map +1 -1
- package/lib/tools/shared/line/index.js +43 -66
- package/lib/tools/shared/line/index.js.map +1 -1
- package/lib/tools/shared/line/line-path.js +29 -42
- package/lib/tools/shared/line/line-path.js.map +1 -1
- package/lib/tools/shared/line/with-root-edge.js +12 -14
- package/lib/tools/shared/line/with-root-edge.js.map +1 -1
- package/lib/tools/shared/point/arrow-point.js +24 -39
- package/lib/tools/shared/point/arrow-point.js.map +1 -1
- package/lib/tools/shared/point/arrow.js +23 -37
- package/lib/tools/shared/point/arrow.js.map +1 -1
- package/lib/tools/shared/point/base-point.js +24 -38
- package/lib/tools/shared/point/base-point.js.map +1 -1
- package/lib/tools/shared/point/index.js +6 -6
- package/lib/tools/shared/point/index.js.map +1 -1
- package/lib/tools/shared/styles.js +7 -5
- package/lib/tools/shared/styles.js.map +1 -1
- package/lib/tools/shared/types.js +2 -2
- package/lib/tools/shared/types.js.map +1 -1
- package/lib/tools/sine/component.js +2 -2
- package/lib/tools/sine/component.js.map +1 -1
- package/lib/tools/sine/index.js +5 -5
- package/lib/tools/sine/index.js.map +1 -1
- package/lib/tools/vector/component.js +8 -11
- package/lib/tools/vector/component.js.map +1 -1
- package/lib/tools/vector/index.js +2 -2
- package/lib/tools/vector/index.js.map +1 -1
- package/lib/undo-redo.js +19 -31
- package/lib/undo-redo.js.map +1 -1
- package/lib/use-debounce.js +5 -13
- package/lib/use-debounce.js.map +1 -1
- package/lib/utils.js +2 -2
- package/lib/utils.js.map +1 -1
- package/package.json +5 -4
- package/src/graph-with-controls.jsx +26 -0
- package/src/graph.jsx +32 -4
- package/src/labels.jsx +85 -21
- package/src/toggle-bar.jsx +143 -13
- package/src/tool-menu.jsx +15 -0
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.9.0",
|
|
7
7
|
"description": "Graphing components",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"react",
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@mapbox/point-geometry": "^0.1.0",
|
|
20
20
|
"@material-ui/core": "^3.8.3",
|
|
21
|
+
"@pie-lib/drag": "^1.1.52",
|
|
21
22
|
"@pie-lib/graphing-utils": "^1.1.20",
|
|
22
|
-
"@pie-lib/plot": "^2.
|
|
23
|
-
"@pie-lib/render-ui": "^4.
|
|
23
|
+
"@pie-lib/plot": "^2.3.0",
|
|
24
|
+
"@pie-lib/render-ui": "^4.13.1",
|
|
24
25
|
"@vx/axis": "^0.0.189",
|
|
25
26
|
"@vx/clip-path": "^0.0.189",
|
|
26
27
|
"@vx/event": "^0.0.189",
|
|
@@ -43,6 +44,6 @@
|
|
|
43
44
|
"peerDependencies": {
|
|
44
45
|
"react": "^16.8.1"
|
|
45
46
|
},
|
|
46
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "5f0932d39d7f01be0f96665b8fbe45ee745c2868",
|
|
47
48
|
"scripts": {}
|
|
48
49
|
}
|
|
@@ -54,6 +54,12 @@ const Collapsible = ({ classes, children, title }) => (
|
|
|
54
54
|
</ExpansionPanel>
|
|
55
55
|
);
|
|
56
56
|
|
|
57
|
+
Collapsible.propTypes = {
|
|
58
|
+
classes: PropTypes.object,
|
|
59
|
+
children: PropTypes.array,
|
|
60
|
+
title: PropTypes.string
|
|
61
|
+
};
|
|
62
|
+
|
|
57
63
|
export class GraphWithControls extends React.Component {
|
|
58
64
|
static propTypes = {
|
|
59
65
|
...graphPropTypes,
|
|
@@ -66,6 +72,10 @@ export class GraphWithControls extends React.Component {
|
|
|
66
72
|
static defaultProps = {
|
|
67
73
|
collapsibleToolbar: false,
|
|
68
74
|
collapsibleToolbarTitle: '',
|
|
75
|
+
disabledLabels: false,
|
|
76
|
+
disabledTitle: false,
|
|
77
|
+
showLabels: true,
|
|
78
|
+
showTitle: true,
|
|
69
79
|
toolbarTools: []
|
|
70
80
|
};
|
|
71
81
|
|
|
@@ -103,14 +113,22 @@ export class GraphWithControls extends React.Component {
|
|
|
103
113
|
collapsibleToolbar,
|
|
104
114
|
collapsibleToolbarTitle,
|
|
105
115
|
disabled,
|
|
116
|
+
disabledLabels,
|
|
117
|
+
disabledTitle,
|
|
106
118
|
domain,
|
|
119
|
+
draggableTools,
|
|
107
120
|
labels,
|
|
121
|
+
onChangeLabels,
|
|
108
122
|
onChangeMarks,
|
|
123
|
+
onChangeTitle,
|
|
124
|
+
onChangeTools,
|
|
109
125
|
onUndo,
|
|
110
126
|
onRedo,
|
|
111
127
|
onReset,
|
|
112
128
|
range,
|
|
113
129
|
size,
|
|
130
|
+
showLabels,
|
|
131
|
+
showTitle,
|
|
114
132
|
title
|
|
115
133
|
} = this.props;
|
|
116
134
|
let { backgroundMarks, marks, toolbarTools } = this.props;
|
|
@@ -136,10 +154,12 @@ export class GraphWithControls extends React.Component {
|
|
|
136
154
|
<ToolMenu
|
|
137
155
|
currentToolType={currentTool && currentTool.type}
|
|
138
156
|
disabled={!!disabled}
|
|
157
|
+
draggableTools={draggableTools}
|
|
139
158
|
labelModeEnabled={labelModeEnabled}
|
|
140
159
|
onChange={tool => this.changeCurrentTool(tool, tools)}
|
|
141
160
|
onToggleLabelMode={this.toggleLabelMode}
|
|
142
161
|
toolbarTools={toolbarTools}
|
|
162
|
+
onChangeTools={onChangeTools}
|
|
143
163
|
/>
|
|
144
164
|
|
|
145
165
|
{!disabled && <UndoRedo onUndo={onUndo} onRedo={onRedo} onReset={onReset} />}
|
|
@@ -165,13 +185,19 @@ export class GraphWithControls extends React.Component {
|
|
|
165
185
|
backgroundMarks={backgroundMarks}
|
|
166
186
|
coordinatesOnHover={coordinatesOnHover}
|
|
167
187
|
currentTool={currentTool}
|
|
188
|
+
disabledLabels={disabledLabels}
|
|
189
|
+
disabledTitle={disabledTitle}
|
|
168
190
|
domain={domain}
|
|
169
191
|
labels={labels}
|
|
170
192
|
labelModeEnabled={labelModeEnabled}
|
|
171
193
|
marks={marks}
|
|
172
194
|
onChangeMarks={!disabled ? onChangeMarks : undefined}
|
|
195
|
+
onChangeLabels={onChangeLabels}
|
|
196
|
+
onChangeTitle={onChangeTitle}
|
|
173
197
|
range={range}
|
|
174
198
|
size={size}
|
|
199
|
+
showLabels={showLabels}
|
|
200
|
+
showTitle={showTitle}
|
|
175
201
|
title={title}
|
|
176
202
|
tools={tools}
|
|
177
203
|
/>
|
package/src/graph.jsx
CHANGED
|
@@ -20,17 +20,23 @@ export const graphPropTypes = {
|
|
|
20
20
|
className: PropTypes.string,
|
|
21
21
|
collapsibleToolbar: PropTypes.bool,
|
|
22
22
|
collapsibleToolbarTitle: PropTypes.string,
|
|
23
|
+
disabledLabels: PropTypes.bool,
|
|
24
|
+
disabledTitle: PropTypes.bool,
|
|
23
25
|
domain: types.DomainType,
|
|
24
26
|
labels: PropTypes.shape(LabelType),
|
|
25
27
|
labelModeEnabled: PropTypes.bool,
|
|
26
28
|
coordinatesOnHover: PropTypes.bool,
|
|
27
29
|
marks: PropTypes.array,
|
|
30
|
+
onChangeLabels: PropTypes.func,
|
|
28
31
|
onChangeMarks: PropTypes.func,
|
|
32
|
+
onChangeTitle: PropTypes.func,
|
|
29
33
|
range: types.DomainType,
|
|
30
34
|
size: PropTypes.shape({
|
|
31
35
|
width: PropTypes.number.isRequired,
|
|
32
36
|
height: PropTypes.number.isRequired
|
|
33
37
|
}),
|
|
38
|
+
showLabels: PropTypes.bool,
|
|
39
|
+
showTitle: PropTypes.bool,
|
|
34
40
|
title: PropTypes.string,
|
|
35
41
|
tools: PropTypes.array
|
|
36
42
|
};
|
|
@@ -64,7 +70,9 @@ export class Graph extends React.Component {
|
|
|
64
70
|
};
|
|
65
71
|
|
|
66
72
|
static defaultProps = {
|
|
67
|
-
onChangeMarks: () => {}
|
|
73
|
+
onChangeMarks: () => {},
|
|
74
|
+
disabledLabels: false,
|
|
75
|
+
disabledTitle: false
|
|
68
76
|
};
|
|
69
77
|
|
|
70
78
|
state = {};
|
|
@@ -151,12 +159,18 @@ export class Graph extends React.Component {
|
|
|
151
159
|
currentTool,
|
|
152
160
|
coordinatesOnHover,
|
|
153
161
|
size,
|
|
162
|
+
disabledLabels,
|
|
163
|
+
disabledTitle,
|
|
154
164
|
domain,
|
|
155
165
|
backgroundMarks,
|
|
156
166
|
range,
|
|
157
167
|
title,
|
|
158
168
|
labels,
|
|
159
|
-
labelModeEnabled
|
|
169
|
+
labelModeEnabled,
|
|
170
|
+
showLabels,
|
|
171
|
+
showTitle,
|
|
172
|
+
onChangeLabels,
|
|
173
|
+
onChangeTitle
|
|
160
174
|
} = this.props;
|
|
161
175
|
let { marks } = this.props;
|
|
162
176
|
|
|
@@ -167,8 +181,14 @@ export class Graph extends React.Component {
|
|
|
167
181
|
marks = removeBuildingToolIfCurrentToolDiffers({ marks: marks || [], currentTool });
|
|
168
182
|
|
|
169
183
|
return (
|
|
170
|
-
<Root
|
|
171
|
-
|
|
184
|
+
<Root
|
|
185
|
+
rootRef={r => (this.rootNode = r)}
|
|
186
|
+
disabledTitle={disabledTitle}
|
|
187
|
+
showTitle={showTitle}
|
|
188
|
+
title={title}
|
|
189
|
+
onChangeTitle={onChangeTitle}
|
|
190
|
+
{...common}
|
|
191
|
+
>
|
|
172
192
|
<g transform={`translate(${domain.padding}, ${range.padding})`}>
|
|
173
193
|
<Grid {...common} />
|
|
174
194
|
<Axes {...axesSettings} {...common} />
|
|
@@ -222,6 +242,14 @@ export class Graph extends React.Component {
|
|
|
222
242
|
/>
|
|
223
243
|
</g>
|
|
224
244
|
</g>
|
|
245
|
+
{showLabels && (
|
|
246
|
+
<Labels
|
|
247
|
+
disabledLabels={disabledLabels}
|
|
248
|
+
value={labels}
|
|
249
|
+
onChange={onChangeLabels}
|
|
250
|
+
{...common}
|
|
251
|
+
/>
|
|
252
|
+
)}
|
|
225
253
|
</Root>
|
|
226
254
|
);
|
|
227
255
|
}
|
package/src/labels.jsx
CHANGED
|
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types';
|
|
|
3
3
|
import { withStyles } from '@material-ui/core/styles';
|
|
4
4
|
import { types } from '@pie-lib/plot';
|
|
5
5
|
import { color, Readable } from '@pie-lib/render-ui';
|
|
6
|
+
import EditableHtml from '@pie-lib/editable-html';
|
|
7
|
+
import cn from 'classnames';
|
|
6
8
|
|
|
7
9
|
const rotations = {
|
|
8
10
|
left: -90,
|
|
@@ -31,13 +33,13 @@ export const getTransform = (side, width, height) => {
|
|
|
31
33
|
const getY = (side, height) => {
|
|
32
34
|
switch (side) {
|
|
33
35
|
case 'left':
|
|
34
|
-
return -height;
|
|
36
|
+
return -height + 6;
|
|
35
37
|
case 'top':
|
|
36
|
-
return -height +
|
|
38
|
+
return -height + 6;
|
|
37
39
|
case 'right':
|
|
38
|
-
return -height
|
|
40
|
+
return -height;
|
|
39
41
|
default:
|
|
40
|
-
return
|
|
42
|
+
return -height - 15;
|
|
41
43
|
}
|
|
42
44
|
};
|
|
43
45
|
|
|
@@ -46,11 +48,12 @@ class RawLabel extends React.Component {
|
|
|
46
48
|
text: PropTypes.string,
|
|
47
49
|
side: PropTypes.string,
|
|
48
50
|
classes: PropTypes.object,
|
|
51
|
+
disabledLabel: PropTypes.bool,
|
|
49
52
|
graphProps: types.GraphPropsType.isRequired
|
|
50
53
|
};
|
|
51
54
|
|
|
52
55
|
render() {
|
|
53
|
-
const { text, side, graphProps, classes } = this.props;
|
|
56
|
+
const { disabledLabel, text, side, graphProps, classes, onChange } = this.props;
|
|
54
57
|
const { size, domain, range } = graphProps;
|
|
55
58
|
const totalHeight = (size.height || 500) + (range.padding || 0) * 2;
|
|
56
59
|
const totalWidth = (size.width || 500) + (domain.padding || 0) * 2;
|
|
@@ -60,17 +63,41 @@ class RawLabel extends React.Component {
|
|
|
60
63
|
const height = 36;
|
|
61
64
|
const y = getY(side, height);
|
|
62
65
|
|
|
66
|
+
const activePlugins = [
|
|
67
|
+
'bold',
|
|
68
|
+
'italic',
|
|
69
|
+
'underline',
|
|
70
|
+
'strikethrough'
|
|
71
|
+
// 'languageCharacters'
|
|
72
|
+
];
|
|
73
|
+
|
|
63
74
|
return (
|
|
64
75
|
<foreignObject
|
|
65
76
|
x={-(width / 2)}
|
|
66
77
|
y={y}
|
|
67
78
|
width={width}
|
|
68
|
-
height={height}
|
|
79
|
+
height={height * 2}
|
|
69
80
|
transform={transform}
|
|
70
81
|
textAnchor="middle"
|
|
71
82
|
>
|
|
72
83
|
<Readable false>
|
|
73
|
-
<
|
|
84
|
+
<EditableHtml
|
|
85
|
+
className={cn(
|
|
86
|
+
{
|
|
87
|
+
[classes.bottomLabel]: side === 'bottom',
|
|
88
|
+
[classes.disabledAxisLabel]: disabledLabel
|
|
89
|
+
},
|
|
90
|
+
classes.axisLabel
|
|
91
|
+
)}
|
|
92
|
+
markup={text || ''}
|
|
93
|
+
onChange={onChange}
|
|
94
|
+
placeholder={!disabledLabel && `Click here to add a ${side} label`}
|
|
95
|
+
toolbarOpts={{
|
|
96
|
+
position: side === 'bottom' ? 'top' : 'bottom',
|
|
97
|
+
noBorder: true
|
|
98
|
+
}}
|
|
99
|
+
activePlugins={activePlugins}
|
|
100
|
+
/>
|
|
74
101
|
</Readable>
|
|
75
102
|
</foreignObject>
|
|
76
103
|
);
|
|
@@ -82,8 +109,14 @@ const Label = withStyles(theme => ({
|
|
|
82
109
|
fill: color.secondary()
|
|
83
110
|
},
|
|
84
111
|
axisLabel: {
|
|
85
|
-
fontSize: theme.typography.fontSize,
|
|
112
|
+
fontSize: theme.typography.fontSize - 2,
|
|
86
113
|
textAlign: 'center'
|
|
114
|
+
},
|
|
115
|
+
disabledAxisLabel: {
|
|
116
|
+
pointerEvents: 'none'
|
|
117
|
+
},
|
|
118
|
+
bottomLabel: {
|
|
119
|
+
marginTop: '44px'
|
|
87
120
|
}
|
|
88
121
|
}))(RawLabel);
|
|
89
122
|
|
|
@@ -98,29 +131,60 @@ export class Labels extends React.Component {
|
|
|
98
131
|
static propTypes = {
|
|
99
132
|
classes: PropTypes.object,
|
|
100
133
|
className: PropTypes.string,
|
|
134
|
+
disabledLabels: PropTypes.bool,
|
|
101
135
|
value: PropTypes.shape(LabelType),
|
|
102
136
|
graphProps: PropTypes.object
|
|
103
137
|
};
|
|
104
138
|
|
|
105
139
|
static defaultProps = {};
|
|
106
140
|
|
|
141
|
+
onChangeLabel = (newValue, side) => {
|
|
142
|
+
const { value, onChange } = this.props;
|
|
143
|
+
const labels = {
|
|
144
|
+
...value,
|
|
145
|
+
[side]: newValue
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
onChange(labels);
|
|
149
|
+
};
|
|
150
|
+
|
|
107
151
|
render() {
|
|
108
|
-
const { value, graphProps } = this.props;
|
|
152
|
+
const { disabledLabels, value = {}, graphProps } = this.props;
|
|
109
153
|
|
|
110
154
|
return (
|
|
111
155
|
<React.Fragment>
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
156
|
+
<Label
|
|
157
|
+
key="left"
|
|
158
|
+
side="left"
|
|
159
|
+
text={value.left}
|
|
160
|
+
disabledLabel={disabledLabels}
|
|
161
|
+
graphProps={graphProps}
|
|
162
|
+
onChange={value => this.onChangeLabel(value, 'left')}
|
|
163
|
+
/>
|
|
164
|
+
<Label
|
|
165
|
+
key="top"
|
|
166
|
+
side="top"
|
|
167
|
+
text={value.top}
|
|
168
|
+
disabledLabel={disabledLabels}
|
|
169
|
+
graphProps={graphProps}
|
|
170
|
+
onChange={value => this.onChangeLabel(value, 'top')}
|
|
171
|
+
/>
|
|
172
|
+
<Label
|
|
173
|
+
key="bottom"
|
|
174
|
+
side="bottom"
|
|
175
|
+
text={value.bottom}
|
|
176
|
+
disabledLabel={disabledLabels}
|
|
177
|
+
graphProps={graphProps}
|
|
178
|
+
onChange={value => this.onChangeLabel(value, 'bottom')}
|
|
179
|
+
/>
|
|
180
|
+
<Label
|
|
181
|
+
key="right"
|
|
182
|
+
side="right"
|
|
183
|
+
text={value.right}
|
|
184
|
+
disabledLabel={disabledLabels}
|
|
185
|
+
graphProps={graphProps}
|
|
186
|
+
onChange={value => this.onChangeLabel(value, 'right')}
|
|
187
|
+
/>
|
|
124
188
|
</React.Fragment>
|
|
125
189
|
);
|
|
126
190
|
}
|
package/src/toggle-bar.jsx
CHANGED
|
@@ -5,6 +5,7 @@ import cn from 'classnames';
|
|
|
5
5
|
import Button from '@material-ui/core/Button';
|
|
6
6
|
import { color } from '@pie-lib/render-ui';
|
|
7
7
|
import { allTools } from './tools/index';
|
|
8
|
+
import { withDragContext, DragSource, DropTarget } from '@pie-lib/drag';
|
|
8
9
|
|
|
9
10
|
const buttonStyles = () => ({
|
|
10
11
|
root: {
|
|
@@ -52,6 +53,7 @@ export const MiniButton = withStyles(buttonStyles)(props => {
|
|
|
52
53
|
|
|
53
54
|
MiniButton.propTypes = {
|
|
54
55
|
disabled: PropTypes.bool,
|
|
56
|
+
classes: PropTypes.object,
|
|
55
57
|
className: PropTypes.string,
|
|
56
58
|
disabledClassName: PropTypes.string,
|
|
57
59
|
selected: PropTypes.bool,
|
|
@@ -66,31 +68,53 @@ export class ToggleBar extends React.Component {
|
|
|
66
68
|
options: PropTypes.arrayOf(PropTypes.string),
|
|
67
69
|
selectedToolType: PropTypes.string,
|
|
68
70
|
disabled: PropTypes.bool,
|
|
69
|
-
|
|
71
|
+
draggableTools: PropTypes.bool,
|
|
72
|
+
onChange: PropTypes.func,
|
|
73
|
+
onChangeToolsOrder: PropTypes.func
|
|
70
74
|
};
|
|
71
75
|
|
|
72
76
|
static defaultProps = {};
|
|
73
77
|
|
|
74
78
|
select = e => this.props.onChange(e.target.textContent);
|
|
75
79
|
|
|
80
|
+
moveTool = (dragIndex, hoverIndex) => {
|
|
81
|
+
const { options, onChangeToolsOrder } = this.props;
|
|
82
|
+
const dragged = options[dragIndex];
|
|
83
|
+
|
|
84
|
+
options.splice(dragIndex, 1);
|
|
85
|
+
options.splice(hoverIndex, 0, dragged);
|
|
86
|
+
|
|
87
|
+
onChangeToolsOrder(options);
|
|
88
|
+
};
|
|
89
|
+
|
|
76
90
|
render() {
|
|
77
|
-
const { classes, className, disabled, options, selectedToolType } = this.props;
|
|
91
|
+
const { classes, className, disabled, options, selectedToolType, draggableTools } = this.props;
|
|
92
|
+
|
|
78
93
|
return (
|
|
79
|
-
<div className={cn(className)}>
|
|
80
|
-
{(options || []).map(option => {
|
|
94
|
+
<div className={cn(className, classes.toolsContainer)}>
|
|
95
|
+
{(options || []).map((option, index) => {
|
|
81
96
|
if ((allTools || []).includes(option)) {
|
|
82
97
|
const isSelected = option === selectedToolType;
|
|
98
|
+
const toolRef = React.createRef();
|
|
83
99
|
|
|
84
100
|
return (
|
|
85
|
-
<
|
|
101
|
+
<DragTool
|
|
86
102
|
key={option}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
103
|
+
index={index}
|
|
104
|
+
draggable={draggableTools}
|
|
105
|
+
moveTool={this.moveTool}
|
|
106
|
+
classes={classes}
|
|
107
|
+
toolRef={toolRef}
|
|
108
|
+
>
|
|
109
|
+
<MiniButton
|
|
110
|
+
className={cn(classes.button, isSelected && classes.selected)}
|
|
111
|
+
disabled={disabled}
|
|
112
|
+
disableRipple={true}
|
|
113
|
+
onClick={this.select}
|
|
114
|
+
value={option}
|
|
115
|
+
selected={isSelected}
|
|
116
|
+
/>
|
|
117
|
+
</DragTool>
|
|
94
118
|
);
|
|
95
119
|
}
|
|
96
120
|
})}
|
|
@@ -100,12 +124,118 @@ export class ToggleBar extends React.Component {
|
|
|
100
124
|
}
|
|
101
125
|
|
|
102
126
|
const styles = theme => ({
|
|
127
|
+
toolsContainer: {
|
|
128
|
+
display: 'flex',
|
|
129
|
+
flexWrap: 'wrap'
|
|
130
|
+
},
|
|
103
131
|
button: {
|
|
104
132
|
marginRight: theme.spacing.unit / 2,
|
|
105
133
|
marginBottom: theme.spacing.unit / 2,
|
|
106
134
|
color: color.text(),
|
|
107
135
|
backgroundColor: color.background()
|
|
136
|
+
},
|
|
137
|
+
under: {
|
|
138
|
+
position: 'absolute',
|
|
139
|
+
top: 0,
|
|
140
|
+
left: 0,
|
|
141
|
+
zIndex: -1,
|
|
142
|
+
pointerEvents: 'none'
|
|
143
|
+
},
|
|
144
|
+
wrapper: {
|
|
145
|
+
position: 'relative'
|
|
146
|
+
},
|
|
147
|
+
hidden: {
|
|
148
|
+
opacity: 0
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
export default withDragContext(withStyles(styles)(ToggleBar));
|
|
153
|
+
|
|
154
|
+
const DRAG_TYPE = 'tool';
|
|
155
|
+
|
|
156
|
+
export class Item extends React.Component {
|
|
157
|
+
static propTypes = {
|
|
158
|
+
classes: PropTypes.object.isRequired,
|
|
159
|
+
className: PropTypes.string,
|
|
160
|
+
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
|
|
161
|
+
connectDragSource: PropTypes.func.isRequired,
|
|
162
|
+
connectDragPreview: PropTypes.func.isRequired,
|
|
163
|
+
connectDropTarget: PropTypes.func.isRequired,
|
|
164
|
+
isDragging: PropTypes.bool
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
static defaultProps = {};
|
|
168
|
+
|
|
169
|
+
render() {
|
|
170
|
+
const {
|
|
171
|
+
classes,
|
|
172
|
+
children,
|
|
173
|
+
connectDragSource,
|
|
174
|
+
connectDropTarget,
|
|
175
|
+
connectDragPreview,
|
|
176
|
+
isDragging,
|
|
177
|
+
toolRef
|
|
178
|
+
} = this.props;
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
<div className={classes.wrapper} ref={toolRef}>
|
|
182
|
+
{connectDragSource(
|
|
183
|
+
connectDropTarget(<div className={isDragging && classes.hidden}>{children}</div>)
|
|
184
|
+
)}
|
|
185
|
+
{connectDragPreview(<div className={classes.under}>{children}</div>)}
|
|
186
|
+
</div>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const itemSource = {
|
|
192
|
+
canDrag(props) {
|
|
193
|
+
return props.draggable;
|
|
194
|
+
},
|
|
195
|
+
beginDrag(props) {
|
|
196
|
+
return {
|
|
197
|
+
index: props.index
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const itemTarget = {
|
|
203
|
+
hover(props, monitor) {
|
|
204
|
+
const dragIndex = monitor.getItem().index;
|
|
205
|
+
const { toolRef, index: hoverIndex } = props;
|
|
206
|
+
|
|
207
|
+
if (dragIndex === hoverIndex || !toolRef.current) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const hoverBoundingRect = toolRef.current?.getBoundingClientRect();
|
|
212
|
+
const hoverMiddleX = (hoverBoundingRect.right - hoverBoundingRect.left) / 2;
|
|
213
|
+
const clientOffset = monitor.getClientOffset();
|
|
214
|
+
const hoverClientX = clientOffset.x - hoverBoundingRect.left;
|
|
215
|
+
|
|
216
|
+
if (dragIndex < hoverIndex && hoverClientX < hoverMiddleX) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (dragIndex > hoverIndex && hoverClientX > hoverMiddleX) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
props.moveTool(dragIndex, hoverIndex);
|
|
225
|
+
monitor.getItem().index = hoverIndex;
|
|
108
226
|
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const collectTarget = connect => ({ connectDropTarget: connect.dropTarget() });
|
|
230
|
+
|
|
231
|
+
const collectSource = (connect, monitor) => ({
|
|
232
|
+
connectDragSource: connect.dragSource(),
|
|
233
|
+
connectDragPreview: connect.dragPreview(),
|
|
234
|
+
isDragging: monitor.isDragging()
|
|
109
235
|
});
|
|
110
236
|
|
|
111
|
-
|
|
237
|
+
const DragTool = DropTarget(
|
|
238
|
+
DRAG_TYPE,
|
|
239
|
+
itemTarget,
|
|
240
|
+
collectTarget
|
|
241
|
+
)(DragSource(DRAG_TYPE, itemSource, collectSource)(Item));
|
package/src/tool-menu.jsx
CHANGED
|
@@ -9,9 +9,11 @@ export class ToolMenu extends React.Component {
|
|
|
9
9
|
className: PropTypes.string,
|
|
10
10
|
currentToolType: PropTypes.string,
|
|
11
11
|
disabled: PropTypes.bool,
|
|
12
|
+
draggableTools: PropTypes.bool,
|
|
12
13
|
labelModeEnabled: PropTypes.bool,
|
|
13
14
|
onChange: PropTypes.func,
|
|
14
15
|
onToggleLabelMode: PropTypes.func,
|
|
16
|
+
onChangeTools: PropTypes.func,
|
|
15
17
|
toolbarTools: PropTypes.arrayOf(PropTypes.string)
|
|
16
18
|
};
|
|
17
19
|
|
|
@@ -19,11 +21,22 @@ export class ToolMenu extends React.Component {
|
|
|
19
21
|
toolbarTools: []
|
|
20
22
|
};
|
|
21
23
|
|
|
24
|
+
updateToolsOrder = (tools, showLabel) => {
|
|
25
|
+
const { onChangeTools } = this.props;
|
|
26
|
+
|
|
27
|
+
if (showLabel) {
|
|
28
|
+
tools.push('label');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
onChangeTools(tools);
|
|
32
|
+
};
|
|
33
|
+
|
|
22
34
|
render() {
|
|
23
35
|
const {
|
|
24
36
|
className,
|
|
25
37
|
currentToolType,
|
|
26
38
|
disabled,
|
|
39
|
+
draggableTools,
|
|
27
40
|
labelModeEnabled,
|
|
28
41
|
onToggleLabelMode,
|
|
29
42
|
onChange
|
|
@@ -38,9 +51,11 @@ export class ToolMenu extends React.Component {
|
|
|
38
51
|
<div className={classNames(className)}>
|
|
39
52
|
<ToggleBar
|
|
40
53
|
disabled={disabled}
|
|
54
|
+
draggableTools={draggableTools}
|
|
41
55
|
options={toolbarTools}
|
|
42
56
|
selectedToolType={currentToolType}
|
|
43
57
|
onChange={onChange}
|
|
58
|
+
onChangeToolsOrder={tools => this.updateToolsOrder(tools, showLabel)}
|
|
44
59
|
/>
|
|
45
60
|
|
|
46
61
|
{showLabel && (
|