From c88c45a3a35ad241357c6d4572e305fd594186b2 Mon Sep 17 00:00:00 2001 From: mantou132 <709922234@qq.com> Date: Sat, 2 Mar 2024 14:46:27 +0800 Subject: [PATCH] [duoyun-ui] Improve `` --- .../duoyun-ui/src/elements/cascader-picker.ts | 2 +- packages/duoyun-ui/src/elements/cascader.ts | 117 +++++++++++------- packages/gem-examples/src/cascader/index.ts | 18 ++- 3 files changed, 89 insertions(+), 48 deletions(-) diff --git a/packages/duoyun-ui/src/elements/cascader-picker.ts b/packages/duoyun-ui/src/elements/cascader-picker.ts index 0e7db3f0..b6688555 100644 --- a/packages/duoyun-ui/src/elements/cascader-picker.ts +++ b/packages/duoyun-ui/src/elements/cascader-picker.ts @@ -101,7 +101,7 @@ export class DuoyunCascaderPickerElement extends GemElement implements BasePicke ContextMenu.open( html` { } // set new value(children part) - const generator = (item: Option): any => - item.children - ? item.children.reduce((p, c) => { - const v = generator(c); - const k = getOptionValue(c); - if (v === false) { - delete p[k]; - } else { - p[k] = generator(c); - } - return p; - }, {} as any) - : evt.detail; + const generator = (item: Option): any => { + if (!item.children?.length) { + return evt.detail; + } + return item.children.reduce((p, c) => { + const v = generator(c); + const k = getOptionValue(c); + if (v === false) { + delete p[k]; + } else { + p[k] = generator(c); + } + return p; + }, {} as any); + }; obj[getOptionValue(item)] = generator(item); @@ -158,12 +179,13 @@ export class DuoyunCascaderElement extends GemElement { this.change(value); }; - #onClick = (index: number, item: Option) => { + #onClick = (level: number, item: Option) => { + if (item.disabled) return; const { selected } = this.state; - const clickValue = selected.slice(0, index).concat(item); - if (selected[index] !== item) { + const clickValue = selected.slice(0, level).concat(item); + if (selected[level] !== item) { this.setState({ selected: clickValue }); - if (item.children || item.childrenPlaceholder) { + if (hasChildren(item)) { this.expand(item); } } @@ -180,12 +202,15 @@ export class DuoyunCascaderElement extends GemElement { // init state if (!this.state.selected.length) { const selected: Option[] = []; - this.#value?.[0]?.forEach((val, index) => { + const firstValue = this.#value?.[0] || []; + for (let index = 0; index < firstValue.length; index++) { + const val = firstValue[index]; const item = (index ? selected[selected.length - 1].children! : this.options!).find( (e) => val === getOptionValue(e), )!; + if (item.disabled) break; selected.push(item); - }); + } this.setState({ selected }); } }, @@ -212,25 +237,22 @@ export class DuoyunCascaderElement extends GemElement { const key = getOptionDisplayValue(item); const sub = readProp(this.#valueObj, [...path, key]); if (sub === true || !sub) return; - const keys = Object.keys(sub); - if (!keys.length) sub[token] = -1; - sub[token] = item.children?.reduce((p, e) => { + const isAll = item.children?.reduce((p, e) => { const k = getOptionDisplayValue(e); if (sub[k] === true) { return p; } else { check([...path, key], e); - if (sub[k] && sub[k][token] === 1) return p; + if (sub[k] && sub[k][checkboxStatusToken] === CheckboxStatus.Checked) return p; } return false; - }, true) - ? 1 - : 0; + }, true); + sub[checkboxStatusToken] = isAll ? CheckboxStatus.Checked : CheckboxStatus.Indeterminate; }; this.options?.forEach((e) => check([], e)); }, - () => [this.value], + () => [this.value, this.options], ); }; @@ -238,44 +260,55 @@ export class DuoyunCascaderElement extends GemElement { if (!this.options) return html``; const { selected } = this.state; const listStyle = styleMap({ width: this.fit ? `${100 / this.#deep}%` : undefined }); + const contents = [ + this.options, + ...selected.map((item) => item.children || item.childrenPlaceholder).filter(isNotNullish), + ]; return html` - ${[this.options, ...selected.map((e) => e.children || e.childrenPlaceholder).filter(isNotNullish)].map( - (list, index) => - Array.isArray(list) - ? html` + ${contents.map((list, level) => + !Array.isArray(list) + ? html`
${list}
` + : !list.length + ? html`
${locale.noData}
` + : html`
    ${list.map( ( item, _i, _arr, + disabled = level === 0 && item.disabled, status = readProp( this.#valueObj, - [...selected.slice(0, index), item].map((e) => getOptionDisplayValue(e)), + [...selected.slice(0, level), item].map((e) => getOptionDisplayValue(e)), ), ) => html`
  • this.#onClick(index, item)} + class=${classMap({ item: true, selected: selected[level] === item })} + @click=${() => this.#onClick(level, item)} > ${this.multiple ? html` ) => this.#onChange(index, item, evt)} - ?checked=${status === true || status?.[token] === 1} - ?indeterminate=${status !== true && status?.[token] === 0} + @change=${(evt: CustomEvent) => this.#onChange(level, item, evt)} + ?disabled=${disabled} + ?checked=${status === true || status?.[checkboxStatusToken] === CheckboxStatus.Checked} + ?indeterminate=${status !== true && + status?.[checkboxStatusToken] === CheckboxStatus.Indeterminate} > ` : ''} - ${getOptionDisplayValue(item)} - + ${getOptionDisplayValue(item)} +
  • `, )}
- ` - : html`
${list}
`, + `, )} `; }; diff --git a/packages/gem-examples/src/cascader/index.ts b/packages/gem-examples/src/cascader/index.ts index 12d8addb..57552367 100644 --- a/packages/gem-examples/src/cascader/index.ts +++ b/packages/gem-examples/src/cascader/index.ts @@ -10,13 +10,13 @@ import '../elements/layout'; const [store, update] = useStore({ selected: [['Item 3', 'Item 3.3', 'Item 3.3.1']], options: [ - { label: 'Item 1' }, - { label: 'Item 2' }, + { label: 'Item 1', disabled: true }, + { label: 'Item 2', childrenPlaceholder: html`` }, { label: 'Item 3', children: [ { label: 'Item 3.1' }, - { label: 'Item 3.2' }, + { label: 'Item 3.2', childrenPlaceholder: html`` }, { label: 'Item 3.3', children: [{ label: 'Item 3.3.1' }], @@ -31,11 +31,19 @@ const [store, update] = useStore({ function onChange({ detail }: CustomEvent) { update({ selected: detail }); } - +let i = 10; async function onExpand({ detail }: CustomEvent