diff --git a/components/components.less b/components/components.less index 6a11b57a2d6..ce82446ad87 100644 --- a/components/components.less +++ b/components/components.less @@ -13,6 +13,7 @@ @import "./collapse/style/entry.less"; @import "./comment/style/entry.less"; @import "./date-picker/style/entry.less"; +@import "./descriptions/style/entry.less"; @import "./divider/style/entry.less"; @import "./drawer/style/entry.less"; @import "./dropdown/style/entry.less"; diff --git a/components/core/public-api.ts b/components/core/public-api.ts index a66ca691426..bf33ab9b4e6 100644 --- a/components/core/public-api.ts +++ b/components/core/public-api.ts @@ -21,3 +21,4 @@ export * from './util/public-api'; export * from './wave/public-api'; export * from './dropdown/public-api'; export * from './logger/public-api'; +export * from './responsive/public-api'; diff --git a/components/core/responsive/break-point.ts b/components/core/responsive/break-point.ts new file mode 100644 index 00000000000..ee56ddcaee5 --- /dev/null +++ b/components/core/responsive/break-point.ts @@ -0,0 +1,27 @@ +/** + * @license + * Copyright Alibaba.com All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE + */ + +export enum Breakpoint { + xxl = 'xxl', + xl = 'xl', + lg = 'lg', + md = 'md', + sm = 'sm', + xs = 'xs' +} + +export type BreakpointMap = { [key in Breakpoint]: string }; + +export const responsiveMap: BreakpointMap = { + xs: '(max-width: 575px)', + sm: '(min-width: 576px)', + md: '(min-width: 768px)', + lg: '(min-width: 992px)', + xl: '(min-width: 1200px)', + xxl: '(min-width: 1600px)' +}; diff --git a/components/core/responsive/index.ts b/components/core/responsive/index.ts new file mode 100644 index 00000000000..7e1a213e3ea --- /dev/null +++ b/components/core/responsive/index.ts @@ -0,0 +1 @@ +export * from './public-api'; diff --git a/components/core/responsive/public-api.ts b/components/core/responsive/public-api.ts new file mode 100644 index 00000000000..0c19caa1de9 --- /dev/null +++ b/components/core/responsive/public-api.ts @@ -0,0 +1 @@ +export * from './break-point'; diff --git a/components/descriptions/demo/basic.md b/components/descriptions/demo/basic.md new file mode 100644 index 00000000000..a8f124f7544 --- /dev/null +++ b/components/descriptions/demo/basic.md @@ -0,0 +1,14 @@ +--- +order: 0 +title: + zh-CN: 基本 + en-US: Basic +--- + +## zh-CN + +简单的展示。 + +## en-US + +Basic usage. diff --git a/components/descriptions/demo/basic.ts b/components/descriptions/demo/basic.ts new file mode 100644 index 00000000000..9f909c92009 --- /dev/null +++ b/components/descriptions/demo/basic.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'nz-demo-descriptions-basic', + template: ` + + Zhou Maomao + 18100000000 + Hangzhou, Zhejiang + Empty + + No. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China + + + ` +}) + +export class NzDemoDescriptionsBasicComponent { + +} diff --git a/components/descriptions/demo/border.md b/components/descriptions/demo/border.md new file mode 100644 index 00000000000..49b1f24d44c --- /dev/null +++ b/components/descriptions/demo/border.md @@ -0,0 +1,14 @@ +--- +order: 1 +title: + zh-CN: 带边框的 + en-US: Border +--- + +## zh-CN + +带边框和背景颜色列表。 + +## en-US + +Descriptions with border and background color. diff --git a/components/descriptions/demo/border.ts b/components/descriptions/demo/border.ts new file mode 100644 index 00000000000..eaae3002dce --- /dev/null +++ b/components/descriptions/demo/border.ts @@ -0,0 +1,38 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'nz-demo-descriptions-border', + template: ` + + Cloud Database + Prepaid + YES + + 2018-04-24 18:00:00 + + + 2018-04-24 18:00:00 To 2019-04-24 18:00:00 + + + + + $80.00 + $20.00 + $60.00 + + Data disk type: MongoDB +
+ Database version: 3.4 +
+ Package: dds.mongo.mid +
+ Storage space: 10 GB +
+ Replication_factor:3 +
+ Region: East China 1
+
+
+ ` +}) +export class NzDemoDescriptionsBorderComponent {} diff --git a/components/descriptions/demo/custom-size.md b/components/descriptions/demo/custom-size.md new file mode 100644 index 00000000000..2b45f11ce9b --- /dev/null +++ b/components/descriptions/demo/custom-size.md @@ -0,0 +1,14 @@ +--- +order: 2 +title: + zh-CN: 自定义尺寸 + en-US: Custom size +--- + +## zh-CN + +自定义尺寸,适应在各种容器中展示。 + +## en-US + +Custom sizes to fit in a variety of containers. diff --git a/components/descriptions/demo/custom-size.ts b/components/descriptions/demo/custom-size.ts new file mode 100644 index 00000000000..56ed159791f --- /dev/null +++ b/components/descriptions/demo/custom-size.ts @@ -0,0 +1,41 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'nz-demo-descriptions-custom-size', + template: ` + + + + + +
+
+ + + Cloud Database + + Prepaid + 18:00:00 + $80.00 + $20.00 + $60.00 + + Data disk type: MongoDB +
+ Database version: 3.4 +
+ Package: dds.mongo.mid +
+ Storage space: 10 GB +
+ Replication_factor:3 +
+ Region: East China 1 +
+
+
+ ` +}) +export class NzDemoDescriptionsCustomSizeComponent { + size = 'default'; +} diff --git a/components/descriptions/demo/responsive.md b/components/descriptions/demo/responsive.md new file mode 100644 index 00000000000..342861dd890 --- /dev/null +++ b/components/descriptions/demo/responsive.md @@ -0,0 +1,14 @@ +--- +order: 3 +title: + zh-CN: 响应式 + en-US: Responsive +--- + +## zh-CN + +通过响应式的配置可以实现在小屏幕设备上的完美呈现。 + +## en-US + +Responsive configuration enables perfect presentation on small screen devices. diff --git a/components/descriptions/demo/responsive.ts b/components/descriptions/demo/responsive.ts new file mode 100644 index 00000000000..45d41b2eaa2 --- /dev/null +++ b/components/descriptions/demo/responsive.ts @@ -0,0 +1,32 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'nz-demo-descriptions-responsive', + template: ` + + + Cloud Database + + Prepaid + 18:00:00 + $80.00 + $20.00 + $60.00 + + Data disk type: MongoDB +
+ Database version: 3.4 +
+ Package: dds.mongo.mid +
+ Storage space: 10 GB +
+ Replication_factor:3 +
+ Region: East China 1 +
+
+
+ ` +}) +export class NzDemoDescriptionsResponsiveComponent {} diff --git a/components/descriptions/doc/index.en-US.md b/components/descriptions/doc/index.en-US.md new file mode 100644 index 00000000000..1308e191df5 --- /dev/null +++ b/components/descriptions/doc/index.en-US.md @@ -0,0 +1,38 @@ +--- +category: Components +type: Data Display +title: Descriptions +cols: 1 +--- + +Display multiple read-only fields in groups. + +## When To Use + +Commonly displayed on the details page. + +## API + +### nz-descriptions + +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| `[nzTitle]` | Describe the title of the list, displayed at the top | `string\|TemplateRef` | `false` | +| `[nzBordered]` | Whether to display the border | `boolean` | `false` | +| `[nzColumn]` | The number of `nz-descriptions-item` in a row. It could be a number or a object like `{ xs: 8, sm: 16, md: 24}` | `number\|object` | `{ xxl: 3, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }` | +| `[nzSize]` | Set the size of the list. Only works when `nzBordered` is set | `'default'|'middle'|'small'` | `'default'` | + +### Import this Component Individually + +You can get more detail [here](/docs/getting-started/en#import-a-component-individually). + +```ts +import { NzDescriptionsModule } from 'ng-zorro-antd'; +``` + +### nz-descriptions-item + +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| `[nzTitle]` | Description of the content | `boolean` | `string\|TemplateRef` | +| `[nzSpan]` | The number of columns included | `number` | `1` | diff --git a/components/descriptions/doc/index.zh-CN.md b/components/descriptions/doc/index.zh-CN.md new file mode 100644 index 00000000000..de534607788 --- /dev/null +++ b/components/descriptions/doc/index.zh-CN.md @@ -0,0 +1,39 @@ +--- +category: Components +type: 数据展示 +title: Descriptions +subtitle: 描述列表 +cols: 1 +--- + +成组显示多个只读字段。 + +## 何时使用 + +常见于详情页的信息展示。 + +## API + +### nz-descriptions + +| 参数 | 说明 | 类型 | 默认值 | +| -------- | ----------- | ---- | ------- | +| `[nzTitle]` | 描述列表的标题,显示在最顶部 | `string\|TemplateRef` | `false` | +| `[nzBorder]` | 是否展示边框 | `boolean` | `false` | +| `[nzColumn]` | 一行的 `nz-descriptions-item` 的数量,可以写成像素值或支持响应式的对象写法 `{ xs: 8, sm: 16, md: 24}` | `number\|object` | `{ xxl: 3, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }` | +| `[nzSize]` | 设置列表的大小(只有设置 `nzBordered` 时生效) | `'default'|'middle'|'small'` | `'default'` | + +### 单独引入此组件 + +想要了解更多关于单独引入组件的内容,可以在[快速上手](/docs/getting-started/zh#单独引入某个组件)页面进行查看。 + +```ts +import { NzDescriptionsModule } from 'ng-zorro-antd'; +``` + +### nz-descriptions-item + +| 参数 | 说明 | 类型 | 默认值 | +| -------- | ----------- | ---- | ------- | +| `[nzTitle]` | 内容的描述 | `string\|TemplateRef` | - | +| `[nzSpan]` | 包含列的数量 | `number` | `1` | diff --git a/components/descriptions/index.ts b/components/descriptions/index.ts new file mode 100644 index 00000000000..f17e95188c8 --- /dev/null +++ b/components/descriptions/index.ts @@ -0,0 +1,9 @@ +/** + * @license + * Copyright Alibaba.com All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE + */ + +export * from './public-api'; diff --git a/components/descriptions/nz-descriptions-definitions.ts b/components/descriptions/nz-descriptions-definitions.ts new file mode 100644 index 00000000000..3bf5f35d83a --- /dev/null +++ b/components/descriptions/nz-descriptions-definitions.ts @@ -0,0 +1,17 @@ +/** + * @license + * Copyright Alibaba.com All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE + */ + +import { TemplateRef } from '@angular/core'; + +export type NzDescriptionsSize = 'default' | 'middle' | 'small'; + +export interface NzDescriptionsItemRenderProps { + title: string | TemplateRef; + span: number; + content: TemplateRef; +} diff --git a/components/descriptions/nz-descriptions-item.component.html b/components/descriptions/nz-descriptions-item.component.html new file mode 100644 index 00000000000..4e11e7abdec --- /dev/null +++ b/components/descriptions/nz-descriptions-item.component.html @@ -0,0 +1,4 @@ + + + + diff --git a/components/descriptions/nz-descriptions-item.component.ts b/components/descriptions/nz-descriptions-item.component.ts new file mode 100644 index 00000000000..0fed16f4a19 --- /dev/null +++ b/components/descriptions/nz-descriptions-item.component.ts @@ -0,0 +1,26 @@ +/** + * @license + * Copyright Alibaba.com All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE + */ + +import { ChangeDetectionStrategy, Component, Input, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core'; + +import { InputNumber } from 'ng-zorro-antd/core'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, + selector: 'nz-descriptions-item', + templateUrl: './nz-descriptions-item.component.html', + exportAs: 'nzDescriptionsItem', + preserveWhitespaces: false +}) +export class NzDescriptionsItemComponent { + @ViewChild(TemplateRef) content: TemplateRef; + + @Input() @InputNumber() nzSpan = 1; + @Input() nzTitle: string = ''; +} diff --git a/components/descriptions/nz-descriptions.component.html b/components/descriptions/nz-descriptions.component.html new file mode 100644 index 00000000000..ebc00505cad --- /dev/null +++ b/components/descriptions/nz-descriptions.component.html @@ -0,0 +1,33 @@ +
+ {{ nzTitle }} +
+
+ + + + + + + + + + + + + + + +
+ {{ item.title }} + + + + {{ item.title }} + +
+
diff --git a/components/descriptions/nz-descriptions.component.ts b/components/descriptions/nz-descriptions.component.ts new file mode 100644 index 00000000000..7100f6f6642 --- /dev/null +++ b/components/descriptions/nz-descriptions.component.ts @@ -0,0 +1,189 @@ +/** + * @license + * Copyright Alibaba.com All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE + */ + +import { MediaMatcher } from '@angular/cdk/layout'; +import { Platform } from '@angular/cdk/platform'; +import { + isDevMode, + AfterContentInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + ContentChildren, + Input, + NgZone, + OnChanges, + OnDestroy, + QueryList, + SimpleChanges, + TemplateRef, + ViewEncapsulation +} from '@angular/core'; +import { fromEvent, merge, Subject } from 'rxjs'; +import { auditTime, startWith, takeUntil } from 'rxjs/operators'; + +import { responsiveMap, Breakpoint, InputBoolean } from 'ng-zorro-antd/core'; +import { NzDescriptionsItemRenderProps, NzDescriptionsSize } from './nz-descriptions-definitions'; +import { NzDescriptionsItemComponent } from './nz-descriptions-item.component'; + +const defaultColumnMap: { [size: string]: number } = { + xxl: 3, + xl: 3, + lg: 3, + md: 3, + sm: 2, + xs: 1 +}; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, + selector: 'nz-descriptions', + templateUrl: './nz-descriptions.component.html', + exportAs: 'nzDescriptions', + preserveWhitespaces: false, + host: { + class: 'ant-descriptions', + '[class.bordered]': 'nzBordered', + '[class.middle]': 'nzSize === "middle"', + '[class.small]': 'nzSize === "small"' + }, + styles: [ + ` + nz-descriptions { + display: block; + } + ` + ] +}) +export class NzDescriptionsComponent implements OnChanges, OnDestroy, AfterContentInit { + @ContentChildren(NzDescriptionsItemComponent) items: QueryList; + + @Input() @InputBoolean() nzBordered = false; + @Input() nzColumn: number | { [key: string]: number } = defaultColumnMap; + @Input() nzSize: NzDescriptionsSize = 'default'; + @Input() nzTitle: string | TemplateRef = ''; + + itemMatrix: NzDescriptionsItemRenderProps[][] = []; + + realColumn = 3; + + private destroy$ = new Subject(); + private resize$ = new Subject(); + + constructor( + private cdr: ChangeDetectorRef, + private ngZone: NgZone, + private mediaMatcher: MediaMatcher, + private platform: Platform + ) {} + + ngOnChanges(changes: SimpleChanges): void { + if (changes.nzColumn) { + this.resize$.next(); + } + } + + ngAfterContentInit(): void { + merge( + this.items.changes.pipe( + startWith(this.items), + takeUntil(this.destroy$) + ), + this.resize$ + ) + .pipe(takeUntil(this.destroy$)) + .subscribe(() => { + this.prepareMatrix(); + this.cdr.markForCheck(); + }); + + if (this.platform.isBrowser) { + this.ngZone.runOutsideAngular(() => { + fromEvent(window, 'resize') + .pipe( + auditTime(16), + takeUntil(this.destroy$) + ) + .subscribe(() => { + this.ngZone.run(() => { + this.resize$.next(); + }); + }); + }); + } + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + this.resize$.complete(); + } + + /** + * Prepare the render matrix according to description items' spans. + */ + private prepareMatrix(): void { + let currentRow: NzDescriptionsItemRenderProps[] = []; + let width = 0; + + const column = (this.realColumn = this.getColumn()); + const items: NzDescriptionsItemComponent[] = this.items.toArray(); + const matrix: NzDescriptionsItemRenderProps[][] = []; + const flushRow = () => { + matrix.push(currentRow); + currentRow = []; + width = 0; + }; + + items.forEach(item => { + const { nzTitle: title, content, nzSpan: span } = item; + + currentRow.push({ title, content, span }); + width += span; + + // If the last item make the row's length exceeds `nzColumn`, the last + // item should take all the space left. This logic is implemented in the template. + // Warn user about that. + if (width >= column) { + if (width > column && isDevMode()) { + console.warn(`"nzColumn" is ${column} but we have row length ${width}`); + } + flushRow(); + } + }); + + if (currentRow.length) { + flushRow(); + } + + this.itemMatrix = matrix; + } + + private matchMedia(): Breakpoint { + let bp: Breakpoint = Breakpoint.md; + + Object.keys(responsiveMap).map((breakpoint: string) => { + const castBP = breakpoint as Breakpoint; + const matchBelow = this.mediaMatcher.matchMedia(responsiveMap[castBP]).matches; + if (matchBelow) { + bp = castBP; + } + }); + + return bp; + } + + private getColumn(): number { + if (typeof this.nzColumn !== 'number') { + return this.nzColumn[this.matchMedia()]; + } + + return this.nzColumn; + } +} diff --git a/components/descriptions/nz-descriptions.module.ts b/components/descriptions/nz-descriptions.module.ts new file mode 100644 index 00000000000..575f573c86b --- /dev/null +++ b/components/descriptions/nz-descriptions.module.ts @@ -0,0 +1,22 @@ +/** + * @license + * Copyright Alibaba.com All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE + */ + +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { NzAddOnModule } from 'ng-zorro-antd/core'; + +import { NzDescriptionsItemComponent } from './nz-descriptions-item.component'; +import { NzDescriptionsComponent } from './nz-descriptions.component'; + +@NgModule({ + imports: [CommonModule, NzAddOnModule], + declarations: [NzDescriptionsComponent, NzDescriptionsItemComponent], + exports: [NzDescriptionsComponent, NzDescriptionsItemComponent] +}) +export class NzDescriptionsModule {} diff --git a/components/descriptions/nz-descriptions.spec.ts b/components/descriptions/nz-descriptions.spec.ts new file mode 100644 index 00000000000..c0e2e0024f2 --- /dev/null +++ b/components/descriptions/nz-descriptions.spec.ts @@ -0,0 +1,123 @@ +import { CommonModule } from '@angular/common'; +import { Component, ViewChild } from '@angular/core'; +import { fakeAsync, tick, ComponentFixture, TestBed } from '@angular/core/testing'; +import { NzDescriptionsComponent } from './nz-descriptions.component'; +import { NzDescriptionsModule } from './nz-descriptions.module'; + +// tslint:disable-next-line no-any +declare const viewport: any; + +describe('nz descriptions', () => { + let testComponent: NzTestDescriptionsComponent; + let componentElement: HTMLElement; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [CommonModule, NzDescriptionsModule], + declarations: [NzTestDescriptionsComponent] + }).compileComponents(); + }); + + describe('with different spans', () => { + let rows; + + beforeEach(() => { + fixture = TestBed.createComponent(NzTestDescriptionsComponent); + testComponent = fixture.componentInstance; + componentElement = fixture.debugElement.nativeElement; + + fixture.detectChanges(); + }); + + it('should have correct layout', () => { + let title = componentElement.querySelector('.ant-descriptions-title'); + const view = componentElement.querySelector('.ant-descriptions-view'); + + expect(title).toBeTruthy(); + expect(view).toBeTruthy(); + + testComponent.title = ''; + fixture.detectChanges(); + title = componentElement.querySelector('.ant-descriptions-title'); + expect(title).toBeFalsy(); + }); + + it('should render spans correctly', () => { + const spyOnWarn = spyOn(console, 'warn'); + + rows = componentElement.querySelectorAll('.ant-descriptions-row'); + expect(rows.length).toBe(1); + + testComponent.colspanArray = [1, 1, 1, 2, 3, 1, 5]; + fixture.detectChanges(); + rows = componentElement.querySelectorAll('.ant-descriptions-row'); + expect(rows.length).toBe(3); + expect(spyOnWarn).toHaveBeenCalledTimes(2); + expect(spyOnWarn).toHaveBeenCalledWith('"nzColumn" is 3 but we have row length 5'); + expect(spyOnWarn).toHaveBeenCalledWith('"nzColumn" is 3 but we have row length 6'); + + testComponent.column = 5; + testComponent.colspanArray = [1, 2, 3]; + fixture.detectChanges(); + rows = componentElement.querySelectorAll('.ant-descriptions-row'); + expect(rows.length).toBe(1); + expect(spyOnWarn).toHaveBeenCalledTimes(4); + expect(spyOnWarn).toHaveBeenCalledWith('"nzColumn" is 5 but we have row length 6'); + + testComponent.colspanArray = [1, 2, 2]; + fixture.detectChanges(); + rows = componentElement.querySelectorAll('.ant-descriptions-row'); + expect(rows.length).toBe(1); + }); + + it('should responsive work', fakeAsync(() => { + testComponent.column = { + xxl: 3, + xl: 3, + lg: 3, + md: 3, + sm: 2, + xs: 1 + }; + testComponent.colspanArray = [1, 1, 1, 2, 3, 1, 5]; + + viewport.set(1024, 1024); + window.dispatchEvent(new Event('resize')); + fixture.autoDetectChanges(); + tick(1000); + fixture.autoDetectChanges(); + rows = componentElement.querySelectorAll('.ant-descriptions-row'); + expect(rows.length).toBe(3); + + viewport.set(320, 320); + window.dispatchEvent(new Event('resize')); + fixture.autoDetectChanges(); + tick(1000); + fixture.autoDetectChanges(); + + rows = componentElement.querySelectorAll('.ant-descriptions-row'); + expect(rows.length).toBe(7); + + viewport.reset(); + })); + }); +}); + +@Component({ + selector: 'nz-test-descriptions', + template: ` + + + + + ` +}) +export class NzTestDescriptionsComponent { + @ViewChild(NzDescriptionsComponent) + descriptionComponent: NzDescriptionsComponent; + bordered = false; + colspanArray: number[] = [1, 1, 1]; + column: number | { [key: string]: number } = 3; + title = 'Title'; +} diff --git a/components/descriptions/package.json b/components/descriptions/package.json new file mode 100644 index 00000000000..ded1e7a9fdf --- /dev/null +++ b/components/descriptions/package.json @@ -0,0 +1,7 @@ +{ + "ngPackage": { + "lib": { + "entryFile": "public-api.ts" + } + } +} diff --git a/components/descriptions/public-api.ts b/components/descriptions/public-api.ts new file mode 100644 index 00000000000..13c21f06cf0 --- /dev/null +++ b/components/descriptions/public-api.ts @@ -0,0 +1,13 @@ +/** + * @license + * Copyright Alibaba.com All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE + */ + +export { NzDescriptionsModule } from './nz-descriptions.module'; +export { NzDescriptionsComponent } from './nz-descriptions.component'; +export { NzDescriptionsItemComponent } from './nz-descriptions-item.component'; + +export * from './nz-descriptions-definitions'; diff --git a/components/descriptions/style/entry.less b/components/descriptions/style/entry.less new file mode 100644 index 00000000000..fa29965e8e4 --- /dev/null +++ b/components/descriptions/style/entry.less @@ -0,0 +1 @@ +@import "./index.less"; diff --git a/components/descriptions/style/index.less b/components/descriptions/style/index.less new file mode 100644 index 00000000000..fcc29e539b7 --- /dev/null +++ b/components/descriptions/style/index.less @@ -0,0 +1,118 @@ +@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%; + } + } + + &-row { + > td { + padding-bottom: 16px; + } + &:last-child { + border-bottom: none; + } + } + + &-item-label { + color: @heading-color; + 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-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; + } + .@{descriptions-prefix-cls}-item-label { + float: left; + padding: 0 !important; + } + .@{descriptions-prefix-cls}-item-content { + float: left; + padding: 0 !important; + } + } + + // padding setting + .@{descriptions-prefix-cls}-item-label, + .@{descriptions-prefix-cls}-item-content { + padding: @descriptions-default-padding; + } + + &.bordered.middle { + .@{descriptions-prefix-cls}-item-label, + .@{descriptions-prefix-cls}-item-content { + padding: @descriptions-middle-padding; + } + } + &.bordered.small { + .@{descriptions-prefix-cls}-item-label, + .@{descriptions-prefix-cls}-item-content { + padding: @descriptions-small-padding; + } + } + &.bordered { + .@{descriptions-prefix-cls}-view { + border: 1px solid @border-color-split; + } + .@{descriptions-prefix-cls}-item-label, + .@{descriptions-prefix-cls}-item-content { + border-right: 1px solid @border-color-split; + } + + .@{descriptions-prefix-cls}-item-label:last-child, + .@{descriptions-prefix-cls}-item-content:last-child { + border-right: none; + } + + .@{descriptions-prefix-cls}-row { + border-bottom: 1px solid @border-color-split; + &:last-child { + border-bottom: none; + } + } + + .@{descriptions-prefix-cls}-item-label { + background-color: #fafafa; + &::after { + display: none; + } + } + } +} diff --git a/components/grid/demo/gutter.ts b/components/grid/demo/gutter.ts index e89abcd36d4..605cce12dd9 100755 --- a/components/grid/demo/gutter.ts +++ b/components/grid/demo/gutter.ts @@ -20,7 +20,7 @@ import { Component } from '@angular/core';
-
+
col-6
diff --git a/components/grid/nz-grid.spec.ts b/components/grid/nz-grid.spec.ts index fd46c17d36d..a0ae969387b 100644 --- a/components/grid/nz-grid.spec.ts +++ b/components/grid/nz-grid.spec.ts @@ -16,6 +16,9 @@ import { NzColDirective } from './nz-col.directive'; import { NzGridModule } from './nz-grid.module'; import { NzRowDirective } from './nz-row.directive'; +// tslint:disable-next-line no-any +declare const viewport: any; + describe('grid', () => { describe('basic', () => { let fixture: ComponentFixture; @@ -172,22 +175,32 @@ describe('grid', () => { expect(cols.slice(0, 4).every(col => col.nativeElement.classList.contains('gutter-row'))).toBe(true); }); - it('should responsive work', () => { - // TODO: fake media query + it('should responsive work', fakeAsync(() => { + viewport.set(1000, 1000); + window.dispatchEvent(new Event('resize')); fixture.detectChanges(); - expect(rows[1].nativeElement.style.cssText).toBe('margin-left: -4px; margin-right: -4px;'); + tick(100); + fixture.detectChanges(); + + expect(rows[1].nativeElement.style.cssText).toBe('margin-left: -16px; margin-right: -16px;'); expect( - cols.slice(4, 8).every(col => col.nativeElement.style.cssText === 'padding-left: 4px; padding-right: 4px;') + cols.slice(4, 8).every(col => col.nativeElement.style.cssText === 'padding-left: 16px; padding-right: 16px;') ).toBe(true); expect(cols.slice(4, 8).every(col => col.nativeElement.classList.contains('gutter-row'))).toBe(true); + + viewport.set(480, 480); window.dispatchEvent(new Event('resize')); fixture.detectChanges(); + tick(100); + fixture.detectChanges(); expect(rows[1].nativeElement.style.cssText).toBe('margin-left: -4px; margin-right: -4px;'); expect( cols.slice(4, 8).every(col => col.nativeElement.style.cssText === 'padding-left: 4px; padding-right: 4px;') ).toBe(true); expect(cols.slice(4, 8).every(col => col.nativeElement.classList.contains('gutter-row'))).toBe(true); - }); + + viewport.reset(); + })); }); describe('offset', () => { diff --git a/components/grid/nz-row.directive.ts b/components/grid/nz-row.directive.ts index 75636858870..2880da18f06 100644 --- a/components/grid/nz-row.directive.ts +++ b/components/grid/nz-row.directive.ts @@ -24,32 +24,12 @@ import { Platform } from '@angular/cdk/platform'; import { fromEvent, Subject } from 'rxjs'; import { auditTime, takeUntil } from 'rxjs/operators'; -import { IndexableObject, NzUpdateHostClassService } from 'ng-zorro-antd/core'; +import { responsiveMap, Breakpoint, IndexableObject, NzUpdateHostClassService } from 'ng-zorro-antd/core'; export type NzJustify = 'start' | 'end' | 'center' | 'space-around' | 'space-between'; export type NzAlign = 'top' | 'middle' | 'bottom'; export type NzType = 'flex' | null; -export enum Breakpoint { - 'xxl', - 'xl', - 'lg', - 'md', - 'sm', - 'xs' -} - -export type BreakpointMap = { [index in keyof typeof Breakpoint]: string }; - -const responsiveMap: BreakpointMap = { - xs: '(max-width: 575px)', - sm: '(min-width: 576px)', - md: '(min-width: 768px)', - lg: '(min-width: 992px)', - xl: '(min-width: 1200px)', - xxl: '(min-width: 1600px)' -}; - @Directive({ selector: '[nz-row],nz-row', exportAs: 'nzRow', @@ -88,11 +68,11 @@ export class NzRowDirective implements OnInit, OnChanges, AfterViewInit, OnDestr } watchMedia(): void { - // @ts-ignore - Object.keys(responsiveMap).map((screen: Breakpoint) => { - const matchBelow = this.mediaMatcher.matchMedia(responsiveMap[screen]).matches; + Object.keys(responsiveMap).map((screen: string) => { + const castBP = screen as Breakpoint; + const matchBelow = this.mediaMatcher.matchMedia(responsiveMap[castBP]).matches; if (matchBelow) { - this.breakPoint = screen; + this.breakPoint = castBP; } }); this.updateGutter(); diff --git a/components/karma.conf.js b/components/karma.conf.js index 7abe9e875ea..e70138f4561 100644 --- a/components/karma.conf.js +++ b/components/karma.conf.js @@ -4,14 +4,15 @@ module.exports = function(config) { config.set({ basePath: '', - frameworks: ['jasmine', '@angular-devkit/build-angular'], + frameworks: ['jasmine', '@angular-devkit/build-angular', 'viewport'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-spec-reporter'), require('karma-jasmine-html-reporter'), require('karma-coverage-istanbul-reporter'), - require('@angular-devkit/build-angular/plugins/karma') + require('@angular-devkit/build-angular/plugins/karma'), + require('karma-viewport') ], client: { clearContext: true // leave Jasmine Spec Runner output visible in browser diff --git a/components/ng-zorro-antd.module.ts b/components/ng-zorro-antd.module.ts index f5ffc7d29bb..6304d925c33 100644 --- a/components/ng-zorro-antd.module.ts +++ b/components/ng-zorro-antd.module.ts @@ -18,6 +18,7 @@ import { NzCollapseModule } from 'ng-zorro-antd/collapse'; import { NzCommentModule } from 'ng-zorro-antd/comment'; import { NzNoAnimationModule, NzWaveModule } from 'ng-zorro-antd/core'; import { NzDatePickerModule } from 'ng-zorro-antd/date-picker'; +import { NzDescriptionsModule } from 'ng-zorro-antd/descriptions'; import { NzDividerModule } from 'ng-zorro-antd/divider'; import { NzDrawerModule } from 'ng-zorro-antd/drawer'; import { NzDropDownModule } from 'ng-zorro-antd/dropdown'; @@ -78,6 +79,7 @@ export * from 'ng-zorro-antd/collapse'; export * from 'ng-zorro-antd/comment'; export * from 'ng-zorro-antd/core'; export * from 'ng-zorro-antd/date-picker'; +export * from 'ng-zorro-antd/descriptions'; export * from 'ng-zorro-antd/divider'; export * from 'ng-zorro-antd/drawer'; export * from 'ng-zorro-antd/drawer'; @@ -185,7 +187,8 @@ export * from './version'; NzNoAnimationModule, NzSkeletonModule, NzStatisticModule, - NzEmptyModule + NzEmptyModule, + NzDescriptionsModule ] }) export class NgZorroAntdModule { diff --git a/package.json b/package.json index 755c8cde3dd..8c8bcc6c00b 100644 --- a/package.json +++ b/package.json @@ -60,8 +60,8 @@ "@angular/http": "~7.2.0", "@angular/language-service": "~7.2.0", "@angular/platform-browser": "~7.2.0", - "@angular/platform-server": "^7.2.14", "@angular/platform-browser-dynamic": "~7.2.0", + "@angular/platform-server": "^7.2.14", "@angular/pwa": "^0.12.2", "@angular/router": "~7.2.0", "@angular/service-worker": "~7.2.0", @@ -88,6 +88,7 @@ "karma-jasmine": "~1.1.2", "karma-jasmine-html-reporter": "^0.2.2", "karma-spec-reporter": "0.0.32", + "karma-viewport": "^1.0.4", "less": "^3.9.0", "less-plugin-clean-css": "^1.5.1", "lint-staged": "^8.1.5", diff --git a/scripts/prerender/static.paths.ts b/scripts/prerender/static.paths.ts index 939de5cfb02..1abf82c30a2 100644 --- a/scripts/prerender/static.paths.ts +++ b/scripts/prerender/static.paths.ts @@ -34,6 +34,8 @@ export const ROUTES = [ '/components/comment/zh', '/components/date-picker/en', '/components/date-picker/zh', + '/components/descriptions/en', + '/components/descriptions/zh', '/components/divider/en', '/components/divider/zh', '/components/drawer/en',