@salesforce/design-system-react
Version:
Salesforce Lightning Design System for React
178 lines (158 loc) • 4.39 kB
JSX
/* Copyright (c) 2015-present, salesforce.com, inc. All rights reserved */
/* Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import ToggleButton, { TOGGLE_BUTTON_WIDTH } from './private/toggle-button';
import { SPLIT_VIEW } from '../../utilities/constants';
import generateId from '../../utilities/generate-id';
const propTypes = {
/**
* **Assistive text for accessibility**
* * `toggleButtonOpen`: The button used to open the split view.
* * `toggleButtonClose`: The button used to close the split view.
*/
assistiveText: PropTypes.shape({
toggleButtonOpen: PropTypes.string,
toggleButtonClose: PropTypes.string,
}),
/**
* HTML Id for the component.
*/
id: PropTypes.string,
/**
* CSS classes to be added to the root `div` tag. Uses `classNames` [API](https://github.com/JedWatson/classnames).
*/
className: PropTypes.oneOfType([
PropTypes.array,
PropTypes.object,
PropTypes.string,
]),
/**
* Sets the split view to be open or closed.
*/
isOpen: PropTypes.bool,
/**
* Event Callbacks
* * `onClose`: Triggered when the split view has closed.
* * `onOpen`: Triggered when the split view has opened.
*/
events: PropTypes.shape({
onClose: PropTypes.func,
onOpen: PropTypes.func,
}),
/**
* The React component that is rendered in the master section.
* You need to pass in an array of elements in order for the scrolling to in the SplitViewList to work correctly.
* React requires that you also supply a unique `key` for each element [React Lists and Keys](https://reactjs.org/docs/lists-and-keys.html#keys).
*/
master: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.element),
PropTypes.element,
]).isRequired,
/**
* The width of the master section.
*/
masterWidth: PropTypes.string,
/**
* The React component that is rendered in the detail section.
*/
detail: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.element),
PropTypes.element,
]).isRequired,
};
const defaultProps = {
assistiveText: {
toggleButtonOpen: 'Close split view',
toggleButtonClose: 'Open split view',
},
events: {},
masterWidth: '20rem',
};
/**
* Split view is used to navigate between records in a list while staying on the same screen.
*/
class SplitView extends React.Component {
static displayName = SPLIT_VIEW;
static propTypes = propTypes;
static defaultProps = defaultProps;
constructor(props) {
super(props);
this.state = {
isOpen: typeof props.isOpen === 'boolean' ? props.isOpen : true,
};
this.generatedId = generateId();
}
getId() {
return this.props.id || this.generatedId;
}
getIsOpen() {
return typeof this.props.isOpen === 'boolean'
? this.props.isOpen
: this.state.isOpen;
}
getMasterViewId() {
return `master_view_${this.getId()}`;
}
toggle(event) {
if (typeof this.props.isOpen !== 'boolean') {
this.setState((prevState) => ({
isOpen: !prevState.isOpen,
}));
}
const isOpen = this.getIsOpen();
if (isOpen && this.props.events.onClose) {
this.props.events.onClose(event);
} else if (!isOpen && this.props.events.onOpen) {
this.props.events.onOpen(event);
}
}
render() {
return (
<div
id={this.getId()}
className={classNames('slds-grid', this.props.className)}
style={{
height: '100%',
}}
>
<div
style={{
maxWidth: this.getIsOpen() ? this.props.masterWidth : '0',
minWidth: this.getIsOpen() ? this.props.masterWidth : '0',
}}
className={classNames(
'slds-split-view_container',
{ 'slds-is-open': this.getIsOpen() },
{ 'slds-is-closed': !this.getIsOpen() }
)}
>
<ToggleButton
assistiveText={this.props.assistiveText}
ariaControls={this.getMasterViewId()}
isOpen={this.getIsOpen()}
events={{
onClick: (event) => this.toggle(event),
}}
/>
<article
id={this.getMasterViewId()}
className="slds-split-view slds-grid slds-grid_vertical slds-grow slds-scrollable_none"
>
{this.getIsOpen() ? this.props.master : null}
</article>
</div>
<div
style={{
marginLeft: TOGGLE_BUTTON_WIDTH,
}}
className="slds-grow slds-scrollable_y"
>
{this.props.detail}
</div>
</div>
);
}
}
export default SplitView;