From d6d20a3482f5ae705cb42a9d74e6aec97f42ae0f Mon Sep 17 00:00:00 2001 From: GuoJikun Date: Mon, 7 Nov 2022 21:00:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=AE=AB=E6=A0=BC?= =?UTF-8?q?=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/src/components.d.ts | 47 ++++++++++----- .../ivy-grid-item/ivy-grid-item.css | 8 +++ .../ivy-grid-item/ivy-grid-item.tsx | 31 ++++++++++ .../ivy-grid-item/test/ivy-grid-item.e2e.ts | 11 ++++ .../ivy-grid-item/test/ivy-grid-item.spec.tsx | 18 ++++++ .../src/components/ivy-grid/ivy-grid.css | 11 ++++ .../src/components/ivy-grid/ivy-grid.tsx | 58 +++++++++++++++++++ .../test/ivy-grid.e2e.ts} | 6 +- .../test/ivy-grid.spec.tsx} | 12 ++-- .../src/components/ivy-space/ivy-space.css | 41 ------------- .../src/components/ivy-space/ivy-space.tsx | 50 ---------------- components/src/index.html | 22 +++++-- components/src/utils/utils.ts | 11 ++++ 13 files changed, 207 insertions(+), 119 deletions(-) create mode 100644 components/src/components/ivy-grid-item/ivy-grid-item.css create mode 100644 components/src/components/ivy-grid-item/ivy-grid-item.tsx create mode 100644 components/src/components/ivy-grid-item/test/ivy-grid-item.e2e.ts create mode 100644 components/src/components/ivy-grid-item/test/ivy-grid-item.spec.tsx create mode 100644 components/src/components/ivy-grid/ivy-grid.css create mode 100644 components/src/components/ivy-grid/ivy-grid.tsx rename components/src/components/{ivy-space/test/ivy-space.e2e.ts => ivy-grid/test/ivy-grid.e2e.ts} (56%) rename components/src/components/{ivy-space/test/ivy-space.spec.tsx => ivy-grid/test/ivy-grid.spec.tsx} (59%) delete mode 100644 components/src/components/ivy-space/ivy-space.css delete mode 100644 components/src/components/ivy-space/ivy-space.tsx diff --git a/components/src/components.d.ts b/components/src/components.d.ts index 5172432..16dbaa3 100644 --- a/components/src/components.d.ts +++ b/components/src/components.d.ts @@ -82,6 +82,14 @@ export namespace Components { } interface IvyEmpty { } + interface IvyGrid { + "border": boolean; + "col": string; + "square": boolean; + } + interface IvyGridItem { + "col": string; + } interface IvyImage { "alt": string; "lazy": boolean; @@ -93,8 +101,6 @@ export namespace Components { } interface IvyRow { } - interface IvySpace { - } interface IvyTag { "size": string; "theme": string; @@ -233,6 +239,18 @@ declare global { prototype: HTMLIvyEmptyElement; new (): HTMLIvyEmptyElement; }; + interface HTMLIvyGridElement extends Components.IvyGrid, HTMLStencilElement { + } + var HTMLIvyGridElement: { + prototype: HTMLIvyGridElement; + new (): HTMLIvyGridElement; + }; + interface HTMLIvyGridItemElement extends Components.IvyGridItem, HTMLStencilElement { + } + var HTMLIvyGridItemElement: { + prototype: HTMLIvyGridItemElement; + new (): HTMLIvyGridItemElement; + }; interface HTMLIvyImageElement extends Components.IvyImage, HTMLStencilElement { } var HTMLIvyImageElement: { @@ -251,12 +269,6 @@ declare global { prototype: HTMLIvyRowElement; new (): HTMLIvyRowElement; }; - interface HTMLIvySpaceElement extends Components.IvySpace, HTMLStencilElement { - } - var HTMLIvySpaceElement: { - prototype: HTMLIvySpaceElement; - new (): HTMLIvySpaceElement; - }; interface HTMLIvyTagElement extends Components.IvyTag, HTMLStencilElement { } var HTMLIvyTagElement: { @@ -305,10 +317,11 @@ declare global { "ivy-divider": HTMLIvyDividerElement; "ivy-drawer": HTMLIvyDrawerElement; "ivy-empty": HTMLIvyEmptyElement; + "ivy-grid": HTMLIvyGridElement; + "ivy-grid-item": HTMLIvyGridItemElement; "ivy-image": HTMLIvyImageElement; "ivy-pager": HTMLIvyPagerElement; "ivy-row": HTMLIvyRowElement; - "ivy-space": HTMLIvySpaceElement; "ivy-tag": HTMLIvyTagElement; "ivy-timeline": HTMLIvyTimelineElement; "ivy-timeline-item": HTMLIvyTimelineItemElement; @@ -391,6 +404,14 @@ declare namespace LocalJSX { } interface IvyEmpty { } + interface IvyGrid { + "border"?: boolean; + "col"?: string; + "square"?: boolean; + } + interface IvyGridItem { + "col"?: string; + } interface IvyImage { "alt"?: string; "lazy"?: boolean; @@ -403,8 +424,6 @@ declare namespace LocalJSX { } interface IvyRow { } - interface IvySpace { - } interface IvyTag { "size"?: string; "theme"?: string; @@ -445,10 +464,11 @@ declare namespace LocalJSX { "ivy-divider": IvyDivider; "ivy-drawer": IvyDrawer; "ivy-empty": IvyEmpty; + "ivy-grid": IvyGrid; + "ivy-grid-item": IvyGridItem; "ivy-image": IvyImage; "ivy-pager": IvyPager; "ivy-row": IvyRow; - "ivy-space": IvySpace; "ivy-tag": IvyTag; "ivy-timeline": IvyTimeline; "ivy-timeline-item": IvyTimelineItem; @@ -477,10 +497,11 @@ declare module "@stencil/core" { "ivy-divider": LocalJSX.IvyDivider & JSXBase.HTMLAttributes; "ivy-drawer": LocalJSX.IvyDrawer & JSXBase.HTMLAttributes; "ivy-empty": LocalJSX.IvyEmpty & JSXBase.HTMLAttributes; + "ivy-grid": LocalJSX.IvyGrid & JSXBase.HTMLAttributes; + "ivy-grid-item": LocalJSX.IvyGridItem & JSXBase.HTMLAttributes; "ivy-image": LocalJSX.IvyImage & JSXBase.HTMLAttributes; "ivy-pager": LocalJSX.IvyPager & JSXBase.HTMLAttributes; "ivy-row": LocalJSX.IvyRow & JSXBase.HTMLAttributes; - "ivy-space": LocalJSX.IvySpace & JSXBase.HTMLAttributes; "ivy-tag": LocalJSX.IvyTag & JSXBase.HTMLAttributes; "ivy-timeline": LocalJSX.IvyTimeline & JSXBase.HTMLAttributes; "ivy-timeline-item": LocalJSX.IvyTimelineItem & JSXBase.HTMLAttributes; diff --git a/components/src/components/ivy-grid-item/ivy-grid-item.css b/components/src/components/ivy-grid-item/ivy-grid-item.css new file mode 100644 index 0000000..7ad2819 --- /dev/null +++ b/components/src/components/ivy-grid-item/ivy-grid-item.css @@ -0,0 +1,8 @@ +:host { + display: block; + box-sizing: border-box; + border-right: var(--ivy-grid-item-border); + border-bottom: var(--ivy-grid-item-border); + width: var(--ivy-grid-item-width); + height: var(--ivy-grid-item-height); +} diff --git a/components/src/components/ivy-grid-item/ivy-grid-item.tsx b/components/src/components/ivy-grid-item/ivy-grid-item.tsx new file mode 100644 index 0000000..45445a3 --- /dev/null +++ b/components/src/components/ivy-grid-item/ivy-grid-item.tsx @@ -0,0 +1,31 @@ +import { Component, Host, h, State, Prop, Watch, Element } from '@stencil/core'; + +@Component({ + tag: 'ivy-grid-item', + styleUrl: 'ivy-grid-item.css', + shadow: true, +}) +export class IvyGridItem { + @Element() $el: HTMLElement; + + @State() _col: number = 3; + + @Prop() col: string = '3'; + + @Watch('col') + watchColHandler(val: string) { + const tmp = parseInt(val); + if (tmp !== this._col) { + throw new Error(`type attr is must be string number`); + } + this._col = tmp; + } + + render() { + return ( + + + + ); + } +} diff --git a/components/src/components/ivy-grid-item/test/ivy-grid-item.e2e.ts b/components/src/components/ivy-grid-item/test/ivy-grid-item.e2e.ts new file mode 100644 index 0000000..7845be6 --- /dev/null +++ b/components/src/components/ivy-grid-item/test/ivy-grid-item.e2e.ts @@ -0,0 +1,11 @@ +import { newE2EPage } from '@stencil/core/testing'; + +describe('ivy-grid-item', () => { + it('renders', async () => { + const page = await newE2EPage(); + await page.setContent(''); + + const element = await page.find('ivy-grid-item'); + expect(element).toHaveClass('hydrated'); + }); +}); diff --git a/components/src/components/ivy-grid-item/test/ivy-grid-item.spec.tsx b/components/src/components/ivy-grid-item/test/ivy-grid-item.spec.tsx new file mode 100644 index 0000000..dc2d7ef --- /dev/null +++ b/components/src/components/ivy-grid-item/test/ivy-grid-item.spec.tsx @@ -0,0 +1,18 @@ +import { newSpecPage } from '@stencil/core/testing'; +import { IvyGridItem } from '../ivy-grid-item'; + +describe('ivy-grid-item', () => { + it('renders', async () => { + const page = await newSpecPage({ + components: [IvyGridItem], + html: ``, + }); + expect(page.root).toEqualHtml(` + + + + + + `); + }); +}); diff --git a/components/src/components/ivy-grid/ivy-grid.css b/components/src/components/ivy-grid/ivy-grid.css new file mode 100644 index 0000000..0f42a5e --- /dev/null +++ b/components/src/components/ivy-grid/ivy-grid.css @@ -0,0 +1,11 @@ +:host { + display: flex; + box-sizing: border-box; + flex-wrap: wrap; +} + +:host([border]) { + border-left: 1px solid var(--ivy-border-color, #dcdfe6); + border-top: 1px solid var(--ivy-border-color, #dcdfe6); + --ivy-grid-item-border: 1px solid var(--ivy-border-color, #dcdfe6); +} diff --git a/components/src/components/ivy-grid/ivy-grid.tsx b/components/src/components/ivy-grid/ivy-grid.tsx new file mode 100644 index 0000000..f5a4d67 --- /dev/null +++ b/components/src/components/ivy-grid/ivy-grid.tsx @@ -0,0 +1,58 @@ +import { Component, Host, h, Prop, Watch, State, Element, writeTask } from '@stencil/core'; + +@Component({ + tag: 'ivy-grid', + styleUrl: 'ivy-grid.css', + shadow: true, +}) +export class IvyGrid { + @Element() $el: HTMLElement; + + @State() styles: { [key: string]: string } = { + '--ivy-grid-item-width': `33.3333333%`, + }; + + @Prop() square: boolean = false; + @Prop({ + attribute: 'border', + reflect: true, + }) + border: boolean = false; + + @Prop() col: string = '3'; + + @Watch('col') + watchColHandler(val: string) { + const tmp = parseInt(val); + if (tmp.toString() !== val) { + throw new Error(`type attr is must be string number`); + } + } + + componentWillLoad() { + writeTask(() => { + let wrapWidth = this.$el.getBoundingClientRect().width; + if (this.border) { + wrapWidth -= 1; + } + const widthNumber = wrapWidth / parseInt(this.col); + const width = parseInt((widthNumber * 1000).toString()) / 1000; + if (this.square) { + this.styles = { + '--ivy-grid-item-width': `${width}px`, + '--ivy-grid-item-height': `${width}px`, + }; + } else { + this.styles = { '--ivy-grid-item-width': `${width}px` }; + } + }); + } + + render() { + return ( + + + + ); + } +} diff --git a/components/src/components/ivy-space/test/ivy-space.e2e.ts b/components/src/components/ivy-grid/test/ivy-grid.e2e.ts similarity index 56% rename from components/src/components/ivy-space/test/ivy-space.e2e.ts rename to components/src/components/ivy-grid/test/ivy-grid.e2e.ts index bdda015..610b6f3 100644 --- a/components/src/components/ivy-space/test/ivy-space.e2e.ts +++ b/components/src/components/ivy-grid/test/ivy-grid.e2e.ts @@ -1,11 +1,11 @@ import { newE2EPage } from '@stencil/core/testing'; -describe('ivy-space', () => { +describe('ivy-grid', () => { it('renders', async () => { const page = await newE2EPage(); - await page.setContent(''); + await page.setContent(''); - const element = await page.find('ivy-space'); + const element = await page.find('ivy-grid'); expect(element).toHaveClass('hydrated'); }); }); diff --git a/components/src/components/ivy-space/test/ivy-space.spec.tsx b/components/src/components/ivy-grid/test/ivy-grid.spec.tsx similarity index 59% rename from components/src/components/ivy-space/test/ivy-space.spec.tsx rename to components/src/components/ivy-grid/test/ivy-grid.spec.tsx index 087e57c..2ccb753 100644 --- a/components/src/components/ivy-space/test/ivy-space.spec.tsx +++ b/components/src/components/ivy-grid/test/ivy-grid.spec.tsx @@ -1,18 +1,18 @@ import { newSpecPage } from '@stencil/core/testing'; -import { IvySpace } from '../ivy-space'; +import { IvyGrid } from '../ivy-grid'; -describe('ivy-space', () => { +describe('ivy-grid', () => { it('renders', async () => { const page = await newSpecPage({ - components: [IvySpace], - html: ``, + components: [IvyGrid], + html: ``, }); expect(page.root).toEqualHtml(` - + - + `); }); }); diff --git a/components/src/components/ivy-space/ivy-space.css b/components/src/components/ivy-space/ivy-space.css deleted file mode 100644 index bd045dc..0000000 --- a/components/src/components/ivy-space/ivy-space.css +++ /dev/null @@ -1,41 +0,0 @@ -:host { - display: inline-flex; - box-sizing: border-box; -} - -:host(vertical) { - flex-direction: column; -} - -.space { - display: inline-flex; - box-sizing: border-box; -} - -.space-item { - margin-right: 12px; - box-sizing: border-box; -} -.space-item:last-child { - margin-right: 0; -} - -:host([align='center']), -:host([align]) { - align-items: center; -} - -:host([align='start']) { - align-items: flex-start; -} - -:host([align='end']) { - align-items: flex-end; -} - -:host([align='baseline']) { - align-items: baseline; -} -.hidden { - display: none; -} diff --git a/components/src/components/ivy-space/ivy-space.tsx b/components/src/components/ivy-space/ivy-space.tsx deleted file mode 100644 index 1459856..0000000 --- a/components/src/components/ivy-space/ivy-space.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Component, Host, h, Element, State } from '@stencil/core'; - -@Component({ - tag: 'ivy-space', - styleUrl: 'ivy-space.css', - shadow: true, -}) -export class IvySpace { - @State() children = []; - @Element() el: HTMLElement; - render() { - return ( - -
- {this.children.map(c => { - return ( -
- {c.nodeType === 3 - ? c.textContent - : h( - c.nodeName.toLowerCase(), - { - ...c, - }, - c.textContent, - )} -
- ); - })} -
- -
- ); - } - - componentWillLoad() { - this.children = []; - this.el.childNodes.forEach(el => { - console.log(el.nodeType); - if (el.nodeType === 1) { - this.children.push(el); - } else if (el.nodeType === 3 && el.textContent.trim() !== '') { - this.children.push(el); - } - }); - console.log(this.children); - } -} diff --git a/components/src/index.html b/components/src/index.html index 4d98e57..f1a9f85 100644 --- a/components/src/index.html +++ b/components/src/index.html @@ -55,12 +55,22 @@
- - Text 文字 - - Button - - + + + Button 1 + + + Button 2
324324 +
+ + Button 3 + + + Button 2
324324 +
+
+ + 312312
diff --git a/components/src/utils/utils.ts b/components/src/utils/utils.ts index 0d6dc0d..3a8c43a 100644 --- a/components/src/utils/utils.ts +++ b/components/src/utils/utils.ts @@ -31,3 +31,14 @@ export const getBrotherElements = (self: HTMLElement, isSelf: Boolean = false) = } return list; }; + +/** + * 查询当前元素下符合条件的所有元素 + * @param self + * @param tag 合法的css选择器 + * @returns + */ +export const findChildrenElements = (self: HTMLElement, tag: string) => { + const children = self.querySelectorAll(tag); + return children as unknown as Array; +}; -- GitLab