diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d3e9e593..9f0f5db93 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,16 @@
# 更新日志
+## 2.2.0
+
+- 新增 `` 走马灯组件 [#115](https://github.com/XiaoMi/hiui/issues/115)
+- 新增 `` clearable 属性控制是否可清空 [#590](https://github.com/XiaoMi/hiui/issues/590)
+- 新增 `` visible 属性手动控制显示或隐藏 [#589](https://github.com/XiaoMi/hiui/issues/589)
+- 新增 `` visible 属性手动控制显示或隐藏 [#588](https://github.com/XiaoMi/hiui/issues/588)
+- 修复 `` 异步用法 params 不生效的问题 [#587](https://github.com/XiaoMi/hiui/issues/587)
+- 修复 `` 包裹禁用按钮时不能隐藏的问题 [#583](https://github.com/XiaoMi/hiui/issues/583)
+- 修复 `` 中含输入项时失焦造成的问题 [#581](https://github.com/XiaoMi/hiui/issues/581)
+- 修复 `` 清空搜索条件后无法收起的问题 [#561](https://github.com/XiaoMi/hiui/issues/561)
+
## 2.1.2
- 修复 `` clearable 不生效的问题 [#580](https://github.com/XiaoMi/hiui/issues/580)
diff --git a/components/button/index.js b/components/button/index.js
index 90d973197..4023ddb59 100644
--- a/components/button/index.js
+++ b/components/button/index.js
@@ -3,4 +3,5 @@ import ButtonGroup from './ButtonGroup'
import './style/index'
Button.Group = ButtonGroup
+Button.IS_HI_COMPONENT = true
export default Button
diff --git a/components/carousel/index.js b/components/carousel/index.js
new file mode 100644
index 000000000..c35fd31e5
--- /dev/null
+++ b/components/carousel/index.js
@@ -0,0 +1,177 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import Icon from '../icon'
+import classNames from 'classnames'
+import './style/index'
+
+// const url = 'http://i1.mifile.cn/f/i/hiui/docs/'
+class Carousel extends Component {
+ constructor (props) {
+ super(props)
+ this.rootRef = React.createRef()
+ const defaultActive = props.defaultActive
+ this.state = {
+ rootWidth: 0,
+ showArrow: false,
+ active: (defaultActive >= props.children.length || defaultActive < 0) ? 0 : defaultActive
+ }
+ this.timer = null
+ }
+
+ componentDidMount () {
+ this.setState({
+ rootWidth: this.rootRef.current.clientWidth
+ }, () => {
+ if (this.props.duration) {
+ this.autoPage()
+ }
+ })
+ }
+
+ goTo (page) {
+ if (page > this.props.children.length || page < 0) {
+ return
+ }
+ this.setState({
+ active: page
+ })
+ }
+ componentWillUnmount () {
+ this.timer && window.clearInterval(this.timer)
+ }
+
+ autoPage () {
+ this.timer = window.setInterval(() => {
+ this.preNextEvent(1)
+ }, this.props.duration)
+ }
+
+ pageEvent (active) {
+ this.setState({
+ active
+ })
+ }
+
+ preNextEvent (val) {
+ let active = this.state.active + val
+ if (active >= this.props.children.length) {
+ active = 0
+ }
+ this.setState({
+ active
+ })
+ }
+
+ renderDot (type, key, index, active) {
+ if (type === 'sign') {
+ return
+ } else {
+ const cls = classNames(
+ 'hi-carousel__dot',
+ active === index && 'hi-carousel__dot--active'
+ )
+ return (
+
+ )
+ }
+ }
+
+ mouseEvent (type) {
+ let showArrow = true
+ if (type === 'over') {
+ this.timer && window.clearInterval(this.timer)
+ } else {
+ showArrow = false
+ this.props.duration && this.autoPage()
+ }
+ this.setState({showArrow})
+ }
+ render () {
+ const { rootWidth, active, showArrow } = this.state
+ const { showDots, showArrows } = this.props
+ const children = React.Children.toArray(this.props.children)
+ const arrowCls = classNames(
+ 'hi-carousel__arrows',
+ showArrow && 'hi-carousel__arrows--show'
+ )
+ return
+
+ {
+ children.map((child, index) => {
+ return React.cloneElement(child, {
+ key: index,
+ style: {
+ position: 'relative',
+ opacity: active === index ? 1 : 0,
+ transition: 'opacity 300ms ease 0s',
+ left: -(rootWidth * index),
+ width: rootWidth,
+ display: 'inline-block',
+ fontSize: 24,
+ ...child.props.style
+ }
+ })
+ })
+ }
+
+ {
+ showArrows &&
+ }
+ {
+ showDots &&
+ {
+ children.map((_, index) => {
+ const cls = classNames('hi-carousel__dot', active === index && 'hi-carousel__dot--active')
+ return
+ })
+ }
+
+ }
+
+ }
+}
+
+Carousel.propTypes = {
+ duration: PropTypes.number,
+ onClick: PropTypes.func,
+ beforeChange: PropTypes.func,
+ afterChange: PropTypes.func,
+ showDots: PropTypes.bool,
+ showArrows: PropTypes.bool,
+ defaultActive: PropTypes.number
+}
+Carousel.defaultProps = {
+ duration: 0,
+ onClick: () => {},
+ beforeChange: () => {},
+ afterChange: () => {},
+ showDots: true,
+ showArrows: true,
+ defaultActive: 0
+}
+
+export default Carousel
diff --git a/components/carousel/style/index.js b/components/carousel/style/index.js
new file mode 100644
index 000000000..63810a681
--- /dev/null
+++ b/components/carousel/style/index.js
@@ -0,0 +1 @@
+import './index.scss'
diff --git a/components/carousel/style/index.scss b/components/carousel/style/index.scss
new file mode 100644
index 000000000..cf049545b
--- /dev/null
+++ b/components/carousel/style/index.scss
@@ -0,0 +1,74 @@
+.hi-carousel {
+ width: 100%;
+ color: rgba(153, 153, 153, 1);
+ overflow: hidden;
+ position: relative;
+
+ &__container {
+ height: 100%;
+ transition: all 500ms;
+ }
+
+ &__dots {
+ position: absolute;
+ bottom: 24px;
+ margin: 0;
+ padding: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ &__dot {
+ width: 24px;
+ height: 4px;
+ background: rgba(255, 255, 255, 0.4);
+ border-radius: 2px;
+ display: inline-block;
+ margin-left: 4px;
+ cursor: pointer;
+ transition: all 1s;
+
+ &--active:not(.hi-carousel__dot--sign) {
+ background: rgba(255, 255, 255, 1);
+ width: 48px;
+ }
+
+ &--sign {
+ width: 24px;
+ }
+ }
+
+ &__arrows {
+ position: absolute;
+ width: 100%;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ top: 50%;
+ transform: translateY(-28px);
+ display: flex;
+ justify-content: space-between;
+ visibility: hidden;
+
+ &--show {
+ visibility: visible;
+ }
+ }
+
+ &__arrow {
+ width: 56px;
+ height: 56px;
+ background: rgba(0, 0, 0, 0.25);
+ border-radius: 50%;
+ text-align: center;
+ line-height: 56px;
+ color: #fff;
+ font-size: 32px;
+ margin-left: 24px;
+ cursor: pointer;
+
+ &:last-child {
+ margin-right: 24px;
+ }
+ }
+}
diff --git a/components/date-picker/BasePicker.js b/components/date-picker/BasePicker.js
index a2019459e..ae183cb54 100644
--- a/components/date-picker/BasePicker.js
+++ b/components/date-picker/BasePicker.js
@@ -264,12 +264,13 @@ class BasePicker extends Component {
}
_icon () {
const {isFocus} = this.state
+ const { clearable } = this.props
const iconCls = classNames(
'hi-datepicker__input-icon',
'hi-icon',
- isFocus ? 'icon-close-circle clear' : 'icon-date'
+ (isFocus && clearable) ? 'icon-close-circle clear' : 'icon-date'
)
- return isFocus
+ return (isFocus && clearable)
?
: {
if (this.props.disabled) return
@@ -341,6 +342,9 @@ BasePicker.propTypes = {
if (val === undefined || val === null) {
return null
}
+ if (!val) {
+ return null
+ }
if (val.start && val.end) {
const _start = dateFormat(val.start)
const _end = dateFormat(val.end)
@@ -364,13 +368,15 @@ BasePicker.propTypes = {
if (val < 5 || val > 480 || (val > 60 && val % 60 !== 0) || (val < 60 && 60 % val !== 0)) {
return new Error(`Invalid prop ${propName} supplied to ${componentName}. This value must be greater than 5 and less than 480 and is a multiple of 60.`)
}
- }
+ },
+ clearable: PropTypes.bool
}
BasePicker.defaultProps = {
type: 'date',
disabled: false,
showWeekNumber: true,
weekOffset: 0,
- timeInterval: 240
+ timeInterval: 240,
+ clearable: true
}
export default BasePicker
diff --git a/components/index.js b/components/index.js
index 823896e3c..51ee73cd2 100755
--- a/components/index.js
+++ b/components/index.js
@@ -42,4 +42,5 @@ export { default as Rate } from './rate'
export { default as Message } from './message'
export { default as Tag } from './tag'
export { default as Breadcrumb } from './breadcrumb'
+export { default as Carousel } from './carousel'
export { ThemeContext, LocaleContext } from './context'
diff --git a/components/popover/index.js b/components/popover/index.js
index e242cf4d0..78a1131ef 100644
--- a/components/popover/index.js
+++ b/components/popover/index.js
@@ -65,7 +65,6 @@ export default class Popover extends Component {
this.element = ReactDOM.findDOMNode(this)
const referenceRef = ReactDOM.findDOMNode(this.referenceRef)
- // this.reference = ReactDOM.findDOMNode(this.refs.reference)
if (referenceRef === null) return
if (trigger === 'click') {
@@ -105,27 +104,28 @@ export default class Popover extends Component {
this.unbindHover = false
popper.current.addEventListener('mouseenter', e => {
this.eventTarget = e.target
- // this.showPopper()
})
popper.current.addEventListener('mouseleave', e => {
- this.delayHidePopper(e)
+ const poperPosition = popper.current.getBoundingClientRect()
+ if (e.clientY > poperPosition.y + poperPosition.height - 1 || e.clientY < poperPosition.y || e.clientX < poperPosition.x || e.clientX > poperPosition.x + poperPosition.width - 1) {
+ this.delayHidePopper(e)
+ }
})
}
}
render () {
- const { style, className, title, content, placement, width } = this.props
+ const { style, className, title, content, placement, width, visible } = this.props
const {
showPopper
} = this.state
-
return (
{ this.popoverContainer = node }}>
{ React.cloneElement(React.Children.only(this.props.children), { ref: (el) => { this.referenceRef = el }, tabIndex: '0' }) }
{
- if (!queryParams) {
- return ''
- }
- if (typeof params === 'string') {
- return params
- }
- if (Object.prototype.toString.call(params) === '[object Object]') {
- return Object.keys(params)
- .map((key) => `&${key}=${params[key]}`)
- .join('')
- }
- })()
-
+ const queryParams = qs.stringify(Object.assign({}, params, key && {[key]: keyword}))
url =
- url.indexOf('?') === -1
- ? `${url}?${[key]}=${keyword}${queryParams}`
- : `${url}&${[key]}=${keyword}${queryParams}`
+ url.includes('?')
+ ? `${url}&${queryParams}`
+ : `${url}?${queryParams}`
if (type.toUpperCase() === 'POST') {
options.body = JSON.stringify(data)
@@ -443,7 +432,7 @@ class Select extends Component {
() => this.resetFocusedIndex()
)
- if (this.props.dataSource) {
+ if (this.props.dataSource && this.props.dataSource.key) {
if (
this.props.autoload ||
keyword.toString().length >= this.state.queryLength
diff --git a/components/tooltip/index.js b/components/tooltip/index.js
index 7519c2e84..035145ff8 100644
--- a/components/tooltip/index.js
+++ b/components/tooltip/index.js
@@ -25,9 +25,21 @@ class Tooltip extends Component {
state = {
tooltipShow: this.props.defaultVisible
}
-
+ // 兼容处理 button disabled tooltip 不消失的问题
+ compatDisabledBtn = el => {
+ if (el.type.IS_HI_COMPONENT && el.props.disabled) {
+ return React.cloneElement(el, {
+ style: {
+ ...el.props.style,
+ pointerEvents: 'none'
+ }
+ })
+ } else {
+ return el
+ }
+ }
render () {
- const { placement, style, className, onClick, title, children } = this.props
+ const { placement, style, className, onClick, title, children, visible } = this.props
const eleClass = classNames(`${prefixCls}-base`, placement && `${prefixCls}-${placement}`)
const { tooltipShow } = this.state
return (
@@ -49,7 +61,7 @@ class Tooltip extends Component {
>
{title}
- {children}
+ {this.compatDisabledBtn(children)}
)
}
diff --git a/components/tree/tree-legacy/util.js b/components/tree/tree-legacy/util.js
index 674717088..d57019592 100644
--- a/components/tree/tree-legacy/util.js
+++ b/components/tree/tree-legacy/util.js
@@ -293,7 +293,7 @@ export const getAncestorIds = (id, data, arr = []) => {
// 收集所有需要展开的节点 id
export const collectExpandId = (data, searchValue, collection = [], allData) => {
data.forEach(item => {
- if (item.title.includes(searchValue)) {
+ if (searchValue && item.title.includes(searchValue)) {
const parentIds = getAncestorIds(item.id, allData, [])
collection.splice(collection.length - 1, 0, ...parentIds)
}
diff --git a/components/tree/util.js b/components/tree/util.js
index 674717088..d57019592 100644
--- a/components/tree/util.js
+++ b/components/tree/util.js
@@ -293,7 +293,7 @@ export const getAncestorIds = (id, data, arr = []) => {
// 收集所有需要展开的节点 id
export const collectExpandId = (data, searchValue, collection = [], allData) => {
data.forEach(item => {
- if (item.title.includes(searchValue)) {
+ if (searchValue && item.title.includes(searchValue)) {
const parentIds = getAncestorIds(item.id, allData, [])
collection.splice(collection.length - 1, 0, ...parentIds)
}
diff --git a/docs/demo/breadcrumb/section-base.jsx b/docs/demo/breadcrumb/section-base.jsx
index 4a7f39e5f..a8dc191ef 100644
--- a/docs/demo/breadcrumb/section-base.jsx
+++ b/docs/demo/breadcrumb/section-base.jsx
@@ -3,7 +3,7 @@ import DocViewer from '../../../libs/doc-viewer'
import Breadcrumb from '../../../components/breadcrumb'
const prefix = 'alert-base'
const code = `import React from 'react'
-import Alert from '@hi-ui/hiui/es/alert'\n
+import Breadcrumb from '@hi-ui/hiui/es/breadcrumb'\n
class Demo extends React.Component {
render () {
const data = [{
diff --git a/docs/demo/carousel/section-base.jsx b/docs/demo/carousel/section-base.jsx
new file mode 100644
index 000000000..f0470c742
--- /dev/null
+++ b/docs/demo/carousel/section-base.jsx
@@ -0,0 +1,31 @@
+import React from 'react'
+import DocViewer from '../../../libs/doc-viewer'
+import Carousel from '../../../components/carousel'
+const prefix = 'carousel-base'
+const code = `import React from 'react'
+import Carousel from '@hi-ui/hiui/es/carousel'\n
+class Demo extends React.Component {
+ constructor (props) {
+ super(props)
+ }
+
+ render () {
+ const data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
+ return (
+
+
+ {
+ data.map((item) => {
+ return {item}
+ })
+ }
+
+
+ )
+ }
+}`
+
+const DemoBase = () =>
+export default DemoBase
diff --git a/docs/demo/carousel/section-icon.jsx b/docs/demo/carousel/section-icon.jsx
new file mode 100644
index 000000000..5ab0544a3
--- /dev/null
+++ b/docs/demo/carousel/section-icon.jsx
@@ -0,0 +1,27 @@
+import React from 'react'
+import DocViewer from '../../../libs/doc-viewer'
+import Carousel from '../../../components/carousel'
+const prefix = 'carousel-base'
+const code = `import React from 'react'
+import Carousel from '@hi-ui/hiui/es/carousel'\n
+class Demo extends React.Component {
+ render () {
+ const data = [1, 2, 3, 4, 5, 6, 7, 8]
+ return (
+
+
+ {
+ data.map((item, index) => {
+ return
+ })
+ }
+
+
+ )
+ }
+}`
+
+const DemoBase = () =>
+export default DemoBase
diff --git a/docs/demo/date-picker/section-ban-date.jsx b/docs/demo/date-picker/section-ban-date.jsx
index fa296ca8c..254d93345 100644
--- a/docs/demo/date-picker/section-ban-date.jsx
+++ b/docs/demo/date-picker/section-ban-date.jsx
@@ -18,6 +18,7 @@ class Demo extends React.Component {
min={new Date()}
max={new Date().getTime() + 30 * 24 * 60 * 60 * 1000}
onChange={(date) => {
+ console.log(date)
this.setState({date})
}}
/>
diff --git a/docs/zh-CN/components/carousel.mdx b/docs/zh-CN/components/carousel.mdx
new file mode 100644
index 000000000..baae2b0b7
--- /dev/null
+++ b/docs/zh-CN/components/carousel.mdx
@@ -0,0 +1,22 @@
+# Carousel 走马灯
+
+## 基础用法
+
+import DemoBase from '../../demo/carousel/section-base.jsx'
+
+
+
+## 图片展示
+
+import DemoImage from '../../demo/carousel/section-icon.jsx'
+
+
+
+## Props
+
+| 参数 | 说明 | 类型 | 可选值 | 默认值 |
+| -------------- | ------------------------------------------------- | --------------------------- | ------------- | ------------------------------------------------------- |
+| duration | 自动切换间隔,默认不自动切换 | number | - | 0 |
+| showDots | 是否显示分页指示器 | boolean | true \| false | false |
+| showArrows | 是否显示箭头指示器 | boolean | true \| false | false |
+| defaultActive | 默认激活索引,从0开始 | number | - | 0 |
diff --git a/docs/zh-CN/components/changelog.mdx b/docs/zh-CN/components/changelog.mdx
index 6748c294a..91b88af8e 100644
--- a/docs/zh-CN/components/changelog.mdx
+++ b/docs/zh-CN/components/changelog.mdx
@@ -1,13 +1,22 @@
# 更新日志
+## 2.2.0
+
+- 新增 `` 走马灯组件 [#115](https://github.com/XiaoMi/hiui/issues/115)
+- 新增 `` clearable 属性控制是否可清空 [#590](https://github.com/XiaoMi/hiui/issues/590)
+- 新增 `` visible 属性手动控制显示或隐藏 [#589](https://github.com/XiaoMi/hiui/issues/589)
+- 新增 `` visible 属性手动控制显示或隐藏 [#588](https://github.com/XiaoMi/hiui/issues/588)
+- 修复 `` 异步用法 params 不生效的问题 [#587](https://github.com/XiaoMi/hiui/issues/587)
+- 修复 `` 包裹禁用按钮时不能隐藏的问题 [#583](https://github.com/XiaoMi/hiui/issues/583)
+- 修复 `` 中含输入项时失焦造成的问题 [#581](https://github.com/XiaoMi/hiui/issues/581)
+- 修复 `` 清空搜索条件后无法收起的问题 [#561](https://github.com/XiaoMi/hiui/issues/561)
+
## 2.1.2
- 修复 `` clearable 不生效的问题 [#580](https://github.com/XiaoMi/hiui/issues/580)
- 修复 `` 中的自定义上传结合 maxCount 不能上传的问题 [#582](https://github.com/XiaoMi/hiui/issues/582)
- 修复 `` type 为 textarea 时的底部的样式问题 [#584](https://github.com/XiaoMi/hiui/issues/584)
-
-
## 2.1.0
- 新增 `` 面包屑组件 [#573](https://github.com/XiaoMi/hiui/issues/573)
diff --git a/docs/zh-CN/components/date-picker.mdx b/docs/zh-CN/components/date-picker.mdx
index 0b93cb340..c4a0c94ae 100755
--- a/docs/zh-CN/components/date-picker.mdx
+++ b/docs/zh-CN/components/date-picker.mdx
@@ -95,6 +95,7 @@ import DemoModal from '../../demo/date-picker/section-modal.jsx'
| minDate | 最小日期 | Date | null | null |
| maxDate | 最大日期 | Date | null | null |
| disabled | 是否禁用输入框 | boolean | true \| false | false |
+| clearable | 是否可以清空 | boolean | true \| false | true |
| showTime | 是否在日期选择器中显示时间选择器 | boolean | true \| false | false |
| shortcuts | 快捷面板 | string[] | 近一周, 近一月, 近三月, 近一年 | null |
| weekOffset | 周起始
默认周日做为第一列 | number | 0/1 | 0 |
diff --git a/docs/zh-CN/components/popover.mdx b/docs/zh-CN/components/popover.mdx
index 7e326a90e..675eb8ec5 100755
--- a/docs/zh-CN/components/popover.mdx
+++ b/docs/zh-CN/components/popover.mdx
@@ -16,3 +16,4 @@ import DemoBase from '../../demo/popover/section-base.jsx'
| content | 气泡卡片内容 | string \| ReactNode | - | - |
| placement | 气泡卡片显示的位置 | string | 'top' \| 'right' \| 'bottom' \| 'left' | 'top' |
| trigger | 气泡卡片触发方式 | string | 'click' \| 'focus' \| 'hover' | 'click' |
+| visible | 控制气泡卡片的显示和隐藏(需要组件完全受控时使用) | boolean |true \| false | - |
diff --git a/docs/zh-CN/components/tooltip.mdx b/docs/zh-CN/components/tooltip.mdx
index 45b9ef7e7..e82b9835d 100755
--- a/docs/zh-CN/components/tooltip.mdx
+++ b/docs/zh-CN/components/tooltip.mdx
@@ -20,6 +20,7 @@ import DemoApi from '../../demo/tooltip/section-api.jsx'
| --------- | ------------------ | ------ | -------------------------------------- | ------ |
| title | 提示文字内容 | string | 字符串 | -- |
| placement | tooltip 显示的位置 | string | 'top' \| 'right' \| 'bottom' \| 'left' | 'top' |
+| visible | 控制 tooltip 的显示和隐藏(需要组件完全受控时使用) | boolean | true \| false | - |
## Methods
diff --git a/package.json b/package.json
index 6200e1546..eb81a22ac 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@hi-ui/hiui",
- "version": "2.1.2",
+ "version": "2.2.0",
"description": "HIUI for React",
"scripts": {
"test": "node_modules/.bin/standard && node_modules/.bin/stylelint --config .stylelintrc 'components/**/*.scss'",
@@ -52,6 +52,7 @@
"github-markdown-css": "^3.0.1",
"hoist-non-react-statics": "^2.5.0",
"lodash": "^4.17.11",
+ "qs": "^6.8.0",
"react": "^16.8.6",
"react-addons-css-transition-group": "^15.6.2",
"react-click-outside": "^3.0.1",
diff --git a/site/locales/zh-CN.js b/site/locales/zh-CN.js
index 2ba8da091..b2e923332 100755
--- a/site/locales/zh-CN.js
+++ b/site/locales/zh-CN.js
@@ -51,7 +51,8 @@ module.exports = {
transfer: 'Transfer 穿梭框',
switch: 'Switch 开关',
rate: 'Rate 评分',
- breadcrumb: 'Breadcrumb 面包屑'
+ breadcrumb: 'Breadcrumb 面包屑',
+ carousel: 'Carousel 走马灯'
},
designs: {
summarize: '概述',
diff --git a/site/pages/components/index.js b/site/pages/components/index.js
index 1581ea15a..cbcaf03a3 100755
--- a/site/pages/components/index.js
+++ b/site/pages/components/index.js
@@ -51,7 +51,8 @@ export default {
popover: components['popover'],
progress: components['progress'],
card: components['card'],
- timeline: components['timeline']
+ timeline: components['timeline'],
+ carousel: components['carousel']
},
'group-tips': {
modal: components['modal'],