Skip to content

Commit

Permalink
Merge pull request #1564 from XiaoMi/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
zhan8863 authored Jan 29, 2021
2 parents 8c50111 + 2febbe2 commit 16fff7d
Show file tree
Hide file tree
Showing 101 changed files with 3,280 additions and 234 deletions.
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ Desktop.ini
Thumbs.db
.Spotlight-V100
.Trashes
postcss.config.js
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
# 更新日志

## 3.4.0

- 优化组件弹出层自动计算合适的左右位置 [#1494](https://github.com/XiaoMi/hiui/issues/1494)
- 新增 `Select SelectTree Cascader DatePicker Input` 等组件无边框形态 [#1553](https://github.com/XiaoMi/hiui/issues/1553)
- 新增 `Preview` 预览组件 [#1546](https://github.com/XiaoMi/hiui/issues/1546)
- 新增 `Select` 组件 onSearch、onOverlayScroll 方法 [#1522](https://github.com/XiaoMi/hiui/issues/1522)
- 修复 `SelectTree` 搜索输入框在输入值时失焦问题 [#1491](https://github.com/XiaoMi/hiui/issues/1491)
- 修复 `SelectTree` 单选形态下受控问题 [#1519](https://github.com/XiaoMi/hiui/issues/1519)
- 修复 `Select` 组件分组形态 filterOption 函数无法使用问题 [#1497](https://github.com/XiaoMi/hiui/issues/1497)
- 修复 `Select` 组件分组形态全选以及受控问题 [#1501](https://github.com/XiaoMi/hiui/issues/1501)
- 修复 `Select` 异步数据请求返回结果顺序异常 [#1543](https://github.com/XiaoMi/hiui/issues/1543)
- 修复 `Tabs` 组件垂直方向样式显示异常问题 [#1493](https://github.com/XiaoMi/hiui/issues/1493)
- 修复 `Form` DatePicker、SelectTree 在 Form.Item 中点击清空Icon 无效问题 [#1524](https://github.com/XiaoMi/hiui/issues/1524)
- 修复 `DatePicker` minDate、maxDate、disabledDate 在非 date 类型下不生效问题 [#1547](https://github.com/XiaoMi/hiui/issues/1547)
- 优化 `Checkbox` 样式相关内容 [#1482](https://github.com/XiaoMi/hiui/issues/1482)
- 优化 `SelectTree` 异步受控数据返显问题 [#1510](https://github.com/XiaoMi/hiui/issues/1510)
- 优化 `Select SelectTree` 计数根据窗口自动调整 [#1527](https://github.com/XiaoMi/hiui/issues/1527)
- 优化 `Drawer` 组件支持className属性 [#1536](https://github.com/XiaoMi/hiui/issues/1536)

## 3.3.0

- 新增 `Card` 模式模式下 loading 加载中状态 [#1454](https://github.com/XiaoMi/hiui/issues/1454)
- 新增 `Table` loading 加载中状态 [#1466](https://github.com/XiaoMi/hiui/issues/1466)
- 新增 `Table` 列冻结结合树形使用 [#1424](https://github.com/XiaoMi/hiui/issues/1424)
Expand Down
1 change: 0 additions & 1 deletion components/_util/EventEmitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ class EventEmitter {

// 触发事件
emit(type, ...arg) {
console.log(this.event)
this.event[type] && this.event[type](...arg)
}

Expand Down
14 changes: 7 additions & 7 deletions components/button/ButtonGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ class ButtonGroup extends Component {
prefixCls: 'hi-btn-group'
}

render () {
const {
prefixCls,
style,
className
} = this.props
render() {
const { prefixCls, style, className } = this.props
const classes = classNames(`${prefixCls}`, className)
return <div className={classes} style={style}>{this.props.children}</div>
return (
<div className={classes} style={style}>
{this.props.children}
</div>
)
}
}

Expand Down
11 changes: 10 additions & 1 deletion components/button/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,14 @@ interface ButtonProps {
icon?: string
onClick?: () => void
}
declare const Button: React.ComponentType<Props>
interface ButtonGroupProps {
className?: string
style?: object
prefixCls?: string
}
declare class ButtonGroup extends React.Component<ButtonGroupProps, any> {
}
declare class Button extends React.Component<ButtonProps, any> {
static Group = ButtonGroup
}
export default Button
2 changes: 2 additions & 0 deletions components/card/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ interface Props {
extraType?: 'default' | 'hover'
coverUrl?: string
content?: string | JSX.Element
style?: CSSProperties
className?: string
}
declare class Card extends React.Component<Props, any> {
}
Expand Down
2 changes: 2 additions & 0 deletions components/carousel/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ interface Props {
defaultActive?: number
showPages?: boolean
children: JSX.Element[]
style?: CSSProperties
className?: string
}
declare const Carousel: React.ComponentType<Props>
export default Carousel
11 changes: 11 additions & 0 deletions components/carousel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ class Carousel extends Component {
this.setState({ showArrow })
}

handleKeyDown = (evt) => {
const { keyCode } = evt
if ([39, 37].includes(keyCode)) {
evt.preventDefault()
evt.stopPropagation()
this.preNextEvent(keyCode === 37 ? -1 : 1)
}
}

render() {
const { rootWidth, active, showArrow } = this.state
const { showDots, showArrows, showPages } = this.props
Expand All @@ -81,6 +90,8 @@ class Carousel extends Component {
<div
className="hi-carousel"
ref={this.rootRef}
tabIndex="0"
onKeyDown={this.handleKeyDown}
onMouseOver={this.mouseEvent.bind(this, 'over')}
onMouseOut={this.mouseEvent.bind(this, 'out')}
>
Expand Down
2 changes: 2 additions & 0 deletions components/carousel/style/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
color: #fff;
overflow: hidden;
position: relative;
outline: none;

&__container {
height: 100%;
Expand Down Expand Up @@ -54,6 +55,7 @@
visibility: hidden;
height: 0;
z-index: 2;

&--show {
visibility: visible;
}
Expand Down
195 changes: 184 additions & 11 deletions components/cascader/Cascader.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useRef, useState, useCallback, useEffect } from 'react'

import classNames from 'classnames'

import _ from 'lodash'
import Popper from '../popper'

import Menu from './Menu'
Expand All @@ -25,12 +25,9 @@ const Cascader = (props) => {
changeOnSelect = false,
localeDatas,
onChange = noop,
onActiveItemChange = noop
onActiveItemChange = noop,
bordered = true
} = props
const data = props.data || props.options // 兼容1.x API 2.x 改为data
const emptyContent = props.emptyContent || props.noFoundTip // 兼容1.x API 2.x改为 emptyContent
const expandTrigger = props.expandTrigger || props.trigger || 'click' // 兼容2.x API 1.x改为 expandTrigger

const getLabelKey = useCallback(() => {
return fieldNames.label || 'content'
}, [])
Expand All @@ -42,7 +39,25 @@ const Cascader = (props) => {
const getChildrenKey = useCallback(() => {
return fieldNames.children || 'children'
}, [])

const parseData = useCallback(
(data) => {
const _data = _.cloneDeep(data)
const setDataItemPath = (data = [], parent) => {
data.forEach((item, index) => {
item._path = parent ? parent._path + '-' + index : index
if (item[getChildrenKey()]) {
setDataItemPath(item[getChildrenKey()], item)
}
})
}
setDataItemPath(_data)
return _data
},
[props.data, props.options]
)
const data = parseData(props.data || props.options) // 兼容1.x API 2.x 改为data
const emptyContent = props.emptyContent || props.noFoundTip // 兼容1.x API 2.x改为 emptyContent
const expandTrigger = props.expandTrigger || props.trigger || 'click' // 兼容2.x API 1.x改为 expandTrigger
const getCascaderLabel = useCallback(
(values, dataList) => {
if (displayRender) {
Expand Down Expand Up @@ -83,7 +98,9 @@ const Cascader = (props) => {
const [cacheValue, setCacheValue] = useState(value || defaultValue || [])
const [cascaderValue, setCascaderValue] = useState(value || defaultValue || [])
const [cascaderLabel, setCascaderLabel] = useState(getCascaderLabel(value || defaultValue || []))

const [focusOptionIndex, setFocusOptionIndex] = useState(-1)
const targetByKeyDown = useRef(false)
const currentDeep = useRef(0)
const [popperShow, setPopperShow] = useState(false)
const [keyword, setKeyword] = useState('')

Expand All @@ -97,6 +114,10 @@ const Cascader = (props) => {
setCacheValue(value)
}
}, [value])
useEffect(() => {
setFocusOptionIndex(-1)
currentDeep.current = 0
}, [popperShow])

useEffect(() => {
setCascaderLabel(getCascaderLabel(cacheValue))
Expand Down Expand Up @@ -355,12 +376,160 @@ const Cascader = (props) => {
[popperShow, cacheValue, cascaderValue, keyword]
)

const parseFocusOptionIndex = useCallback(
(deep = currentDeep.current) => {
const optionIndexs = focusOptionIndex < 0 ? [focusOptionIndex] : String(focusOptionIndex).split('-')
return {
optionIndexs: optionIndexs.slice(0, deep + 1),
focusOptionIndex: optionIndexs[deep] || -1
}
},
[focusOptionIndex, currentDeep.current]
)
// 获取不同深度的数据, 该深度的全部数据而不是单条数据
const getDeepData = useCallback(
(deep = currentDeep.current) => {
const { optionIndexs } = parseFocusOptionIndex(deep)
let _data = data
if (optionIndexs.length <= 1) {
return _data
}
_data = optionIndexs.reduce((deepData, current, index) => {
if (index === 0) return deepData
const _index = optionIndexs[index - 1]
return deepData[_index][getChildrenKey()]
}, data)
return _data || []
},
[parseFocusOptionIndex, data, currentDeep.current]
)
// 上下按键
const moveFocusedIndex = useCallback(
(direction) => {
targetByKeyDown.current = true
const _data = currentDeep.current === 0 ? data : getDeepData()
const { focusOptionIndex: _focusOptionIndex } = parseFocusOptionIndex()
const isAllDisabled = _data.every((item) => {
return item.disabled
})
let index = direction === 'down' ? _focusOptionIndex / 1 + 1 : _focusOptionIndex / 1 - 1
if (index < 0) {
index = _data.length - 1
} else if (index >= _data.length) {
index = 0
}
if (!isAllDisabled) {
while (data[index] && data[index].disabled) {
index++
}
if (currentDeep.current > 0) {
const _focusOptionIndex = String(focusOptionIndex).split('-')
_focusOptionIndex[currentDeep.current] = index
index = _focusOptionIndex.join('-')
} else {
index = String(index)
}
setFocusOptionIndex(index)
} else {
setFocusOptionIndex(-1)
}
},
[targetByKeyDown.current, currentDeep.current, data, getDeepData, parseFocusOptionIndex, focusOptionIndex]
)
// 右方向按键
const rightHandle = useCallback(() => {
targetByKeyDown.current = true
currentDeep.current++
const { optionIndexs } = parseFocusOptionIndex()
const optionValues = []
const l = optionIndexs.length
optionIndexs.map((item, index) => {
const _data = getDeepData(index)
optionValues.push(_data[item].id)
})
const currentItem = getDeepData(l - 1)[optionIndexs[l - 1]] || {}
const children = currentItem[getChildrenKey()] || []
const hasChildren = !!children.length
onChangeValue(optionValues, hasChildren)
let index = 0
while (children[index] && children[index].disabled) {
index++
}
index = hasChildren ? focusOptionIndex + '-' + index : focusOptionIndex
setFocusOptionIndex(index)
}, [targetByKeyDown.current, parseFocusOptionIndex, focusOptionIndex, onChangeValue, currentDeep.current])
// 左方向按键
const leftHandle = useCallback(() => {
targetByKeyDown.current = true

const optionsIndex = focusOptionIndex.split('-')
if (cascaderValue.length === 0) {
currentDeep.current = 0
return
}
currentDeep.current--
setFocusOptionIndex(optionsIndex.splice(0, optionsIndex.length - 1).join('-'))
onChangeValue(cascaderValue.splice(0, cascaderValue.length - 1), true)
}, [focusOptionIndex, targetByKeyDown.current, onChangeValue, currentDeep.current, cascaderValue])
// 按键操作
const handleKeyDown = useCallback(
(evt) => {
// space
if (evt.keyCode === 32 && !searchable) {
evt.preventDefault()
evt.stopPropagation()
setPopperShow(!popperShow)
}
// esc
if (evt.keyCode === 27) {
evt.stopPropagation()
setPopperShow(false)
}
if (popperShow) {
// down
if (evt.keyCode === 40) {
evt.stopPropagation()
evt.preventDefault()
moveFocusedIndex('down')
}
// up
if (evt.keyCode === 38) {
evt.preventDefault()
evt.stopPropagation()
moveFocusedIndex('up')
}
// right
if (evt.keyCode === 39 || evt.keyCode === 13) {
evt.preventDefault()
evt.stopPropagation()
rightHandle()
}
// left
if (evt.keyCode === 37) {
evt.preventDefault()
evt.stopPropagation()
leftHandle()
}
}
},
[moveFocusedIndex, rightHandle, leftHandle]
)

const expandIcon = popperShow ? 'icon-up' : 'icon-down'
const placeholder = cascaderLabel || localeDatasProps('placeholder')

return (
<div className={classNames('hi-cascader', `theme__${theme}`, className, extraClass)} style={style} ref={hiCascader}>
<div className="hi-cascader__input-container" ref={inputContainer} onClick={handleClick}>
<div
className={classNames('hi-cascader', `theme__${theme}`, className, extraClass)}
style={style}
ref={hiCascader}
tabIndex="0"
onKeyDown={handleKeyDown}
>
<div
className={classNames('hi-cascader__input-container', { bordered })}
ref={inputContainer}
onClick={handleClick}
>
<input
ref={inputRef}
className="hi-cascader__input-keyword"
Expand Down Expand Up @@ -414,7 +583,11 @@ const Cascader = (props) => {
childrenKey={getChildrenKey()}
onSelect={onChangeValue}
onHover={onHover}
currentDeep={currentDeep}
expandTrigger={expandTrigger}
focusOptionIndex={focusOptionIndex}
setFocusOptionIndex={setFocusOptionIndex}
targetByKeyDown={targetByKeyDown}
emptyContent={emptyContent}
localeDatasProps={localeDatasProps}
/>
Expand Down
Loading

0 comments on commit 16fff7d

Please sign in to comment.