@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.
Files changed (106) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/lib/axis/arrow.js +15 -25
  3. package/lib/axis/arrow.js.map +1 -1
  4. package/lib/axis/axes.js +41 -73
  5. package/lib/axis/axes.js.map +1 -1
  6. package/lib/axis/index.js +1 -1
  7. package/lib/bg.js +20 -31
  8. package/lib/bg.js.map +1 -1
  9. package/lib/container/index.js +27 -41
  10. package/lib/container/index.js.map +1 -1
  11. package/lib/container/reducer.js +2 -2
  12. package/lib/container/reducer.js.map +1 -1
  13. package/lib/coordinates-label.js +5 -5
  14. package/lib/coordinates-label.js.map +1 -1
  15. package/lib/graph-with-controls.js +53 -38
  16. package/lib/graph-with-controls.js.map +1 -1
  17. package/lib/graph.js +68 -75
  18. package/lib/graph.js.map +1 -1
  19. package/lib/grid-setup.js +6 -6
  20. package/lib/grid-setup.js.map +1 -1
  21. package/lib/grid.js +28 -46
  22. package/lib/grid.js.map +1 -1
  23. package/lib/index.js +3 -3
  24. package/lib/index.js.map +1 -1
  25. package/lib/labels.js +107 -57
  26. package/lib/labels.js.map +1 -1
  27. package/lib/mark-label.js +10 -20
  28. package/lib/mark-label.js.map +1 -1
  29. package/lib/toggle-bar.js +177 -45
  30. package/lib/toggle-bar.js.map +1 -1
  31. package/lib/tool-menu.js +49 -32
  32. package/lib/tool-menu.js.map +1 -1
  33. package/lib/tools/circle/bg-circle.js +27 -38
  34. package/lib/tools/circle/bg-circle.js.map +1 -1
  35. package/lib/tools/circle/component.js +36 -54
  36. package/lib/tools/circle/component.js.map +1 -1
  37. package/lib/tools/circle/index.js +5 -5
  38. package/lib/tools/circle/index.js.map +1 -1
  39. package/lib/tools/line/component.js +11 -25
  40. package/lib/tools/line/component.js.map +1 -1
  41. package/lib/tools/line/index.js +2 -2
  42. package/lib/tools/line/index.js.map +1 -1
  43. package/lib/tools/parabola/component.js +2 -2
  44. package/lib/tools/parabola/component.js.map +1 -1
  45. package/lib/tools/parabola/index.js +5 -5
  46. package/lib/tools/parabola/index.js.map +1 -1
  47. package/lib/tools/point/component.js +30 -47
  48. package/lib/tools/point/component.js.map +1 -1
  49. package/lib/tools/point/index.js +5 -5
  50. package/lib/tools/point/index.js.map +1 -1
  51. package/lib/tools/polygon/component.js +59 -107
  52. package/lib/tools/polygon/component.js.map +1 -1
  53. package/lib/tools/polygon/index.js +9 -19
  54. package/lib/tools/polygon/index.js.map +1 -1
  55. package/lib/tools/polygon/line.js +28 -41
  56. package/lib/tools/polygon/line.js.map +1 -1
  57. package/lib/tools/polygon/polygon.js +28 -42
  58. package/lib/tools/polygon/polygon.js.map +1 -1
  59. package/lib/tools/ray/component.js +11 -25
  60. package/lib/tools/ray/component.js.map +1 -1
  61. package/lib/tools/ray/index.js +2 -2
  62. package/lib/tools/ray/index.js.map +1 -1
  63. package/lib/tools/segment/component.js +8 -11
  64. package/lib/tools/segment/component.js.map +1 -1
  65. package/lib/tools/segment/index.js +2 -2
  66. package/lib/tools/segment/index.js.map +1 -1
  67. package/lib/tools/shared/arrow-head.js +2 -2
  68. package/lib/tools/shared/arrow-head.js.map +1 -1
  69. package/lib/tools/shared/line/index.js +43 -66
  70. package/lib/tools/shared/line/index.js.map +1 -1
  71. package/lib/tools/shared/line/line-path.js +29 -42
  72. package/lib/tools/shared/line/line-path.js.map +1 -1
  73. package/lib/tools/shared/line/with-root-edge.js +12 -14
  74. package/lib/tools/shared/line/with-root-edge.js.map +1 -1
  75. package/lib/tools/shared/point/arrow-point.js +24 -39
  76. package/lib/tools/shared/point/arrow-point.js.map +1 -1
  77. package/lib/tools/shared/point/arrow.js +23 -37
  78. package/lib/tools/shared/point/arrow.js.map +1 -1
  79. package/lib/tools/shared/point/base-point.js +24 -38
  80. package/lib/tools/shared/point/base-point.js.map +1 -1
  81. package/lib/tools/shared/point/index.js +6 -6
  82. package/lib/tools/shared/point/index.js.map +1 -1
  83. package/lib/tools/shared/styles.js +7 -5
  84. package/lib/tools/shared/styles.js.map +1 -1
  85. package/lib/tools/shared/types.js +2 -2
  86. package/lib/tools/shared/types.js.map +1 -1
  87. package/lib/tools/sine/component.js +2 -2
  88. package/lib/tools/sine/component.js.map +1 -1
  89. package/lib/tools/sine/index.js +5 -5
  90. package/lib/tools/sine/index.js.map +1 -1
  91. package/lib/tools/vector/component.js +8 -11
  92. package/lib/tools/vector/component.js.map +1 -1
  93. package/lib/tools/vector/index.js +2 -2
  94. package/lib/tools/vector/index.js.map +1 -1
  95. package/lib/undo-redo.js +19 -31
  96. package/lib/undo-redo.js.map +1 -1
  97. package/lib/use-debounce.js +5 -13
  98. package/lib/use-debounce.js.map +1 -1
  99. package/lib/utils.js +2 -2
  100. package/lib/utils.js.map +1 -1
  101. package/package.json +5 -4
  102. package/src/graph-with-controls.jsx +26 -0
  103. package/src/graph.jsx +32 -4
  104. package/src/labels.jsx +85 -21
  105. package/src/toggle-bar.jsx +143 -13
  106. 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.7.0",
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.2.0",
23
- "@pie-lib/render-ui": "^4.12.9",
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": "2f841d92dcda7472f18cbce517eb664dec2f6442",
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 rootRef={r => (this.rootNode = r)} title={title} {...common}>
171
- <Labels value={labels} {...common} />
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 + 10;
38
+ return -height + 6;
37
39
  case 'right':
38
- return -height + 10;
40
+ return -height;
39
41
  default:
40
- return 0;
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
- <div dangerouslySetInnerHTML={{ __html: text }} className={classes.axisLabel} />
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
- {value && value.left && (
113
- <Label key="left" side="left" text={value.left} graphProps={graphProps} />
114
- )}
115
- {value && value.top && (
116
- <Label key="top" side="top" text={value.top} graphProps={graphProps} />
117
- )}
118
- {value && value.bottom && (
119
- <Label key="bottom" side="bottom" text={value.bottom} graphProps={graphProps} />
120
- )}
121
- {value && value.right && (
122
- <Label key="right" side="right" text={value.right} graphProps={graphProps} />
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
  }
@@ -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
- onChange: PropTypes.func
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
- <MiniButton
101
+ <DragTool
86
102
  key={option}
87
- className={cn(classes.button, isSelected && classes.selected)}
88
- disabled={disabled}
89
- disableRipple={true}
90
- onClick={this.select}
91
- value={option}
92
- selected={isSelected}
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
- export default withStyles(styles)(ToggleBar);
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 && (