|
| 1 | +// matchMedia polyfill for |
| 2 | +// https://github.com/WickyNilliams/enquire.js/issues/82 |
| 3 | +if (typeof window !== 'undefined') { |
| 4 | + const matchMediaPolyfill = (mediaQuery) => { |
| 5 | + return { |
| 6 | + media: mediaQuery, |
| 7 | + matches: false, |
| 8 | + addListener () { |
| 9 | + }, |
| 10 | + removeListener () { |
| 11 | + }, |
| 12 | + } |
| 13 | + } |
| 14 | + window.matchMedia = window.matchMedia || matchMediaPolyfill |
| 15 | +} |
| 16 | + |
| 17 | +import classNames from 'classnames' |
| 18 | +import PropTypes from '../_util/vue-types' |
| 19 | +import Icon from '../icon' |
| 20 | +import { initDefaultProps, getOptionProps, hasProp, getComponentFromProp } from '../_util/props-util' |
| 21 | +import BaseMixin from '../_util/BaseMixin' |
| 22 | + |
| 23 | +const dimensionMap = { |
| 24 | + xs: '480px', |
| 25 | + sm: '576px', |
| 26 | + md: '768px', |
| 27 | + lg: '992px', |
| 28 | + xl: '1200px', |
| 29 | + xxl: '1600px', |
| 30 | +} |
| 31 | + |
| 32 | +// export type CollapseType = 'clickTrigger' | 'responsive'; |
| 33 | + |
| 34 | +export const SiderProps = { |
| 35 | + prefixCls: PropTypes.string, |
| 36 | + collapsible: PropTypes.bool, |
| 37 | + collapsed: PropTypes.bool, |
| 38 | + defaultCollapsed: PropTypes.bool, |
| 39 | + reverseArrow: PropTypes.bool, |
| 40 | + // onCollapse?: (collapsed: boolean, type: CollapseType) => void; |
| 41 | + trigger: PropTypes.any, |
| 42 | + width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), |
| 43 | + collapsedWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), |
| 44 | + breakpoint: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl', 'xxl']), |
| 45 | +} |
| 46 | + |
| 47 | +// export interface SiderState { |
| 48 | +// collapsed?: boolean; |
| 49 | +// below: boolean; |
| 50 | +// belowShow?: boolean; |
| 51 | +// } |
| 52 | + |
| 53 | +// export interface SiderContext { |
| 54 | +// siderCollapsed: boolean; |
| 55 | +// } |
| 56 | + |
| 57 | +const generateId = (() => { |
| 58 | + let i = 0 |
| 59 | + return (prefix = '') => { |
| 60 | + i += 1 |
| 61 | + return `${prefix}${i}` |
| 62 | + } |
| 63 | +})() |
| 64 | + |
| 65 | +export default { |
| 66 | + name: 'ALayoutSider', |
| 67 | + __ANT_LAYOUT_SIDER: true, |
| 68 | + mixins: [BaseMixin], |
| 69 | + props: initDefaultProps(SiderProps, { |
| 70 | + prefixCls: 'ant-layout-sider', |
| 71 | + collapsible: false, |
| 72 | + defaultCollapsed: false, |
| 73 | + reverseArrow: false, |
| 74 | + width: 200, |
| 75 | + collapsedWidth: 80, |
| 76 | + }), |
| 77 | + |
| 78 | + // static childContextTypes = { |
| 79 | + // siderCollapsed: PropTypes.bool, |
| 80 | + // collapsedWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), |
| 81 | + // }; |
| 82 | + |
| 83 | + // static contextTypes = { |
| 84 | + // siderHook: PropTypes.object, |
| 85 | + // }; |
| 86 | + |
| 87 | + // private mql: MediaQueryList; |
| 88 | + // private uniqueId: string; |
| 89 | + |
| 90 | + data () { |
| 91 | + this.uniqueId = generateId('ant-sider-') |
| 92 | + let matchMedia |
| 93 | + if (typeof window !== 'undefined') { |
| 94 | + matchMedia = window.matchMedia |
| 95 | + } |
| 96 | + const props = getOptionProps(this) |
| 97 | + if (matchMedia && props.breakpoint && props.breakpoint in dimensionMap) { |
| 98 | + this.mql = matchMedia(`(max-width: ${dimensionMap[props.breakpoint]})`) |
| 99 | + } |
| 100 | + let sCollapsed |
| 101 | + if ('collapsed' in props) { |
| 102 | + sCollapsed = props.collapsed |
| 103 | + } else { |
| 104 | + sCollapsed = props.defaultCollapsed |
| 105 | + } |
| 106 | + return { |
| 107 | + sCollapsed, |
| 108 | + below: false, |
| 109 | + belowShow: false, |
| 110 | + } |
| 111 | + }, |
| 112 | + provide () { |
| 113 | + return { |
| 114 | + layoutSiderContext: this, // menu组件中使用 |
| 115 | + } |
| 116 | + }, |
| 117 | + inject: { |
| 118 | + siderHook: { default: {}}, |
| 119 | + }, |
| 120 | + // getChildContext() { |
| 121 | + // return { |
| 122 | + // siderCollapsed: this.state.collapsed, |
| 123 | + // collapsedWidth: this.props.collapsedWidth, |
| 124 | + // }; |
| 125 | + // } |
| 126 | + watch: { |
| 127 | + collapsed (val) { |
| 128 | + this.setState({ |
| 129 | + sCollapsed: val, |
| 130 | + }) |
| 131 | + }, |
| 132 | + }, |
| 133 | + |
| 134 | + mounted () { |
| 135 | + this.$nextTick(() => { |
| 136 | + if (this.mql) { |
| 137 | + this.mql.addListener(this.responsiveHandler) |
| 138 | + this.responsiveHandler(this.mql) |
| 139 | + } |
| 140 | + |
| 141 | + if (this.siderHook.addSider) { |
| 142 | + this.siderHook.addSider(this.uniqueId) |
| 143 | + } |
| 144 | + }) |
| 145 | + }, |
| 146 | + |
| 147 | + beforeDestroy () { |
| 148 | + if (this.mql) { |
| 149 | + this.mql.removeListener(this.responsiveHandler) |
| 150 | + } |
| 151 | + |
| 152 | + if (this.siderHook.removeSider) { |
| 153 | + this.siderHook.removeSider(this.uniqueId) |
| 154 | + } |
| 155 | + }, |
| 156 | + model: { |
| 157 | + prop: 'collapsed', |
| 158 | + event: 'collapse', |
| 159 | + }, |
| 160 | + methods: { |
| 161 | + responsiveHandler (mql) { |
| 162 | + this.setState({ below: mql.matches }) |
| 163 | + if (this.sCollapsed !== mql.matches) { |
| 164 | + this.setCollapsed(mql.matches, 'responsive') |
| 165 | + } |
| 166 | + }, |
| 167 | + |
| 168 | + setCollapsed (collapsed, type) { |
| 169 | + if (!hasProp(this, 'collapsed')) { |
| 170 | + this.setState({ |
| 171 | + sCollapsed: collapsed, |
| 172 | + }) |
| 173 | + } |
| 174 | + this.$emit('collapse', collapsed, type) |
| 175 | + }, |
| 176 | + |
| 177 | + toggle () { |
| 178 | + const collapsed = !this.sCollapsed |
| 179 | + this.setCollapsed(collapsed, 'clickTrigger') |
| 180 | + }, |
| 181 | + |
| 182 | + belowShowChange () { |
| 183 | + this.setState({ belowShow: !this.belowShow }) |
| 184 | + }, |
| 185 | + }, |
| 186 | + |
| 187 | + render () { |
| 188 | + const { prefixCls, |
| 189 | + collapsible, reverseArrow, width, collapsedWidth, |
| 190 | + } = getOptionProps(this) |
| 191 | + const trigger = getComponentFromProp(this, 'trigger') |
| 192 | + let siderWidth = this.sCollapsed ? collapsedWidth : width |
| 193 | + siderWidth = typeof siderWidth === 'string' ? siderWidth.replace('px', '') : siderWidth |
| 194 | + // special trigger when collapsedWidth == 0 |
| 195 | + const zeroWidthTrigger = collapsedWidth === 0 || collapsedWidth === '0' || collapsedWidth === '0px' ? ( |
| 196 | + <span onClick={this.toggle} class={`${prefixCls}-zero-width-trigger`}> |
| 197 | + <Icon type='bars' /> |
| 198 | + </span> |
| 199 | + ) : null |
| 200 | + const iconObj = { |
| 201 | + 'expanded': reverseArrow ? <Icon type='right' /> : <Icon type='left' />, |
| 202 | + 'collapsed': reverseArrow ? <Icon type='left' /> : <Icon type='right' />, |
| 203 | + } |
| 204 | + const status = this.sCollapsed ? 'collapsed' : 'expanded' |
| 205 | + const defaultTrigger = iconObj[status] |
| 206 | + const triggerDom = ( |
| 207 | + trigger !== null |
| 208 | + ? zeroWidthTrigger || ( |
| 209 | + <div className={`${prefixCls}-trigger`} onClick={this.toggle} style={{ width: `${siderWidth}px` }}> |
| 210 | + {trigger || defaultTrigger} |
| 211 | + </div> |
| 212 | + ) : null |
| 213 | + ) |
| 214 | + const divStyle = { |
| 215 | + // ...style, |
| 216 | + flex: `0 0 ${siderWidth}px`, |
| 217 | + maxWidth: `${siderWidth}px`, // Fix width transition bug in IE11 |
| 218 | + minWidth: `${siderWidth}px`, // https://github.com/ant-design/ant-design/issues/6349 |
| 219 | + width: `${siderWidth}px`, |
| 220 | + } |
| 221 | + const siderCls = classNames(prefixCls, { |
| 222 | + [`${prefixCls}-collapsed`]: !!this.sCollapsed, |
| 223 | + [`${prefixCls}-has-trigger`]: collapsible && trigger !== null && !zeroWidthTrigger, |
| 224 | + [`${prefixCls}-below`]: !!this.below, |
| 225 | + [`${prefixCls}-zero-width`]: siderWidth === 0 || siderWidth === '0' || siderWidth === '0px', |
| 226 | + }) |
| 227 | + const divProps = { |
| 228 | + on: this.$listeners, |
| 229 | + class: siderCls, |
| 230 | + style: divStyle, |
| 231 | + } |
| 232 | + return ( |
| 233 | + <div {...divProps}> |
| 234 | + <div class={`${prefixCls}-children`}>{this.$slots.default}</div> |
| 235 | + {collapsible || (this.below && zeroWidthTrigger) ? triggerDom : null} |
| 236 | + </div> |
| 237 | + ) |
| 238 | + }, |
| 239 | +} |
0 commit comments