lucid-ui
Version:
A UI component library from Xandr.
204 lines • 8.16 kB
JavaScript
import _, { omit } from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import { lucidClassNames } from '../../util/style-helpers';
import { filterTypes, findTypes, } from '../../util/component-types';
import { buildModernHybridComponent } from '../../util/state-management';
import * as reducers from './Submarine.reducers';
import SplitHorizontal from '../SplitHorizontal/SplitHorizontal';
import ChevronIcon from '../Icon/ChevronIcon/ChevronIcon';
import GripperHorizontalIcon from '../Icon/GripperHorizontalIcon/GripperHorizontalIcon';
import Button from '../Button/Button';
const cx = lucidClassNames.bind('&-Submarine');
const { any, bool, func, node, number, string, oneOf, oneOfType } = PropTypes;
const Primary = (_props) => null;
Primary.peek = {
description: `Primary content rendered beside the Submarine.`,
};
Primary.displayName = 'SplitHorizontal.Primary';
Primary.propName = 'Primary';
const Title = (_props) => null;
Title.peek = {
description: `Submarine title.`,
};
Title.displayName = 'Submarine.Title';
Title.propName = 'Title';
const Bar = (_props) => null;
Bar.peek = {
description: `Submarine bar.`,
};
Bar.displayName = 'Submarine.Bar';
Bar.propName = 'Bar';
Bar.propTypes = {
/**
Set the title of the Submarine. (alias for \`Submarine.Title\`)
*/
Title: any,
};
/** Submarine */
const defaultProps = {
isExpanded: true,
isAnimated: true,
height: 250,
position: 'bottom',
isResizeDisabled: false,
isHidden: false,
isTitleShownCollapsed: false,
onResizing: _.noop,
onResize: _.noop,
onToggle: _.noop,
};
class Submarine extends React.Component {
constructor() {
super(...arguments);
this.handleExpanderClick = ({ event, }) => {
const { onToggle } = this.props;
onToggle({ props: this.props, event });
};
this.handleResizing = (height, { event }) => {
const { onResizing } = this.props;
onResizing(height, { props: this.props, event });
};
this.handleResize = (height, { event }) => {
const { onResize } = this.props;
onResize(height, { props: this.props, event });
};
}
render() {
const { children, className, isExpanded, isAnimated, position, isResizeDisabled, height, isHidden, isTitleShownCollapsed, ...passThroughs } = this.props;
const primaryProps = _.get(_.first(filterTypes(children, Submarine.Primary)), 'props', {}); // props from first Primary
const barProps = _.get(_.first(filterTypes(children, Submarine.Bar)), 'props', {}); // props from first Bar
const titleProps = _.get(findTypes(barProps, Submarine.Title).concat(findTypes(this.props, Submarine.Title)), // get titles from Bar and parent Submarine
'[0].props', // select props from the first title element
React.createElement(Submarine.Title).props // default props
);
let PrimaryPane, BarPane; // using Left/Right Pane as primary depends on position
if (position !== 'bottom') {
PrimaryPane = SplitHorizontal.BottomPane;
BarPane = SplitHorizontal.TopPane;
}
else {
PrimaryPane = SplitHorizontal.TopPane;
BarPane = SplitHorizontal.BottomPane;
}
// leave 33px of sidebar to stick out when collapsed, or 0px if hidden
const collapseShift = isHidden ? 0 : 33;
return (React.createElement(SplitHorizontal, { ...omit(passThroughs, [
'className',
'children',
'height',
'isExpanded',
'isHidden',
'isTitleShownCollapsed',
'isAnimated',
'position',
'isResizeDisabled',
'Title',
'Bar',
'Primary',
'onResizing',
'onResize',
'onToggle',
].concat('initialState')), className: cx('&', {
'&-is-resize-disabled': isResizeDisabled,
'&-is-position-bottom': position === 'bottom',
'&-is-position-top': position !== 'bottom',
}, className), isAnimated: isAnimated, isExpanded: isExpanded && !isHidden, collapseShift: collapseShift, onResizing: this.handleResizing, onResize: this.handleResize },
React.createElement(BarPane, { ...omit(barProps, ['Title'].concat('initialState')), className: cx('&-Bar', barProps.className), height: height },
React.createElement("div", { className: cx('&-Bar-overlay') }),
React.createElement("div", { className: cx('&-Bar-header') },
React.createElement("div", { ...titleProps, className: cx('&-Bar-Title', { '&-Bar-Title-is-shown-collapsed': isTitleShownCollapsed }, titleProps.className) }),
React.createElement(Button, { className: cx('&-expander'), kind: 'invisible', onClick: this.handleExpanderClick, hasOnlyIcon: true },
React.createElement(ChevronIcon, { direction: (isExpanded && position === 'bottom') ||
(!isExpanded && position !== 'bottom')
? 'down'
: 'up' }))),
React.createElement("div", { className: cx('&-Bar-content') }, barProps.children)),
React.createElement(SplitHorizontal.Divider, { className: cx('&-Divider') },
React.createElement(GripperHorizontalIcon, { className: cx('&-Divider-gripper') })),
React.createElement(PrimaryPane, { ...primaryProps, className: cx('&-Primary', primaryProps.className), isPrimary: true })));
}
}
Submarine.displayName = 'Submarine';
Submarine.Bar = Bar;
Submarine.Title = Title;
Submarine.Primary = Primary;
Submarine.peek = {
description: `\`Submarine\` renders a collapsible, resizeable side bar panel next to primary content.`,
categories: ['layout'],
madeFrom: ['SplitHorizontal', 'ChevronIcon', 'GripperHorizontalIcon'],
};
Submarine.reducers = reducers;
Submarine.propTypes = {
/**
Appended to the component-specific class names set on the root element.
Value is run through the \`classnames\` library.
*/
className: string,
/**
Direct children must be types {Submarine.Primary, Submarine.Bar,
Submarine.Title}. All content is composed as children of these
respective elements.
*/
children: node,
/**
Sets the starting height of the Bar.
*/
height: oneOfType([number, string]),
/**
Force the Submarine to be expanded or collapsed.
*/
isExpanded: bool,
/**
Indicates if the Submarine should be shown or not. This will override
the value of isExpanded.
*/
isHidden: bool,
/**
Indicates if the Title should be shown when the Submarine is collapsed
*/
isTitleShownCollapsed: bool,
/**
Allows animated expand and collapse behavior.
*/
isAnimated: bool,
/**
Render the Submarine to the top or bottom of primary content.
*/
position: oneOf(['top', 'bottom']),
/**
Disable user resizing of the Submarine.
*/
isResizeDisabled: bool,
/**
Set the title of the Submarine.
*/
Title: any,
/**
Set the Submarine Bar content.
*/
Bar: any,
/**
Set the primary content of the Submarine.
*/
Primary: any,
/**
Called when the user is currently resizing the Submarine. Signature:
\`(height, { event, props }) => {}\`
*/
onResizing: func,
/**
Called when the user resizes the Submarine. Signature:
\`(height, { event, props }) => {}\`
*/
onResize: func,
/**
Called when the user expands or collapses the Submarine. Signature:
\`({ event, props }) => {}\`
*/
onToggle: func,
};
Submarine.defaultProps = defaultProps;
export default buildModernHybridComponent(Submarine, { reducers });
export { Submarine as SubmarineDumb };
//# sourceMappingURL=Submarine.js.map