From dff0951dcdfd7dc2804c7223f4d012c155997142 Mon Sep 17 00:00:00 2001 From: zkwolf Date: Thu, 10 Oct 2019 20:07:56 -0700 Subject: [PATCH] Feat descriptions (#1251) * feat: add descriptions * fix: add descriptions types and fix docs * fix: lint change code * fix: demo warning * fix: update demo, snapshot and remove classnames --- components/_util/responsiveObserve.js | 96 ++++++ components/descriptions/Col.jsx | 74 +++++ .../__tests__/__snapshots__/demo.test.js.snap | 287 ++++++++++++++++++ .../descriptions/__tests__/demo.test.js | 3 + components/descriptions/demo/basic.md | 23 ++ components/descriptions/demo/border.md | 41 +++ components/descriptions/demo/index.vue | 53 ++++ components/descriptions/demo/responsive.md | 41 +++ components/descriptions/demo/size.md | 69 +++++ .../descriptions/demo/vertical-border.md | 42 +++ components/descriptions/demo/vertical.md | 23 ++ components/descriptions/index.en-US.md | 21 ++ components/descriptions/index.jsx | 264 ++++++++++++++++ components/descriptions/index.zh-CN.md | 21 ++ components/descriptions/style/index.js | 2 + components/descriptions/style/index.less | 145 +++++++++ components/index.js | 4 + components/style.js | 1 + components/style/themes/default.less | 3 + site/components.js | 2 + site/demo.js | 6 + site/demoRoutes.js | 8 + tests/__snapshots__/index.test.js.snap | 1 + types/ant-design-vue.d.ts | 2 + types/descriptions/descriptions-item.d.ts | 20 ++ types/descriptions/descriptions.d.ts | 57 ++++ 26 files changed, 1309 insertions(+) create mode 100644 components/_util/responsiveObserve.js create mode 100644 components/descriptions/Col.jsx create mode 100644 components/descriptions/__tests__/__snapshots__/demo.test.js.snap create mode 100644 components/descriptions/__tests__/demo.test.js create mode 100644 components/descriptions/demo/basic.md create mode 100644 components/descriptions/demo/border.md create mode 100644 components/descriptions/demo/index.vue create mode 100644 components/descriptions/demo/responsive.md create mode 100644 components/descriptions/demo/size.md create mode 100644 components/descriptions/demo/vertical-border.md create mode 100644 components/descriptions/demo/vertical.md create mode 100644 components/descriptions/index.en-US.md create mode 100644 components/descriptions/index.jsx create mode 100644 components/descriptions/index.zh-CN.md create mode 100644 components/descriptions/style/index.js create mode 100644 components/descriptions/style/index.less create mode 100644 types/descriptions/descriptions-item.d.ts create mode 100644 types/descriptions/descriptions.d.ts diff --git a/components/_util/responsiveObserve.js b/components/_util/responsiveObserve.js new file mode 100644 index 000000000..c5d2f8796 --- /dev/null +++ b/components/_util/responsiveObserve.js @@ -0,0 +1,96 @@ +// matchMedia polyfill for +// https://github.com/WickyNilliams/enquire.js/issues/82 +let enquire; + +// TODO: Will be removed in antd 4.0 because we will no longer support ie9 +if (typeof window !== 'undefined') { + const matchMediaPolyfill = (mediaQuery) => { + return { + media: mediaQuery, + matches: false, + addListener() {}, + removeListener() {}, + }; + }; + // ref: https://github.com/ant-design/ant-design/issues/18774 + if (!window.matchMedia) window.matchMedia = matchMediaPolyfill; + // eslint-disable-next-line global-require + enquire = require('enquire.js'); +} + +export const responsiveArray = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs']; + +export const responsiveMap = { + xs: '(max-width: 575px)', + sm: '(min-width: 576px)', + md: '(min-width: 768px)', + lg: '(min-width: 992px)', + xl: '(min-width: 1200px)', + xxl: '(min-width: 1600px)', +}; + +let subscribers = []; +let subUid = -1; +let screens = {}; + +const responsiveObserve = { + dispatch(pointMap) { + screens = pointMap; + if (subscribers.length < 1) { + return false; + } + + subscribers.forEach(item => { + item.func(screens); + }); + + return true; + }, + subscribe(func) { + if (subscribers.length === 0) { + this.register(); + } + const token = (++subUid).toString(); + subscribers.push({ + token, + func, + }); + func(screens); + return token; + }, + unsubscribe(token) { + subscribers = subscribers.filter(item => item.token !== token); + if (subscribers.length === 0) { + this.unregister(); + } + }, + unregister() { + Object.keys(responsiveMap).map((screen) => + enquire.unregister(responsiveMap[screen]), + ); + }, + register() { + Object.keys(responsiveMap).map((screen) => + enquire.register(responsiveMap[screen], { + match: () => { + const pointMap = { + ...screens, + [screen]: true, + }; + this.dispatch(pointMap); + }, + unmatch: () => { + const pointMap = { + ...screens, + [screen]: false, + }; + this.dispatch(pointMap); + }, + // Keep a empty destory to avoid triggering unmatch when unregister + destroy() {}, + }), + ); + }, +}; + +export default responsiveObserve; diff --git a/components/descriptions/Col.jsx b/components/descriptions/Col.jsx new file mode 100644 index 000000000..f0c456adf --- /dev/null +++ b/components/descriptions/Col.jsx @@ -0,0 +1,74 @@ +import PropTypes from '../_util/vue-types'; +import { getOptionProps, getSlots, getComponentFromProp } from '../_util/props-util'; + +const ColProps = { + child: PropTypes.any, + bordered: PropTypes.bool, + colon: PropTypes.bool, + type: PropTypes.oneOf(['label', 'content']), + layout: PropTypes.oneOf(['horizontal', 'vertical']), +}; + +const Col = { + props: ColProps, + render() { + const { child, bordered, colon, type, layout } = this.$props; + const { prefixCls, span = 1 } = getOptionProps(child); + + const label = getComponentFromProp(child, 'label'); + const slots = getSlots(child); + const labelProps = { + attrs: {}, + class: [`${prefixCls}-item-label`, { + [`${prefixCls}-item-colon`]: colon, + [`${prefixCls}-item-no-label`]: !label, + }], + key: 'label', + }; + if (layout === 'vertical') { + labelProps.attrs.colSpan = span * 2 - 1; + } + + if (bordered) { + if (type === 'label') { + return {label}; + } + return ( + + {slots.default} + + ); + } + if (layout === 'vertical') { + if (type === 'content') { + return ( + + + {slots.default} + + + ); + } + return ( + + + {label} + + + ); + } + return ( + + {label} + + {slots.default} + + + ); + }, +}; + +export default Col; diff --git a/components/descriptions/__tests__/__snapshots__/demo.test.js.snap b/components/descriptions/__tests__/__snapshots__/demo.test.js.snap new file mode 100644 index 000000000..5234d8a8a --- /dev/null +++ b/components/descriptions/__tests__/__snapshots__/demo.test.js.snap @@ -0,0 +1,287 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders ./components/descriptions/demo/basic.md correctly 1`] = ` +
+
User Info
+
+ + + + + + + + + + + + +
UserNameZhou MaomaoTelephone1810000000LiveHangzhou, Zhejiang
RemarkemptyAddress + No. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China +
+
+
+`; + +exports[`renders ./components/descriptions/demo/border.md correctly 1`] = ` +
+
User Info
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ProductCloud DatabaseBilling ModePrepaidAutomatic RenewalYES
Order time2018-04-24 18:00:00Usage Time + 2019-04-24 18:00:00 +
StatusRunning
Negotiated Amount$80.00Discount$20.00Official Receipts$60.00
Config Info + Data disk type: MongoDB +
+ Database version: 3.4 +
+ Package: dds.mongo.mid +
+ Storage space: 10 GB +
+ Replication_factor:3 +
+ Region: East China 1
+
+
+`; + +exports[`renders ./components/descriptions/demo/responsive.md correctly 1`] = ` +
+
+
Responsive Descriptions
+
+ + + + + + + + + + + + + + + + + + + + + + + +
ProductCloud DatabaseBillingPrepaidtime18:00:00
Amount$80.00Discount$20.00Official$60.00
Config Info + Data disk type: MongoDB +
+ Database version: 3.4 +
+ Package: dds.mongo.mid +
+ Storage space: 10 GB +
+ Replication_factor:3 +
+ Region: East China 1 +
+
+
+
+`; + +exports[`renders ./components/descriptions/demo/size.md correctly 1`] = ` +
+


+
+
Custom Size
+
+ + + + + + + + + + + + + + + + + + + + + + + +
ProductCloud DatabaseBillingPrepaidtime18:00:00
Amount$80.00Discount$20.00Official$60.00
Config Info + Data disk type: MongoDB +
+ Database version: 3.4 +
+ Package: dds.mongo.mid +
+ Storage space: 10 GB +
+ Replication_factor:3 +
+ Region: East China 1
+
+


+
+
Custom Size
+
+ + + + + + + + + + + + + +
ProductCloud DatabaseBillingPrepaidtime18:00:00
Amount$80.00Discount$20.00Official$60.00
+
+
+
+`; + +exports[`renders ./components/descriptions/demo/vertical.md correctly 1`] = ` +
+
User Info
+
+ + + + + + + + + + + + + + + + + + + + + +
UserNameTelephoneLive
Zhou Maomao1810000000Hangzhou, Zhejiang
AddressRemark
+ No. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China + empty
+
+
+`; + +exports[`renders ./components/descriptions/demo/vertical-border.md correctly 1`] = ` +
+
User Info
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ProductBilling ModeAutomatic Renewal
Cloud DatabasePrepaidYES
Order timeUsage Time
2018-04-24 18:00:00 + 2019-04-24 18:00:00 +
Status
Running
Negotiated AmountDiscountOfficial Receipts
$80.00$20.00$60.00
Config Info
+ Data disk type: MongoDB +
+ Database version: 3.4 +
+ Package: dds.mongo.mid +
+ Storage space: 10 GB +
+ Replication_factor:3 +
+ Region: East China 1
+
+
+`; diff --git a/components/descriptions/__tests__/demo.test.js b/components/descriptions/__tests__/demo.test.js new file mode 100644 index 000000000..7d16a4ab6 --- /dev/null +++ b/components/descriptions/__tests__/demo.test.js @@ -0,0 +1,3 @@ +import demoTest from '../../../tests/shared/demoTest'; + +demoTest('descriptions'); \ No newline at end of file diff --git a/components/descriptions/demo/basic.md b/components/descriptions/demo/basic.md new file mode 100644 index 000000000..9a2c8682b --- /dev/null +++ b/components/descriptions/demo/basic.md @@ -0,0 +1,23 @@ + +#### 基本 +简单的展示。 + + + +#### Basic +Simplest Usage. + + +```tpl + +``` diff --git a/components/descriptions/demo/border.md b/components/descriptions/demo/border.md new file mode 100644 index 000000000..509fb344e --- /dev/null +++ b/components/descriptions/demo/border.md @@ -0,0 +1,41 @@ + +#### 带边框的 + + + +#### border +Descriptions with border and background color. + + +```tpl + +``` diff --git a/components/descriptions/demo/index.vue b/components/descriptions/demo/index.vue new file mode 100644 index 000000000..a99deb91c --- /dev/null +++ b/components/descriptions/demo/index.vue @@ -0,0 +1,53 @@ + diff --git a/components/descriptions/demo/responsive.md b/components/descriptions/demo/responsive.md new file mode 100644 index 000000000..9cff357fb --- /dev/null +++ b/components/descriptions/demo/responsive.md @@ -0,0 +1,41 @@ + +#### 响应式 +通过响应式的配置可以实现在小屏幕设备上的完美呈现。 + + + +#### responsive +通过响应式的配置可以实现在小屏幕设备上的完美呈现。 + + +```tpl + +``` diff --git a/components/descriptions/demo/size.md b/components/descriptions/demo/size.md new file mode 100644 index 000000000..05375dccd --- /dev/null +++ b/components/descriptions/demo/size.md @@ -0,0 +1,69 @@ + +#### 自定义尺寸 +自定义尺寸,适应在各种容器中展示。 + + + +#### Custom size +Custom sizes to fit in a variety of containers. + + +```tpl + + +``` diff --git a/components/descriptions/demo/vertical-border.md b/components/descriptions/demo/vertical-border.md new file mode 100644 index 000000000..f49ce391f --- /dev/null +++ b/components/descriptions/demo/vertical-border.md @@ -0,0 +1,42 @@ + +#### 垂直带边框的 +垂直带边框和背景颜色的列表。 + + + +#### Vertical border +Descriptions with border and background color. + + +```tpl + +``` diff --git a/components/descriptions/demo/vertical.md b/components/descriptions/demo/vertical.md new file mode 100644 index 000000000..1f5d89caa --- /dev/null +++ b/components/descriptions/demo/vertical.md @@ -0,0 +1,23 @@ + +#### 垂直 +垂直的列表。 + + + +#### Vertical +Simplest Usage. + + +```tpl + +``` diff --git a/components/descriptions/index.en-US.md b/components/descriptions/index.en-US.md new file mode 100644 index 000000000..7e745e809 --- /dev/null +++ b/components/descriptions/index.en-US.md @@ -0,0 +1,21 @@ +## API + +### Descriptions props + +| Property | Description | Type | Default | +| --- | --- | --- | --- | +| title | The title of the description list, placed at the top | string \| VNode \| v-slot:title | - | +| bordered | whether to display the border | boolean | false | +| column | the number of `DescriptionItems` in a row,could be a number or a object like `{ xs: 8, sm: 16, md: 24}`,(Only set `bordered={true}` to take effect) | number | 3 | +| size | set the size of the list. Can be set to `middle`,`small`, or not filled | `default | middle | small` | `default` | +| layout | Define description layout | `horizontal | vertical` | `horizontal` | +| colon | change default props `colon` value of `Descriptions.Item` | boolean | true | + +### Item props + +| Property | Description | Type | Default | +| -------- | ------------------------------ | ------------------------------- | ------- | +| label | description of the content | string \| VNode \| v-slot:label | - | +| span | The number of columns included | number | 1 | + +> The number of span Descriptions.Item. span={2} takes up the width of two DescriptionsItems. diff --git a/components/descriptions/index.jsx b/components/descriptions/index.jsx new file mode 100644 index 000000000..39742d3b7 --- /dev/null +++ b/components/descriptions/index.jsx @@ -0,0 +1,264 @@ +import warning from '../_util/warning'; +import ResponsiveObserve, { responsiveArray } from '../_util/responsiveObserve'; +import { ConfigConsumerProps } from '../config-provider'; +import Col from './Col'; +import PropTypes from '../_util/vue-types'; +import { + initDefaultProps, + isValidElement, + getOptionProps, + getComponentFromProp, +} from '../_util/props-util'; +import BaseMixin from '../_util/BaseMixin'; +import Base from '../base'; +import { cloneElement } from '../_util/vnode'; + +export const DescriptionsItemProps = { + prefixCls: PropTypes.string, + label: PropTypes.any, + span: PropTypes.number, +}; + +function toArray(value) { + let ret = value; + if (value === undefined) { + ret = []; + } else if (!Array.isArray(value)) { + ret = [value]; + } + return ret; +} + +export const DescriptionsItem = { + name: 'ADescriptionsItem', + props: initDefaultProps(DescriptionsItemProps, { span: 1 }), +}; + +export const DescriptionsProps = { + prefixCls: PropTypes.string, + bordered: PropTypes.bool, + size: PropTypes.oneOf(['default', 'middle', 'small']).def('default'), + title: PropTypes.any, + column: PropTypes.oneOfType([PropTypes.number, PropTypes.object]), + layout: PropTypes.oneOf(['horizontal', 'vertical']), + colon: PropTypes.bool, +}; + +/** + * Convert children into `column` groups. + * @param children: DescriptionsItem + * @param column: number + */ +const generateChildrenRows = (children, column) => { + const rows = []; + let columns = null; + let leftSpans; + + const itemNodes = toArray(children); + itemNodes.forEach((node, index) => { + const itemProps = getOptionProps(node); + let itemNode = node; + + if (!columns) { + leftSpans = column; + columns = []; + rows.push(columns); + } + + // Always set last span to align the end of Descriptions + const lastItem = index === itemNodes.length - 1; + let lastSpanSame = true; + if (lastItem) { + lastSpanSame = !itemProps.span || itemProps.span === leftSpans; + itemNode = cloneElement(itemNode, { + props: { + span: leftSpans, + }, + }); + } + + // Calculate left fill span + const { span = 1 } = itemProps; + columns.push(itemNode); + leftSpans -= span; + + if (leftSpans <= 0) { + columns = null; + + warning( + leftSpans === 0 && lastSpanSame, + 'Descriptions: Sum of column `span` in a line exceeds `column` of Descriptions.', + ); + } + }); + + return rows; +}; + +const defaultColumnMap = { + xxl: 3, + xl: 3, + lg: 3, + md: 3, + sm: 2, + xs: 1, +}; + +const Descriptions = { + name: 'ADescriptions', + Item: DescriptionsItem, + mixins: [BaseMixin], + inject: { + configProvider: { default: () => ConfigConsumerProps }, + }, + props: initDefaultProps(DescriptionsProps, { + column: defaultColumnMap, + }), + data() { + return { + screens: {}, + token: undefined, + }; + }, + methods: { + getColumn() { + const { column } = this.$props; + if (typeof column === 'object') { + for (let i = 0; i < responsiveArray.length; i++) { + const breakpoint = responsiveArray[i]; + if (this.screens[breakpoint] && column[breakpoint] !== undefined) { + return column[breakpoint] || defaultColumnMap[breakpoint]; + } + } + } + // If the configuration is not an object, it is a number, return number + if (typeof column === 'number') { + return column; + } + // If it is an object, but no response is found, this happens only in the test. + // Maybe there are some strange environments + return 3; + }, + renderRow(children, index, { prefixCls }, bordered, layout, colon) { + const renderCol = (colItem, type, idx) => { + return ( + + ); + }; + + const cloneChildren = []; + const cloneContentChildren = []; + toArray(children).forEach((childrenItem, idx) => { + cloneChildren.push(renderCol(childrenItem, 'label', idx)); + if (layout === 'vertical') { + cloneContentChildren.push(renderCol(childrenItem, 'content', idx)); + } else if (bordered) { + cloneChildren.push(renderCol(childrenItem, 'content', idx)); + } + }); + + if (layout === 'vertical') { + return [ + + {cloneChildren} + , + + {cloneContentChildren} + , + ]; + } + + return ( + + {cloneChildren} + + ); + }, + }, + mounted() { + const { column } = this.$props; + this.token = ResponsiveObserve.subscribe(screens => { + if (typeof column !== 'object') { + return; + } + this.setState({ + screens, + }); + }); + }, + beforeDestory() { + ResponsiveObserve.unsubscribe(this.token); + }, + render() { + const { + prefixCls: customizePrefixCls, + size, + bordered = false, + layout = 'horizontal', + colon = true, + } = this.$props; + const title = getComponentFromProp(this, 'title') || null; + const getPrefixCls = this.configProvider.getPrefixCls; + const prefixCls = getPrefixCls('descriptions', customizePrefixCls); + + const column = this.getColumn(); + const children = this.$slots.default; + const cloneChildren = toArray(children) + .map(child => { + if (isValidElement(child)) { + return cloneElement(child, { + props: { + prefixCls, + }, + }); + } + return null; + }) + .filter(node => node); + + const childrenArray = generateChildrenRows(cloneChildren, column); + return ( +
+ {title &&
{title}
} +
+ + + {childrenArray.map((child, index) => + this.renderRow( + child, + index, + { + prefixCls, + }, + bordered, + layout, + colon, + ), + )} + +
+
+
+ ); + }, +}; + +Descriptions.install = function(Vue) { + Vue.use(Base); + Vue.component(Descriptions.name, Descriptions); + Vue.component(Descriptions.Item.name, Descriptions.Item); +}; + +export default Descriptions; diff --git a/components/descriptions/index.zh-CN.md b/components/descriptions/index.zh-CN.md new file mode 100644 index 000000000..85bd87ead --- /dev/null +++ b/components/descriptions/index.zh-CN.md @@ -0,0 +1,21 @@ +## API + +### Descriptions props + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| title | 描述列表的标题,显示在最顶部 | string \| VNode \| v-slot:title | - | +| bordered | 是否展示边框 | boolean | false | +| column | 一行的 `DescriptionItems` 数量,可以写成像素值或支持响应式的对象写法 `{ xs: 8, sm: 16, md: 24}` | number | 3 | +| size | 设置列表的大小。可以设置为 `middle` 、`small`, 或不填(只有设置 `bordered={true}` 生效) | `default | middle | small` | `default` | +| layout | 描述布局 | `horizontal | vertical` | `horizontal` | +| colon | 配置 `Descriptions.Item` 的 `colon` 的默认值 | boolean | true | + +### Item props + +| 参数 | 说明 | 类型 | 默认值 | +| ----- | ------------ | ------------------------------- | ------ | +| label | 内容的描述 | string \| VNode \| v-slot:label | - | +| span | 包含列的数量 | number | 1 | + +> span 是 Descriptions.Item 的数量。 span={2} 会占用两个 DescriptionsItem 的宽度。 diff --git a/components/descriptions/style/index.js b/components/descriptions/style/index.js new file mode 100644 index 000000000..3a3ab0de5 --- /dev/null +++ b/components/descriptions/style/index.js @@ -0,0 +1,2 @@ +import '../../style/index.less'; +import './index.less'; diff --git a/components/descriptions/style/index.less b/components/descriptions/style/index.less new file mode 100644 index 000000000..dae1baeb7 --- /dev/null +++ b/components/descriptions/style/index.less @@ -0,0 +1,145 @@ +@import '../../style/themes/default'; +@import '../../style/mixins/index'; + +@descriptions-prefix-cls: ~'@{ant-prefix}-descriptions'; + +@descriptions-default-padding: 16px 24px; +@descriptions-middle-padding: 12px 24px; +@descriptions-small-padding: 8px 16px; + +.@{descriptions-prefix-cls} { + &-title { + margin-bottom: 20px; + color: @heading-color; + font-weight: bold; + font-size: @font-size-lg; + line-height: @line-height-base; + } + + &-view { + width: 100%; + overflow: hidden; + border-radius: @border-radius-base; + table { + width: 100%; + table-layout: fixed; + } + } + + &-row { + > th, + > td { + padding-bottom: 16px; + } + &:last-child { + border-bottom: none; + } + } + + &-item-label { + color: @heading-color; + font-weight: normal; + font-size: @font-size-base; + line-height: @line-height-base; + white-space: nowrap; + + &::after { + position: relative; + top: -0.5px; + margin: 0 8px 0 2px; + content: ' '; + } + } + + &-item-colon { + &::after { + content: ':'; + } + } + + &-item-no-label { + &::after { + margin: 0; + content: ''; + } + } + + &-item-content { + display: table-cell; + color: @text-color; + font-size: @font-size-base; + line-height: @line-height-base; + } + + &-item { + padding-bottom: 0; + > span { + display: inline-block; + } + } + + &-middle { + .@{descriptions-prefix-cls}-row { + > th, + > td { + padding-bottom: 12px; + } + } + } + + &-small { + .@{descriptions-prefix-cls}-row { + > th, + > td { + padding-bottom: 8px; + } + } + } + + &-bordered { + .@{descriptions-prefix-cls}-view { + border: 1px solid @border-color-split; + > table { + table-layout: auto; + } + } + + .@{descriptions-prefix-cls}-item-label, + .@{descriptions-prefix-cls}-item-content { + padding: @descriptions-default-padding; + border-right: 1px solid @border-color-split; + + &:last-child { + border-right: none; + } + } + + .@{descriptions-prefix-cls}-item-label { + background-color: @descriptions-bg; + &::after { + display: none; + } + } + + .@{descriptions-prefix-cls}-row { + border-bottom: 1px solid @border-color-split; + &:last-child { + border-bottom: none; + } + } + + &.@{descriptions-prefix-cls}-middle { + .@{descriptions-prefix-cls}-item-label, + .@{descriptions-prefix-cls}-item-content { + padding: @descriptions-middle-padding; + } + } + + &.@{descriptions-prefix-cls}-small { + .@{descriptions-prefix-cls}-item-label, + .@{descriptions-prefix-cls}-item-content { + padding: @descriptions-small-padding; + } + } + } +} diff --git a/components/index.js b/components/index.js index cfb3b4429..ce0b3e234 100644 --- a/components/index.js +++ b/components/index.js @@ -139,6 +139,8 @@ import { default as Empty } from './empty'; import { default as Result } from './result'; +import { default as Descriptions } from './descriptions'; + const components = [ Base, Affix, @@ -198,6 +200,7 @@ const components = [ ConfigProvider, Empty, Result, + Descriptions, ]; const install = function(Vue) { @@ -283,6 +286,7 @@ export { ConfigProvider, Empty, Result, + Descriptions, }; export default { diff --git a/components/style.js b/components/style.js index f3903fd01..2dd79c5ff 100644 --- a/components/style.js +++ b/components/style.js @@ -56,3 +56,4 @@ import './config-provider/style'; import './empty/style'; import './statistic/style'; import './result/style'; +import './descriptions/style'; diff --git a/components/style/themes/default.less b/components/style/themes/default.less index 07d809d16..5100de991 100644 --- a/components/style/themes/default.less +++ b/components/style/themes/default.less @@ -174,6 +174,9 @@ @checkbox-check-color: #fff; @checkbox-border-width: @border-width-base; +// Descriptions +@descriptions-bg: #fafafa; + // Empty @empty-font-size: @font-size-base; diff --git a/site/components.js b/site/components.js index 5fd855ddf..e0ca62f30 100644 --- a/site/components.js +++ b/site/components.js @@ -62,6 +62,7 @@ import { Empty, Base, Result, + Descriptions, } from 'ant-design-vue'; Vue.prototype.$message = message; @@ -132,6 +133,7 @@ Vue.use(Comment); Vue.use(ConfigProvider); Vue.use(Empty); Vue.use(Result); +Vue.use(Descriptions); /* v1.1.2 registration methods */ // Vue.component(Affix.name, Affix) // a-affix diff --git a/site/demo.js b/site/demo.js index 636ccf3bb..69a3029fd 100644 --- a/site/demo.js +++ b/site/demo.js @@ -364,4 +364,10 @@ export default { type: 'Data Display', title: 'Statistic', }, + descriptions: { + category: 'Components', + subtitle: '描述列表', + type: 'Data Display', + title: 'Descriptions' + } }; diff --git a/site/demoRoutes.js b/site/demoRoutes.js index 5aa0e8445..74e3b496d 100644 --- a/site/demoRoutes.js +++ b/site/demoRoutes.js @@ -463,4 +463,12 @@ export default [ path: 'result-cn', component: () => import('../components/result/demo/index.vue'), }, + { + path: 'descriptions', + component: () => import('../components/descriptions/demo/index.vue'), + }, + { + path: 'descriptions-cn', + component: () => import('../components/descriptions/demo/index.vue'), + }, ]; diff --git a/tests/__snapshots__/index.test.js.snap b/tests/__snapshots__/index.test.js.snap index b39917af9..8329ddeef 100644 --- a/tests/__snapshots__/index.test.js.snap +++ b/tests/__snapshots__/index.test.js.snap @@ -63,6 +63,7 @@ Array [ "Comment", "ConfigProvider", "Empty", + "Descriptions", "default", ] `; diff --git a/types/ant-design-vue.d.ts b/types/ant-design-vue.d.ts index 5b3deaf84..927bb40ea 100644 --- a/types/ant-design-vue.d.ts +++ b/types/ant-design-vue.d.ts @@ -62,6 +62,7 @@ import { Timeline } from './timeline/timeline'; import { Tooltip } from './tootip/tooltip'; import { Upload } from './upload'; import { Result } from './result'; +import { Descriptions } from './descriptions/descriptions' /** * Install all ant-design-vue components into Vue. @@ -131,4 +132,5 @@ export { Drawer, Skeleton, Result, + Descriptions, }; diff --git a/types/descriptions/descriptions-item.d.ts b/types/descriptions/descriptions-item.d.ts new file mode 100644 index 000000000..55d0eec28 --- /dev/null +++ b/types/descriptions/descriptions-item.d.ts @@ -0,0 +1,20 @@ +// Project: https://github.com/vueComponent/ant-design-vue +// Definitions by: akki-jat +// Definitions: https://github.com/vueComponent/ant-design-vue/types + +import { AntdComponent } from '../component'; + +export declare class DescriptionsItem extends AntdComponent { + /** + * the label of descriptions item + * @type any + */ + label: any; + + /** + * can be set to small large or omitted + * @default 1 + * @type number + */ + span: number; +} diff --git a/types/descriptions/descriptions.d.ts b/types/descriptions/descriptions.d.ts new file mode 100644 index 000000000..0c98966e1 --- /dev/null +++ b/types/descriptions/descriptions.d.ts @@ -0,0 +1,57 @@ +// Project: https://github.com/vueComponent/ant-design-vue +// Definitions by: akki-jat +// Definitions: https://github.com/vueComponent/ant-design-vue/types + +import { AntdComponent } from '../component'; +import { DescriptionsItem } from './descriptions-item'; + +export declare class Descriptions extends AntdComponent { + static Item: typeof DescriptionsItem; + + /** + * descriptions size type + * @default 'default' + * @type string + */ + size: 'default' | 'middle' | 'small'; + + /** + * custom prefixCls + * @type string + */ + prefixCls: string; + + /** + * whether descriptions have border + * @default false + * @type boolean + */ + bordered: boolean; + + /** + * custom title + * @type any + */ + title: any; + + /** + * the number of descriptionsitem in one line + * @default 3 + * @type number | object + */ + column: number | object; + + /** + * descriptions layout + * @default 'horizontal' + * @type string + */ + layout: 'horizontal' | 'vertical'; + + /** + * whether have colon in descriptionsitem + * @default true + * @type boolean + */ + colon: boolean; +} \ No newline at end of file