diff --git a/CHANGELOG.md b/CHANGELOG.md index 81645fe50..0f3c265d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,54 @@ # 更新日志 + +# 3.8.0 + +- 新增 所有组件 props TS 类型定义的导出 [#1933](https://github.com/XiaoMi/hiui/issues/1933) +- 新增 `Modal` confirmLoading 控制确定按钮的 loading 状态 [#1866](https://github.com/XiaoMi/hiui/issues/1866) +- 新增 `Cascader` onOpen 下拉菜单打开、onClose 下拉菜单关闭回调方法,优化动态加载数据功能 [#1854](https://github.com/XiaoMi/hiui/issues/1854) +- 新增 `Table` 组件 align 属性接受 center 属性 [#1835](https://github.com/XiaoMi/hiui/issues/1835) +- 新增 `Table` 组件 拖拽功能 [#1851](https://github.com/XiaoMi/hiui/issues/1851) +- 新增 `Table` 组件 自定义列筛选 [#1850](https://github.com/XiaoMi/hiui/issues/1850) +- 新增 `Table` 树形组件 onExpand 事件 [#1939](https://github.com/XiaoMi/hiui/issues/1939) +- 新增 `Select` 组件 renderExtraFooter 自定义下拉菜单底部渲染函数 [#1864](https://github.com/XiaoMi/hiui/issues/1864) +- 新增 `Select` 组件 onBlur 事件 [#1901](https://github.com/XiaoMi/hiui/issues/1901) +- 新增 `SelectTree` 组件 className 设置 [#1921](https://github.com/XiaoMi/hiui/issues/1921) +- 新增 `Tree` 组件指定节点设置 selectable [#1893](https://github.com/XiaoMi/hiui/issues/1893) +- 新增 `DatePicker` 组件中对时间选择器的禁选功能 [#1917](https://github.com/XiaoMi/hiui/issues/1917) +- 新增 `SelectTree` 组件节点支持 disabled 禁用状态 [#1870](https://github.com/XiaoMi/hiui/issues/1870) +- 新增 `SelectTree` 组件节点支持 fieldNames 属性 [#1879](https://github.com/XiaoMi/hiui/issues/1879) +- 优化 `DatePicker` 组件在 `Table` 组件中受控形态下无法选中问题 [#1844](https://github.com/XiaoMi/hiui/issues/1844) +- 优化 `Carousel` 组件内容宽度根据容器改变自适应 [#1834](https://github.com/XiaoMi/hiui/issues/1834) +- 优化 `Select` 组件多选模式标签顺序与value顺序一致化 [#1898](https://github.com/XiaoMi/hiui/issues/1898) +- 优化 `Charts` 组件文档中对 echarts 版本约束 [#1896](https://github.com/XiaoMi/hiui/issues/1896) +- 优化 `Tabs` 组件滚动方向交互控制 [#1928](https://github.com/XiaoMi/hiui/issues/1928) +- 优化 `Message` 组件文本溢出折行处理 [#1936](https://github.com/XiaoMi/hiui/issues/1936) +- 修复 `Cascader` 组件 异步加载在受控形态下,无法选中数据 [#1875](https://github.com/XiaoMi/hiui/issues/1875) +- 修复 `Form` 组件对 Counter 组件默认值为 0 校验异常问题 [#1842](https://github.com/XiaoMi/hiui/issues/1842) +- 修复 `Preview` 组件,图片打开失败时,页面一直处在加载状态 [#1816](https://github.com/XiaoMi/hiui/issues/1816) +- 修复 `HiRequest` 在 type='download'时 不能正确解析 filename 问题 [#1820](https://github.com/XiaoMi/hiui/issues/1820) +- 修复 `SelectTree` searchMode 为 filter 时,搜索后勾选,SelectTree 已选节点被清空 [#1791](https://github.com/XiaoMi/hiui/issues/#1791) +- 修复 `Select` data 属性发生改变,选中值未更新问题 [#1823](https://github.com/XiaoMi/hiui/issues/1823) +- 修复 `Popper` 基础弹层组件弹出位置未能及时更新问题 [#1857](https://github.com/XiaoMi/hiui/issues/1857) +- 修复 `Form` 组件中使用 schemaFrom 时,schema 更新未生效问题 [#1862](https://github.com/XiaoMi/hiui/issues/1862) +- 修复 `Form` 组件中使用 List 组件,输出值格式异常 [#1872](https://github.com/XiaoMi/hiui/issues/1872) +- 修复 `Form` 组件 onBlur 触发无效的 onChange,导致 value 更新失效 [#1910](https://github.com/XiaoMi/hiui/issues/1910) +- 修复 `Form` 组件中 SchemaForm 重渲染导致表单控件无法输入 [#1908](https://github.com/XiaoMi/hiui/issues/1908) +- 修复 `Form` 组件中对 rules 的动态更新校验 [#1935](https://github.com/XiaoMi/hiui/issues/1935) +- 修复 `Select` 组件异步搜索模式下,清空搜索内容未触发搜索问题 [#1883](https://github.com/XiaoMi/hiui/issues/1883) +- 修复 `Table` 组件子节点 isLeaf 属性为 false 时,显示展开 icon [#1887](https://github.com/XiaoMi/hiui/issues/1887) +- 修复 `Table` 组件列更新时,setting 列未跟随更新问题 [#1885](https://github.com/XiaoMi/hiui/issues/1885) +- 修复 `Alert` 组件 type 属性值文档描述错误 [#1877](https://github.com/XiaoMi/hiui/issues/1877) +- 修复 `Transfer` 组件中搜索输入框交互样式异常 [#1895](https://github.com/XiaoMi/hiui/issues/1895) +- 修复 `DatePicker` 组件在 Form 校验失败时边框爆红提示未正常显示 [#1897](https://github.com/XiaoMi/hiui/issues/1897) +- 修复 `Input` 组件中输入手机号在11位时再尝试输入,总会多出一位 [#1919](https://github.com/XiaoMi/hiui/issues/1919) +- 修复 `Badge` 组件 offset 属性设置状态点的位置偏移异常 [#1931](https://github.com/XiaoMi/hiui/issues/1931) +- 修复 `Carousel` 组件左侧切换按钮点击失效 [#1942](https://github.com/XiaoMi/hiui/issues/1942) + # 3.7.0 -- 新增 `Message` 组件 onClick、onClose方法[#1727](https://github.com/XiaoMi/hiui/issues/1727) -- 新增 `From` 组件 setListItemFieldsValue 方法, 设置表单中From.List的指定项的值[#1760](https://github.com/XiaoMi/hiui/issues/1760) + +- 新增 `Collapse` 组件 extra 属性作为标题额外元素扩展[#1831](https://github.com/XiaoMi/hiui/issues/1831) +- 新增 `Message` 组件 onClick、onClose 方法[#1727](https://github.com/XiaoMi/hiui/issues/1727) +- 新增 `From` 组件 setListItemFieldsValue 方法, 设置表单中 From.List 的指定项的值[#1760](https://github.com/XiaoMi/hiui/issues/1760) - 新增 `Table` 组件 onLoadChildren 方法, 树形表格下异步加载子数据 [#1725](https://github.com/XiaoMi/hiui/issues/1725) - 新增 `Badge` 组件 offset 属性设置状态点的位置偏移 [#1786](https://github.com/XiaoMi/hiui/issues/1786) - 新增 `Slider` 组件 showRangeLabel 属性设置是否显示范围值 [#1783](https://github.com/XiaoMi/hiui/issues/1783) @@ -26,12 +73,15 @@ - 修复 `DatePicker` 组件 yearrange、monthrange 无法通过 min、max 限制时间区间问题 [#1780](https://github.com/XiaoMi/hiui/issues/1780) - 修复 `Form` 组件值校验问题 [#1802](https://github.com/XiaoMi/hiui/issues/1802) - 修复 `Tree` 自定义右侧菜单参数错误问题 [#1812](https://github.com/XiaoMi/hiui/issues/1812) -- 修复 `Tree` 在 onBeforeSave 返回 false后依然可以新增子节点问题 [#1813](https://github.com/XiaoMi/hiui/issues/1813) +- 修复 `Tree` 在 onBeforeSave 返回 false 后依然可以新增子节点问题 [#1813](https://github.com/XiaoMi/hiui/issues/1813) # 3.6.1 + - 修复部分组件 'regeneratorRuntime is not defined' 问题 [#1719](https://github.com/XiaoMi/hiui/issues/1719) -- 修复 `Slider` max 和min 受控问题 [#1703](https://github.com/XiaoMi/hiui/issues/1703) +- 修复 `Slider` max 和 min 受控问题 [#1703](https://github.com/XiaoMi/hiui/issues/1703) + # 3.6.0 + - 新增 `Table` 组件 rowExpandable 方法,对内嵌式表格中左侧箭头进行自定义[#1679](https://github.com/XiaoMi/hiui/issues/1679) - 新增 `Form` 组件新增 clearValidates 方法,用于清除表单校验 [#1691](https://github.com/XiaoMi/hiui/issues/1691) - 新增 `Form` 组件 getFieldsError、getFieldsValue 方法,用于静默获取表单状态 [#1680](https://github.com/XiaoMi/hiui/issues/1680) @@ -42,15 +92,15 @@ - 修复 `Modal` 组件 closeable 属性无效问题 [#1645](https://github.com/XiaoMi/hiui/issues/1645) - 修复 `Form` 组件 setFieldsValue 方式调用显示异常问题 [#1642](https://github.com/XiaoMi/hiui/issues/1642) - 修复 `Form` 组件中包裹多个 List 组件,值未展示问题 [#1649](https://github.com/XiaoMi/hiui/issues/1649) -- 修复 `Table` 组件 data值为带正负符号的数字类型字符串时,无法进行求和及平均值的问题 [#1616](https://github.com/XiaoMi/hiui/issues/1616) -- 修复 `Tabs` 组件 panes 数据源异步变更,导致Tabs.Pane重渲染时,底部高亮线偏移的问题 [#1651](https://github.com/XiaoMi/hiui/issues/1651) +- 修复 `Table` 组件 data 值为带正负符号的数字类型字符串时,无法进行求和及平均值的问题 [#1616](https://github.com/XiaoMi/hiui/issues/1616) +- 修复 `Tabs` 组件 panes 数据源异步变更,导致 Tabs.Pane 重渲染时,底部高亮线偏移的问题 [#1651](https://github.com/XiaoMi/hiui/issues/1651) - 修复 `DatePicker` 组件 type 为 timeperiod 在受控时,选择完成时间后该组件内容显示为空 [#1653](https://github.com/XiaoMi/hiui/issues/1653) - 修复 `Select` 组件在分组形态下,搜索功能无效 [#1655](https://github.com/XiaoMi/hiui/issues/1655) - 修复 `DatePicker` type 为 daterange 时,且 showTime 为 true 选择时间显示异常 [#1640](https://github.com/XiaoMi/hiui/issues/1640) - 修复 `Cascader` id 为 Number 类型时导致节点重复添加问题[#1648](https://github.com/XiaoMi/hiui/issues/1648) - 修复 `Tabs` 组件 onDelete、onAdd 等方法获取数据操作异常问题[#1676](https://github.com/XiaoMi/hiui/issues/1676) - 修复 `DatePicker` maxDate 属性设置日期后,月份禁用错误 [#1690](https://github.com/XiaoMi/hiui/issues/1690) -- 修复 `Upload` 在 type 为 drag 时,通过拖动文件上传,data数据不可更新[#1693](https://github.com/XiaoMi/hiui/issues/1693) +- 修复 `Upload` 在 type 为 drag 时,通过拖动文件上传,data 数据不可更新[#1693](https://github.com/XiaoMi/hiui/issues/1693) - 修复 `DatePicker` 在 type 为 daterange 时, 时间区间选择同一天无效问题[#1688](https://github.com/XiaoMi/hiui/issues/1688) ## 3.5.0 @@ -61,17 +111,17 @@ - 新增 `Form` SchemaForm 中 component 属性接受 ReactNode,SchemaForm 新增 updateSchema 更新函数 [#1612](https://github.com/XiaoMi/hiui/issues/1612) - 新增 `DatePicker` onSelect 选择日期的回调函数 [#1592](https://github.com/XiaoMi/hiui/issues/1592) - 新增 `Transfer` 组件 render 自定义菜单渲染函数 [#1575](https://github.com/XiaoMi/hiui/issues/1575) -- 优化 `Select` 组件异步类型时,searchable 属性可控制筛选框的显示隐藏 [#1577](https://github.com/XiaoMi/hiui/issues/1577) -- 优化 `DatePicker` type 为 week 形态时显示内容 [#1587](https://github.com/XiaoMi/hiui/issues/1587) -- 修复 `DatePicker` type 为 week 或者 weekrange 时 输入相应格式日期解析错误问题 [#1579](https://github.com/XiaoMi/hiui/issues/1579) +- 优化 `Select` 组件异步类型时,searchable 属性可控制筛选框的显示隐藏 [#1577](https://github.com/XiaoMi/hiui/issues/1577) +- 优化 `DatePicker` type 为 week 形态时显示内容 [#1587](https://github.com/XiaoMi/hiui/issues/1587) +- 修复 `DatePicker` type 为 week 或者 weekrange 时 输入相应格式日期解析错误问题 [#1579](https://github.com/XiaoMi/hiui/issues/1579) - 修复 `Form` 触发 onValuesChange 数据更新出现旧值问题 [#1618](https://github.com/XiaoMi/hiui/issues/1618) -- 修复 `DatePicker` type 为 timeperiod 时,设置 timeInterval 分钟显示不正确问题 [#1604](https://github.com/XiaoMi/hiui/issues/1604) +- 修复 `DatePicker` type 为 timeperiod 时,设置 timeInterval 分钟显示不正确问题 [#1604](https://github.com/XiaoMi/hiui/issues/1604) - 修复 `Preview` 图片预览组件,滚轮放大缩小错误 [#1573](https://github.com/XiaoMi/hiui/issues/1573) - 修复 `TimePicker` 时间范围选择,为空时无法选择打开弹窗时的当前值 [#1530](https://github.com/XiaoMi/hiui/issues/1530) -- 修复 `Collapse` onChange 属性未传入控制台报错问题 [#1580](https://github.com/XiaoMi/hiui/issues/1580) +- 修复 `Collapse` onChange 属性未传入控制台报错问题 [#1580](https://github.com/XiaoMi/hiui/issues/1580) - 修复 `Select` 组件在异步多选时,关闭弹层下拉选项内容丢失问题 [#1578](https://github.com/XiaoMi/hiui/issues/1578) -- 修复 `Table` 组件 data值为数字类型字符串时,无法进行求和及平均值的问题 [#1616](https://github.com/XiaoMi/hiui/issues/1616) - +- 修复 `Table` 组件 data 值为数字类型字符串时,无法进行求和及平均值的问题 [#1616](https://github.com/XiaoMi/hiui/issues/1616) + ## 3.4.0 - 优化组件弹出层自动计算合适的左右位置 [#1494](https://github.com/XiaoMi/hiui/issues/1494) @@ -84,12 +134,12 @@ - 修复 `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) +- 修复 `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) +- 优化 `Drawer` 组件支持 className 属性 [#1536](https://github.com/XiaoMi/hiui/issues/1536) ## 3.3.0 @@ -116,7 +166,7 @@ - 修复 `Loading` children 不存在时,设置 visible 为 false 无效的问题 [#1461](https://github.com/XiaoMi/hiui/issues/1461) - 优化 `Tabs` 组件弹出层样式[#1437](https://github.com/XiaoMi/hiui/issues/1437) - 优化 `DatePicker` 类型为 week 时输入框显示内容以及周起始方式 [#1475](https://github.com/XiaoMi/hiui/issues/1475) -- 优化 `Progress` width、height 属性支持传入String类型 [#1480](https://github.com/XiaoMi/hiui/issues/1480) +- 优化 `Progress` width、height 属性支持传入 String 类型 [#1480](https://github.com/XiaoMi/hiui/issues/1480) ## 3.2.0 @@ -265,4 +315,3 @@ ## 1.x [更新日志汇总](https://github.com/XiaoMi/hiui/blob/stable/1.x/CHANGELOG.md) - diff --git a/components/alert/index.d.ts b/components/alert/index.d.ts index 71b87c0e2..37a746d80 100644 --- a/components/alert/index.d.ts +++ b/components/alert/index.d.ts @@ -1,6 +1,6 @@ import React from 'react' -interface AlertProps { +export interface AlertProps { prefixCls?: string style?: React.CSSProperties className?: string diff --git a/components/badge/Badge.js b/components/badge/Badge.js index 2b73de7b5..989f7372a 100755 --- a/components/badge/Badge.js +++ b/components/badge/Badge.js @@ -22,19 +22,25 @@ class Badge extends Component { render() { const { content, prefixCls, max, type, visible, style, color, offset = [] } = this.props - const [left, top] = offset - const badage = + const _style = { + backgroundColor: color, + marginTop: offset[1] || 0, + marginRight: -(offset[0] || 0) + } + + const badgeNode = type === 'dot' ? ( - + ) : ( - + {typeof content === 'number' ? (content > max ? max + '+' : content) : content} ) + return (
{this.props.children} - {visible && badage} + {visible ? badgeNode : null}
) } diff --git a/components/badge/index.d.ts b/components/badge/index.d.ts index 669c8e723..515bc5c2d 100644 --- a/components/badge/index.d.ts +++ b/components/badge/index.d.ts @@ -1,11 +1,12 @@ import React from 'react' -interface BadgeProps { +export interface BadgeProps { content?: string | number type?:'bubble' | 'dot' max?: number visible?: boolean color?: string + style?: CSSProperties offset?: [number | string, number | string] } diff --git a/components/badge/style/index.scss b/components/badge/style/index.scss index 31a65260f..efb0090a9 100755 --- a/components/badge/style/index.scss +++ b/components/badge/style/index.scss @@ -20,7 +20,6 @@ color: use-color('white'); letter-spacing: 0; text-align: center; - z-indx: 1; &.hi-hide { display: none; diff --git a/components/breadcrumb/index.d.ts b/components/breadcrumb/index.d.ts index ff4681e70..a9ccb44e1 100644 --- a/components/breadcrumb/index.d.ts +++ b/components/breadcrumb/index.d.ts @@ -1,4 +1,6 @@ -type DataItem = { +import React from 'react' + +export type BreadcrumbItem = { content: string | JSX.Element path?: string href?: boolean @@ -6,11 +8,12 @@ type DataItem = { target?: '_self' | '_blank' | '_parent' | '_top' } -interface Props { - data: DataItem[] +export interface BreadcrumbProps { + data: BreadcrumbItem[] separator?: string onClick?: (path: string) => void - } -declare const Breadcrumb: React.ComponentType + +declare const Breadcrumb: React.ComponentType + export default Breadcrumb diff --git a/components/button/index.d.ts b/components/button/index.d.ts index 306e3f158..2af12e2af 100644 --- a/components/button/index.d.ts +++ b/components/button/index.d.ts @@ -1,3 +1,5 @@ +import React from 'react' + export interface ButtonProps { type?: 'primary' | 'line' | 'success' | 'danger' | 'default' | 'warning' size?: 'large' | 'small' | 'normal' | 'default' @@ -11,7 +13,7 @@ export interface ButtonProps { icon?: string onClick?: () => void } -interface ButtonGroupProps { +export interface ButtonGroupProps { className?: string style?: object prefixCls?: string diff --git a/components/card/index.d.ts b/components/card/index.d.ts index 557782911..f651a1c0a 100644 --- a/components/card/index.d.ts +++ b/components/card/index.d.ts @@ -1,4 +1,5 @@ -interface Props { +import React from 'react' +export interface CardProps { title?: string | JSX.Element bordered?: boolean size?: 'small' | 'default' | 'large' @@ -8,10 +9,10 @@ interface Props { extraType?: 'default' | 'hover' coverUrl?: string content?: string | JSX.Element - style?: CSSProperties + style?: React.CSSProperties className?: string showHeaderDivider?: boolean } -declare class Card extends React.Component { +declare class Card extends React.Component { } export default Card diff --git a/components/carousel/index.d.ts b/components/carousel/index.d.ts index aab7f57d8..6bd80bf22 100644 --- a/components/carousel/index.d.ts +++ b/components/carousel/index.d.ts @@ -1,12 +1,13 @@ -interface Props { +import React from 'react' +export interface CarouselProps { duration?: number showDots?: boolean showArrows?: boolean defaultActive?: number showPages?: boolean children: JSX.Element[] - style?: CSSProperties + style?: React.CSSProperties className?: string } -declare const Carousel: React.ComponentType +declare const Carousel: React.ComponentType export default Carousel diff --git a/components/carousel/index.js b/components/carousel/index.js index e2257bbb2..d2e8d7507 100644 --- a/components/carousel/index.js +++ b/components/carousel/index.js @@ -18,21 +18,28 @@ class Carousel extends Component { this.timer = null } - componentDidMount() { + resizeRootWidth = () => { this.setState( { rootWidth: this.rootRef.current.clientWidth }, () => { if (this.props.duration) { + this.timer && window.clearInterval(this.timer) this.autoPage() } } ) } + componentDidMount() { + this.resizeRootWidth() + window.addEventListener('resize', this.resizeRootWidth) + } + componentWillUnmount() { this.timer && window.clearInterval(this.timer) + window.removeEventListener('resize', this.resizeRootWidth) } autoPage() { diff --git a/components/cascader/Cascader.js b/components/cascader/Cascader.js index 66e4bdb6e..75a3158e1 100644 --- a/components/cascader/Cascader.js +++ b/components/cascader/Cascader.js @@ -1,7 +1,16 @@ import React, { useRef, useState, useCallback, useEffect } from 'react' - -import classNames from 'classnames' import _ from 'lodash' +import classNames from 'classnames' + +import { + getLabelKey, + getValueKey, + getChildrenKey, + parseData, + getCascaderLabel, + getSearchId, + getfilterOptions +} from './utils' import Popper from '../popper' import Menu from './Menu' @@ -26,78 +35,33 @@ const Cascader = (props) => { localeDatas, onChange = noop, onActiveItemChange = noop, - bordered = true + bordered = true, + data: propsData, + options: propsOptions, + onOpen, + onClose } = props - const getLabelKey = useCallback(() => { - return fieldNames.label || 'content' - }, []) - - const getValueKey = useCallback(() => { - return fieldNames.value || 'id' - }, []) + const initData = _.cloneDeep(propsData || propsOptions) + const cacheData = useRef([]) + const [data, setData] = useState(parseData(initData, fieldNames)) + useEffect(() => { + // useEffect 无法监控到数组 栈值的改变 + if (!_.isEqual(cacheData.current, initData)) { + cacheData.current = initData + setData(parseData(initData, fieldNames)) + } + }, [initData]) - 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) { - return displayRender(values) - } - - if (!values || values.length === 0) { - return '' - } else { - const labels = [] - let index = 0 - let _options = dataList || data - const labelKey = getLabelKey() - const valueKey = getValueKey() - const childrenKey = getChildrenKey() - - while (_options && _options.length > 0 && labels.length <= values.length) { - const value = values[index] - index++ - _options.every((option) => { - if (option[valueKey] === value) { - labels.push(option[labelKey]) - _options = option[childrenKey] - return false - } else { - _options = [] - return true - } - }) - } - return labels.join(' / ') - } - }, - [data] - ) const [filterOptions, setFilterOptions] = useState(false) // 缓存原始value,用户可能点击option但是没选中,用于恢复初始value const [cacheValue, setCacheValue] = useState(value || defaultValue || []) + // 选中态 value const [cascaderValue, setCascaderValue] = useState(value || defaultValue || []) - const [cascaderLabel, setCascaderLabel] = useState(getCascaderLabel(value || defaultValue || [])) + const [cascaderLabel, setCascaderLabel] = useState( + getCascaderLabel(value || defaultValue || [], fieldNames, displayRender, data) + ) const [focusOptionIndex, setFocusOptionIndex] = useState(-1) const targetByKeyDown = useRef(false) const currentDeep = useRef(0) @@ -117,18 +81,26 @@ const Cascader = (props) => { useEffect(() => { setFocusOptionIndex(-1) currentDeep.current = 0 + if (onOpen && popperShow) { + const dataSource = onOpen() + if (dataSource && dataSource.toString() === '[object Promise]') { + dataSource.then((res) => { + setData(parseData(res, fieldNames)) + }) + } + if (Array.isArray(onOpen)) { + setData(parseData(dataSource, fieldNames)) + } + } }, [popperShow]) useEffect(() => { - setCascaderLabel(getCascaderLabel(cacheValue)) setCascaderValue(cacheValue) }, [cacheValue]) - const extraClass = { - 'hi-cascader--disabled': disabled, - 'hi-cascader--focused': popperShow, - 'hi-cascader--clearable': clearable - } + useEffect(() => { + setCascaderLabel(getCascaderLabel(cacheValue, fieldNames, displayRender, data)) + }, [cacheValue, data]) const onChangeValue = useCallback( (values, hasChildren) => { @@ -184,109 +156,13 @@ const Cascader = (props) => { setPopperShow(false) return } - let filterOptions = [] const initMatchOptions = { options: [], matchCount: 0 } - const labelKey = getLabelKey() - const valueKey = getValueKey() - const childrenKey = getChildrenKey() - const _checkOptions = (options, match) => { - options.map((option) => { - const label = option[labelKey] - const value = option[valueKey] - const children = option[childrenKey] - if (label.toString().includes(keyword) || value.toString().includes(keyword)) { - match.matchCount++ - } - - match.options.push({ - [labelKey]: label, - [valueKey]: value, - disabled: option.disabled - }) - - if (children && children.length > 0) { - _checkOptions(children, match) - } else { - if (match.matchCount > 0) { - filterOptions.push(match.options.slice()) - } - } - if (label.toString().includes(keyword) || value.toString().includes(keyword)) { - match.matchCount-- - } - - match.options.pop() - }) - } - - _checkOptions(data, initMatchOptions) - - const ids = getSearchId(filterOptions, keyword) - + let filterOptions = getfilterOptions(data, initMatchOptions, fieldNames, keyword) + const ids = getSearchId(filterOptions, keyword, filterOption, fieldNames) setCascaderValue(ids) filterOptions = formatFilterOptions(data, keyword) setPopperShow(true) }, [keyword, data]) - // 获取默认选中的最近的id - const getSearchId = useCallback((filterOptions, keyword) => { - const filterFunc = filterOption - const levelItems = [] - const levelItemsObj = {} - - const labelKey = getLabelKey() - const valueKey = getValueKey() - if (filterOptions.length === 0) { - return [] - } else { - filterOptions.map((options) => { - const jointOption = { - jointOption: true, - [labelKey]: [], - [valueKey]: [] - } - options.map((option, index) => { - const levelItem = { - [valueKey]: '' - } - - levelItem[valueKey] = jointOption[valueKey].concat(option[valueKey]) - - jointOption[valueKey].push(option[valueKey]) - option.disabled && (jointOption.disabled = option.disabled) - option.disabled && (levelItem.disabled = option.disabled) - - if (!levelItemsObj[levelItem[valueKey]]) { - levelItemsObj[levelItem[valueKey]] = levelItem[valueKey] - if (filterFunc) { - if ( - filterFunc(keyword, option) && - (levelItem[valueKey].toString().includes(keyword) || option[labelKey].toString().includes(keyword)) - ) { - levelItems.push(levelItem) - } - } else { - if (option[labelKey].toString().includes(keyword)) { - levelItems.push(levelItem) - } - } - } - }) - }) - } - if (levelItems.length === 0) { - return [] - } - - const ids = levelItems.map((item) => item.id) - let targetId = ids[0].join(',') - for (let i = 1; i < ids.length; i++) { - if (ids[i].join(',').includes(targetId)) { - targetId = ids[i].join(',') - } - } - - return targetId.split(',').map((item) => Number(item)) - }, []) // 配置化 const localeDatasProps = useCallback((key) => { @@ -294,9 +170,9 @@ const Cascader = (props) => { }, []) const formatFilterOptions = useCallback((data, keyword) => { - const labelKey = getLabelKey() - const valueKey = getValueKey() - const childrenKey = getChildrenKey() + const labelKey = getLabelKey(fieldNames) + const valueKey = getValueKey(fieldNames) + const childrenKey = getChildrenKey(fieldNames) if (data.length === 0) { return [] @@ -397,7 +273,7 @@ const Cascader = (props) => { _data = optionIndexs.reduce((deepData, current, index) => { if (index === 0) return deepData const _index = optionIndexs[index - 1] - return deepData[_index][getChildrenKey()] + return deepData[_index][getChildrenKey(fieldNames)] }, data) return _data || [] }, @@ -448,7 +324,7 @@ const Cascader = (props) => { optionValues.push(_data[item].id) }) const currentItem = getDeepData(l - 1)[optionIndexs[l - 1]] || {} - const children = currentItem[getChildrenKey()] || [] + const children = currentItem[getChildrenKey(fieldNames)] || [] const hasChildren = !!children.length onChangeValue(optionValues, hasChildren) let index = 0 @@ -514,7 +390,11 @@ const Cascader = (props) => { }, [moveFocusedIndex, rightHandle, leftHandle] ) - + const extraClass = { + 'hi-cascader--disabled': disabled, + 'hi-cascader--focused': popperShow, + 'hi-cascader--clearable': clearable + } const expandIcon = popperShow ? 'icon-up' : 'icon-down' const placeholder = cascaderLabel || localeDatasProps('placeholder') return ( @@ -570,6 +450,7 @@ const Cascader = (props) => { placement="top-bottom-start" onClickOutside={() => { setPopperShow(false) + onClose && onClose() }} > { theme={theme} isFiltered={filterOptions} filterOptionWidth={hiCascader.current && hiCascader.current.clientWidth} - valueKey={getValueKey()} - labelKey={getLabelKey()} - childrenKey={getChildrenKey()} + valueKey={getValueKey(fieldNames)} + labelKey={getLabelKey(fieldNames)} + childrenKey={getChildrenKey(fieldNames)} onSelect={onChangeValue} onHover={onHover} currentDeep={currentDeep} diff --git a/components/cascader/Menu.js b/components/cascader/Menu.js index d692bb036..88eb65ac2 100644 --- a/components/cascader/Menu.js +++ b/components/cascader/Menu.js @@ -39,64 +39,67 @@ const Menu = forwardRef( // currentDeep.current = deep if ((isFiltered && value.length > deep) || !isFiltered) { menus.push( -
    - {_currentOptions.length === 0 && } - {_currentOptions.map((option, index) => { - const optionValue = option[valueKey] - const hasChildren = Array.isArray(option[childrenKey]) - const isExpanded = hasChildren && optionValue === currentValue - const expandIcon = 'icon-right' - const { _path } = option - const _deep = deep - const optionValues = option.jointOption ? optionValue : getOptionValues(value, optionValue, deep) // jointOption为true代表搜索拼接出来的option,直接取value即可 - if (isExpanded) { - currentOptions = option[childrenKey] - } - return ( -
  • { - e.stopPropagation() - if (!option.disabled) { - onSelect(optionValues, hasChildren) - targetByKeyDown.current = false - setFocusOptionIndex(_path) - currentDeep.current = _deep - } - }} - onMouseEnter={(e) => { - e.stopPropagation() - if (!option.disabled && expandTrigger === 'hover') { - onHover(optionValues, hasChildren) - targetByKeyDown.current = false - setFocusOptionIndex(_path) - currentDeep.current = _deep - } - }} - key={optionValue + option[labelKey]} - > - - {isFiltered && option.hightlight - ? (option.hightlight || []).map((item, index) => {item}) - : option[labelKey]} - - {hasChildren && } -
  • - ) - })} -
+ +
    + {_currentOptions.map((option, index) => { + const optionValue = option[valueKey] + const hasChildren = Array.isArray(option[childrenKey]) + const isExpanded = hasChildren && optionValue === currentValue + const expandIcon = 'icon-right' + const { _path } = option + const _deep = deep + const optionValues = option.jointOption ? optionValue : getOptionValues(value, optionValue, deep) // jointOption为true代表搜索拼接出来的option,直接取value即可 + if (isExpanded) { + currentOptions = option[childrenKey] + } + return ( +
  • { + e.stopPropagation() + if (!option.disabled) { + onSelect(optionValues, hasChildren) + targetByKeyDown.current = false + setFocusOptionIndex(_path) + currentDeep.current = _deep + } + }} + onMouseEnter={(e) => { + e.stopPropagation() + if (!option.disabled && expandTrigger === 'hover') { + onHover(optionValues, hasChildren) + targetByKeyDown.current = false + setFocusOptionIndex(_path) + currentDeep.current = _deep + } + }} + key={optionValue + option[labelKey]} + > + + {isFiltered && option.hightlight + ? (option.hightlight || []).map((item, index) => {item}) + : option[labelKey]} + + {hasChildren && ( + + )} +
  • + ) + })} +
+
) deep++ } diff --git a/components/cascader/index.d.ts b/components/cascader/index.d.ts index 988b01fad..3a2df0451 100644 --- a/components/cascader/index.d.ts +++ b/components/cascader/index.d.ts @@ -1,33 +1,36 @@ -type DataItem = { - content: string +import React from 'react' +export type CascaderItem = { id: string | number + content: string disabled?: boolean + children?: CascaderItem[] } -type FieldNames = { +export type CascaderFieldNames = { label?: string value?: string children?: string } -interface Props { - fieldNames?: FieldNames - data: DataItem +export interface CascaderProps { + fieldNames?: CascaderFieldNames + data: CascaderItem value: string[] | number[] defaultValue: string[] | number[] expandTrigger?: 'click' | 'hover' searchable?: boolean bordered?: boolean - filterOption?: (keyword: string, item: DataItem) => boolean + filterOption?: (keyword: string, item: CascaderItem) => boolean clearable?: boolean disabled?: boolean changeOnSelect?: boolean placeholder?: string - emptyContent?: string | JSX.Element + emptyContent?: string | React.ReactNode displayRender?: (value: string[] | number[]) => string - style?: object onChange?: (value: string[] | number[]) => void + onOpen?: () => void + onClose?: () => void overlayClassName?: string - style?: CSSProperties + style?: React.CSSProperties className?: string } -declare const Card: React.ComponentType -export default Card +declare const Cascader: React.ComponentType +export default Cascader diff --git a/components/cascader/utils.js b/components/cascader/utils.js new file mode 100644 index 000000000..3c6d735aa --- /dev/null +++ b/components/cascader/utils.js @@ -0,0 +1,160 @@ +import _ from 'lodash' + +export const getLabelKey = (fieldNames = {}) => { + return fieldNames.label || 'content' +} + +export const getValueKey = (fieldNames = {}) => { + return fieldNames.value || 'id' +} + +export const getChildrenKey = (fieldNames = {}) => { + return fieldNames.children || 'children' +} +export const parseData = (data, fieldNames) => { + const _data = _.cloneDeep(data) + const setDataItemPath = (data = [], parent) => { + data.forEach((item, index) => { + item._path = parent ? parent._path + '-' + index : index + if (item[getChildrenKey(fieldNames)]) { + setDataItemPath(item[getChildrenKey()], item) + } + }) + } + setDataItemPath(_data) + return _.cloneDeep(_data) +} + +export const getCascaderLabel = (values, fieldNames, displayRender, data, dataList) => { + if (displayRender) { + return displayRender(values) + } + + if (!values || values.length === 0) { + return '' + } else { + const labels = [] + let index = 0 + let _options = dataList || data + const labelKey = getLabelKey(fieldNames) + const valueKey = getValueKey(fieldNames) + const childrenKey = getChildrenKey(fieldNames) + + while (_options && _options.length > 0 && labels.length <= values.length) { + const value = values[index] + index++ + _options.every((option) => { + if (option[valueKey] === value) { + labels.push(option[labelKey]) + _options = option[childrenKey] + return false + } else { + _options = [] + return true + } + }) + } + if (!(Array.isArray(data) && data.length > 0) && labels.length === 0) { + return values.join(' / ') + } + return labels.join(' / ') + } +} + +export const getSearchId = (filterOptions, keyword, filterOption, fieldNames) => { + const filterFunc = filterOption + const levelItems = [] + const levelItemsObj = {} + + const labelKey = getLabelKey(fieldNames) + const valueKey = getValueKey(fieldNames) + if (filterOptions.length === 0) { + return [] + } else { + filterOptions.map((options) => { + const jointOption = { + jointOption: true, + [labelKey]: [], + [valueKey]: [] + } + options.map((option, index) => { + const levelItem = { + [valueKey]: '' + } + + levelItem[valueKey] = jointOption[valueKey].concat(option[valueKey]) + + jointOption[valueKey].push(option[valueKey]) + option.disabled && (jointOption.disabled = option.disabled) + option.disabled && (levelItem.disabled = option.disabled) + + if (!levelItemsObj[levelItem[valueKey]]) { + levelItemsObj[levelItem[valueKey]] = levelItem[valueKey] + if (filterFunc) { + if ( + filterFunc(keyword, option) && + (levelItem[valueKey].toString().includes(keyword) || option[labelKey].toString().includes(keyword)) + ) { + levelItems.push(levelItem) + } + } else { + if (option[labelKey].toString().includes(keyword)) { + levelItems.push(levelItem) + } + } + } + }) + }) + } + if (levelItems.length === 0) { + return [] + } + + const ids = levelItems.map((item) => item.id) + let targetId = ids[0].join(',') + for (let i = 1; i < ids.length; i++) { + if (ids[i].join(',').includes(targetId)) { + targetId = ids[i].join(',') + } + } + + return targetId.split(',').map((item) => Number(item)) +} + +export const getfilterOptions = (data, initMatchOptions, fieldNames, keyword) => { + const filterOptions = [] + const labelKey = getLabelKey(fieldNames) + const valueKey = getValueKey(fieldNames) + const childrenKey = getChildrenKey(fieldNames) + const _checkOptions = (options, match) => { + options.map((option) => { + const label = option[labelKey] + const value = option[valueKey] + const children = option[childrenKey] + if (label.toString().includes(keyword) || value.toString().includes(keyword)) { + match.matchCount++ + } + + match.options.push({ + [labelKey]: label, + [valueKey]: value, + disabled: option.disabled + }) + + if (children && children.length > 0) { + _checkOptions(children, match) + } else { + if (match.matchCount > 0) { + filterOptions.push(match.options.slice()) + } + } + if (label.toString().includes(keyword) || value.toString().includes(keyword)) { + match.matchCount-- + } + + match.options.pop() + }) + } + _checkOptions(data, initMatchOptions) + return filterOptions +} diff --git a/components/charts/index.d.ts b/components/charts/index.d.ts index b5cc0cd11..65c74c33c 100644 --- a/components/charts/index.d.ts +++ b/components/charts/index.d.ts @@ -1,8 +1,8 @@ -import React, { CSSProperties } from 'react' +import React from 'react' -interface ChartsProps { +export interface ChartsProps { option: object - style?: CSSProperties + style?: React.CSSProperties className?: string showLoading?: boolean } diff --git a/components/checkbox/index.d.ts b/components/checkbox/index.d.ts index 0ed189b3f..020cddbdb 100644 --- a/components/checkbox/index.d.ts +++ b/components/checkbox/index.d.ts @@ -1,34 +1,34 @@ -import { CSSProperties } from "react" +import React from "react" -type DataItem = { +export type CheckboxItem = { content: string | number id: string | number disabled?: boolean } -interface Props { +export interface CheckboxProps { autoFocus?: boolean checked?: boolean defaultChecked?: boolean disabled?: boolean indeterminate?: boolean className?: string - onChange?: (event: ChangeEvent) => void, + onChange?: (event: React.ChangeEvent) => void, focusable?: boolean } -interface GroupProps { +export interface CheckboxGroupProps { className?: string placement?: string - data: DataItem[] | string[] | number[] + data: CheckboxItem[] | string[] | number[] defaultValue?: string[] | number[] disabled?: boolean name?: string onChange?: (checkedList: string[] | number[]) => void - style?: CSSProperties + style?: React.CSSProperties value?: string[] | number[] } -declare class Group extends React.Component { +declare class Group extends React.Component { } -declare class Checkbox extends React.Component { +declare class Checkbox extends React.Component { static Group = Group } export default Checkbox diff --git a/components/collapse/Panel.jsx b/components/collapse/Panel.jsx index df0820be7..86d92ba2f 100644 --- a/components/collapse/Panel.jsx +++ b/components/collapse/Panel.jsx @@ -10,6 +10,7 @@ const Panel = ({ disabled = false, isActive, children, + extra, onClickPanel, showArrow, panels, @@ -91,6 +92,7 @@ const Panel = ({ > {showArrow && arrow === 'left' && }
{header}
+ {extra ?
{extra}
: null} {showArrow && arrow === 'right' && }
{children}
diff --git a/components/collapse/index.d.ts b/components/collapse/index.d.ts index 9de69bb7d..44b6d652f 100644 --- a/components/collapse/index.d.ts +++ b/components/collapse/index.d.ts @@ -1,22 +1,24 @@ -interface Props { +import React from "react" +export interface CollapseProps { accordion?: boolean defaultActiveId?: string | string[] activeId?: string | string[] | number | number[] arrowPlacement?: 'left' | 'right' showArrow?: boolean onChange?: () => void - children: Collapse.Panel - style?: CSSProperties + children: JSX.Element + style?: React.CSSProperties className?: string } -interface PanelProps { +export interface CollapsePanelProps { id?: string title?: string | JSX.Element disabled?: boolean + extra?: React.ReactNode } -declare class Panel extends React.Component { +declare class Panel extends React.Component { } -declare class Collapse extends React.Component { +declare class Collapse extends React.Component { static Panel = Panel } export default Collapse diff --git a/components/collapse/index.js b/components/collapse/index.js index 21c18f986..0a66174a0 100755 --- a/components/collapse/index.js +++ b/components/collapse/index.js @@ -17,7 +17,8 @@ class Collapse extends Component { type: PropTypes.string, // TODO:废弃 arrow: PropTypes.oneOf(['left', 'right']), // TODO:废弃,使用 arrowPlacement arrowPlacement: PropTypes.oneOf(['left', 'right']), - showArrow: PropTypes.bool + showArrow: PropTypes.bool, + extra: PropTypes.node } static defaultProps = { @@ -79,7 +80,7 @@ class Collapse extends Component { Children.forEach(children, (child, index) => { if (!child) return const key = child.props.id || child.key || String(index) - const { header, disabled, title } = child.props + const { header, disabled, title, extra } = child.props const isActive = accordion ? activeKey[0] === key : activeKey.includes(key) const props = { @@ -93,7 +94,8 @@ class Collapse extends Component { onClickPanel: disabled ? noop : () => this.onClickPanel(key), panels: children, panelContainer: this.panelContainer, - idx: index + idx: index, + extra } newChildren.push(React.cloneElement(child, props)) }) diff --git a/components/collapse/style/index.scss b/components/collapse/style/index.scss index b112e8ef7..ca767e988 100755 --- a/components/collapse/style/index.scss +++ b/components/collapse/style/index.scss @@ -25,6 +25,10 @@ line-height: 1; } + .collapse-item__extra { + margin-right: 12px; + } + > .collapse-item__icon { flex: none; margin-right: 10px; diff --git a/components/counter/index.d.ts b/components/counter/index.d.ts index 0b22e0848..0b19d0039 100644 --- a/components/counter/index.d.ts +++ b/components/counter/index.d.ts @@ -1,11 +1,13 @@ -interface ButtonProps { +import React from 'react' + +export interface CounterProps { value?: number defaultValue?: number step?: number min?: number max?: number disabled?: boolean - onChange?: (e: ChangeEvent) => void + onChange?: (e: React.ChangeEvent) => void } -declare const Counter: React.ComponentType +declare const Counter: React.ComponentType export default Counter diff --git a/components/date-picker/TimePicker.d.ts b/components/date-picker/TimePicker.d.ts index c5b93cfd1..f4e7739ee 100644 --- a/components/date-picker/TimePicker.d.ts +++ b/components/date-picker/TimePicker.d.ts @@ -1,12 +1,13 @@ -interface TimeProps extends CommonProps { +export interface TimeProps extends CommonProps { type?: 'default' | 'timerange' hourStep?: number minuteStep?: number secondStep?: number + placement?: string disabledHours?: () => number[] disabledMinutes?: (selectedHour: number) => number[] disabledSeconds?: (selectedHour: number, selectedMinute: number) => number[] - style?: CSSProperties + style?: React.CSSProperties className?: string } declare const TimePicker: React.ComponentType diff --git a/components/date-picker/components/Root.jsx b/components/date-picker/components/Root.jsx index f497e40a3..9744ba1ef 100644 --- a/components/date-picker/components/Root.jsx +++ b/components/date-picker/components/Root.jsx @@ -33,7 +33,7 @@ const Root = ({ } = useContext(DPContext) const [inputData, setInputData] = useState(outDate) const inputRef = useRef(null) - const [placeholders] = usePlaceholder({ + const placeholders = usePlaceholder({ type, showTime, placeholder, diff --git a/components/date-picker/components/Time.jsx b/components/date-picker/components/Time.jsx index e19ba8ce6..36f5037d7 100644 --- a/components/date-picker/components/Time.jsx +++ b/components/date-picker/components/Time.jsx @@ -14,7 +14,8 @@ const Time = ({ date, onChange, timeRangePanelType, startDate, currentDate }) => hourStep = 1, minuteStep = 1, secondStep = 1, - type: PropsType + type: PropsType, + showTime } = useContext(DPContext) const isShowHMS = () => { return { @@ -28,7 +29,7 @@ const Time = ({ date, onChange, timeRangePanelType, startDate, currentDate }) => // 设置Date的选中状态 const setDisableTime = (type, i, disabledTime = []) => { let isDisabled = disabledTime.includes(i) - if (PropsType === 'timerange' || PropsType === 'time' || PropsType === 'default') { + if (PropsType === 'timerange' || PropsType === 'time' || PropsType === 'default' || showTime) { if (timeRangePanelType === 'right') { const { hour, minute, second } = deconstructDate(startDate) const { hour: endHour, minute: endMinute } = date ? deconstructDate(date) : deconstructDate(new Date()) diff --git a/components/date-picker/components/TimeList.jsx b/components/date-picker/components/TimeList.jsx index ee0ffab17..8999956da 100644 --- a/components/date-picker/components/TimeList.jsx +++ b/components/date-picker/components/TimeList.jsx @@ -75,6 +75,7 @@ const TimeList = ({ type, datas, value, disabledList, onSelect, hourStep, minute } const scrollEvent = (e) => { e.persist() + e.stopPropagation() clearTimeout(timeRef.current) const st = e.target.scrollTop topValue1.current = st diff --git a/components/date-picker/hooks/usePlaceholder.js b/components/date-picker/hooks/usePlaceholder.js index 6d922ecc8..aa4278100 100644 --- a/components/date-picker/hooks/usePlaceholder.js +++ b/components/date-picker/hooks/usePlaceholder.js @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react' +import { useMemo } from 'react' const parsePlaceholder = ({ type, placeholder: _placeholder, showTime, localeDatas }) => { const typePlaceholder = localeDatas.datePicker.placeholders[type] @@ -12,21 +12,17 @@ const parsePlaceholder = ({ type, placeholder: _placeholder, showTime, localeDat if (_placeholder instanceof Array) { leftPlaceholder = _placeholder[0] rightPlaceholder = _placeholder[1] || _placeholder[0] - } else if (typeof placeholder === 'string') { + } else if (typeof _placeholder !== 'undefined') { leftPlaceholder = _placeholder rightPlaceholder = _placeholder } return [leftPlaceholder, rightPlaceholder] } const usePlaceholder = (args) => { - const { type } = args - const [placeholders, setPlaceholders] = useState([]) + const { type, showTime, placeholder, localeDatas } = args - useEffect(() => { - setPlaceholders(parsePlaceholder(args)) - }, [type]) - - return [placeholders] + const placeholders = useMemo(() => parsePlaceholder(args), [type, showTime, placeholder, localeDatas]) + return placeholders } export default usePlaceholder diff --git a/components/date-picker/index.d.ts b/components/date-picker/index.d.ts index 2697d64e8..43af00a94 100644 --- a/components/date-picker/index.d.ts +++ b/components/date-picker/index.d.ts @@ -1,21 +1,24 @@ +import React from 'react' export type DateRange = { start: Date | string | number | undefined | null end: Date | string | number | undefined | null } -type DateRangeString = { +export type DateRangeString = { start: string end: string } -type CalendarItem = { +export type CalendarItem = { date?: Date | string text?: string highlight?: boolean } -export interface CommonProps { + +interface CommonProps { value?: Date | string | number | DateRange | undefined | null defaultValue?: Date | string | number | DateRange | undefined | null disabled?: boolean + placement?: 'bottom-start' | 'top-start' | 'bottom' | 'top' clearable?: boolean placeholder?: string | string[] format?: string @@ -24,12 +27,13 @@ export interface CommonProps { onChange?: (date: Date | DateRange, dateStr: string | DateRangeString) => void onSelect?: (date: Date, isCompleted: boolean) => void } -type Shortcuts = { + +export type DatePickerShortcuts = { title: string range: Date[] | number[] } -interface DateProps extends CommonProps { +export interface DatePickerProps extends CommonProps { type?: 'date' | 'daterange' | 'year' | 'month' | 'week' | 'weekrange' | 'timeperiod' | 'yearrange' | 'monthrange' min?: Date minDate?: Date @@ -39,16 +43,19 @@ interface DateProps extends CommonProps { timeperiod?: number disabledDate?: (currentDate: Date) => boolean showTime?: boolean - shortcuts?: string[] | Shortcuts[] + shortcuts?: string[] | DatePickerShortcuts[] + disabledHours?: () => number[] + disabledMinutes?: (selectedHour: number) => number[] + disabledSeconds?: (selectedHour: number, selectedMinute: number) => number[] weekOffset?: 0 | 1 altCalendar?: CalendarItem altCalendarPreset?: 'zh-CN' | 'id-ID' dateMarkRender?: (currentDate: Date, today: Date) => JSX.Element dateMarkPreset?: 'zh-CN' overlayClassName?: string - style?: CSSProperties + style?: React.CSSProperties className?: string } -declare const DatePicker: React.ComponentType +declare const DatePicker: React.ComponentType export default DatePicker diff --git a/components/drawer/index.d.ts b/components/drawer/index.d.ts index 7b86c9baf..dc4978f09 100644 --- a/components/drawer/index.d.ts +++ b/components/drawer/index.d.ts @@ -1,6 +1,6 @@ -import { CSSProperties } from "react" +import React from "react" -interface Props { +export interface DrawerProps { title?: string | JSX.Element visible?: boolean closable?: boolean @@ -9,9 +9,10 @@ interface Props { width?: number footer?: JSX.Element placement?: 'left' | 'right' - onClose?: (e: MouseEvent) => void - style?: CSSProperties + onClose?: (e: React.MouseEvent) => void + style?: React.CSSProperties className?: string } -declare const Drawer: React.ComponentType + +declare const Drawer: React.ComponentType export default Drawer diff --git a/components/dropdown/index.d.ts b/components/dropdown/index.d.ts index 75e4538a1..b8457fbf9 100644 --- a/components/dropdown/index.d.ts +++ b/components/dropdown/index.d.ts @@ -1,6 +1,6 @@ -import { CSSProperties } from "react" +import React from "react" -type DataItem = { +export type DropdownItem = { title: string | JSX.Element id: string | number disabled?: boolean @@ -8,22 +8,22 @@ type DataItem = { target?: '_self' | '_blank' | '_parent' | '_top' } -interface TriggersArray { +export interface TriggersArray { [index: number]: 'click' | 'contextmenu' | 'hover' } -interface Props { +export interface DropdownProps { trigger?: TriggersArray[number] | TriggersArray - data: DataItem[] + data: DropdownItem[] title: string | JSX.Element type?: 'text' | 'button' | 'group' placement?: 'bottom-start' | 'top-start' | 'bottom' | 'top' disabled?: boolean width?: number className?: string - style?: CSSProperties + style?: React.CSSProperties onClick?: (id: string | number) => void - onButtonClick?: (event: MouseEvent) => void + onButtonClick?: (event: React.MouseEvent) => void overlayClassName?: string } -declare const Dropdown: React.ComponentType +declare const Dropdown: React.ComponentType export default Dropdown diff --git a/components/filter/index.d.ts b/components/filter/index.d.ts index 042916248..f1c95fdd6 100644 --- a/components/filter/index.d.ts +++ b/components/filter/index.d.ts @@ -1,16 +1,18 @@ -type DataItem = { +import React from "react" + +export type FilterItem = { id?: string | number content?: string | JSX.Element disabled?: boolean } -export interface Props { +export interface FilterProps { label?: string[] labelWidth?: number showUnderline?: boolean - data?: DataItem[] + data?: FilterItem[] defaultValue?: string[] | number[] value?: string[] | number[] onChange?: (value: number | string) => void } -declare const Filter: React.ComponentType +declare const Filter: React.ComponentType export default Filter diff --git a/components/form/Form.js b/components/form/Form.js index c201b9543..c31e7961e 100644 --- a/components/form/Form.js +++ b/components/form/Form.js @@ -46,10 +46,10 @@ const InternalForm = (props) => { const _fields = _Immutable.current.currentStateFields() const { listNames } = _Immutable.current.currentState() _fields.forEach((item) => { - const { field } = item + const { realField } = item // eslint-disable-next-line no-prototype-builtins - if (_values.hasOwnProperty(field)) { - const value = values[field] + if (_values.hasOwnProperty(realField)) { + const value = values[realField] item.value = value item.setValue(value) } @@ -103,8 +103,8 @@ const InternalForm = (props) => { Object.keys(changeValues).forEach((changeValuesKey) => { fields.forEach((filedItem) => { - const { field, _type, listname } = filedItem - if (field === changeValuesKey && _type === 'list') { + const { realField, _type, listname } = filedItem + if (realField === changeValuesKey && _type === 'list') { _changeValues[listname] = _transformValues[listname] delete _changeValues[changeValuesKey] } @@ -120,7 +120,7 @@ const InternalForm = (props) => { (resetNames) => { let _fields = _Immutable.current.currentStateFields() _fields = _fields.filter((childrenField) => { - return Array.isArray(resetNames) ? resetNames.includes(childrenField.field) : true + return Array.isArray(resetNames) ? resetNames.includes(childrenField.realField) : true }) _fields.forEach((item) => { item.clearValidate() @@ -136,14 +136,14 @@ const InternalForm = (props) => { let _fields = _Immutable.current.currentStateFields() const { listNames, listValues } = _Immutable.current.currentState() _fields = _fields.filter((childrenField) => { - return Array.isArray(resetNames) ? resetNames.includes(childrenField.field) : true + return Array.isArray(resetNames) ? resetNames.includes(childrenField.realField) : true }) _fields.forEach((item) => { - const { field, listname } = item - const changeFieldkey = listname || field + const { realField, listname } = item + const changeFieldkey = listname || realField const isToDefault = toDefault && initialValues && typeof initialValues[changeFieldkey] !== 'undefined' - const value = isToDefault ? initialValues[field] : '' + const value = isToDefault ? initialValues[realField] : '' const changeFieldVal = isToDefault ? initialValues[changeFieldkey] : '' changeValues[changeFieldkey] = changeFieldVal allValues[changeFieldVal] = value @@ -190,13 +190,13 @@ const InternalForm = (props) => { return } const _fields = fields.filter((fieldChild) => { - const { field, value } = fieldChild - values[field] = value - return Array.isArray(validateNames) ? validateNames.includes(field) : true + const { realField, value } = fieldChild + values[realField] = value + return Array.isArray(validateNames) ? validateNames.includes(realField) : true }) _fields.forEach((fieldChild) => { - const { field, value } = fieldChild + const { value, realField } = fieldChild // 对指定的字段进行校验 其他字段过滤不校验 fieldChild.validate( '', @@ -205,7 +205,7 @@ const InternalForm = (props) => { const errorsMsg = error.map((err) => { return err.message }) - errors[field] = { errors: errorsMsg } + errors[realField] = { errors: errorsMsg } } }, value, @@ -224,12 +224,12 @@ const InternalForm = (props) => { const errors = {} const fields = _.cloneDeep(_Immutable.current.currentStateFields()) const _fields = fields.filter((fieldChild) => { - const { field } = fieldChild - return Array.isArray(validateNames) ? validateNames.includes(field) : true + const { realField } = fieldChild + return Array.isArray(validateNames) ? validateNames.includes(realField) : true }) _fields.forEach((fieldChild) => { - const { field, value } = fieldChild + const { realField, value } = fieldChild // 对指定的字段进行校验 其他字段过滤不校验 fieldChild.validate( '', @@ -238,7 +238,7 @@ const InternalForm = (props) => { const errorsMsg = error.map((err) => { return err.message }) - errors[field] = { errors: errorsMsg } + errors[realField] = { errors: errorsMsg } } }, value, @@ -259,12 +259,12 @@ const InternalForm = (props) => { } fields .filter((fieldChild) => { - const { field } = fieldChild - return Array.isArray(validateNames) ? validateNames.includes(field) : true + const { realField } = fieldChild + return Array.isArray(validateNames) ? validateNames.includes(realField) : true }) .forEach((item) => { - const { field, value } = item - values[field] = value + const { realField, value } = item + values[realField] = value }) return transformValues(values, fields) }, @@ -276,7 +276,7 @@ const InternalForm = (props) => { let value const fields = _.cloneDeep(_Immutable.current.currentStateFields()) const field = fields.filter((fieldChild) => { - if (fieldChild.field === key) { + if (fieldChild.realField === key) { value = fieldChild.value return true } diff --git a/components/form/Item.js b/components/form/Item.js index 0b764e8c6..150656451 100644 --- a/components/form/Item.js +++ b/components/form/Item.js @@ -34,6 +34,7 @@ const FormItem = (props) => { children, label, required, + rules: rulesProp, className, showColon: shouldItemShowColon, style, @@ -45,9 +46,9 @@ const FormItem = (props) => { sort, uuid, column, - row + row, + realField } = props - const { showColon: shouldFormShowColon, initialValues = {}, @@ -59,7 +60,7 @@ const FormItem = (props) => { // 初始化FormItem的内容 const [value, setValue] = useState(_propsValue) const [error, setError] = useState('') - const eventInfo = useRef() + const eventInfo = useRef(null) const getItemfield = useCallback(() => { let _propsField = propsField if (_type === 'list' && name) { @@ -71,13 +72,23 @@ const FormItem = (props) => { const [field, setField] = useState(getItemfield()) const [validating, setValidating] = useState(false) + const childrenRef = useRef() + childrenRef.current = children + useEffect(() => { - const { eventName, e, args, componentProps } = eventInfo.current || {} - const _children = children || {} - const _props = componentProps || _children.props - eventName === 'onChange' && _props.onChange && _props.onChange(e, ...args) - eventName === 'onBlur' && _props.onBlur && _props.onBlur(e, ...args) - eventInfo.current = {} + const onChangeInfo = eventInfo.current + + if (onChangeInfo) { + const { e, args, componentProps } = onChangeInfo + const _children = childrenRef.current + const _props = componentProps || (_children && _children.props) + + if (_props && _props.onChange) { + _props.onChange(e, ...args) + } + } + + eventInfo.current = null }, [value]) useEffect(() => { @@ -91,12 +102,18 @@ const FormItem = (props) => { } }, [_propsValue, field]) + useEffect(() => { + updateField() + }, [rulesProp, required]) + // 更新 const updateField = (_value, triggerType) => { - const childrenFiled = { - value: _value, - ...updateFieldInfoToReducer() + const childrenFiled = updateFieldInfoToReducer() + + if (typeof _value !== 'undefined') { + childrenFiled.value = _value } + const { field } = childrenFiled if (field) { const _fields = _.cloneDeep(_Immutable.current.currentStateFields()) @@ -176,16 +193,16 @@ const FormItem = (props) => { } // Bug of `async-validator` const rules = getRules().map((item) => { - if (currentValue !== '') { + if (!!currentValue || currentValue === 0) { item.type = item.type || 'any' } return item }) - + const _field = realField || field const validator = new AsyncValidator({ - [field]: rules + [_field]: rules }) - const model = { [field]: currentValue } + const model = { [_field]: currentValue } validator.validate( model, { @@ -204,6 +221,7 @@ const FormItem = (props) => { ) const updateFieldInfoToReducer = () => { + const _realField = _type === 'list' ? field : realField || field return { field, rules: getRules(), @@ -219,7 +237,8 @@ const FormItem = (props) => { column, row, name, - updateField + updateField, + realField: _realField } } @@ -265,17 +284,38 @@ const FormItem = (props) => { const beObject = Object.prototype.toString.call(e) === '[object Object]' beObject && Object.prototype.toString.call(e.persist) === '[object Function]' && e.persist() const displayName = component && component.type && component.type.displayName - let value = + let nextValue = beObject && e.target && Object.prototype.hasOwnProperty.call(e.target, valuePropName) ? e.target[valuePropName] : e if (displayName === 'Counter') { - value = args[0] + nextValue = args[0] || 0 + } + + if (eventName === 'onChange') { + eventInfo.current = { + eventName, + e, + args, + componentProps, + value: nextValue + } + + handleField(eventName, nextValue) + setValue(nextValue) + } else if (eventName === 'onBlur') { + handleField(eventName, eventInfo.current ? eventInfo.current.value : value) + + // 处理 onBlur 事件 + const _children = childrenRef.current + const _props = componentProps || (_children && _children.props) + + if (_props && _props.onBlur) { + _props.onBlur(e, ...args) + } } - eventInfo.current = { eventName, e, args, componentProps, value } - setValue(value) - handleField(eventName, value) } + useEffect(() => { return () => { _type !== 'list' && @@ -285,6 +325,7 @@ const FormItem = (props) => { }) } }, []) + // jsx渲染方式 const renderChildren = () => { let _value = value @@ -294,17 +335,23 @@ const FormItem = (props) => { const isExist = _fields.some((item) => { return item.field === _field }) + const displayName = !!children && children.type && children.type.displayName + if (displayName === 'Counter' && _value === undefined) { + _value = 0 + } if (_field && !isExist) { _value = initialValues && typeof initialValues[field] !== 'undefined' ? initialValues[_field] : _value if (_type === 'list' && listItemValue) { _value = Object.keys(listItemValue).includes(name) ? listItemValue[name] : listItemValue } + const updateFieldInfoToReducerData = updateFieldInfoToReducer() _Immutable.current.setState({ type: FILEDS_INIT, payload: { value: _value, - ...updateFieldInfoToReducer(), - field: _field + ...updateFieldInfoToReducerData, + field: _field, + realField: _type === 'list' ? _field : updateFieldInfoToReducerData.realField } }) updateField(_value) @@ -338,6 +385,7 @@ const FormItem = (props) => { return null } const propChild = children ? children.props : {} + return Array.isArray(children) || !React.isValidElement(children) ? children : React.cloneElement(children, { diff --git a/components/form/List.js b/components/form/List.js index 0c01f0f67..dbfcf07dc 100644 --- a/components/form/List.js +++ b/components/form/List.js @@ -39,8 +39,7 @@ const List = (props) => { listItemValue: value, sort: index, column: index, - uuid, - name + uuid }) }) setListCount(cachelistCount) diff --git a/components/form/SchemaForm.js b/components/form/SchemaForm.js index eea5fac9c..a86a2a742 100644 --- a/components/form/SchemaForm.js +++ b/components/form/SchemaForm.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback, forwardRef } from 'react' +import React, { useState, useEffect, useCallback, useMemo, forwardRef } from 'react' import _ from 'lodash' import * as HIUI from '../' import Provider from '../context' @@ -48,6 +48,8 @@ const InternalSchemaForm = (props) => { setSchema(schemaProps) }, [schemaProps]) + const componentUUID = useMemo(() => parseInt((Math.random() * 9 + 1) * 100000), []) + const renderSchemaFormItem = useCallback(() => { if (Array.isArray(schema)) { return schema.map((schemaItem, index) => { @@ -61,12 +63,17 @@ const InternalSchemaForm = (props) => { } return React.createElement(FormItem, { ..._.omit(schemaItem, 'component', 'componentProps'), - key: component + index, + field: schemaItem.field + '&&' + componentUUID, + realField: schemaItem.field, + key: componentUUID + schemaItem.field, children: child }) }) } - }, [schema]) + }, [schema, componentUUID]) + + const schemaFormItems = useMemo(() => renderSchemaFormItem(), [renderSchemaFormItem]) + return (
{ ref={innerRef} _type="SchemaForm" > - {renderSchemaFormItem()} + {schemaFormItems} {childrenProps} {(submit || reset) && ( diff --git a/components/form/index.d.ts b/components/form/index.d.ts index fcb5343e8..ee1e8ca6d 100644 --- a/components/form/index.d.ts +++ b/components/form/index.d.ts @@ -1,7 +1,7 @@ -import { CSSProperties } from "react" +import React from "react" import { ButtonProps } from '../button' -type formData = { +type FormData = { [prop: string]: any } @@ -11,24 +11,24 @@ export interface FormListFieldData { column?: number name?: string } -interface FormListOperation { +export interface FormListOperation { add: () => void remove: (fieldItem: FormListFieldData) => void } -interface FormProps { - initialValues?: formData +export interface FormProps { + initialValues?: FormData rules?: object labelWidth?: string | number labelPlacement?: 'right' | 'left' | 'top' placement?: 'horizontal' | 'vertical' showColon?: boolean children: Form.Item - style?: CSSProperties + style?: React.CSSProperties className?: string onValuesChange?: (changedValues: object, allValues: object) => void } -interface ItemProps { +export interface FormItemProps { field?: string | string[] label?: string | JSX.Element name?: string @@ -39,35 +39,35 @@ interface ItemProps { labelWidth?: string required?: boolean showColon?: boolean - style?: CSSProperties + style?: React.CSSProperties className?: string } -interface SchemaItem extends ItemProps { +export interface FormSchemaItem extends FormItemProps { component?: string | JSX.Element componentProps?: string } -interface SchemaProps { - schema?: SchemaItem +export interface FormSchemaProps { + schema?: FormSchemaItem submit?: FormSubmit reset?: FormReset } -interface FormSubmit extends ButtonProps{ +export interface FormSubmit extends ButtonProps { onClick?: (value: object, errors: object) => void validate?: any[] } -interface FormReset extends ButtonProps{ +export interface FormReset extends ButtonProps { onClick?: () => void fields?: any[] toDefault?: boolean } -interface FormList { +export interface FormList { name?: string children?: (fields: FormListFieldData[], operation: FormListOperation) => React.ReactNode } -declare class Item extends React.Component { +declare class Item extends React.Component { } -declare class SchemaForm extends React.Component { +declare class SchemaForm extends React.Component { } declare class Form extends React.Component { static Item = Item diff --git a/components/form/style/index.scss b/components/form/style/index.scss index 5ef997703..b6acd36e6 100644 --- a/components/form/style/index.scss +++ b/components/form/style/index.scss @@ -51,6 +51,7 @@ &--label--top { padding-right: 0; text-align: left; + &.hi-form--inline { // 上下布局只在水平表单中自动填充高度 .hi-form-item__span { @@ -117,6 +118,7 @@ .hi-select__input, .hi-cascader__input-container, .hi-datepicker__input, + .hi-datepicker__picker, .tree-select__tag-wrapper, .hi-input { border-color: get-color($palette-secondary, 'danger'); diff --git a/components/form/utils.js b/components/form/utils.js index 9cfefa0ad..70cc813b4 100644 --- a/components/form/utils.js +++ b/components/form/utils.js @@ -2,8 +2,9 @@ import _ from 'lodash' // 需要做一个filed的规则解析 const tranformListValues = (field, listNestValues, value, listname) => { - const key = field.split('#')[1] - const keyName = field.split('#')[0] + const fieldSplit = field.split('#') + const key = fieldSplit[1] + const keyName = fieldSplit[0] if (listNestValues[listname][keyName]) { listNestValues[listname][keyName] = _.merge(listNestValues[listname][keyName], { [key]: value @@ -19,11 +20,11 @@ export const transformValues = (allvalue, fields) => { // 根据sort进行数据排列 const sortfields = _.sortBy(fields, ['sort']) sortfields.forEach((filedItem) => { - const { field, propsField, _type, listname } = filedItem + const { realField, propsField, _type, listname } = filedItem if (_type === 'list') { - if (propsField !== field) { + if (propsField !== realField) { listNestValues[listname] = listNestValues[listname] || {} - tranformListValues(field, listNestValues, allvalue[field], listname) + tranformListValues(realField, listNestValues, allvalue[realField], listname) Object.keys(listNestValues).forEach((key) => { const arr = [] Object.keys(listNestValues[key]).forEach((item) => { @@ -34,18 +35,18 @@ export const transformValues = (allvalue, fields) => { return } if (tranformValues[listname]) { - tranformValues[listname].push(allvalue[field]) + tranformValues[listname].push(allvalue[realField]) } else { - tranformValues[listname] = [allvalue[field]] + tranformValues[listname] = [allvalue[realField]] } } else { if (Array.isArray(propsField)) { const chainKeys = propsField.reduceRight((pre, next) => { return { [next]: pre } - }, allvalue[field]) + }, allvalue[realField]) tranformValues = _.merge(tranformValues, chainKeys) } else { - tranformValues = _.merge(tranformValues, { [field]: allvalue[field] }) + tranformValues = _.merge(tranformValues, { [realField]: allvalue[realField] }) } } }) diff --git a/components/grid/index.d.ts b/components/grid/index.d.ts index 938fbf4b7..6036c312d 100644 --- a/components/grid/index.d.ts +++ b/components/grid/index.d.ts @@ -1,15 +1,15 @@ import React from "react"; -interface GridProps {} +export interface GridProps {} -type BaseProps = { +export type BaseProps = { children?: React.ReactNode; style?: React.CSSProperties; id?: React.ReactText; className?: string; }; -interface RowProps extends BaseProps { +export interface RowProps extends BaseProps { justify?: | "flex-start" | "flex-end" @@ -19,7 +19,7 @@ interface RowProps extends BaseProps { gutter?: boolean; } -interface ColProps extends BaseProps { +export interface ColProps extends BaseProps { justify?: | "flex-start" | "flex-end" diff --git a/components/hi-base-table/index.d.ts b/components/hi-base-table/index.d.ts index bf5ed43d1..4330c71e1 100644 --- a/components/hi-base-table/index.d.ts +++ b/components/hi-base-table/index.d.ts @@ -155,7 +155,7 @@ declare module 'react-base-table' { readonly NONE: false; }; } - type FixedOption = { + export type FixedOption = { left?: string right?: string } diff --git a/components/hi-request/download.ts b/components/hi-request/download.ts index 7ba6e3773..c9a0ffcf7 100644 --- a/components/hi-request/download.ts +++ b/components/hi-request/download.ts @@ -45,7 +45,7 @@ const download = (options: HiRequestOptions) => { // 如果没有自定义文件名,则根据响应头部信息生成 function getDownloadFilename(response: AxiosResponse) { const contentDisposition = response?.headers?.['content-disposition'] - const serverFilename = decodeURI(contentDisposition?.split(';')[1]?.split('filename=')[1] || '未命名') + const serverFilename = decodeURIComponent(contentDisposition?.split(';')[1]?.split('filename=')[1] || '未命名') return serverFilename } diff --git a/components/icon/index.d.ts b/components/icon/index.d.ts index ce76f3e63..81b2302dd 100644 --- a/components/icon/index.d.ts +++ b/components/icon/index.d.ts @@ -1,11 +1,11 @@ import React from 'react' -interface IconProps { +export interface IconProps { style?: React.CSSProperties className?: string filled?: boolean name?: string - onClick?: (event: React.MouseEvent) => void + onClick?: (event: React.MouseEvent) => void } declare class Icon extends React.Component {} diff --git a/components/index.d.ts b/components/index.d.ts index 1487c76fa..d5e443df2 100644 --- a/components/index.d.ts +++ b/components/index.d.ts @@ -1,46 +1,95 @@ +/* eslint-disable import/export */ export { default as Button } from './button' -export { default as Card } from './card/index' +export * from './button' +export { default as Card } from './card' +export * from './card/index' export { default as Checkbox } from './checkbox' +export * from './checkbox' export { default as Carousel } from './carousel' +export * from './carousel' export { default as Cascader } from './cascader' +export * from './cascader' export { default as Collapse } from './collapse' +export * from './collapse' +export { default as Badge } from './badge' +export * from './badge' export { default as Counter } from './counter' +export * from './counter' export { default as DatePicker } from './date-picker' +export * from './date-picker' export { default as TimePicker } from './date-picker/TimePicker' +export * from './date-picker/TimePicker' export { default as Dropdown } from './dropdown' +export * from './dropdown' export { default as Form } from './form' +export * from './form' export { default as Grid } from './grid' +export * from './grid' export { default as Input } from './input' +export * from './input' export { default as Loading } from './loading' +export * from './loading' export { default as Menu } from './menu' +export * from './menu' export { default as Message } from './message' +export * from './message' export { default as Modal } from './modal' +export * from './modal' export { default as Notification } from './notification' +export * from './notification' export { default as Pagination } from './pagination' +export * from './pagination' export { default as Popover } from './popover' +export * from './popover' export { default as Progress } from './progress' +export * from './progress' export { default as Radio } from './radio' +export * from './radio' export { default as Rate } from './rate' +export * from './rate' export { default as Select } from './select' +export * from './select' export { default as Stepper } from './stepper' +export * from './stepper' export { default as Switch } from './switch' +export * from './switch' export { default as Table } from './table' +export * from './table' export { default as Tabs } from './tabs' +export * from './tabs' export { default as Tag } from './tag' +export * from './tag' export { default as Timeline } from './timeline' +export * from './timeline' export { default as Tooltip } from './tooltip' +export * from './tooltip' export { default as Transfer } from './transfer' +export * from './transfer' export { default as Tree } from './tree' +export * from './tree' export { default as Upload } from './upload' +export * from './upload' export { default as Watermark } from './watermark' +export * from './watermark' export { default as List } from './list' +export * from './list' export { default as SelectTree } from './select-tree' +export * from './select-tree' export { default as Filter } from './filter' +export * from './filter' export { default as Drawer } from './drawer' +export * from './drawer' export { default as Search } from './search' +export * from './search' export { default as Slider } from './slider' +export * from './slider' export { default as Preview } from './preview' +export * from './preview' export { default as Popper } from './popper' +export * from './popper' export { default as Icon } from './icon' +export * from './icon' export { default as Charts } from './charts' -export { ThemeContext, LocaleContext } from './context' +export * from './charts' + +export * from './context' diff --git a/components/input/Input.js b/components/input/Input.js index 1ba7816a2..a042da657 100644 --- a/components/input/Input.js +++ b/components/input/Input.js @@ -160,6 +160,9 @@ class Input extends Component { } value = format(value, type) + // 保证 onChange 拿到的是值是最新的 formatted value + e.target.value = value + this.props.onChange && this.props.onChange(e, valueTrue) this.props.value === undefined && this.setState({ value, valueTrue }) diff --git a/components/input/index.d.ts b/components/input/index.d.ts index 66ff8729c..700347365 100644 --- a/components/input/index.d.ts +++ b/components/input/index.d.ts @@ -1,4 +1,6 @@ -interface Props { +import React from 'react' + +export interface InputProps { type?: 'text' | 'textarea' | 'id' | 'tel' | 'card' | 'amount' | 'email' value?: string | number defaultValue?: string | number @@ -7,7 +9,7 @@ interface Props { disabled?: boolean clearable?: boolean placeholder?: string - style?: CSSProperties + style?: React.CSSProperties className?: string bordered?: boolean maxLength?: number @@ -20,5 +22,5 @@ interface Props { onInput?: (e: React.FormEvent) => void onChange?: (e: React.ChangeEvent) => void } -declare const Input: React.ComponentType +declare const Input: React.ComponentType export default Input diff --git a/components/list/index.d.ts b/components/list/index.d.ts index fde61e583..aae5267e7 100644 --- a/components/list/index.d.ts +++ b/components/list/index.d.ts @@ -1,19 +1,21 @@ +import React from 'react' import {PaginationProps} from '../pagination' -type DataItem = { + +export type ListItem = { title: string | JSX.Element titleTag?: string | JSX.Element titleTagType?: 'primary' | 'success' |'warning' | 'danger' description?: string | JSX.Element extra?: string | string[] avatar?: string - style?: CSSProperties + style?: React.CSSProperties className?: string } -interface Props { +export interface ListProps { type?: 'default' | 'card' - data: DataItem[] - renderItem?: (item: DataItem) => JSX.Element - action?: (item: DataItem) => JSX.Element + data: ListItem[] + renderItem?: (item: ListItem) => JSX.Element + action?: (item: ListItem) => JSX.Element actionPosition?: 'top' | 'center' |'bottom' split?: boolean pagination?: boolean | PaginationProps @@ -21,8 +23,8 @@ interface Props { hoverable?: boolean layout?: 'vertical' | 'horizontal' emptyText?: string | JSX.Element - style?: CSSProperties + style?: React.CSSProperties className?: string } -declare const List: React.ComponentType +declare const List: React.ComponentType export default List diff --git a/components/loading/index.d.ts b/components/loading/index.d.ts index 2f1cfc4e6..b9b9fe914 100644 --- a/components/loading/index.d.ts +++ b/components/loading/index.d.ts @@ -1,22 +1,23 @@ -interface Props { +import React from 'react' +export interface LoadingProps { size?: 'large' | 'default' | 'small' content?: string | JSX.Element visible?: boolean full?: boolean - style?: CSSProperties + style?: React.CSSProperties className?: string } -type Options = { +export type LoadingOptions = { content?: string | JSX.Element key: string | number duration?: number size?: 'large' | 'default' | 'small' } -const OpenFun: (target: HTMLElement, options: Options) => void +const OpenFun: (target: HTMLElement, options: LoadingOptions) => void const CloseFun: (key: string | number) => void -declare class Loading extends React.Component { +declare class Loading extends React.Component { static open = OpenFun static close = CloseFun } diff --git a/components/menu/index.d.ts b/components/menu/index.d.ts index 8ae822aa1..d14e15b93 100644 --- a/components/menu/index.d.ts +++ b/components/menu/index.d.ts @@ -1,24 +1,26 @@ -type DataItem = { +import React from 'react' + +export type MenuItem = { content: string | JSX.Element icon?: string | JSX.Element id: string | number disabled?: boolean - children?: DataItem[] + children?: MenuItem[] } -interface Props { - data: DataItem[] +export interface MenuProps { + data: MenuItem[] activeId?: string | number placement?: 'horizontal' | 'vertical' collapsed?: boolean showCollapse?: boolean showAllSubMenus?: boolean accordion?: boolean - style?: CSSProperties + style?: React.CSSProperties className?: string onClick?: (activeId: string | number, prevActiveId: string | number) => void onClickSubMenu?: (subMenuIndexs: number) => void onCollapse?: (collapsed: boolean) => void overlayClassName?: string } -declare const Menu: React.ComponentType +declare const Menu: React.ComponentType export default Menu diff --git a/components/message/index.d.ts b/components/message/index.d.ts index 7b3f93b12..f7d2a0bba 100644 --- a/components/message/index.d.ts +++ b/components/message/index.d.ts @@ -1,17 +1,18 @@ -interface Props { +import React from 'react' -} -type Options = { +export interface MessageProps {} + +export type MessageOptions = { type?: 'info' | 'success' | 'error' | 'warning' title: string duration?: number - style?: CSSProperties + style?: React.CSSProperties className?: string - onClick?: (event: MouseEvent) => void + onClick?: (event: React.MouseEvent) => void onClose?: () => void } -const OpenFun: (options: Options) => void -declare class Message extends React.Component { +const OpenFun: (options: MessageOptions) => void +declare class Message extends React.Component { static open = OpenFun } export default Message diff --git a/components/message/style/index.scss b/components/message/style/index.scss index 3aa840abd..587519d61 100755 --- a/components/message/style/index.scss +++ b/components/message/style/index.scss @@ -46,6 +46,7 @@ $color-map: ( .hi-message__title { color: use-color('black') !important; font-size: $font-size-normal; + word-break: break-word; } .hi-message__icon { diff --git a/components/modal/index.d.ts b/components/modal/index.d.ts index 6c090f799..cfcc37db2 100644 --- a/components/modal/index.d.ts +++ b/components/modal/index.d.ts @@ -1,5 +1,5 @@ -import { CSSProperties } from "react" -interface Props { +import React from "react" +export interface ModalProps { title?: string | JSX.Element visible?: boolean closeable?: boolean @@ -7,15 +7,20 @@ interface Props { cancelText?: string confirmText?: string size?: 'default' | 'large' - style?: CSSProperties + style?: React.CSSProperties footer?: JSX.Element | null - onCancel?: (e: MouseEvent) => void - onConfirm?: (e: MouseEvent) => void - style?: CSSProperties + onCancel?: (e: React.MouseEvent) => void + onConfirm?: (e: React.MouseEvent) => void + style?: React.CSSProperties className?: string + confirmLoading?: boolean } -const confirmFun: (options:Props) => void -declare class Modal extends React.Component { + +export interface ModalOptions extends ModalProps {} + +const confirmFun: (options: ModalOptions) => void + +declare class Modal extends React.Component { static confirm = confirmFun } export default Modal diff --git a/components/modal/index.jsx b/components/modal/index.jsx index cf82f72ec..b929018fe 100644 --- a/components/modal/index.jsx +++ b/components/modal/index.jsx @@ -32,6 +32,7 @@ const InternalModalComp = ({ showFooterDivider = true, footer, confirmText, + confirmLoading, cancelText, style, className, @@ -195,6 +196,7 @@ const InternalModalComp = ({ @@ -225,12 +233,12 @@ const code = [ codeDisabled: false } this.form = React.createRef() - + } getCode () { - + let countDownTime - + countDownTime = setInterval(()=>{ const {countDown} = this.state if(countDown-1 <=0){ @@ -253,7 +261,7 @@ const code = [ const { initialValues, singleList, codeLoading, formData, codeDisabled, countDown } = this.state const Row = Grid.Row const Col = Grid.Col - + return ( - + - + @@ -468,12 +476,12 @@ const code = [ /> - { console.log('Get form value:',values,errors)} } >提交 - {console.log('reset form')}} >重置 @@ -372,6 +372,95 @@ const code = [ ) } }` + }, + { + opt: ['受控 Rules'], + code: `import React from 'react' +import { Form, Radio, Input } from '@hi-ui/hiui'\n +class Demo extends React.Component { + constructor(props){ + super(props) + this.state = { + initialValues:{ + radio: 'Required', + price: '' + }, + formData: { + radio: 'Required', + price: '' + }, + radioList: [{ + content: 'Required', + id: 'Required' + },{ + content: 'UnRequired', + id: 'UnRequired' + }], + } + this.form = React.createRef() + } + render () { + const FormItem = Form.Item + const FormSubmit = Form.Submit + const FormReset = Form.Reset + const {initialValues, radioList, formData } = this.state + + const Row = Grid.Row + const Col = Grid.Col + + return ( + { + console.log('changedValues,allValues',changedValues,allValues) + this.setState({ + formData: allValues, + }) + }} + > + + 受控 Rules + + + + console.log("Radio data",data)}/> + + + + + + + + { + console.log('Get form value:',values,errors)} + }> + 提交 + + + {console.log('reset form')}} > + 重置 + + + + ) + } +}` } ] diff --git a/docs/demo/form/section-schema.jsx b/docs/demo/form/section-schema.jsx index 14c0eeaa1..e45b59a18 100644 --- a/docs/demo/form/section-schema.jsx +++ b/docs/demo/form/section-schema.jsx @@ -159,6 +159,193 @@ const code = [ } }` }, + { + opt: ['基础用法2'], + code: `import React from 'react' + import { Form,Counter} from '@hi-ui/hiui'\n + class Demo extends React.Component { + constructor(props){ + super(props) + this.defaultSchema = [ + { + label: '输入框1', + field: 'inputField', + rules: [ + { + required: true, + min: 5, + max: 16, + message: '输入框1', + trigger: 'onBlur', + type: 'array' + }, + ], + component: 'Input', + componentProps: { + placeholder: 'schema', + clearable: true, + style: { width: 300 }, + }, + }, + { + label: '下拉框1', + field: 'selectField', + component: 'Select', + rules: [{ required: true, message: '下拉框1', trigger: 'onBlur' }], + componentProps: { + placeholder: 'schema', + style: { width: 300 }, + data: [ + { title: '电视', id: '3', disabled: true }, + { title: '手机', id: '2' }, + { title: '笔记本', id: '4', disabled: true }, + { title: '生活周边', id: '5' }, + { title: '办公', id: '6' }, + ], + }, + }, + ] + this.state = { + schemas:this.defaultSchema, + type: 1 + } + this.formRef6 = React.createRef() + } + addSchema() { + const copySchema = [...this.defaultSchema] + copySchema.push({ + label: '输入框2', + field: 'inputField2', + rules: [ + { + required: true, + min: 5, + max: 16, + message: '输入框2', + trigger: 'onBlur', + }, + ], + component: 'Input', + componentProps: { + placeholder: 'schema', + clearable: true, + style: { width: 300 }, + }, + }) + return copySchema + } + subSchema() { + const copySchema = [...this.defaultSchema] + copySchema.push({ + label: '输入框2', + field: 'inputField2', + rules: [ + { + required: true, + min: 5, + max: 16, + message: '输入框2', + trigger: 'onBlur', + }, + ], + component: 'Input', + componentProps: { + placeholder: 'schema', + clearable: true, + style: { width: 300 }, + }, + }) + copySchema.splice(0, 1, { + label: '输入框3', + field: 'inputField3', + rules: [ + { + required: true, + min: 5, + max: 16, + message: '输入框3', + trigger: 'onBlur', + }, + ], + component: 'Input', + componentProps: { + placeholder: 'schema', + clearable: true, + style: { width: 300 }, + }, + }) + return copySchema + } + btnClick(idx) { + console.log('this.formRef6', this.formRef6) + this.formRef6.current.clearValidates() + let nSc = [] + switch (idx) { + case 2: + nSc = this.addSchema() + break + case 3: + nSc = this.subSchema() + break + default: + nSc = this.defaultSchema + break + } + console.log('nSc', nSc) + this.setState({ + schemas: nSc, + type: idx + }) + } + render () { + const {schemas, type} = this.state + const SchemaForm = Form.SchemaForm + + return ( +
+ + + + {console.log('schemas', schemas)} + { + console.log('value,errors', value, errors) + }, + }} + > + +
+ ) + } + }` + }, { opt: ['动态表单'], code: `import React from 'react' diff --git a/docs/demo/modal/section-async.jsx b/docs/demo/modal/section-async.jsx new file mode 100644 index 000000000..3ef629883 --- /dev/null +++ b/docs/demo/modal/section-async.jsx @@ -0,0 +1,49 @@ +import React from 'react' +import DocViewer from '../../../libs/doc-viewer' +import Button from '../../../components/button' +import Modal from '../../../components/modal' +const prefix = 'modal-async' +const desc = '通过 confirmLoading 控制确定按钮的 loading 状态,实现异步关闭' +const code = `import React from 'react' +import Button from '@hi-ui/hiui/es/button' +import Modal from '@hi-ui/hiui/es/modal'\n +class Demo extends React.Component { + constructor (props) { + super(props) + this.state = { + visible: false, + loading: false + } + } + cancelEvent () { + this.setState({loading: true}) + setTimeout(()=>{ + this.setState({ + visible: false, + loading: false + }) + },1000) + console.log("自定义关闭事件") + } + render(){ + return( +
+ + + 一些消息....
+ 一些消息...
+ 一些消息... +
+
+ ) + } +}` + +const DemoAsync = () => +export default DemoAsync diff --git a/docs/demo/select-tree/section-bread.jsx b/docs/demo/select-tree/section-bread.jsx index 9ae1d7fd7..9d186d65f 100644 --- a/docs/demo/select-tree/section-bread.jsx +++ b/docs/demo/select-tree/section-bread.jsx @@ -17,6 +17,7 @@ const code = [ { title: 'Node 0', id: '0', + disabled: true, children: [ { title: 'Child Node 0-0', diff --git a/docs/demo/select-tree/section-filter.jsx b/docs/demo/select-tree/section-filter.jsx index 1f5044770..115cc7c65 100644 --- a/docs/demo/select-tree/section-filter.jsx +++ b/docs/demo/select-tree/section-filter.jsx @@ -7,7 +7,7 @@ const desc = '通过搜索框定位目标数据' const defaultStr = `constructor () { super() this.state = { - value: '3', + value: [], singleList: [ { title: '手机类', @@ -101,7 +101,14 @@ class Demo extends React.Component { return ( { + console.log(val) + this.setState({ + value:val + }) + }} type='multiple' + value={this.state.value} data={singleList} /> ) diff --git a/docs/demo/select-tree/section-multiple.jsx b/docs/demo/select-tree/section-multiple.jsx index 1af174988..c29873ea6 100644 --- a/docs/demo/select-tree/section-multiple.jsx +++ b/docs/demo/select-tree/section-multiple.jsx @@ -2,7 +2,7 @@ import React from 'react' import DocViewer from '../../../libs/doc-viewer' import SelectTree from '../../../components/select-tree' const prefix = 'tree-select-multiple' -const rightOptions = ['基础', '默认值', '数据回显', '默认展开'] +const rightOptions = ['基础', '默认值', '数据回显', '默认展开', '数据转换'] const desc = '展示从多个收起的备选项中选出的一个选项' const defaultStr = `constructor () { super() @@ -16,6 +16,7 @@ const defaultStr = `constructor () { { title: 'Redmi系列', id: '0-0', + disabled: true, children: [{ id: '0-0-1', title: 'Redmi K30' @@ -139,8 +140,74 @@ class Demo extends React.Component { code: `import React from 'react' import SelectTree from '@hi-ui/hiui/es/select-tree'\n class Demo extends React.Component { - ${defaultStr} - + constructor () { + super() + this.state = { + value: ['0-0'], + singleList: [ + { + content: '手机类', + id: '0', + children: [ + { + content: 'Redmi系列', + id: '0-0', + disabled: true, + children: [{ + id: '0-0-1', + content: 'Redmi K30' + }, { + id: '0-0-2', + content: 'Redmi K30 Pro' + }, { + id: '0-0-3', + content: 'Redmi 10X 5G' + }, { + id: '0-0-4', + content: 'Redmi Note 8' + }, { + id: '0-0-5', + content: 'Redmi 9' + }, { + id: '0-0-6', + content: 'Redmi 9A' + }] + },{ + content: '小米手机', + id: '0-1', + children: [{ + id: '0-1-1', + content: '小米10 Pro' + }, { + id: '0-1-2', + content: '小米10' + }, { + id: '0-1-3', + content: '小米10 青春版 5G' + }, { + id: '0-1-4', + content: '小米MIX Alpha' + }] + }, + ] + }, + { + content: '电视', + id: '1', + children: [{ + content: '小米电视 大师 65英寸OLED', + id: '1-0' + }, { + content: 'Redmi 智能电视 MAX 98', + id: '1-1' + }, { + content: '小米电视4A 60英寸', + id: '1-2' + }] + } + ] + } + } render () { const { singleList } = this.state return ( @@ -148,12 +215,13 @@ class Demo extends React.Component { clearable type='multiple' data={singleList} + fieldNames={{title: 'content'}} defaultExpandIds={['1-0']} /> ) } }`, - opt: ['默认展开'] + opt: ['数据转换'] } ] const DemoType = () => ( diff --git a/docs/demo/select-tree/section-single.jsx b/docs/demo/select-tree/section-single.jsx index fa67f9593..48bdbcb53 100644 --- a/docs/demo/select-tree/section-single.jsx +++ b/docs/demo/select-tree/section-single.jsx @@ -3,7 +3,7 @@ import DocViewer from '../../../libs/doc-viewer' import SelectTree from '../../../components/select-tree' import Button from '../../../components/button' const prefix = 'tree-select-single' -const rightOptions = ['基础', '默认值', '无边框', '禁用', '默认展开'] +const rightOptions = ['基础', '默认值', '无边框', '禁用', '默认展开', '数据转换'] const desc = '展示从多个收起的备选项中选出的一个选项' const defaultJson = `constructor () { super() @@ -13,6 +13,7 @@ const defaultJson = `constructor () { { title: '手机类', id: '0', + disabled: true, children: [ { title: 'Redmi系列', @@ -164,6 +165,93 @@ const code = [ } }`, opt: ['无边框'] + }, + { + code: `import React from 'react' + import SelectTree from '@hi-ui/hiui/es/select-tree'\n + class Demo extends React.Component { + constructor () { + super() + this.state = { + value:['0'], + singleList: [ + { + content: '手机类', + id: '0', + disabled: true, + children: [ + { + content: 'Redmi系列', + id: '0-0', + children: [{ + id: '0-0-1', + content: 'Redmi K30' + }, { + id: '0-0-2', + content: 'Redmi K30 Pro' + }, { + id: '0-0-3', + content: 'Redmi 10X 5G' + }, { + id: '0-0-4', + content: 'Redmi Note 8' + }, { + id: '0-0-5', + content: 'Redmi 9' + }, { + id: '0-0-6', + content: 'Redmi 9A' + }] + },{ + content: '小米手机', + id: '0-1', + children: [{ + id: '0-1-1', + content: '小米10 Pro' + }, { + id: '0-1-2', + content: '小米10' + }, { + id: '0-1-3', + content: '小米10 青春版 5G' + }, { + id: '0-1-4', + content: '小米MIX Alpha' + }] + }, + ] + }, + { + content: '电视', + id: '1', + children: [{ + content: '小米电视 大师 65英寸OLED', + id: '1-0' + }, { + content: 'Redmi 智能电视 MAX 98', + id: '1-1' + }, { + content: '小米电视4A 60英寸', + id: '1-2' + }] + } + ] + } + } + render () { + const { value, singleList } = this.state + return ( + + ) + } + }`, + opt: ['数据转换'] } ] const DemoType = () => ( diff --git a/docs/demo/select/section-custom.jsx b/docs/demo/select/section-custom.jsx index b803c5d2d..949fff53a 100644 --- a/docs/demo/select/section-custom.jsx +++ b/docs/demo/select/section-custom.jsx @@ -1,6 +1,8 @@ import React from 'react' import DocViewer from '../../../libs/doc-viewer' import Select from '../../../components/select' +import Input from '../../../components/input' +import Button from '../../../components/button' const prefix = 'select-custom' const desc = ['选项结构:可自定义选项的信息结构或样式', '搜索条件:可自定义搜索条件的算法'] const rightOptions = ['选项结构', '搜索条件'] @@ -35,6 +37,12 @@ class Demo extends React.Component { onChange={(item) => { console.log('单选结果', item) }} + renderExtraFooter={()=>{ + return
+ + +
+ }} render={(item, isSelected) => { return ( @@ -92,6 +100,6 @@ class Demo extends React.Component { } ] const DemoCustom = () => ( - + ) export default DemoCustom diff --git a/docs/demo/select/section-type.jsx b/docs/demo/select/section-type.jsx index a33182d79..cdef142a7 100644 --- a/docs/demo/select/section-type.jsx +++ b/docs/demo/select/section-type.jsx @@ -1,7 +1,8 @@ -import React from 'react' +import React, { useState } from 'react' import DocViewer from '../../../libs/doc-viewer' import Select from '../../../components/select' import Tooltip from '../../../components/tooltip' +import Radio from '../../../components/radio' const prefix = 'alert-autoClose' const rightOptions = ['基础', '受控', '带默认值', '可清空', '无边框', '禁用'] const desc = '展示从多个收起的备选项中选出的一个选项' @@ -247,6 +248,12 @@ class Demo extends React.Component { } ] const DemoType = () => ( - + ) export default DemoType diff --git a/docs/demo/table/section-base.jsx b/docs/demo/table/section-base.jsx index 06c73ec16..564568469 100644 --- a/docs/demo/table/section-base.jsx +++ b/docs/demo/table/section-base.jsx @@ -2,13 +2,15 @@ import React from 'react' import DocViewer from '../../../libs/doc-viewer' import Table, { LegacyTable } from '../../../components/table' import Watermark from '../../../components/watermark' +import Icon from '../../../components/icon' const prefix = 'table-base' const desc = ['基础:展示二维数据', '斑马行:优化以行为主的阅读体验', '前端分页:数据量大时分页展示'] -const rightOptions = ['基础', '斑马行', '前端分页'] +const rightOptions = ['基础', '斑马行', '前端分页', '拖拽表格'] const code = [ { code: `import React from 'react' import Table from '@hi-ui/hiui/es/table'\n + import Icon from '@hi-ui/hiui/es/icon'\n class Demo extends React.Component { constructor(props){ super(props) @@ -27,20 +29,16 @@ const code = [ title: '规格', dataKey: 'size', width: 150 - }, { title: '单价', dataKey: 'price', width: 150 - }, - { title: '规格', dataKey: 'size', width: 150 - }, { title: '单价', @@ -277,6 +275,107 @@ const code = [ }`, opt: ['斑马行'] }, + { + code: `import React from 'react' + import Table from '@hi-ui/hiui/es/table'\n + class Demo extends React.Component { + constructor(props){ + super(props) + this.columns = [ + { + title: '商品名', + dataKey: 'name' + }, + { + title: '品类', + dataKey: 'type' + }, + { + title: '规格', + dataKey: 'size' + }, + { + title: '单价', + dataKey: 'price' + }, + { + title: '门店', + dataKey: 'address' + }, + { + title: '库存', + dataKey: 'stock' + } + ] + + this.data = [ + { + name: '小米9', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '3299.00', + address: '华润五彩城店', + stock: '29,000', + key: 1 + }, + { + name: '小米9 SE', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '1999.00', + address: '清河店', + stock: '10,000', + key: 2 + }, + { + name: '小米8', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '2599.00', + address: '双安店', + stock: '12,000', + key: 3 + }, + { + name: 'Redmi Note7', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '999.00', + address: '华润五彩城店', + stock: '140,000', + key: 4 + }, + { + name: '小米8 SE', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '699.00', + address: '双安店', + stock: '12,000', + key: 5 + } + ] + } + render() { + return { + console.log('开始拖拽', ...arg) + }} + onDrop={(...arg)=>{ + console.log('拖拽行放开时触发', ...arg) + return true + }} + onDropEnd={(...arg)=>{ + console.log('拖拽成功时触发', ...arg) + }} + /> + } + }`, + opt: ['拖拽表格'] + }, { code: `import React from 'react' import Table from '@hi-ui/hiui/es/table'\n @@ -425,7 +524,7 @@ const code = [ const DemoBase = () => ( { + console.log(a, b) + return a.price - b.price + } + }, + { + title: '规格', + dataKey: 'size', + width: 150 + + }, + { + title: '门店', + dataKey: 'address', + width: 150 + + }, + { + title: '库存', + dataKey: 'stock', + width: 150 + + } + ] + + this.data = [ + { + name: '小米9', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '3299.00', + address: '华润五彩城店', + stock: '29,000', + key: 1 + }, + { + name: '小米9 SE', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '1999.00', + address: '清河店', + stock: '10,000', + key: 2 + }, + { + name: '小米8', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '2599.00', + address: '双安店', + stock: '12,000', + key: 3 + }, + { + name: 'Redmi Note7', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '999.00', + address: '华润五彩城店', + stock: '140,000', + key: 4 + }, + { + name: '小米8 SE', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '699.00', + address: '双安店', + stock: '12,000', + key: 5 + } + ] + } + render() { + return
+ } + }`, + opt: ['排序'] + }, + { + code: `import React from 'react' + import Table from '@hi-ui/hiui/es/table'\n + import Icon from '@hi-ui/hiui/es/icon'\n + class Demo extends React.Component { + constructor(props){ + super(props) + this.data = [ + { + name: '小米9', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '3299.00', + address: '华润五彩城店', + stock: '29,000', + key: 1 + }, + { + name: '小米9 SE', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '1999.00', + address: '清河店', + stock: '10,000', + key: 2 + }, + { + name: '小米8', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '2599.00', + address: '双安店', + stock: '12,000', + key: 3 + }, + { + name: 'Redmi Note7', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '999.00', + address: '华润五彩城店', + stock: '140,000', + key: 4 + }, + { + name: '小米8 SE', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '699.00', + address: '双安店', + stock: '12,000', + key: 5 + } + ] + this.state = { + data: this.data + } + this.columns = [ + { + title: '商品名', + dataKey: 'name', + width: 150 + }, + { + title: '品类', + dataKey: 'type', + width: 150, + selectFilters: { + filterIcon: , + data: [ + { title:'电视', id:'3', disabled: true }, + { title:'手机', id:'2' }, + { title:'笔记本', id:'4', disabled: true }, + { title:'生活周边', id:'5' }, + { title:'办公', id:'6' }, + ], + renderExtraFooter: ()=>{ + return
+ + +
+ }, + type: 'multiple', + searchable: true, + optionWidth: 200, + onChange:(selectedIds, changedItem, changedItems) => { + console.log('多选结果', changedItems) + this.setState({ + filterSelectValue: selectedIds + }) + const filerTitle = changedItems.map(item=>{ + return item.title + }) + this.filterData(filerTitle, 'type') + } + } + }, + { + title: '单价', + dataKey: 'price', + width: 150, + filterDropdownClassName: 'table-customefilter', + filterIcon: , + filterDropdown: ({columnData, setFilterDropdownVisible}) => { + let keyWork = '' + return ( +
+ { + keyWork = e.target.value + }}/> +
+ + +
+
+ ) + }, + sorter: (a, b) => { + console.log(a, b) + return a.price - b.price + } + }, + { + title: '规格', + dataKey: 'size', + width: 150 + + }, + { + title: '门店', + dataKey: 'address', + width: 150 + + }, + { + title: '库存', + dataKey: 'stock', + width: 150 + + } + ] + } + + customfilterData(keyWord, label) { + this.setState({ + data: this.data.filter(item=>{ + return item[label].includes(keyWord) + }) + }) + } + filterData(filterTitle, label) { + this.setState({ + data: this.data.filter(item=>{ + return filterTitle.includes(item[label]) + }) + }) + } + render() { + return
+ } + }`, + opt: ['筛选'] + }, + { + code: `import React from 'react' + import Table from '@hi-ui/hiui/es/table'\n + import Icon from '@hi-ui/hiui/es/icon'\n + import Button from '@hi-ui/hiui/es/button'\n + class Demo extends React.Component { + constructor(props){ + super(props) + this.columns = [ + { + title: '商品名', + dataKey: 'name', + width: 150, + filterDropdownClassName: 'table-customefilter', + filterIcon: , + filterDropdown: ({columnData, setFilterDropdownVisible}) => { + let keyWork = '' + return ( +
+ { + keyWork = e.target.value + }}/> +
+ + +
+
+ ) + } + }, + { + title: '品类', + dataKey: 'type', + width: 150 + }, + { + title: '规格', + dataKey: 'size', + width: 150 + + }, + { + title: '单价', + dataKey: 'price', + width: 150, + sorter: (a, b) => { + console.log(a, b) + return a - b + } + }, + + { + title: '规格', + dataKey: 'size', + width: 150 + + }, + { + title: '门店', + dataKey: 'address', + width: 150 + + }, + { + title: '库存', + dataKey: 'stock', + width: 150 + + } + ] + this.state = { + data: [ + { + name: '小米9', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '3299.00', + address: '华润五彩城店', + stock: '29,000', + key: 1 + }, + { + name: '小米9 SE', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '1999.00', + address: '清河店', + stock: '10,000', + key: 2 + }, + { + name: '小米8', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '2599.00', + address: '双安店', + stock: '12,000', + key: 3 + }, + { + name: 'Redmi Note7', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '999.00', + address: '华润五彩城店', + stock: '140,000', + key: 4 + }, + { + name: '小米8 SE', + type: '手机', + size: '6G+64G 全息幻彩蓝', + price: '699.00', + address: '双安店', + stock: '12,000', + key: 5 + } + ] + } + } + filterData(keyWord, label) { + this.setState({ + data: this.state.data.filter(item=>{ + return item[label].includes(keyWord) + }) + }) + } + render() { + return
+ } + }`, + opt: ['自定义筛选'] + } +] + +const DemoBase = () => ( + +) +export default DemoBase diff --git a/docs/demo/table/section-special.jsx b/docs/demo/table/section-special.jsx index 17e3c4015..d52a6f814 100644 --- a/docs/demo/table/section-special.jsx +++ b/docs/demo/table/section-special.jsx @@ -171,7 +171,6 @@ const code = [ b: 'b-1-1', c: 'c-1-1', d: 'd-1-1', - isLeaf: true, key: row.key + '1-1' } ]) diff --git a/docs/demo/tree/section-normal.jsx b/docs/demo/tree/section-normal.jsx index 329c5bc07..58cb95319 100644 --- a/docs/demo/tree/section-normal.jsx +++ b/docs/demo/tree/section-normal.jsx @@ -23,7 +23,7 @@ const code = [ { id: 5, title: '前端' } ] }, - { id: 6, title: '产品' } + { id: 6, title: '产品', selectable: false } ] }, { id: 11, title: '小米', diff --git a/docs/zh-CN/components/alert.mdx b/docs/zh-CN/components/alert.mdx index f847ce28c..2b2e49d9b 100755 --- a/docs/zh-CN/components/alert.mdx +++ b/docs/zh-CN/components/alert.mdx @@ -38,7 +38,7 @@ import DemoAutoClose from '../../demo/alert/section-autoClose.jsx' | 参数 | 说明 | 类型 | 可选值 | 默认值 | | --------- | ------------------------ | -------------- | ------------------------------------------- | ------ | -| type | 警告提示类型 | string | 'info' \| 'success' \| 'error' \| 'warning' | 'info' | +| type | 警告提示类型 | string | 'primary' \| 'warning' \| 'success' \| 'danger' | 'primary' | | title | 警告提示标题 | string | - | - | | content | 警告提示内容 | string | - | - | | closeable | 是否可关闭 | boolean | true \| false | false | diff --git a/docs/zh-CN/components/cascader.mdx b/docs/zh-CN/components/cascader.mdx index 4aa773046..3d1883456 100644 --- a/docs/zh-CN/components/cascader.mdx +++ b/docs/zh-CN/components/cascader.mdx @@ -38,7 +38,7 @@ import DemoAdvanced from '../../demo/cascader/section-advanced.jsx' | defaultValue | 设置当前选中值默认值 (3.0 新增) | string[] | - | [] | | expandTrigger | 次级菜单的展开方式,可选 'click' 和 'hover' | string | 'click' \| 'hover' | 'click' | | searchable | 是否可搜索 | boolean | true \| false | false | -| bordered | 是否有边框 | boolean | true \| false | true | +| bordered | 是否有边框 | boolean | true \| false | true | | filterOption | 第一个参数为输入的关键字,第二个为数据项,返回值为 true 时将出现在结果项。仅在 searchable 为 true 时有效 | (keyword: string, item: DataItem) => boolean | - | - | | clearable | 是否可清空 | boolean | true \| false | true | | disabled | 是否禁止使用 | boolean | true \| false | false | @@ -54,6 +54,9 @@ import DemoAdvanced from '../../demo/cascader/section-advanced.jsx' | 名称 | 说明 | 类型 | 参数 | 返回值 | | -------- | ------------ | -------------------------- | ------------------ | ------ | | onChange | 选择后的回调 | (values: string[]) => void | values: 选中项集合 | - | +| onActiveItemChange | 选中项改变时的回调 | (values: string[]) => void | values: 选中项集合 | - | +| onOpen | 下拉菜单打开时回调 | () => void | - | - | +| onClose | 下拉菜单关闭时回调 | () => void | - | - | ## Type diff --git a/docs/zh-CN/components/charts.mdx b/docs/zh-CN/components/charts.mdx index b29a25583..92ca30356 100755 --- a/docs/zh-CN/components/charts.mdx +++ b/docs/zh-CN/components/charts.mdx @@ -8,7 +8,7 @@ 1. 安装 echarts && echarts-for-react ```shell -npm install echarts echarts-for-react --save +npm install echarts@4.9.0 echarts-for-react@2.0.16 --save ``` 2. 引入 Charts 组件 diff --git a/docs/zh-CN/components/collapse.mdx b/docs/zh-CN/components/collapse.mdx index eff446d04..345cc880a 100644 --- a/docs/zh-CN/components/collapse.mdx +++ b/docs/zh-CN/components/collapse.mdx @@ -45,6 +45,7 @@ import DemoAccordion from '../../demo/collapse/section-accordion.jsx' | id | 面板唯一标识 | string | - | - | | title | 面板标题 | string \| ReactNode | - | - | | disabled | 是否禁用面板 | boolean | true \| false | false | +| extra | 添加额外的元素 | ReactNode | - | - | ## Events diff --git a/docs/zh-CN/components/date-picker.mdx b/docs/zh-CN/components/date-picker.mdx index 06981d720..099ec6750 100755 --- a/docs/zh-CN/components/date-picker.mdx +++ b/docs/zh-CN/components/date-picker.mdx @@ -70,6 +70,9 @@ import DemoCalendar from '../../demo/date-picker/section-calendar.jsx' | dateMarkRender | 自定义日期的右上角标记 | (currentDate: Date, today: Date) => React.ReactNode | - | - | | dateMarkPreset | 预置日期的右上角标记(休 \| 班) | string | 'zh-CN' | 'zh-CN' | | overlayClassName | 下拉根元素的类名称 (3.0 新增) | string | - | - | +| disabledHours | 禁止选择的小时,仅在 showTime 开启时生效 | () => number[] \| number[] | - | - | +| disabledMinutes | 禁止选择的分钟,仅在 showTime 开启时生效 | (selectedHour: number) => number[] \| number[] | - | - | +| disabledSeconds | 禁止选择的秒数,仅在 showTime 开启时生效 | (selectedHour: number, selectedMinute: number) => number[] \| number[] | - | - | ## Events @@ -393,7 +396,7 @@ import DemoCalendar from '../../demo/date-picker/section-calendar.jsx'
-### localeData +### localeData `DatePicker.localeData(key?:String)` diff --git a/docs/zh-CN/components/form.mdx b/docs/zh-CN/components/form.mdx index 1a28dca04..a749aaa2d 100755 --- a/docs/zh-CN/components/form.mdx +++ b/docs/zh-CN/components/form.mdx @@ -68,6 +68,7 @@ import DemoSchema from '../../demo/form/section-schema.jsx' + ## useForm import DemoUseForm from '../../demo/form/section-useForm.jsx' @@ -175,7 +176,7 @@ import DemoUseForm from '../../demo/form/section-useForm.jsx' | row | 对应 `Form.Item` 中的row,表示列表的第几行 | string | - | - | | value | 需要更新的值 | any | - | - | -## rules +## Rules > [更多规则](https://github.com/yiminghe/async-validator) diff --git a/docs/zh-CN/components/input.mdx b/docs/zh-CN/components/input.mdx index 91d0b33da..3105b8abb 100755 --- a/docs/zh-CN/components/input.mdx +++ b/docs/zh-CN/components/input.mdx @@ -60,12 +60,12 @@ import DemoTextarea from '../../demo/input/section-textarea.jsx' ## Events -| 名称 | 说明 | 类型 | 参数 | 返回值 | -| ---------- | ------------------ | ------------------------------- | --------------------- | ------ | -| onFocus | 获得焦点时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | - | -| onBlur | 失去焦点时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | - | -| onKeyDown | 键盘按下时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | - | -| onKeyPress | 字符键按下时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | - | -| onInput | 输入字符时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | - | -| onChange | 值改变时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | - | -| onKeyUp | 键盘弹起时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | - | +| 名称 | 说明 | 类型 | 参数 | +| ---------- | ------------------ | ------------------------------- | --------------------- | +| onFocus | 获得焦点时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | +| onBlur | 失去焦点时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | +| onKeyDown | 键盘按下时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | +| onKeyPress | 字符键按下时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | +| onInput | 输入字符时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | +| onChange | 值改变时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | +| onKeyUp | 键盘弹起时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | diff --git a/docs/zh-CN/components/modal.mdx b/docs/zh-CN/components/modal.mdx index 3ee6c6bc6..d9cd6028e 100755 --- a/docs/zh-CN/components/modal.mdx +++ b/docs/zh-CN/components/modal.mdx @@ -14,6 +14,12 @@ import DemoBase from '../../demo/modal/section-base.jsx' +## 异步关闭 + +import DemoAsync from '../../demo/modal/section-async.jsx' + + + ## 自定义尺寸 import DemoSize from '../../demo/modal/section-size.jsx' @@ -46,17 +52,18 @@ import DemoTip from '../../demo/modal/section-tip.jsx' ## Props -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -| ------------- | -------------------------- | ------------------- | -------------------- | --------- | -| title | 模态框标题 | string \| ReactNode | - | - | -| visible | 是否显示模态框 | boolean | true \| false | false | -| closeable | 是否展示右上角关闭按钮 | boolean | true \| false | true | -| maskClosable | 是否允许点击蒙层关闭模态框 | boolean | true \| false | true | -| cancelText | 取消按钮文案 | string | - | '取消' | -| confirmText | 确认按钮文案 | string | - | '确定' | -| size | 模态框尺寸 | string | 'default' \| 'large' | 'default' | -| style | 自定义模态框样式 | object | - | - | -| footer | 自定义模态框底部 | ReactNode \| null | - | - | +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| -------------- | -------------------------- | ------------------- | -------------------- | --------- | +| title | 模态框标题 | string \| ReactNode | - | - | +| visible | 是否显示模态框 | boolean | true \| false | false | +| closeable | 是否展示右上角关闭按钮 | boolean | true \| false | true | +| maskClosable | 是否允许点击蒙层关闭模态框 | boolean | true \| false | true | +| cancelText | 取消按钮文案 | string | - | '取消' | +| confirmText | 确认按钮文案 | string | - | '确定' | +| confrimLoading | 确认按钮 loading 状态 | boolean | true \|false | - | +| size | 模态框尺寸 | string | 'default' \| 'large' | 'default' | +| style | 自定义模态框样式 | object | - | - | +| footer | 自定义模态框底部 | ReactNode \| null | - | - | ## Events @@ -69,13 +76,12 @@ import DemoTip from '../../demo/modal/section-tip.jsx' `Modal.confirm({onConfirm, onCancel, title, content, type, confirmText, cancelText})` -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -| --------- | ------------------------------------- | ----------- | -------------------------------------- | ------ | -| onConfirm | 确认事件触发时的回调 | () => void | - | - | -| onCancel | 取消事件触发时的回调 | () => void | - | - | -| title | confirm 的标题 | string | - | string | -| content | confirm 的内容 | string | - | - | -| type | confirm 的类型 | string | 'default' \| 'success' \| 'error' \| 'warning' \| 'info' | 'default' | -| cancelText | 取消按钮文案 | string | - | '取消' | -| confirmText | 确认按钮文案 | string | - | '确定' | - +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| ----------- | -------------------- | ---------- | -------------------------------------------------------- | --------- | +| onConfirm | 确认事件触发时的回调 | () => void | - | - | +| onCancel | 取消事件触发时的回调 | () => void | - | - | +| title | confirm 的标题 | string | - | string | +| content | confirm 的内容 | string | - | - | +| type | confirm 的类型 | string | 'default' \| 'success' \| 'error' \| 'warning' \| 'info' | 'default' | +| cancelText | 取消按钮文案 | string | - | '取消' | +| confirmText | 确认按钮文案 | string | - | '确定' | diff --git a/docs/zh-CN/components/preview.mdx b/docs/zh-CN/components/preview.mdx index 3abf195db..8ad9f746e 100644 --- a/docs/zh-CN/components/preview.mdx +++ b/docs/zh-CN/components/preview.mdx @@ -19,4 +19,11 @@ import DemoBase from '../../demo/preview/section-base.jsx' | showCount | 是否显示预览窗体上方图片数量 | boolean | true \| false | false | | images | 图片列表 | String[] \| Object[] | - | [] | | simpleData | 是否为简单数据 | boolean | true \| false | false | -| activeIndex | 激活图片索引,从0开始 | number | - | 0 | \ No newline at end of file +| activeIndex | 激活图片索引,从0开始 | number | - | 0 | + +# Events + +| 名称 | 说明 | 类型 | 参数 | 返回值 | +| ---------- | ------------------ | ------------------------------- | --------------------- | ------ | +| onError | 在点击的预览图片预览大图资源加载失败的回调函数 | (index: number) => void | **index** 当前图片的下标值 | - | +| onClose | 在点击关闭按钮回调函数 | () => void | - | - | diff --git a/docs/zh-CN/components/search.mdx b/docs/zh-CN/components/search.mdx index 9f167d7a4..84391a624 100755 --- a/docs/zh-CN/components/search.mdx +++ b/docs/zh-CN/components/search.mdx @@ -43,6 +43,7 @@ import DemoClassic from '../../demo/search/section-classic.jsx' | -------- | ------------------------------------------------------ | ------------------------------------------- | ------------------------------------------------------- | ------ | | onChange | 值改变时的回调 | (event: HTMLInputEvent) => void | event: input 事件对象 | - | | onSearch | 当点击搜索按钮时候、输入框内点击回车或者点击下拉选项时 | (inputVal: string, item ?:DataItem) => void | inputVal: 输入的搜索关键字
item: 选中的搜索关键项 | - | +| onBlur | 下拉框失焦时 | () => void | - | - | ## DataItem diff --git a/docs/zh-CN/components/select-tree.mdx b/docs/zh-CN/components/select-tree.mdx index fc8e17a7f..a43c0e850 100644 --- a/docs/zh-CN/components/select-tree.mdx +++ b/docs/zh-CN/components/select-tree.mdx @@ -41,28 +41,29 @@ import DemoBread from '../../demo/select-tree/section-bread' ## Props -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -| ------------------ | ----------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------ | -| data | 展示数据 | DataItem [] | - | - | -| showCheckedMode | 数据回显模式 | string | ALL: 所有被选中节点,不区分父子节点
PARENT: 当所有子节点被选中时将只保留父节点
CHILD:仅显示子节点 | ALL | -| mode | 数据展示形式 | string | normal \| breadcrumb | normal | -| type | 数据选择类型 | string | single \| multiple | single | -| bordered | 是否有边框 | boolean | true \| false | true | -| disabled | 是否禁用 | boolean | true \| false | false | -| defaultExpandAll | 是否默认展开所有树节点 | boolean | true \| false | false | -| defaultExpandIds | 默认高亮的节点(非受控) | string[] | - | - | -| defaultValue | 默认选中项 (非受控) | DataItem[] \| string[] \| string | - | - | -| value | 默认选中项 (受控) | DataItem[] \| string[] \| string | - | - | -| valueRender | 自定义渲染 Input 中展示内容 | (checkedNodes \| checkedNode) => ReactNode \| string | - | - | -| placeholder | 输入框占位 | string | - | 请选择 | -| searchMode | 节点搜索模式,仅在*mode=normal*模式下生效 | string | highlight \| filter | - | -| autoload | 从远端获取数据,初始时是否自动加载 | boolean | true \| false | false | -| dataSource | 异步加载数据 | (key: string) => DataSource \| DataSource \| Promise | - | - | -| emptyContent | 没有选项时的提示 | string \| ReactNode | - | 无内容 | -| optionWidth | 自定义下拉选项宽度 | number | - | | -| overlayClassName | 下拉根元素的类名称 (3.0 新增) | string | - | - | - - +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| ---------------- | ---------------------------------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | +| data | 展示数据 | DataItem [] | - | - | +| fieldNames | 设置 data 中 id, title, disabled, children 对应的 key (3.0 新增) | object | - | { title: 'title', id: 'id',disabled:'disabled', children: 'children'} | +| showCheckedMode | 数据回显模式 | string | ALL: 所有被选中节点,不区分父子节点
PARENT: 当所有子节点被选中时将只保留父节点
CHILD:仅显示子节点 | ALL | +| mode | 数据展示形式 | string | normal \| breadcrumb | normal | +| type | 数据选择类型 | string | single \| multiple | single | +| bordered | 是否有边框 | boolean | true \| false | true | +| disabled | 是否禁用 | boolean | true \| false | false | +| defaultExpandAll | 是否默认展开所有树节点 | boolean | true \| false | false | +| expandIds | 展开的节点(受控) | string[] | - | - | +| defaultExpandIds | 默认展开的节点(非受控) | string[] | - | - | +| defaultValue | 默认选中项 (非受控) | DataItem[] \| string[] \| string | - | - | +| value | 默认选中项 (受控) | DataItem[] \| string[] \| string | - | - | +| valueRender | 自定义渲染 Input 中展示内容 | (checkedNodes \| checkedNode) => ReactNode \| string | - | - | +| placeholder | 输入框占位 | string | - | 请选择 | +| searchMode | 节点搜索模式,仅在*mode=normal*模式下生效 | string | highlight \| filter | - | +| autoload | 从远端获取数据,初始时是否自动加载 | boolean | true \| false | false | +| dataSource | 异步加载数据 | (key: string) => DataSource \| DataSource \| Promise | - | - | +| emptyContent | 没有选项时的提示 | string \| ReactNode | - | 无内容 | +| optionWidth | 自定义下拉选项宽度 | number | - | | +| className | 自定义类名 | string | - | - | +| overlayClassName | 下拉根元素的类名称 (3.0 新增) | string | - | - | ## Events @@ -76,6 +77,7 @@ import DemoBread from '../../demo/select-tree/section-bread' | -------- | --------------- | ---------------- | ------ | ------ | | title | 下拉选项标题 | string | - | - | | id | 下拉选项唯一 id | string \| number | - | - | +| disabled | 是否禁用 | boolean | - | false | | children | 子级数据 | DataItem[] | - | - | ### DataSource diff --git a/docs/zh-CN/components/select.mdx b/docs/zh-CN/components/select.mdx index 0050cec3b..7c3fba429 100755 --- a/docs/zh-CN/components/select.mdx +++ b/docs/zh-CN/components/select.mdx @@ -62,39 +62,40 @@ import DemoSelectsearchbypinyin from '../../demo/select/section-searchbypinyin' ## Props -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -| ------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | -------------------------------------------- | --------------------------------------------------------------------- | -| type | 下拉框类型 | string | 'single' \| 'multiple' | 'single' | -| data | 下拉框选项数据源 | DataItem[] \| groupData[] | - | - | -| fieldNames | 设置 data 中 id, title, disabled, children 对应的 key (3.0 新增) | object | - | { title: 'title', id: 'id',disabled:'disabled', children: 'children'} | -| dataSource | 异步下拉框选项数据源 | DataSource (keyword: string) => (DataSource \| DataItem \| Promise) | - | - | -| value | 被选中项的值 | string \| string[] | - | - | -| defaultValue | 默认被选中项的值 | string \| string[] | - | - | -| showCheckAll | 是否显示**全选**,只对多选生效 | boolean | true \| false | false | -| showJustSelected | 是否显示**仅看已选**,只对多选生效 (3.0 新增) | boolean | true \| false | false | -| multipleWrap | 多选模式下是否允许选中结果折行,不建议折行因为会变成动态高度 | string | 'wrap' \| 'nowrap' | 'nowrap' | -| searchable | 是否可以筛选 | boolean | true \| false | false | -| filterOption | 第一个参数为输入的关键字,第二个为数据项,返回值为 true 时将出现在结果项。仅在 searchable 为 true 时有效 | (keyword: string, item: DataItem) => boolean | (keyword: string, item: DataItem) => boolean | - | -| clearable | 是否可以清空 | boolean | true \| false | true | -| autoload | origin 从远端获取数据,初始时是否自动加载 | boolean | true \| false | false | -| disabled | 是否禁用 | boolean | true \| false | false | -| placeholder | 输入框占位 | string | - | 请选择 | -| emptyContent | 没有选项时的提示 | string \| ReactNode | - | 无内容 | -| style | 自定义样式 | object | - | | -| bordered | 是否有边框 | boolean | true \| false | true | -| optionWidth | 自定义下拉选项宽度 | number | - | | -| render | 自定义下拉菜单渲染函数,回调值为选项数据和是否被选中 | (item: DataItem, selected: boolean) => ReactNode | - | 无内容 | -| overlayClassName | 下拉根元素的类名称 (3.0 新增) | string | - | - | -| onOverlayScroll | 下拉列表滚动时的回调 | function | - | - | -| onSearch | 下拉弹层中文本框值变化时回调 | function(value: string) | - | - | -| setOverlayContainer | 如遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位 (3.0 新增) | function(triggerNode) | - | () => document.body | +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| -------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | -------------------------------------------- | --------------------------------------------------------------------- | +| type | 下拉框类型 | string | 'single' \| 'multiple' | 'single' | +| data | 下拉框选项数据源 | DataItem[] \| groupData[] | - | - | +| fieldNames | 设置 data 中 id, title, disabled, children 对应的 key (3.0 新增) | object | - | { title: 'title', id: 'id',disabled:'disabled', children: 'children'} | +| dataSource | 异步下拉框选项数据源 | DataSource (keyword: string) => (DataSource \| DataItem \| Promise) | - | - | +| value | 被选中项的值 | string \| string[] | - | - | +| defaultValue | 默认被选中项的值 | string \| string[] | - | - | +| showCheckAll | 是否显示**全选**,只对多选生效 | boolean | true \| false | false | +| showJustSelected | 是否显示**仅看已选**,只对多选生效 (3.0 新增) | boolean | true \| false | false | +| multipleWrap:已废弃 | 多选模式下是否允许选中结果折行,不建议折行因为会变成动态高度 | string | 'wrap' \| 'nowrap' | 'nowrap' | +| searchable | 是否可以筛选 | boolean | true \| false | false | +| filterOption | 第一个参数为输入的关键字,第二个为数据项,返回值为 true 时将出现在结果项。仅在 searchable 为 true 时有效 | (keyword: string, item: DataItem) => boolean | (keyword: string, item: DataItem) => boolean | - | +| clearable | 是否可以清空 | boolean | true \| false | true | +| autoload | origin 从远端获取数据,初始时是否自动加载 | boolean | true \| false | false | +| disabled | 是否禁用 | boolean | true \| false | false | +| placeholder | 输入框占位 | string | - | 请选择 | +| emptyContent | 没有选项时的提示 | string \| ReactNode | - | 无内容 | +| style | 自定义样式 | object | - | | +| bordered | 是否有边框 | boolean | true \| false | true | +| optionWidth | 自定义下拉选项宽度 | number | - | | +| render | 自定义下拉菜单渲染函数,回调值为选项数据和是否被选中 | (item: DataItem, selected: boolean) => ReactNode | - | 无内容 | +| renderExtraFooter | 自定义下拉菜单底部渲染 | () => ReactNode | - | 无内容 | +| overlayClassName | 下拉根元素的类名称 (3.0 新增) | string | - | - | +| onOverlayScroll | 下拉列表滚动时的回调 | function | - | - | +| onSearch | 下拉弹层中文本框值变化时回调 | function(value: string) | - | - | +| setOverlayContainer | 如遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位 (3.0 新增) | function(triggerNode) | - | () => document.body | > 注意,如果发现下拉菜单跟随页面滚动,或者需要在其他弹层中触发 Select,请尝试使用 setOverlayContainer={triggerNode => triggerNode.parentElement} 将下拉弹层渲染节点固定在触发器的父元素中。 ## Events -| 名称 | 说明 | 类型 | 参数 | 返回值 | -| -------- | ------------------ | ------------------------------------------------------ | ---------------------------------------------------------------- | ------ | +| 名称 | 说明 | 类型 | 参数 | 返回值 | +| -------- | ------------------ | ------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------ | | onChange | 改变选项时触发函数 | (selectedIds: string[], changedItem: DataItem, changedItems:DataItem[]) => void | selectedIds: 所有选中项的 id 集合
changedItem: 变更的选项 | - | ## Type diff --git a/docs/zh-CN/components/stepper.mdx b/docs/zh-CN/components/stepper.mdx index 8081f6af4..3bdf97371 100755 --- a/docs/zh-CN/components/stepper.mdx +++ b/docs/zh-CN/components/stepper.mdx @@ -34,12 +34,13 @@ import DemoVertical from '../../demo/stepper/section-vertical.jsx' ## Props -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -| ---------- | ------------------------------- | ---------- | -------------------------- | ------------ | -| data | 步骤数据项源 | DataItem[] | - | - | -| current | 当前步骤位置索引,从 0 开始计数 | number | - | - | -| placement | 水平或垂直展示步骤条 | string | 'vertical' \| 'horizontal' | 'horizontal' | -| itemLayout | 步骤项的布局方式 | string | 'vertical' \| 'horizontal' | 'vertical' | +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| ---------- | ------------------------------- | ------------------------- | -------------------------- | ------------ | +| data | 步骤数据项源 | DataItem[] | - | - | +| current | 当前步骤位置索引,从 0 开始计数 | number | - | - | +| placement | 水平或垂直展示步骤条 | string | 'vertical' \| 'horizontal' | 'horizontal' | +| itemLayout | 步骤项的布局方式 | string | 'vertical' \| 'horizontal' | 'vertical' | +| onChange | 点击切换步骤时触发 | (current: number) => void | - | - | ## Type diff --git a/docs/zh-CN/components/table.mdx b/docs/zh-CN/components/table.mdx index 0154c259c..153f289ad 100755 --- a/docs/zh-CN/components/table.mdx +++ b/docs/zh-CN/components/table.mdx @@ -1,6 +1,5 @@ # Table 表格 - 可容纳多种数据类型的大型数据容器,并可支持多种数据相关和表格属性设置相关的操作,具有强大的统计功能 ## 何时使用 @@ -10,8 +9,10 @@ 当需要对一部分全部数据进行编辑、筛选过滤时 ## 特别说明 + - 按照 React 的规范,所有的数组组件必须绑定 key。Table 组件的 data 属性的每一列也需要指定一个 key 值来表明每一行数据的唯一性。同时基于综合考虑(性能、维护性、功能间的组合性等),当没有 key 传入的时候,组件内部并不会帮您生成 key。当 key 不存在时可能会引起一系列的问题,还请注意。 - 在进行列冻结时,一定要传入**列宽(width)**! + ## 基础用法 import DemoBase from '../../demo/table/section-base.jsx' @@ -31,12 +32,19 @@ import DemoRow from '../../demo/table/section-row.jsx' +## 自定义筛选 + +import Demofilter from '../../demo/table/section-filter.jsx' + + + ## 不同尺寸 import DemoSize from '../../demo/table/section-size.jsx' + ## 特殊表格 import DemoSpecial from '../../demo/table/section-special.jsx' @@ -51,53 +59,64 @@ import DemoAsync from '../../demo/table/section-async.jsx' ## Props -| 属性名 | 描述 | 类型 | 可选值 | 默认值 | -| ------------------ | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | ----------------------------------------- | ---------- | -| data | 表格数据 | object[] | - | - | -| columns | 表格列配置信息 | ColumnItem[] | - | - | -| bordered | 是否显示边框(表头分组模式下,表格自带边框) | boolean | true \| false | false | -| sticky | 是否支持表头吸顶 | boolean | true \| false | false | -| stickyTop | 表头吸顶距离视口顶部距离 | number | - | 0 | -| highlightedColKeys | 高亮列(受控) | string[] | - | [] | -| onLoadChildren | 点击异步加载子项 | (row: DataItem) => object[] \| Promise | - | - | -| expandedRender | 表格展开项 | (record: dataItem, index: number) => ReactNode \| Promise | - | - | -| rowExpandable | 设置是否允许行展开 | (record: dataItem ) => ReactNode \| Boolean | - | true | -| onExpand | 表格展开时的回调函数 | (expanded, row: object) => void | - | - | -| expandRowKeys | 内嵌式表格以及树形表格展开的行 | number[] | - | - | -| maxHeight | 表格最大高度,当穿过该高度时,展示滚动条且表头固定 | number | - | - | -| fixedToColumn | 表格列冻结设置,为 string 时仅支持从左侧冻结至某一列 | string \| FixedOption | columns 中对应的 dataKey | null | -| size | 配置表格尺寸 | string | 'large' \| 'default' \| 'small' \| 'mini' | 'default' | -| pagination | 表格分页配置项 | Pagination | - | null | -| errorRowKeys | 错误列(受控) | string[] | - | [] | -| highlightedRowKeys | 高亮行(受控) | string[] | - | [] | -| rowSelection | 行可选(受控) | RowSelection | - | null | -| dataSource | 异步数据源 | (current: number) => DataSource | - | null | -| showColMenu | 是否支持列操作 | boolean | - | false | -| striped | 是否展示为斑马纹效果 | boolean | - | false | -| setting | 是否集成控制面板功能 | boolean | - | false | -| emptyContent | 数据为空时的展示内容 | string \| () => ReactNode | - | '暂无数据' | -| resizable | 是否能够动态控制列宽 | boolean | true \| false | false | -| standard | 标准模式,默认集成 `showColMenu = true, sticky = true, bordered = true, setting = true, striped = true` | boolean | true \| false | false | -| loading | 加载中状态 | boolean | true \| false | false | -| scrollWidth | 表格滚动的宽度(当表格总设置宽度(含自适应列)大于表格父级容器宽度时需要设置)**3.7.0版本以后,该属性不建议使用** | number | - | - | -| showColHighlight | 表格某一列`hover`时,该列高亮 | boolean | true \| false | false | -| onHeaderRow | 行标题事件处理函数 | (item: ColumnItem[], index: number) => object | - | - | +| 属性名 | 描述 | 类型 | 可选值 | 默认值 | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------- | ----------------------------------------- | ---------- | +| data | 表格数据 | object[] | - | - | +| fieldKey | 指定 data 表格数据中某一属性为 key | string | - | 'key' | +| columns | 表格列配置信息 | ColumnItem[] | - | - | +| bordered | 是否显示边框(表头分组模式下,表格自带边框) | boolean | true \| false | false | +| sticky | 是否支持表头吸顶 | boolean | true \| false | false | +| stickyTop | 表头吸顶距离视口顶部距离 | number | - | 0 | +| highlightedColKeys | 高亮列(受控) | string[] | - | [] | +| expandedRender | 表格展开项 | (record: dataItem, index: number) => ReactNode \| Promise | - | - | +| rowExpandable | 设置是否允许行展开 | (record: dataItem ) => ReactNode \| Boolean | - | true | +| onExpand | 表格展开时的回调函数 | (expanded, row: object) => void | - | - | +| expandRowKeys | 内嵌式表格以及树形表格展开的行 | number[] | - | - | +| maxHeight | 表格最大高度,当穿过该高度时,展示滚动条且表头固定 | number | - | - | +| fixedToColumn | 表格列冻结设置,为 string 时仅支持从左侧冻结至某一列 | string \| FixedOption | columns 中对应的 dataKey | null | +| size | 配置表格尺寸 | string | 'large' \| 'default' \| 'small' \| 'mini' | 'default' | +| pagination | 表格分页配置项 | Pagination | - | null | +| errorRowKeys | 错误列(受控) | string[] | - | [] | +| highlightedRowKeys | 高亮行(受控) | string[] | - | [] | +| rowSelection | 行可选(受控) | RowSelection | - | null | +| dataSource | 异步数据源 | (current: number) => DataSource | - | null | +| showColMenu | 是否支持列操作 | boolean | - | false | +| striped | 是否展示为斑马纹效果 | boolean | - | false | +| setting | 是否集成控制面板功能 | boolean | - | false | +| emptyContent | 数据为空时的展示内容 | string \| () => ReactNode | - | '暂无数据' | +| resizable | 是否能够动态控制列宽 | boolean | true \| false | false | +| standard | 标准模式,默认集成 `showColMenu = true, sticky = true, bordered = true, setting = true, striped = true` | boolean | true \| false | false | +| loading | 加载中状态 | boolean | true \| false | false | +| scrollWidth | 表格滚动的宽度(当表格总设置宽度(含自适应列)大于表格父级容器宽度时需要设置)**3.7.0 版本以后,该属性不建议使用** | number | - | - | +| showColHighlight | 表格某一列`hover`时,该列高亮 | boolean | true \| false | false | +| draggable | 表格行可拖拽 | boolean | true \| false | false | + +## Event + +| 属性名 | 描述 | 类型 | 可选值 | 默认值 | +| -------------- | ------------------ | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | --- | +| onHeaderRow | 行标题事件处理函数 | (item: ColumnItem[], index: number) => object | - | - | +| onLoadChildren | 点击异步加载子项 | (row: DataItem) => object[] \| Promise | - | - | +| onDragStart | 开始拖拽时触发 | (rowData: object) => void | rowData: 当前行的数据 | - | +| onDrop | 拖拽行放开时触发 | (dragRowData: object, dropRowData: object, data: object, level: Level) => boolean | Promise | dragRowData: 拖拽的行数据
dropRowData: 目标行数据
data:当前结构数据
level:当前级别数据 | - | +| onDropEnd | 拖拽成功时触发 | (dragRowData: object, dropRowData: object, data: object) => void | dragRowData: 拖拽的行数据
dropRowData: 目标行数据
data: 拖拽完成后的结构数据 | - | > 在 onLoadChildren 方法中,返回的数据中会根据 `isLeaf` 字符控制左侧展开按钮的显示状态 ### onHeaderRow 使用方法 + ```js // demo 见【行操作-标题事件处理】 { return { - onClick: event => {}, // 点击行 - onDoubleClick: event => {}, - onContextMenu: event => {}, - onMouseEnter: event => {}, // 鼠标移入行 - onMouseLeave: event => {} - }; + onClick: (event) => {}, // 点击行 + onDoubleClick: (event) => {}, + onContextMenu: (event) => {}, + onMouseEnter: (event) => {}, // 鼠标移入行 + onMouseLeave: (event) => {} + } }} /> ``` @@ -106,17 +125,24 @@ import DemoAsync from '../../demo/table/section-async.jsx' ### ColumnItem -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -| -------- | ---------------------- | -------------------------------------------------------------------------------- | ----------------- | ------ | -| title | 列标题 | string | - | - | -| dataKey | 列对应数据项的唯一标识 | string \| number | - | - | -| align | 列对齐方式 | string | 'left' \| 'right' | 'left' | -| sorter | 列排序函数 | () => boolean | - | null | -| avg | 该列是否支持平均值 | boolean | - | false | -| total | 该列是否支持合计 | boolean | - | false | -| width | 该列宽度 | number | - | - | -| children | 多级表头 | ColumnItem[] | - | - | -| render | 控制单元格自定义渲染 | (text: DataItem[ColumnItem[dataKey]], row: DataItem, index: number, dataKey: string) => ReactNode | - | - | +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| ----------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ---------------------------- | ------ | +| title | 列标题 | string \| () => ReactNode | - | - | +| dataKey | 列对应数据项的唯一标识 | string \| number | - | - | +| align | 列对齐方式 | string | 'left' \| 'right' \|'center' | 'left' | +| selectFilters | 表头的筛选菜单, 更多配置请参考 [Select组件](https://infra.mioffice.cn/hiui/zh-CN/components/select) (v3.7.1新增) | object | - | null | +| sorter | 列排序函数 (v3.7.1新增) | () => boolean | - | null | +| defaultSortOrder | 默认排序顺序 (v3.7.1新增) | ascend \| descend | - | null | +| filterIcon | 自定义 filter 图标 (v3.7.1新增) | ReactNode | - | null | +| filterDropdown | 自定义筛选菜单,此函数只负责渲染图层,需要自行编写各种交互 (v3.7.1新增) | (props: {ColumnItem, setFilterDropdownVisible}) => ReactNode | - | null | +| filterDropdownWidth | 自定义筛选菜单宽度 (v3.7.1新增) | number | - | 150 | +| filterDropdownClassName | 自定义筛选菜单 className (v3.7.1新增) | string | - | - | +| onFilterDropdownVisibleChange | 自定义筛选下拉选项显示状态改变时的回调方法 (v3.7.1新增) | (filterDropdownVisible, ColumnItem) => void | true \| false | false | +| avg | 该列是否支持平均值 | boolean | - | false | +| total | 该列是否支持合计 | boolean | - | - | +| width | 该列宽度 | number | - | - | +| children | 多级表头 | ColumnItem[] | - | - | +| render | 控制单元格自定义渲染 | (text: DataItem[ColumnItem[dataKey]], row: DataItem, index: number, dataKey: string) => ReactNode | - | - | ### DataSource @@ -133,7 +159,7 @@ import DemoAsync from '../../demo/table/section-async.jsx' ### Pagination | 参数 | 说明 | 类型 | 可选值 | 默认值 | -| ---------------- | ---------------------------------------------------------- | --------------------------------------------------------- | --------------------------------- | --------- | +| ---------------- | ---------------------------------------------------------- | --------------------------------------------------------- | --------------------------------- | --------- | --- | | type | 分页的类型 | string | 'default' \| 'simple' \| 'shrink' | 'default' | | defaultCurrent | 默认的当前页数 | number | - | 1 | | current | 当前页数 | number | - | - | @@ -144,21 +170,20 @@ import DemoAsync from '../../demo/table/section-async.jsx' | autoHide | 只有一页时是否隐藏分页器 | boolean | true \| false | false | | showJumper | 是否显示跳转 | boolean | true \| false | false | | onJump | 快速跳转时触发,回调值为当前页数 | (current: number) => void | - | - | -| onChange | 页码改变时的回调,回调值为当前页数、之前的页数和每页条数 | (current: number, prev: number, pageSize: number) => void | - | - | - | -| onPageSizeChange | 每页显示条数改变的回调函数,返回改变后的每页条数及当前页数 | (pageSize: number, current: number) => void | - | - | - | +| onChange | 页码改变时的回调,回调值为当前页数、之前的页数和每页条数 | (current: number, prev: number, pageSize: number) => void | - | - | - | +| onPageSizeChange | 每页显示条数改变的回调函数,返回改变后的每页条数及当前页数 | (pageSize: number, current: number) => void | - | - | - | ### FixedOption -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -| ----- | -------------------- | ------ | ------ | ------ | -| left | 表格从左侧冻结至某列 | string | columns 中对应的 dataKey | - | -| right | 表格从右侧冻结至某列 | string | columns 中对应的 dataKey | - | - +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| ----- | -------------------- | ------ | ------------------------ | ------ | +| left | 表格从左侧冻结至某列 | string | columns 中对应的 dataKey | - | +| right | 表格从右侧冻结至某列 | string | columns 中对应的 dataKey | - | ### RowSelection -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -| ----- | -------------------- | ------ | ------ | ------ | -| selectedRowKeys | 选中的行(受控) | string[] | row 中对应的 key | - | -| getCheckboxConfig | 行选择的配置项 | rowData => object | - | - | -| onChange| 选中项发生变化时的回调 | (selectedRowKeys: string[]) => void | - | - | +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| ----------------- | ---------------------- | ----------------------------------- | ---------------- | ------ | +| selectedRowKeys | 选中的行(受控) | string[] | row 中对应的 key | - | +| getCheckboxConfig | 行选择的配置项 | rowData => object | - | - | +| onChange | 选中项发生变化时的回调 | (selectedRowKeys: string[]) => void | - | - | diff --git a/docs/zh-CN/components/tree.mdx b/docs/zh-CN/components/tree.mdx index 4cbb5e7d5..1561d6821 100755 --- a/docs/zh-CN/components/tree.mdx +++ b/docs/zh-CN/components/tree.mdx @@ -112,6 +112,7 @@ import DemoLine from '../../demo/tree/section-line.jsx' | disabled | 是否禁用节点 | boolean | true \| false | false | | children | 该节点的子节点 | TreeNode[] | - | - | | isLeaf | 是否为叶子节点 | boolean | true \| false | - | +| selectable | 节点是否可选中 | boolean | true \| false | true | ### Level diff --git a/gulpfile.js b/gulpfile.js index 6d6d2537a..71d623c8a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -46,7 +46,8 @@ const compile = (modules) => { .pipe( babel({ presets: ['@babel/preset-env', '@babel/preset-react'], - plugins: ['@babel/plugin-transform-runtime', ['transform-remove-console', { exclude: ['error', 'warn'] }]] + plugins: ['@babel/plugin-transform-runtime', ['transform-remove-console', { exclude: ['error', 'warn'] }]], + ignore: ['components/index.js'] }) ) .pipe( diff --git a/package-lock.json b/package-lock.json index dda387c7b..16e1d2f55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@hi-ui/hiui", - "version": "3.6.1", + "version": "3.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 41ede6e00..334f74472 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hi-ui/hiui", - "version": "3.7.0", + "version": "3.8.0", "description": "HIUI for React", "scripts": { "test": "node_modules/.bin/standard && node_modules/.bin/stylelint --config .stylelintrc 'components/**/*.scss'", @@ -38,10 +38,15 @@ "license": "MIT", "main": "index.js", "module": "es/index.js", - "file": [ - "dist", - "es", - "types/*.d.ts" + "types": "es/index.d.ts", + "files": [ + "es" + ], + "sideEffects": [ + "es/**/style/*", + "es/base-css/*", + "es/lib/*", + "es/_util/*" ], "peerDependencies": { "react": ">=16.13.0",