diff --git a/packages/ra-tree-ui-materialui/src/DragLayer.js b/packages/ra-tree-ui-materialui/src/DragLayer.js
index 446378f734a..ab77817964a 100644
--- a/packages/ra-tree-ui-materialui/src/DragLayer.js
+++ b/packages/ra-tree-ui-materialui/src/DragLayer.js
@@ -2,13 +2,13 @@
* Custom DragLayer from Alejandro Hernandez
* See https://github.com/react-dnd/react-dnd/issues/592#issuecomment-399287474
*/
-import React, { Component } from 'react';
+import React from 'react';
import PropTypes from 'prop-types';
import { DragLayer } from 'react-dnd';
-import compose from 'recompose/compose';
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/core/styles';
import isEqual from 'lodash/isEqual';
-const styles = {
+
+const useStyles = makeStyles({
layer: {
position: 'fixed',
pointerEvents: 'none',
@@ -19,56 +19,50 @@ const styles = {
height: '100%',
},
item: {},
-};
-
-class CustomDragLayer extends Component {
- static propTypes = {
- beingDragged: PropTypes.bool,
- classes: PropTypes.object.isRequired,
- dragPreviewComponent: PropTypes.oneOfType([
- PropTypes.element,
- PropTypes.func,
- ]).isRequired,
- itemBeingDragged: PropTypes.object,
- offset: PropTypes.object,
- };
-
- shouldComponentUpdate(nextProps) {
- return !isEqual(this.props.offset, nextProps.offset);
- }
+});
- render() {
- const {
- classes,
- beingDragged,
- dragPreviewComponent: DragPreview,
- itemBeingDragged,
- offset,
- } = this.props;
- if (!beingDragged || !offset) return null;
+const CustomDragLayer = ({
+ beingDragged,
+ dragPreviewComponent: DragPreview,
+ itemBeingDragged,
+ offset,
+}) => {
+ const classes = useStyles();
+ if (!beingDragged || !offset) return null;
- return (
-
-
-
-
+ return (
+
+ );
+};
+
+CustomDragLayer.propTypes = {
+ beingDragged: PropTypes.bool,
+ dragPreviewComponent: PropTypes.oneOfType([
+ PropTypes.element,
+ PropTypes.func,
+ ]).isRequired,
+ itemBeingDragged: PropTypes.object,
+ offset: PropTypes.object,
+};
-export default compose(
- withStyles(styles),
- DragLayer(monitor => ({
- itemBeingDragged: monitor.getItem(),
- componentType: monitor.getItemType(),
- beingDragged: monitor.isDragging(),
- offset: monitor.getSourceClientOffset(),
- }))
-)(CustomDragLayer);
+export default DragLayer(monitor => ({
+ itemBeingDragged: monitor.getItem(),
+ componentType: monitor.getItemType(),
+ beingDragged: monitor.isDragging(),
+ offset: monitor.getSourceClientOffset(),
+}))(
+ React.memo(
+ CustomDragLayer,
+ (prevProps, nextProps) => !isEqual(prevProps.offset, nextProps.offset)
+ )
+);
diff --git a/packages/ra-tree-ui-materialui/src/DragPreview.js b/packages/ra-tree-ui-materialui/src/DragPreview.js
index 9a33376e082..23ce26a67fc 100644
--- a/packages/ra-tree-ui-materialui/src/DragPreview.js
+++ b/packages/ra-tree-ui-materialui/src/DragPreview.js
@@ -1,10 +1,9 @@
-import React, { Component } from 'react';
+import React from 'react';
import PropTypes from 'prop-types';
-import compose from 'recompose/compose';
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/core/styles';
import { translate } from 'ra-core';
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
item: {
alignItems: 'center',
backgroundColor: theme.palette.action.active,
@@ -16,45 +15,35 @@ const styles = theme => ({
paddingLeft: theme.spacing(6),
paddingRight: theme.spacing(4),
},
-});
-class DragPreview extends Component {
- shouldComponentUpdate() {
- return false;
- }
- render() {
- const {
- children,
- className,
- classes,
- node,
- style,
- translate,
- } = this.props;
- return (
-
- {children
- ? typeof children === 'function'
- ? children({ node, translate })
- : children
- : translate('ra.tree.drag_preview', {
- id: node.id,
- smart_count: node.children.length,
- })}
-
- );
- }
-}
+}));
+
+const DragPreview = ({ children, className, node, style, translate }) => {
+ const classes = useStyles();
+
+ return (
+
+ {children
+ ? typeof children === 'function'
+ ? children({ node, translate })
+ : children
+ : translate('ra.tree.drag_preview', {
+ id: node.id,
+ smart_count: node.children.length,
+ })}
+
+ );
+};
DragPreview.propTypes = {
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
className: PropTypes.string,
- classes: PropTypes.object,
node: PropTypes.object,
style: PropTypes.object,
translate: PropTypes.func.isRequired,
};
-export default compose(
- translate,
- withStyles(styles)
-)(DragPreview);
+export default translate()(
+ React.memo(DragPreview, () => {
+ return false;
+ })
+);
diff --git a/packages/ra-tree-ui-materialui/src/NodeActions.js b/packages/ra-tree-ui-materialui/src/NodeActions.js
index 8e239a1a95f..a1c987fc5b1 100644
--- a/packages/ra-tree-ui-materialui/src/NodeActions.js
+++ b/packages/ra-tree-ui-materialui/src/NodeActions.js
@@ -1,34 +1,32 @@
-import React, { cloneElement, Children, Component } from 'react';
+import React, { cloneElement, Children } from 'react';
import PropTypes from 'prop-types';
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/core/styles';
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
root: {
alignItems: 'center',
marginLeft: 'auto',
marginRight: theme.spacing(4),
},
-});
+}));
-export class NodeActions extends Component {
- static propTypes = {
- classes: PropTypes.object.isRequired,
- basePath: PropTypes.string.isRequired,
- children: PropTypes.node,
- record: PropTypes.object.isRequired,
- resource: PropTypes.string.isRequired,
- };
+const NodeActions = ({ children, ...props }) => {
+ const classes = useStyles();
- render() {
- const { children, classes, ...props } = this.props;
- return (
-
- {Children.map(children, action =>
- action ? cloneElement(action, props) : null
- )}
-
- );
- }
-}
+ return (
+
+ {Children.map(children, action =>
+ action ? cloneElement(action, props) : null
+ )}
+
+ );
+};
-export default withStyles(styles)(NodeActions);
+NodeActions.propTypes = {
+ basePath: PropTypes.string.isRequired,
+ children: PropTypes.node,
+ record: PropTypes.object.isRequired,
+ resource: PropTypes.string.isRequired,
+};
+
+export default NodeActions;
diff --git a/packages/ra-tree-ui-materialui/src/NodeForm.js b/packages/ra-tree-ui-materialui/src/NodeForm.js
index efd02427123..5b172a78cf3 100644
--- a/packages/ra-tree-ui-materialui/src/NodeForm.js
+++ b/packages/ra-tree-ui-materialui/src/NodeForm.js
@@ -1,8 +1,8 @@
-import React, { cloneElement, Children, Component } from 'react';
+import React, { cloneElement, Children } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import compose from 'recompose/compose';
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/core/styles';
import { reduxForm } from 'redux-form';
import {
crudUpdate as crudUpdateAction,
@@ -11,13 +11,13 @@ import {
import NodeFormActions from './NodeFormActions';
-const styles = {
+const useStyles = makeStyles({
root: {
alignItems: 'center',
display: 'flex',
flexGrow: 1,
},
-};
+});
const sanitizeRestProps = ({
anyTouched,
@@ -71,30 +71,26 @@ const sanitizeRestProps = ({
validate,
...props
}) => props;
-class NodeForm extends Component {
- static propTypes = {
- actions: PropTypes.node,
- basePath: PropTypes.string.isRequired,
- cancelDropOnChildren: PropTypes.bool,
- children: PropTypes.node,
- classes: PropTypes.object,
- dispatchCrudUpdate: PropTypes.func.isRequired,
- handleSubmit: PropTypes.func.isRequired,
- invalid: PropTypes.bool,
- node: PropTypes.object.isRequired,
- pristine: PropTypes.bool,
- resource: PropTypes.string.isRequired,
- saving: PropTypes.bool,
- startUndoable: PropTypes.func.isRequired,
- submitOnEnter: PropTypes.bool,
- undoable: PropTypes.bool,
- };
- static defaultProps = {
- actions:
,
- };
+const NodeForm = ({
+ actions,
+ basePath,
+ children,
+ invalid,
+ node,
+ pristine,
+ resource,
+ saving,
+ submitOnEnter = true,
+ dispatchCrudUpdate,
+ node: { record },
+ startUndoable,
+ undoable = true,
+ ...props
+}) => {
+ const classes = useStyles();
- handleClick = event => {
+ const handleClick = event => {
event.persist();
// This ensure clicking on an input or button does not collapse/expand a node
// When clicking on the form (empty spaces around inputs) however, it should
@@ -104,25 +100,15 @@ class NodeForm extends Component {
}
};
- handleDrop = event => {
+ const handleDrop = event => {
event.persist();
if (this.props.cancelDropOnChildren) {
event.preventDefault();
}
};
- handleSubmit = () => {
- const {
- basePath,
- dispatchCrudUpdate,
- handleSubmit,
- node: { record },
- resource,
- startUndoable,
- undoable = true,
- } = this.props;
-
- return handleSubmit(values =>
+ const handleSubmit = () => {
+ return props.handleSubmit(values =>
undoable
? startUndoable(
crudUpdateAction(
@@ -145,54 +131,58 @@ class NodeForm extends Component {
);
};
- render() {
- const {
- actions,
- basePath,
- children,
- classes,
- handleSubmit,
- invalid,
- node,
- pristine,
- resource,
- saving,
- submitOnEnter = true,
- ...props
- } = this.props;
+ return (
+
+ );
+};
+
+NodeForm.propTypes = {
+ actions: PropTypes.node,
+ basePath: PropTypes.string.isRequired,
+ cancelDropOnChildren: PropTypes.bool,
+ children: PropTypes.node,
+ dispatchCrudUpdate: PropTypes.func.isRequired,
+ handleSubmit: PropTypes.func.isRequired,
+ invalid: PropTypes.bool,
+ node: PropTypes.object.isRequired,
+ pristine: PropTypes.bool,
+ resource: PropTypes.string.isRequired,
+ saving: PropTypes.bool,
+ startUndoable: PropTypes.func.isRequired,
+ submitOnEnter: PropTypes.bool,
+ undoable: PropTypes.bool,
+};
- return (
-
- );
- }
-}
+NodeForm.defaultProps = {
+ actions:
,
+};
const mapStateToProps = (state, { node }) => ({
form: `tree-node-form-${node.id}`,
@@ -211,6 +201,5 @@ export default compose(
reduxForm({
enableReinitialize: true,
keepDirtyOnReinitialize: true,
- }),
- withStyles(styles)
+ })
)(NodeForm);
diff --git a/packages/ra-tree-ui-materialui/src/NodeView.js b/packages/ra-tree-ui-materialui/src/NodeView.js
index 729ac790005..8838d158bd3 100644
--- a/packages/ra-tree-ui-materialui/src/NodeView.js
+++ b/packages/ra-tree-ui-materialui/src/NodeView.js
@@ -1,17 +1,17 @@
-import React, { cloneElement, Children, Component } from 'react';
+import React, { cloneElement, Children } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/core/styles';
const CONTAINER_CLASS = 'treenode-content';
-const styles = {
+const useStyles = makeStyles({
root: {
alignItems: 'center',
display: 'flex',
flexGrow: 1,
},
-};
+});
const sanitizeRestProps = ({
cancelDropOnChildren,
@@ -30,17 +30,17 @@ const sanitizeRestProps = ({
...rest
}) => rest;
-export class NodeView extends Component {
- static propTypes = {
- actions: PropTypes.node,
- basePath: PropTypes.string.isRequired,
- children: PropTypes.node,
- classes: PropTypes.object,
- node: PropTypes.object.isRequired,
- resource: PropTypes.string.isRequired,
- };
+const NodeView = ({
+ actions,
+ basePath,
+ children,
+ node,
+ resource,
+ ...props
+}) => {
+ const classes = useStyles();
- handleClick = event => {
+ const handleClick = event => {
event.persist();
// This ensure clicking on a button does not collapse/expand a node
// When clicking on the form (empty spaces around buttons) however, it should
@@ -50,41 +50,37 @@ export class NodeView extends Component {
}
};
- render() {
- const {
- actions,
- basePath,
- children,
- classes,
- node,
- resource,
- ...props
- } = this.props;
+ return (
+
+ {Children.map(children, field =>
+ field
+ ? cloneElement(field, {
+ basePath: field.props.basePath || basePath,
+ record: node.record,
+ resource,
+ })
+ : null
+ )}
+ {actions &&
+ cloneElement(actions, {
+ basePath,
+ record: node.record,
+ resource,
+ })}
+
+ );
+};
- return (
-
- {Children.map(children, field =>
- field
- ? cloneElement(field, {
- basePath: field.props.basePath || basePath,
- record: node.record,
- resource,
- })
- : null
- )}
- {actions &&
- cloneElement(actions, {
- basePath,
- record: node.record,
- resource,
- })}
-
- );
- }
-}
+NodeView.propTypes = {
+ actions: PropTypes.node,
+ basePath: PropTypes.string.isRequired,
+ children: PropTypes.node,
+ node: PropTypes.object.isRequired,
+ resource: PropTypes.string.isRequired,
+};
-export default withStyles(styles)(NodeView);
+export default NodeView;
diff --git a/packages/ra-tree-ui-materialui/src/RootDropTarget.js b/packages/ra-tree-ui-materialui/src/RootDropTarget.js
index 8198ffd82d9..553ac33f149 100644
--- a/packages/ra-tree-ui-materialui/src/RootDropTarget.js
+++ b/packages/ra-tree-ui-materialui/src/RootDropTarget.js
@@ -1,9 +1,9 @@
-import React, { Component } from 'react';
+import React from 'react';
import PropTypes from 'prop-types';
import compose from 'recompose/compose';
import classNames from 'classnames';
import { DropTarget } from 'react-dnd';
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import ListItem from '@material-ui/core/ListItem';
import IconGetApp from '@material-ui/icons/GetApp';
@@ -11,7 +11,7 @@ import { translate } from 'ra-core';
import { DROP_TARGET_TYPE } from './constants';
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
root: {
paddingLeft: theme.spacing(6),
},
@@ -23,51 +23,41 @@ const styles = theme => ({
hover: {
backgroundColor: theme.palette.action.active,
},
-});
+}));
-class RootDropTarget extends Component {
- static propTypes = {
- canDrop: PropTypes.bool,
- classes: PropTypes.object.isRequired,
- connectDropTarget: PropTypes.func.isRequired,
- isOverCurrent: PropTypes.bool,
- translate: PropTypes.func.isRequired,
- };
+const RootDropTarget = ({
+ canDrop,
+ connectDropTarget,
+ isOverCurrent,
+ translate,
+}) => {
+ const classes = useStyles();
- shouldComponentUpdate(nextProps) {
- return (
- this.props.canDrop !== nextProps.canDrop ||
- this.props.isOverCurrent !== nextProps.isOverCurrent
- );
- }
+ return (
+
+
+ {connectDropTarget(
+
+
+ {translate('ra.tree.root_target')}
+
+
+ )}
+
+ );
+};
- render() {
- const {
- canDrop,
- classes,
- connectDropTarget,
- isOverCurrent,
- translate,
- } = this.props;
- return (
-
-
- {connectDropTarget(
-
-
- {translate('ra.tree.root_target')}
-
-
- )}
-
- );
- }
-}
+RootDropTarget.propTypes = {
+ canDrop: PropTypes.bool,
+ connectDropTarget: PropTypes.func.isRequired,
+ isOverCurrent: PropTypes.bool,
+ translate: PropTypes.func.isRequired,
+};
const dropTargetSpecs = {
drop(props, monitor) {
@@ -93,6 +83,12 @@ const dropTargetConnect = (connect, monitor) => ({
export default compose(
DropTarget(DROP_TARGET_TYPE, dropTargetSpecs, dropTargetConnect),
- translate,
- withStyles(styles)
-)(RootDropTarget);
+ translate
+)(
+ React.memo(RootDropTarget, (prevProps, nextProps) => {
+ return (
+ prevProps.canDrop !== nextProps.canDrop ||
+ prevProps.isOverCurrent !== nextProps.isOverCurrent
+ );
+ })
+);
diff --git a/packages/ra-tree-ui-materialui/src/Tree.js b/packages/ra-tree-ui-materialui/src/Tree.js
index 394b5febb61..308a0495768 100644
--- a/packages/ra-tree-ui-materialui/src/Tree.js
+++ b/packages/ra-tree-ui-materialui/src/Tree.js
@@ -1,6 +1,6 @@
-import React, { Children, Component, Fragment } from 'react';
+import React, { Children, Fragment, useEffect } from 'react';
import PropTypes from 'prop-types';
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import { TreeController } from 'ra-tree-core';
import { DragDropContext } from 'react-dnd';
@@ -15,12 +15,12 @@ import DefaultTreeNodeContent from './TreeNodeContent';
import DefaultTreeNodeWithChildren from './TreeNodeWithChildren';
import RootDropTarget from './RootDropTarget';
-export const styles = {
+const useStyles = makeStyles({
root: {
display: 'flex',
flexDirection: 'column',
},
-};
+});
const sanitizeRestProps = ({
currentSort,
@@ -100,97 +100,94 @@ If you need actions on each node, use the actions prop on either the NodeView or
`
);
-export class Tree extends Component {
- componentDidMount() {
- const childrenCount = Children.count(this.props.children);
+const Tree = ({
+ allowDropOnRoot,
+ children,
+ dragPreviewComponent,
+ enableDragAndDrop,
+ parentSource,
+ treeNodeComponent,
+ treeNodeWithChildrenComponent,
+ treeNodeContentComponent,
+ ...props
+}) => {
+ useEffect(() => {
+ const childrenCount = Children.count(children);
if (childrenCount > 1 && process.env.NODE_ENV !== 'production') {
warnAboutChildren();
}
- }
-
- render() {
- const {
- allowDropOnRoot,
- children,
- classes,
- dragPreviewComponent,
- enableDragAndDrop,
- parentSource,
- treeNodeComponent,
- treeNodeWithChildrenComponent,
- treeNodeContentComponent,
- ...props
- } = this.props;
- const Container = enableDragAndDrop
- ? DragDropContext(
- TouchBackend({
- enableKeyboardEvents: true,
- enableMouseEvents: true,
- enableTouchEvents: true,
- })
- )('div')
- : Fragment;
-
- const TreeNode = enableDragAndDrop
- ? droppable(treeNodeComponent)
- : treeNodeComponent;
-
- const TreeNodeContent = enableDragAndDrop
- ? draggable(treeNodeContentComponent)
- : treeNodeContentComponent;
-
- return (
-
- {({ getTreeState, tree, ...controllerProps }) => (
-
- {enableDragAndDrop ? (
-
+ }, [children]);
+
+ const classes = useStyles();
+
+ const Container = enableDragAndDrop
+ ? DragDropContext(
+ TouchBackend({
+ enableKeyboardEvents: true,
+ enableMouseEvents: true,
+ enableTouchEvents: true,
+ })
+ )('div')
+ : Fragment;
+
+ const TreeNode = enableDragAndDrop
+ ? droppable(treeNodeComponent)
+ : treeNodeComponent;
+
+ const TreeNodeContent = enableDragAndDrop
+ ? draggable(treeNodeContentComponent)
+ : treeNodeContentComponent;
+
+ return (
+
+ {({ getTreeState, tree, ...controllerProps }) => (
+
+ {enableDragAndDrop ? (
+
+ ) : null}
+
+ {enableDragAndDrop && allowDropOnRoot ? (
+
) : null}
-
- {enableDragAndDrop && allowDropOnRoot ? (
-
- ) : null}
- {tree.map(node => (
-
- {children}
-
- ))}
-
-
- )}
-
- );
- }
-}
+ {tree.map(node => (
+
+ {children}
+
+ ))}
+
+
+ )}
+
+ );
+};
Tree.propTypes = {
allowDropOnRoot: PropTypes.bool,
basePath: PropTypes.string.isRequired,
children: PropTypes.node,
- classes: PropTypes.object,
enableDragAndDrop: PropTypes.bool,
getTreeFromArray: PropTypes.func,
parentSource: PropTypes.string,
@@ -211,7 +208,6 @@ Tree.propTypes = {
};
Tree.defaultProps = {
- classes: {},
parentSource: 'parent_id',
dragPreviewComponent: DefaultDragPreview,
treeNodeComponent: DefaultTreeNode,
@@ -219,4 +215,4 @@ Tree.defaultProps = {
treeNodeWithChildrenComponent: DefaultTreeNodeWithChildren,
};
-export default withStyles(styles)(Tree);
+export default Tree;
diff --git a/packages/ra-tree-ui-materialui/src/TreeNode.js b/packages/ra-tree-ui-materialui/src/TreeNode.js
index 3abba8d2e72..55840c2c685 100644
--- a/packages/ra-tree-ui-materialui/src/TreeNode.js
+++ b/packages/ra-tree-ui-materialui/src/TreeNode.js
@@ -1,10 +1,10 @@
-import React, { Fragment, Component } from 'react';
+import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import ListItem from '@material-ui/core/ListItem';
-import { withStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@material-ui/core/styles';
-const styles = theme => ({
+const useStyles = makeStyles(theme => ({
expandIcon: {
margin: 0,
left: -theme.spacing(6),
@@ -71,132 +71,126 @@ const styles = theme => ({
draggingOver: {
background: theme.palette.action.hover,
},
-});
+}));
-class TreeNode extends Component {
- static propTypes = {
- basePath: PropTypes.string.isRequired,
- canDrop: PropTypes.bool,
- children: PropTypes.node,
- classes: PropTypes.object,
- closeNode: PropTypes.func,
- connectDropTarget: PropTypes.func,
- expandNode: PropTypes.func,
- getIsNodeExpanded: PropTypes.func,
- isOver: PropTypes.bool,
- isOverCurrent: PropTypes.bool,
- itemType: PropTypes.string,
- node: PropTypes.object.isRequired,
- resource: PropTypes.string.isRequired,
- toggleNode: PropTypes.func,
- treeNodeComponent: PropTypes.oneOfType([
- PropTypes.element,
- PropTypes.func,
- ]),
- treeNodeContentComponent: PropTypes.oneOfType([
- PropTypes.element,
- PropTypes.func,
- ]).isRequired,
- treeNodeWithChildrenComponent: PropTypes.oneOfType([
- PropTypes.element,
- PropTypes.func,
- ]),
- };
-
- static defaultProps = {
- connectDropTarget: target => target,
- };
+const TreeNode = ({
+ basePath,
+ canDrop,
+ children,
+ closeNode,
+ connectDropTarget,
+ expandNode,
+ getIsNodeExpanded,
+ isOver,
+ isOverCurrent,
+ itemType,
+ node,
+ resource,
+ treeNodeComponent,
+ treeNodeWithChildrenComponent: TreeNodeWithChildren,
+ treeNodeContentComponent: TreeNodeContent,
+ toggleNode,
+ ...props
+}) => {
+ const classes = useStyles();
- handleDrop = event => {
+ const handleDrop = event => {
if (this.props.isOver && this.props.canDrop) {
event.persit();
event.preventDefault();
}
};
- render() {
- const {
- basePath,
- canDrop,
- children,
- classes,
- closeNode,
- connectDropTarget,
- expandNode,
- getIsNodeExpanded,
- isOver,
- isOverCurrent,
- itemType,
- node,
- resource,
- treeNodeComponent,
- treeNodeWithChildrenComponent: TreeNodeWithChildren,
- treeNodeContentComponent: TreeNodeContent,
- toggleNode,
- ...props
- } = this.props;
- return connectDropTarget(
-
- 0,
- [classes.leaf]: node.children.length === 0,
- [classes.draggingOver]: isOverCurrent,
- }),
- }}
- dense
- disableGutters
- >
- {node.children.length > 0 ? (
-
+ 0,
+ [classes.leaf]: node.children.length === 0,
+ [classes.draggingOver]: isOverCurrent,
+ }),
+ }}
+ dense
+ disableGutters
+ >
+ {node.children.length > 0 ? (
+
+ {children}
+
+ ) : (
+
+
{children}
-
- ) : (
-
-
- {children}
-
-
- )}
-
-
- );
- }
-}
+
+
+ )}
+
+
+ );
+};
+
+TreeNode.propTypes = {
+ basePath: PropTypes.string.isRequired,
+ canDrop: PropTypes.bool,
+ children: PropTypes.node,
+ closeNode: PropTypes.func,
+ connectDropTarget: PropTypes.func,
+ expandNode: PropTypes.func,
+ getIsNodeExpanded: PropTypes.func,
+ isOver: PropTypes.bool,
+ isOverCurrent: PropTypes.bool,
+ itemType: PropTypes.string,
+ node: PropTypes.object.isRequired,
+ resource: PropTypes.string.isRequired,
+ toggleNode: PropTypes.func,
+ treeNodeComponent: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
+ treeNodeContentComponent: PropTypes.oneOfType([
+ PropTypes.element,
+ PropTypes.func,
+ ]).isRequired,
+ treeNodeWithChildrenComponent: PropTypes.oneOfType([
+ PropTypes.element,
+ PropTypes.func,
+ ]),
+};
+
+TreeNode.defaultProps = {
+ connectDropTarget: target => target,
+};
-export default withStyles(styles)(TreeNode);
+export default TreeNode;
diff --git a/packages/ra-tree-ui-materialui/src/TreeNodeContent.js b/packages/ra-tree-ui-materialui/src/TreeNodeContent.js
index 20598e4e33e..50ff4d6e604 100644
--- a/packages/ra-tree-ui-materialui/src/TreeNodeContent.js
+++ b/packages/ra-tree-ui-materialui/src/TreeNodeContent.js
@@ -1,62 +1,57 @@
-import React, { cloneElement, Children, Component, Fragment } from 'react';
+import React, { cloneElement, Children, Fragment } from 'react';
import PropTypes from 'prop-types';
import IconDragHandle from '@material-ui/icons/DragHandle';
-class TreeNodeContent extends Component {
- static propTypes = {
- basePath: PropTypes.string.isRequired,
- cancelDropOnChildren: PropTypes.bool,
- connectDragPreview: PropTypes.func,
- connectDragSource: PropTypes.func,
- containerElement: PropTypes.oneOfType([
- PropTypes.element,
- PropTypes.func,
- PropTypes.string,
- ]),
- children: PropTypes.node,
- classes: PropTypes.object.isRequired,
- expandNode: PropTypes.func,
- isLeaf: PropTypes.bool,
- node: PropTypes.object.isRequired,
- resource: PropTypes.string.isRequired,
- submit: PropTypes.func,
- };
+const TreeNodeContent = ({
+ children,
+ classes,
+ connectDragPreview,
+ connectDragSource,
+ containerElement: Container,
+ expandNode,
+ submit,
+ isLeaf,
+ node,
+ ...props
+}) => (
+