@salesforce/design-system-react
Version:
Salesforce Lightning Design System for React
482 lines (468 loc) • 8.84 kB
JSX
import React from 'react';
import createReactClass from 'create-react-class';
import IconSettings from '~/components/icon-settings';
import PropTypes from 'prop-types';
import Tree from '~/components/tree';
const sampleNodes = {
sampleNodesWithInitialState: [
{
label: 'Grains',
type: 'item',
id: 1,
selected: true
},
{
label: 'Fruits',
type: 'branch',
id: 2,
expanded: true,
nodes: [
{
label: 'Ground Fruits',
type: 'branch',
id: 4,
nodes: [
{
label: 'Watermelon',
type: 'item',
id: 12
},
{
label: 'Canteloupe',
type: 'item',
_iconClass: 'glyphicon-file',
id: 13
},
{
label: 'Strawberries',
type: 'item',
id: 14
}
]
},
{
label: 'Tree Fruits',
type: 'branch',
id: 5,
selected: true,
nodes: [
{
label: 'Peaches',
type: 'item',
id: 15
},
{
label: 'Pears',
type: 'item',
_iconClass: 'glyphicon-file',
id: 16
},
{
label: 'Citrus',
type: 'branch',
id: 17,
nodes: [
{
label: 'Orange',
type: 'item',
id: 20
},
{
label: 'Grapefruit',
type: 'item',
id: 21
},
{
label: 'Lemon',
type: 'item',
id: 22
},
{
label: 'Lime',
type: 'item',
id: 23
}
]
},
{
label: 'Apples',
type: 'branch',
id: 18,
nodes: [
{
label: 'Granny Smith',
type: 'item',
id: 24
},
{
label: 'Pinklady',
type: 'item',
_iconClass: 'glyphicon-file',
id: 25
},
{
label: 'Rotten',
type: 'item',
id: 26
},
{
label: 'Jonathan',
type: 'item',
id: 27
}
]
},
{
label: 'Cherries',
type: 'branch',
id: 19,
nodes: [
{
label: 'Balaton',
type: 'item',
id: 28
},
{
label: 'Erdi Botermo',
type: 'item',
id: 29
},
{
label: 'Montmorency',
type: 'item',
id: 30
},
{
label: 'Queen Ann',
type: 'item',
id: 31
},
{
label: 'Ulster',
type: 'item',
id: 32
},
{
label: 'Viva',
type: 'item',
id: 33
}
]
},
{
label: 'Raspberries',
type: 'item',
id: 6
}
]
}
]
},
{
label: 'Nuts',
type: 'branch',
_iconClass: 'glyphicon-file',
id: 3,
nodes: [
{
label: 'Almonds',
type: 'item',
id: 8
},
{
label: 'Cashews',
type: 'item',
id: 9
},
{
label: 'Pecans',
type: 'item',
id: 10
},
{
label: 'Walnuts',
type: 'item',
id: 11
}
]
},
{
label: 'Empty folder',
type: 'branch',
id: 7,
expanded: true
}
],
sampleNodesDefault: [
{
label: 'Grains',
type: 'item',
id: 1
},
{
label: 'Fruits',
type: 'branch',
id: 2,
nodes: [
{
label: 'Ground Fruits',
type: 'branch',
id: 4,
nodes: [
{
label: 'Watermelon',
type: 'item',
id: 12
},
{
label: 'Canteloupe',
type: 'item',
_iconClass: 'glyphicon-file',
id: 13
},
{
label: 'Strawberries',
type: 'item',
id: 14
}
]
},
{
label: 'Tree Fruits',
type: 'branch',
id: 5,
nodes: [
{
label: 'Peaches',
type: 'item',
id: 15
},
{
label: 'Pears',
type: 'item',
_iconClass: 'glyphicon-file',
id: 16
},
{
label: 'Citrus',
type: 'branch',
id: 17,
nodes: [
{
label: 'Orange',
type: 'item',
id: 20
},
{
label: 'Grapefruit',
type: 'item',
id: 21
},
{
label: 'Lemon',
type: 'item',
id: 22
},
{
label: 'Lime',
type: 'item',
id: 23
}
]
},
{
label: 'Apples',
type: 'branch',
id: 18,
nodes: [
{
label: 'Granny Smith',
type: 'item',
id: 24
},
{
label: 'Pinklady',
type: 'item',
_iconClass: 'glyphicon-file',
id: 25
},
{
label: 'Rotten',
type: 'item',
id: 26
},
{
label: 'Jonathan',
type: 'item',
id: 27
}
]
},
{
label: 'Cherries',
type: 'branch',
id: 19,
nodes: [
{
label: 'Balaton',
type: 'item',
id: 28
},
{
label: 'Erdi Botermo',
type: 'item',
id: 29
},
{
label: 'Montmorency',
type: 'item',
id: 30
},
{
label: 'Queen Ann',
type: 'item',
id: 31
},
{
label: 'Ulster',
type: 'item',
id: 32
},
{
label: 'Viva',
type: 'item',
id: 33
}
]
},
{
label: 'Raspberries',
type: 'item',
id: 6
}
]
}
]
},
{
label: 'Nuts',
type: 'branch',
_iconClass: 'glyphicon-file',
id: 3,
nodes: [
{
label: 'Almonds',
type: 'item',
id: 8
},
{
label: 'Cashews',
type: 'item',
id: 9
},
{
label: 'Pecans',
type: 'item',
id: 10
},
{
label: 'Walnuts',
type: 'item',
id: 11
}
]
},
{
label: 'Empty folder',
type: 'branch',
id: 7
}
]
};
const Example = createReactClass({
displayName: 'TreeExample',
// ### Prop Types
propTypes: {
exampleNodesIndex: PropTypes.string,
noBranchSelection: PropTypes.bool,
searchTerm: PropTypes.string,
searchable: PropTypes.bool,
singleSelection: PropTypes.bool
},
getDefaultProps () {
return {
exampleNodesIndex: 'sampleNodesDefault',
id: 'example-tree'
};
},
getInitialState () {
const initalNodes = this.props.exampleNodesIndex
? sampleNodes[this.props.exampleNodesIndex]
: sampleNodes.sampleNodesDefault;
return {
nodes: initalNodes,
searchTerm: this.props.searchable ? 'fruit' : undefined
};
},
// By default Tree can have multiple selected nodes and folders/branches can be selected. To disable either of these, you can use the following logic. However, `props` are immutable. The node passed in shouldn't be modified, and due to object and arrays being reference variables, forceUpate is needed. This is just a "working example" not a prescription.
handleExpandClick (event, data) {
console.log('[handleExpandClick] (event, data)', event, data);
data.node.loading = data.expand ? true : undefined;
// Fake delay to demonstrate use of loading node attibute
setTimeout(
(node) => {
node.loading = false;
this.forceUpdate();
},
500,
data.node
);
data.node.expanded = data.expand;
},
handleClick (event, data) {
if (this.props.singleSelection) {
data.node.selected = data.select;
this.setState((prevState) => {
if (
this.state.selectedNode &&
this.state.selectedNode.id !== data.node.id
) {
this.state.selectedNode.selected = false;
}
return { selectedNode: data.node };
});
console.log('[handleClick] (event, data)', event, data);
} else if (
!this.props.noBranchSelection ||
(this.props.noBranchSelection && data.node.type !== 'branch')
) {
data.node.selected = data.select;
// trigger render
this.setState((prevState) => ({ ...prevState }));
console.log('[handleClick] (event, data)', event, data);
}
},
handleScroll (event, data) {
console.log('[handleScroll] (event, data)', event, data);
},
handleSearchChange (event) {
this.setState({ searchTerm: event.target.value });
},
render () {
return (
<IconSettings iconPath="/assets/icons">
<div>
<Tree
heading="Miscellaneous Foods"
nodes={this.state.nodes}
onExpandClick={this.handleExpandClick}
onClick={this.handleClick}
onScroll={this.handleScroll}
searchTerm={this.state.searchTerm}
/>
</div>
</IconSettings>
);
}
});
export default Example; // export is replaced with `ReactDOM.render(<Example />, mountNode);` at runtime