UNPKG

@salesforce/design-system-react

Version:

Salesforce Lightning Design System for React

188 lines (168 loc) 4.44 kB
/* 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 shortid from 'shortid'; import classNames from 'classnames'; import isBoolean from 'lodash.isboolean'; import ToggleButton, { TOGGLE_BUTTON_WIDTH } from './private/toggle-button'; import { SPLIT_VIEW } from '../../utilities/constants'; 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: true, }; } componentWillMount() { this.generatedId = shortid.generate(); this.setIsOpen(this.props.isOpen); } componentWillReceiveProps(nextProps) { if (nextProps.isOpen !== this.props.isOpen) { this.setIsOpen(nextProps.isOpen); } } getId() { return this.props.id || this.generatedId; } getMasterViewId() { return `master_view_${this.getId()}`; } setIsOpen(isOpen) { if (isBoolean(isOpen)) { this.setState({ isOpen, }); } } toggle(event) { this.setIsOpen(!this.state.isOpen); if (this.state.isOpen && this.props.events.onClose) { this.props.events.onClose(event); } else if (!this.state.isOpen && this.props.events.onOpen) { this.props.events.onOpen(event); } } masterContent() { return this.state.isOpen ? ( <article id={this.getMasterViewId()} className="slds-split-view slds-grid slds-grid_vertical slds-grow slds-scrollable_none" > {this.props.master} </article> ) : null; } render() { return ( <div id={this.getId()} className={classNames('slds-grid', this.props.className)} style={{ height: '100%', }} > <div style={{ maxWidth: this.state.isOpen ? this.props.masterWidth : '0', }} className={classNames( 'slds-split-view_container', { 'slds-is-open': this.state.isOpen }, { 'slds-is-closed': !this.state.isOpen } )} > <ToggleButton assistiveText={this.props.assistiveText} ariaControls={this.getMasterViewId()} isOpen={this.state.isOpen} events={{ onClick: (event) => this.toggle(event), }} /> {this.masterContent()} </div> <div style={{ marginLeft: TOGGLE_BUTTON_WIDTH, }} className="slds-grow slds-scrollable_y" > {this.props.detail} </div> </div> ); } } export default SplitView;