// matchMedia polyfill for // https://github.com/WickyNilliams/enquire.js/issues/82 if (typeof window !== 'undefined') { const matchMediaPolyfill = (mediaQuery: string): MediaQueryList => { return { media: mediaQuery, matches: false, addListener() { }, removeListener() { }, }; }; window.matchMedia = window.matchMedia || matchMediaPolyfill; } import React from 'react'; import classNames from 'classnames'; import omit from 'omit.js'; import PropTypes from 'prop-types'; import Icon from '../icon'; const dimensionMap = { xs: '480px', sm: '768px', md: '992px', lg: '1200px', xl: '1600px', }; export interface SiderProps { style?: React.CSSProperties; prefixCls?: string; className?: string; collapsible?: boolean; collapsed?: boolean; defaultCollapsed?: boolean; reverseArrow?: boolean; onCollapse?: (collapsed: boolean, type: 'clickTrigger' | 'responsive') => void; trigger?: React.ReactNode; width?: number | string; collapsedWidth?: number | string; breakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'; } export default class Sider extends React.Component { static __ANT_LAYOUT_SIDER: any = true; static defaultProps = { prefixCls: 'ant-layout-sider', collapsible: false, defaultCollapsed: false, reverseArrow: false, width: 200, collapsedWidth: 64, style: {}, }; static childContextTypes = { siderCollapsed: PropTypes.bool, }; private mql: any; constructor(props) { super(props); let matchMedia; if (typeof window !== 'undefined') { matchMedia = window.matchMedia; } if (matchMedia && props.breakpoint && props.breakpoint in dimensionMap) { this.mql = matchMedia(`(max-width: ${dimensionMap[props.breakpoint]})`); } let collapsed; if ('collapsed' in props) { collapsed = props.collapsed; } else { collapsed = props.defaultCollapsed; } this.state = { collapsed, below: false, }; } getChildContext() { return { siderCollapsed: this.props.collapsed, }; } componentWillReceiveProps(nextProps) { if ('collapsed' in nextProps) { this.setState({ collapsed: nextProps.collapsed, }); } } componentDidMount() { if (this.mql) { this.mql.addListener(this.responsiveHandler); this.responsiveHandler(this.mql); } } componentWillUnmount() { if (this.mql) { this.mql.removeListener(this.responsiveHandler); } } responsiveHandler = (mql) => { this.setState({ below: mql.matches }); if (this.state.collapsed !== mql.matches) { this.setCollapsed(mql.matches, 'responsive'); } } setCollapsed = (collapsed, type) => { if (!('collapsed' in this.props)) { this.setState({ collapsed, }); } const { onCollapse } = this.props; if (onCollapse) { onCollapse(collapsed, type); } } toggle = () => { const collapsed = !this.state.collapsed; this.setCollapsed(collapsed, 'clickTrigger'); } belowShowChange = () => { this.setState({ belowShow: !this.state.belowShow }); } render() { const { prefixCls, className, collapsible, reverseArrow, trigger, style, width, collapsedWidth, ...others, } = this.props; const divProps = omit(others, ['collapsed', 'defaultCollapsed', 'onCollapse', 'breakpoint']); const siderWidth = this.state.collapsed ? collapsedWidth : width; // special trigger when collapsedWidth == 0 const zeroWidthTrigger = collapsedWidth === 0 || collapsedWidth === '0' ? ( ) : null; const iconObj = { 'expanded': reverseArrow ? : , 'collapsed': reverseArrow ? : , }; const status = this.state.collapsed ? 'collapsed' : 'expanded'; const defaultTrigger = iconObj[status]; const triggerDom = ( trigger !== null ? zeroWidthTrigger || (
{trigger || defaultTrigger}
) : null ); const divStyle = { ...style, flex: `0 0 ${siderWidth}px`, width: `${siderWidth}px`, }; const siderCls = classNames(className, prefixCls, { [`${prefixCls}-collapsed`]: !!this.state.collapsed, [`${prefixCls}-has-trigger`]: !!trigger, [`${prefixCls}-below`]: !!this.state.below, [`${prefixCls}-zero-width`]: siderWidth === 0 || siderWidth === '0', }); return (
{this.props.children}
{collapsible || (this.state.below && zeroWidthTrigger) ? triggerDom : null}
); } }