From e8d87f765eb2de0fb3b52322c5c637ad45c6c5f7 Mon Sep 17 00:00:00 2001 From: mantou132 <709922234@qq.com> Date: Sun, 1 Sep 2024 14:35:01 +0800 Subject: [PATCH] [duoyun-ui] Closed #191 --- .../duoyun-ui/docs/en/02-elements/empty.md | 1 + .../duoyun-ui/docs/zh/02-elements/empty.md | 1 + packages/duoyun-ui/src/elements/card.ts | 18 +++-- packages/duoyun-ui/src/elements/collapse.ts | 6 +- .../duoyun-ui/src/elements/compartment.ts | 2 +- packages/duoyun-ui/src/elements/empty.ts | 28 ++++++-- packages/duoyun-ui/src/elements/meter.ts | 14 ++-- packages/duoyun-ui/src/elements/modal.ts | 70 +++++++++++-------- packages/duoyun-ui/src/elements/popover.ts | 1 + packages/duoyun-ui/src/elements/result.ts | 25 +++++-- packages/duoyun-ui/src/elements/statistic.ts | 19 ++++- packages/duoyun-ui/src/elements/table.ts | 11 ++- packages/duoyun-ui/src/lib/styles.ts | 1 + packages/duoyun-ui/src/patterns/nav.ts | 4 +- .../004-blog/001-create-standard-element.md | 19 ++++- .../004-blog/001-create-standard-element.md | 20 +++++- 16 files changed, 170 insertions(+), 70 deletions(-) diff --git a/packages/duoyun-ui/docs/en/02-elements/empty.md b/packages/duoyun-ui/docs/en/02-elements/empty.md index f0c48839..f4bc0931 100644 --- a/packages/duoyun-ui/docs/en/02-elements/empty.md +++ b/packages/duoyun-ui/docs/en/02-elements/empty.md @@ -4,6 +4,7 @@ ## API diff --git a/packages/duoyun-ui/docs/zh/02-elements/empty.md b/packages/duoyun-ui/docs/zh/02-elements/empty.md index f0c48839..f4bc0931 100644 --- a/packages/duoyun-ui/docs/zh/02-elements/empty.md +++ b/packages/duoyun-ui/docs/zh/02-elements/empty.md @@ -4,6 +4,7 @@ ## API diff --git a/packages/duoyun-ui/src/elements/card.ts b/packages/duoyun-ui/src/elements/card.ts index 9d188c81..01e8ccfa 100644 --- a/packages/duoyun-ui/src/elements/card.ts +++ b/packages/duoyun-ui/src/elements/card.ts @@ -1,12 +1,13 @@ // https://spectrum.adobe.com/page/cards/ import { adoptedStyle, customElement, attribute, property, part, slot, shadow, aria } from '@mantou/gem/lib/decorators'; -import { createCSSSheet, html, TemplateResult } from '@mantou/gem/lib/element'; +import { createCSSSheet, html } from '@mantou/gem/lib/element'; import { css } from '@mantou/gem/lib/utils'; import { theme } from '../lib/theme'; import { icons } from '../lib/icons'; import { commonHandle } from '../lib/hotkeys'; import { focusStyle } from '../lib/styles'; +import { StringList } from '../lib/types'; import { DuoyunLoadableBaseElement } from './base/loadable'; import { ContextMenuItem, ContextMenu } from './contextmenu'; @@ -105,6 +106,9 @@ export class DuoyunCardElement extends DuoyunLoadableBaseElement { @part static preview: string; @part static avatar: string; + @slot static header: string; + @slot static detail: string; + @slot static detailRight: string; @slot static body: string; @slot static unnamed: string; @slot static footer: string; @@ -112,9 +116,9 @@ export class DuoyunCardElement extends DuoyunLoadableBaseElement { @attribute avatar: string; @attribute preview: string; - @property header?: string | TemplateResult; - @property detail?: string | TemplateResult; - @property detailRight?: string | TemplateResult; + @attribute header: StringList<'slot'>; + @attribute detail: string; + @attribute detailRight: string; @property actions?: ActionItem[]; @attribute crossorigin: 'anonymous' | 'use-credentials'; @@ -149,9 +153,9 @@ export class DuoyunCardElement extends DuoyunLoadableBaseElement { ${this.header ? html`
-
${this.header}
-
${this.detail}
-
${this.detailRight}
+
${this.header}
+
${this.detail}
+
${this.detailRight}
${this.actions ? html` ; @@ -109,7 +109,7 @@ export class DuoyunCollapsePanelElement extends GemElement { @click=${this.toggleState} > - ${this.summary} + ${this.summary}
${expand || this.searchable ? html` diff --git a/packages/duoyun-ui/src/elements/compartment.ts b/packages/duoyun-ui/src/elements/compartment.ts index 36cf7f0b..33a148da 100644 --- a/packages/duoyun-ui/src/elements/compartment.ts +++ b/packages/duoyun-ui/src/elements/compartment.ts @@ -10,7 +10,7 @@ import { contentsContainer } from '../lib/styles'; @adoptedStyle(contentsContainer) @shadow() export class DuoyunCompartmentElement extends GemElement { - @property content?: string | number | TemplateResult; + @property content?: string | number | TemplateResult | Element | Element[]; render = () => { return html`${this.content}`; diff --git a/packages/duoyun-ui/src/elements/empty.ts b/packages/duoyun-ui/src/elements/empty.ts index 06f2038c..22342142 100644 --- a/packages/duoyun-ui/src/elements/empty.ts +++ b/packages/duoyun-ui/src/elements/empty.ts @@ -1,8 +1,17 @@ -import { connectStore, adoptedStyle, customElement, property, shadow } from '@mantou/gem/lib/decorators'; -import { GemElement, html, TemplateResult, createCSSSheet } from '@mantou/gem/lib/element'; +import { + connectStore, + adoptedStyle, + customElement, + property, + shadow, + attribute, + slot, +} from '@mantou/gem/lib/decorators'; +import { GemElement, html, createCSSSheet, render } from '@mantou/gem/lib/element'; import { css } from '@mantou/gem/lib/utils'; import { locale } from '../lib/locale'; +import { theme } from '../lib/theme'; import './use'; @@ -13,9 +22,10 @@ const style = createCSSSheet(css` align-items: center; justify-content: center; gap: 1em; + color: ${theme.describeColor}; } .icon { - width: 3em; + width: 5em; } `); @@ -27,13 +37,21 @@ const style = createCSSSheet(css` @connectStore(locale) @shadow() export class DuoyunEmptyElement extends GemElement { + @slot static unnamed: string; + @property icon?: string | Element | DocumentFragment; - @property description?: string | TemplateResult; + @attribute text: string; + @attribute slotName: string; render = () => { + if (this.slotName && !this.text) { + render(html``, this); + } else { + this.innerHTML = ''; + } return html` ${this.icon ? html`` : ''} -
${this.description || locale.noData}
+
${this.text || locale.noData}
`; }; } diff --git a/packages/duoyun-ui/src/elements/meter.ts b/packages/duoyun-ui/src/elements/meter.ts index 83e7332a..767b6cb0 100644 --- a/packages/duoyun-ui/src/elements/meter.ts +++ b/packages/duoyun-ui/src/elements/meter.ts @@ -8,8 +8,9 @@ import { aria, shadow, effect, + slot, } from '@mantou/gem/lib/decorators'; -import { createCSSSheet, GemElement, html, TemplateResult } from '@mantou/gem/lib/element'; +import { createCSSSheet, GemElement, html } from '@mantou/gem/lib/element'; import { css, styleMap } from '@mantou/gem/lib/utils'; import { theme, getSemanticColor } from '../lib/theme'; @@ -60,15 +61,18 @@ const style = createCSSSheet(css` @aria({ role: 'meter' }) @shadow() export class DuoyunMeterElement extends GemElement { + @slot static label: string; + @slot static valueLabel: string; + /**range: 0-100 */ @numattribute value: number; @numattribute max: number; @numattribute min: number; @attribute color: StringList<'positive' | 'informative' | 'negative' | 'notice'>; @attribute layout: 'stack' | 'flat'; + @attribute label: string; + @attribute valueLabel: StringList<'percentage'>; - @property label?: string | TemplateResult; - @property valueLabel?: 'percentage' | TemplateResult; @property calculateColor = () => { const progress = this.#progress; if (progress > 0.9) return theme.negativeColor; @@ -110,8 +114,8 @@ export class DuoyunMeterElement extends GemElement { render = () => { return html`
- ${this.label} - ${this.#valueLabel} + ${this.label} + ${this.valueLabel}
diff --git a/packages/duoyun-ui/src/elements/modal.ts b/packages/duoyun-ui/src/elements/modal.ts index c0909145..940a06fd 100644 --- a/packages/duoyun-ui/src/elements/modal.ts +++ b/packages/duoyun-ui/src/elements/modal.ts @@ -125,6 +125,7 @@ const style2 = createCSSSheet({ export interface ModalOptions { header?: string | TemplateResult; body?: string | TemplateResult; + footer?: string | TemplateResult; /**render body only */ customize?: boolean; maskClosable?: boolean; @@ -154,12 +155,11 @@ export interface ModalOpenOptions { @shadow({ delegatesFocus: true }) export class DuoyunModalElement extends GemElement { @part static dialog: string; - @part static heading: string; @part static divider: string; + @part @slot static header: string; @part static body: string; - @part @slot static footer: string; - // break change: body -> unnamed @slot static unnamed: string; + @part @slot static footer: string; @boolattribute open: boolean; @boolattribute customize: boolean; @@ -169,18 +169,22 @@ export class DuoyunModalElement extends GemElement { @boolattribute disableDefaultCancelBtn: boolean; @boolattribute disableDefaultOKBtn: boolean; @boolattribute dangerDefaultOkBtn: boolean; + @attribute header: string; + @attribute body: string; @emitter close: Emitter; @emitter ok: Emitter; @emitter maskclick: Emitter; - @property header?: string | TemplateResult; - @property body?: string | TemplateResult; @property openAnimation: PropertyIndexedKeyframes | Keyframe[] = slideInUp; @property closeAnimation: PropertyIndexedKeyframes | Keyframe[] = fadeOut; @state closing: boolean; + headerSlot?: string | TemplateResult; + bodySlot?: string | TemplateResult; + footerSlot?: string | TemplateResult; + // Cannot be used for dynamic forms static open(options: ModalOptions & ModalOpenOptions) { const modal = new this({ ...options, open: true }); @@ -230,23 +234,25 @@ export class DuoyunModalElement extends GemElement { open, customize, maskClosable, - cancelText, - okText, + cancelText = '', + okText = '', body, + footer, disableDefaultCancelBtn, disableDefaultOKBtn, dangerDefaultOkBtn, } = options; - if (header) this.header = header; - if (customize) this.customize = customize; - if (maskClosable) this.maskClosable = maskClosable; - if (open) this.open = open; - if (cancelText) this.cancelText = cancelText; - if (okText) this.okText = okText; - if (disableDefaultCancelBtn) this.disableDefaultCancelBtn = disableDefaultCancelBtn; - if (disableDefaultOKBtn) this.disableDefaultOKBtn = disableDefaultOKBtn; - if (dangerDefaultOkBtn) this.dangerDefaultOkBtn = dangerDefaultOkBtn; - if (body) this.body = body; + this.headerSlot = header; + this.bodySlot = body; + this.footerSlot = footer; + this.customize = !!customize; + this.maskClosable = !!maskClosable; + this.open = !!open; + this.cancelText = cancelText; + this.okText = okText; + this.disableDefaultCancelBtn = !!disableDefaultCancelBtn; + this.disableDefaultOKBtn = !!disableDefaultOKBtn; + this.dangerDefaultOkBtn = !!dangerDefaultOkBtn; } #maskRef = createRef(); @@ -316,7 +322,7 @@ export class DuoyunModalElement extends GemElement { aria-modal="true" class="dialog absolute" > - ${this.body || html``} + ${this.body || this.bodySlot || html``}
` : html` @@ -330,26 +336,30 @@ export class DuoyunModalElement extends GemElement { > ${this.header ? html` -
- ${this.header} +
+ ${this.header || this.headerSlot}
` : ''} - ${this.body} + ${this.body || this.bodySlot}
diff --git a/packages/duoyun-ui/src/elements/popover.ts b/packages/duoyun-ui/src/elements/popover.ts index bf2de3b1..b9c0001b 100644 --- a/packages/duoyun-ui/src/elements/popover.ts +++ b/packages/duoyun-ui/src/elements/popover.ts @@ -67,6 +67,7 @@ export class DuoyunPopoverElement extends GemElement { @attribute trigger: 'click' | 'hover'; @attribute position: Position | 'auto'; + // 不能通过 slot 元素支持 @property content?: string | TemplateResult; @emitter open: Emitter; diff --git a/packages/duoyun-ui/src/elements/result.ts b/packages/duoyun-ui/src/elements/result.ts index 683f25ab..8490ee31 100644 --- a/packages/duoyun-ui/src/elements/result.ts +++ b/packages/duoyun-ui/src/elements/result.ts @@ -1,8 +1,9 @@ -import { GemElement, html, TemplateResult, createCSSSheet } from '@mantou/gem/lib/element'; +import { GemElement, html, createCSSSheet } from '@mantou/gem/lib/element'; import { adoptedStyle, customElement, property, attribute, slot, shadow } from '@mantou/gem/lib/decorators'; import { css } from '@mantou/gem/lib/utils'; import { theme } from '../lib/theme'; +import { StringList } from '../lib/types'; import { Status, getStatusColor } from './status-light'; @@ -45,14 +46,16 @@ const style = createCSSSheet(css` @adoptedStyle(style) @shadow() export class DuoyunResultElement extends GemElement { + @slot static header: string; + @slot static description: string; @slot static unnamed: string; @attribute status: Status; + @attribute header: StringList<'slot'>; + @attribute description: StringList<'slot'>; @property icon?: string | Element | DocumentFragment; @property illustrator?: string | Element | DocumentFragment; - @property header?: string | TemplateResult; - @property description?: string | TemplateResult; get #status() { return this.status || 'default'; @@ -66,8 +69,20 @@ export class DuoyunResultElement extends GemElement { return html` ${this.icon ? html`` : ''} ${this.illustrator ? html`` : ''} - ${this.header ? html`${this.header}` : ''} - ${this.description ? html`${this.description}` : ''} + ${this.header + ? html` + + ${this.header} + + ` + : ''} + ${this.description + ? html` + + ${this.description} + + ` + : ''} `; }; diff --git a/packages/duoyun-ui/src/elements/statistic.ts b/packages/duoyun-ui/src/elements/statistic.ts index 33f4d1ce..99cc002d 100644 --- a/packages/duoyun-ui/src/elements/statistic.ts +++ b/packages/duoyun-ui/src/elements/statistic.ts @@ -7,8 +7,9 @@ import { property, aria, shadow, + slot, } from '@mantou/gem/lib/decorators'; -import { GemElement, html, TemplateResult, createCSSSheet } from '@mantou/gem/lib/element'; +import { GemElement, html, createCSSSheet } from '@mantou/gem/lib/element'; import { css, classMap } from '@mantou/gem/lib/utils'; import { parseDuration } from '../lib/time'; @@ -82,9 +83,13 @@ export const formatFnMap: Record { number: string; @aria({ role: 'group' }) @shadow() export class DuoyunStatisticElement extends GemElement { + @slot static header: string; + @attribute neutral: StatisticNeutral; @attribute type: StatisticType; - @property text: string | TemplateResult; + /**@deprecated */ + @attribute text: string; + @attribute header: string; @property icon: string | Element | DocumentFragment; @boolattribute loading: boolean; @numattribute value: number; @@ -98,6 +103,10 @@ export class DuoyunStatisticElement extends GemElement { return this.type || 'decimal'; } + get #header() { + return this.header || this.text; + } + render = () => { const { number, unit } = formatFnMap[this.#type](this.value); @@ -110,7 +119,11 @@ export class DuoyunStatisticElement extends GemElement { return html`
- ${this.loading ? html`` : this.text} + + ${this.loading + ? html`` + : html`${this.#header}`} +
diff --git a/packages/duoyun-ui/src/elements/table.ts b/packages/duoyun-ui/src/elements/table.ts index 9c6d857a..c13dfd8d 100644 --- a/packages/duoyun-ui/src/elements/table.ts +++ b/packages/duoyun-ui/src/elements/table.ts @@ -11,6 +11,7 @@ import { part, shadow, memo, + slot, } from '@mantou/gem/lib/decorators'; import { createCSSSheet, html, TemplateResult } from '@mantou/gem/lib/element'; import { css, styleMap, classMap, StyleObject, isArrayChange } from '@mantou/gem/lib/utils'; @@ -164,9 +165,11 @@ export class DuoyunTableElement extends DuoyunScrollBoxElement @part static td: string; @part static tr: string; @part static side: string; + @slot static noData: string; @attribute caption: string; @boolattribute headless: boolean; + @attribute noData: string; @boolattribute selectable: boolean; @property selection?: K[]; @@ -180,8 +183,6 @@ export class DuoyunTableElement extends DuoyunScrollBoxElement @property data?: T[] | (T | undefined)[]; @property getRowStyle?: (record: T) => StyleObject; - @property noData?: string | TemplateResult; - @property rowKey?: string | string[]; @property getKey?: (record: T) => K; @property expandedRowRender?: (record: T) => undefined | string | TemplateResult; @@ -476,7 +477,11 @@ export class DuoyunTableElement extends DuoyunScrollBoxElement ${!this.data ? html`
` : this.data.length === 0 - ? html`
${this.noData || html``}
` + ? html` +
+ +
+ ` : ''} `; }; diff --git a/packages/duoyun-ui/src/lib/styles.ts b/packages/duoyun-ui/src/lib/styles.ts index 78a3cd99..6637318c 100644 --- a/packages/duoyun-ui/src/lib/styles.ts +++ b/packages/duoyun-ui/src/lib/styles.ts @@ -38,6 +38,7 @@ export const contentsContainer = createCSSSheet(css` } `); +/** render empty content */ export const noneTemplate = html`