From 9c280f3b0dd15be6329fae1c6e95acdfe6ef95b4 Mon Sep 17 00:00:00 2001 From: sunhao Date: Sat, 27 Jul 2024 18:03:31 +0800 Subject: [PATCH 001/250] * scrollbar: fix css vars not work with class '.dark'. --- lib/scrollbar/src/style/vars.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scrollbar/src/style/vars.css b/lib/scrollbar/src/style/vars.css index c7d842f377..62efba3be3 100644 --- a/lib/scrollbar/src/style/vars.css +++ b/lib/scrollbar/src/style/vars.css @@ -1,4 +1,4 @@ -:root { +:root, .scrollbar { --scrollbar-size: 10px; --scrollbar-opacity: .6; --scrollbar-bg: rgba(var(--color-inverse-rgb), .15); From b9e3bd4b1311a9e43aee435f308f42b47b61f756 Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 09:34:13 +0800 Subject: [PATCH 002/250] * core: support for getting all components from class Component. --- lib/core/src/component/component.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/core/src/component/component.ts b/lib/core/src/component/component.ts index af68e7fd0c..2f7095d695 100644 --- a/lib/core/src/component/component.ts +++ b/lib/core/src/component/component.ts @@ -522,8 +522,12 @@ export class Component { ALL.get(element)?.forEach(checkInstance); }); - } else { + } else if (this !== Component) { TYPED_ALL.get(this.NAME)?.forEach(checkInstance); + } else { + ALL.forEach((components) => { + components.forEach(checkInstance); + }); } return list.sort((a, b) => a.gid - b.gid); } From 5cdb6bdc46fa01970d237251d93aa3bd72d7f11c Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 09:36:10 +0800 Subject: [PATCH 003/250] * popover: save all shown popovers on Popover static property. --- lib/popover/src/vanilla/popover.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index 2d219cc1af..3dce647a72 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -36,6 +36,7 @@ export class Popover(); protected declare _virtual: boolean; @@ -173,12 +174,14 @@ export class Popover Date: Mon, 29 Jul 2024 09:36:56 +0800 Subject: [PATCH 004/250] * popover: save popover zIndex on show. --- lib/popover/src/vanilla/popover.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index 3dce647a72..f797f208fb 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -62,6 +62,8 @@ export class Popover Date: Mon, 29 Jul 2024 11:12:24 +0800 Subject: [PATCH 005/250] * popover: delay show popover at second time. --- lib/popover/src/vanilla/popover.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index f797f208fb..bd642b17af 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -108,7 +108,7 @@ export class Popover); } - this.toggle({event}); + this.toggle({event, delay: true}); event.preventDefault(); }); } From 7286a822b8532eb45ea9aed02ef259c4b56e1f40 Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 11:13:46 +0800 Subject: [PATCH 006/250] * popover: add option to hide other new popovers on hide. --- lib/popover/src/types/popover-options.ts | 1 + lib/popover/src/vanilla/popover.ts | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/popover/src/types/popover-options.ts b/lib/popover/src/types/popover-options.ts index ccee6c3d42..fd3afa6a79 100644 --- a/lib/popover/src/types/popover-options.ts +++ b/lib/popover/src/types/popover-options.ts @@ -28,6 +28,7 @@ export type PopoverOptions = Omit void; onShown?: () => void; diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index bd642b17af..32b1022358 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -33,6 +33,7 @@ export class Popover { + if (popover !== this && popover.zIndex > this.zIndex) { + popover.hide(); + } + }); + } this._resetTimer(() => { onHidden?.call(this); From c7eee92958932116d4b58cc1be2e388d4055207d Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 11:14:56 +0800 Subject: [PATCH 007/250] * popover: refactor global click for popovers. --- lib/popover/src/vanilla/popover.ts | 67 +++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index 32b1022358..8c54b5908b 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -180,7 +180,7 @@ export class Popover { - this.hide(); - }); if (!this._virtual) { $(this._triggerElement as HTMLElement).addClass('with-popover-show'); @@ -231,10 +228,6 @@ export class Popover { if (popover !== this && popover.zIndex > this.zIndex) { @@ -294,7 +286,6 @@ export class Popover { @@ -536,13 +540,6 @@ export class Popover { - const $target = $(event.target as HTMLElement); - if ((!$target.closest(`#${this._id}`).length && (this._virtual || !$target.closest(this._triggerElement as HTMLElement).length) && this._targetElement !== $target.closest('.popover')[0])) { - this.hide(); - } - }; - static show>(this: T, options: O & {event?: Event}): InstanceType { const {element: elementSetting, event, ...otherOptions} = options; const element = elementSetting || (event?.currentTarget as HTMLElement); @@ -575,3 +572,35 @@ Popover.toggle = { }; Popover.register(); + +$(() => { + $(document).on(`click.${Popover.NAMESPACE}`, (event: MouseEvent) => { + const {SHOWN_POPOVERS} = Popover; + if (!SHOWN_POPOVERS.size) { + return; + } + const $target = $(event.target as HTMLElement); + const $popoverTarget = $target.closest('[z-popover]'); + const gid = $popoverTarget.length ? $popoverTarget.z('popover') as number : 0; + const clickedPopover = gid ? SHOWN_POPOVERS.get(gid) : null; + if (clickedPopover) { + const name = clickedPopover.options.name ?? clickedPopover.constructor.ZUI; + if ($target.closest(`[data-dismiss="${name}"]`).length) { + clickedPopover.hide(); + return; + } + + if (clickedPopover.handleClickTarget(event)) { + return; + } + } + const popovers = [...SHOWN_POPOVERS.values()].sort((a, b) => b.zIndex - a.zIndex); + for (const popover of popovers) { + if (popover !== clickedPopover && popover.handleClickOutside(event)) { + return; + } + } + }); +}); + +Object.assign(window, {Popover}); From d9235f4e55eb642155a1642d671bba752c46f542 Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 11:15:05 +0800 Subject: [PATCH 008/250] * popover: refactor hideOthers. --- lib/popover/src/vanilla/popover.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index 8c54b5908b..58453500a8 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -36,7 +36,6 @@ export class Popover(); protected declare _virtual: boolean; @@ -154,7 +153,7 @@ export class Popover { - if (popover !== this && popover.shown && !$target.closest(popover.element).length) { + /* Hide other shown popovers. */ + if (hideOthers) { + SHOWN_POPOVERS.forEach((popover) => { + if (popover !== this) { popover.hide(); } }); From afa03f1e2232ea33dfbe7ff45acbb13f33d5313f Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 11:20:20 +0800 Subject: [PATCH 009/250] * tooltip: refactor global click with popover. --- lib/tooltip/src/vanilla/tooltip.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tooltip/src/vanilla/tooltip.ts b/lib/tooltip/src/vanilla/tooltip.ts index 0c0d584a4b..436345d871 100644 --- a/lib/tooltip/src/vanilla/tooltip.ts +++ b/lib/tooltip/src/vanilla/tooltip.ts @@ -14,10 +14,10 @@ export class Tooltip extends Popover { name: 'tooltip', animation: 'fade', destroyOnHide: 5000, + hideOthers: true, + hideNewOnHide: false, }; - static hideOthers = true; - protected _getRenderOptions(): PopoverPanelOptions { const {type, className, title: originTitle, content: originContent} = this.options; let title = originTitle; From ed1e222d731c21e37df292a271e41c9841c9da9d Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 11:20:52 +0800 Subject: [PATCH 010/250] * dropdown: refactor global click with popover. --- lib/dropdown/src/types/dropdown-options.ts | 2 ++ lib/dropdown/src/vanilla/dropdown.ts | 17 ++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/dropdown/src/types/dropdown-options.ts b/lib/dropdown/src/types/dropdown-options.ts index 392ecd42dd..60ec4dec04 100644 --- a/lib/dropdown/src/types/dropdown-options.ts +++ b/lib/dropdown/src/types/dropdown-options.ts @@ -1,3 +1,4 @@ +import type {Comparator} from '@zui/core'; import type {PopoverOptions} from '@zui/popover'; import type {DropdownMenuOptions} from './dropdown-menu-options'; @@ -7,4 +8,5 @@ export type DropdownOptions = PopoverOptions & { items?: DropdownMenuOptions['items'], relativeTarget?: DropdownMenuOptions['relativeTarget'], onClickItem?: DropdownMenuOptions['onClickItem'], + notHideOnClick?: Comparator; }; diff --git a/lib/dropdown/src/vanilla/dropdown.ts b/lib/dropdown/src/vanilla/dropdown.ts index 69e3fe8353..8fcd51f109 100644 --- a/lib/dropdown/src/vanilla/dropdown.ts +++ b/lib/dropdown/src/vanilla/dropdown.ts @@ -17,8 +17,18 @@ export class Dropdown extends Popov closeBtn: false, animation: 'fade', limitSize: true, + notHideOnClick: '.not-hide-menu,.form-control,input,label,.nested-toggle-icon', }; + handleClickTarget(event: MouseEvent): void | boolean { + const $target = $(event.target as HTMLElement); + const {notHideOnClick} = this.options; + if (!notHideOnClick || !$target.closest(notHideOnClick).length) { + this.hide(); + } + return true; + } + protected _getMenuOptions(): DropdownMenuOptions { const {items, placement, menu, tree, onClickItem, relativeTarget = this._triggerElement} = this.options; return { @@ -46,13 +56,6 @@ export class Dropdown extends Popov } return options; } - - protected _onClickDoc = (event: MouseEvent) => { - const $target = $(event.target as HTMLElement); - if (!$target.closest('.not-hide-menu,.form-control,input,label,.nested-toggle-icon').length && (this._virtual || !$target.closest(this._triggerElement as HTMLElement).length)) { - this.hide(); - } - }; } Dropdown.toggle = { From 8c3b932fb498fb461a15fe3dcc0b6126a6d120e9 Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 11:21:12 +0800 Subject: [PATCH 011/250] * contextmenu: remove unused code. --- lib/contextmenu/src/vanilla/contextmenu.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/contextmenu/src/vanilla/contextmenu.ts b/lib/contextmenu/src/vanilla/contextmenu.ts index 6d1184de12..2a11520e16 100644 --- a/lib/contextmenu/src/vanilla/contextmenu.ts +++ b/lib/contextmenu/src/vanilla/contextmenu.ts @@ -1,4 +1,3 @@ -import {$} from '@zui/core'; import {Dropdown} from '@zui/dropdown'; import type {ContextMenuOptions} from '../types/contextmenu-options'; @@ -22,13 +21,6 @@ export class ContextMenu extends Dropdown { } return options; } - - protected _onClickDoc = (event: MouseEvent) => { - const $target = $(event.target as HTMLElement); - if (!$target.closest('.not-hide-menu,.form-control,input,label,.nested-toggle-icon').length) { - this.hide(); - } - }; } ContextMenu.register(); From 20365e35bc1c83bd1c51e4be61ac09a3b84d3b91 Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 11:21:21 +0800 Subject: [PATCH 012/250] * contextmenu: change dev example. --- lib/contextmenu/README.md | 22 ++++++++++++++++++++++ lib/contextmenu/dev.ts | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/contextmenu/README.md b/lib/contextmenu/README.md index b52a79f30d..b4593e4577 100644 --- a/lib/contextmenu/README.md +++ b/lib/contextmenu/README.md @@ -1,5 +1,27 @@ # 右键菜单 +## 弹出面板中的右键菜单 + +```html:example + + + + + + + +``` + + ## 被动打开目标菜单 ```html:example diff --git a/lib/contextmenu/dev.ts b/lib/contextmenu/dev.ts index a64658000e..ff28e77b6a 100644 --- a/lib/contextmenu/dev.ts +++ b/lib/contextmenu/dev.ts @@ -6,7 +6,7 @@ import 'zui-dev'; import 'preact/debug'; import {ContextMenu} from './src/main'; -onPageLoad(() => { +onPageUpdate(() => { const contextMenu = new ContextMenu('#menuToggle1', { menu: { items: [ From 568eb2735cf46174bb5c1ef9db19992734cee1fc Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 11:21:44 +0800 Subject: [PATCH 013/250] * list: init checks on load lazy items. --- lib/list/src/component/nested-list.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/list/src/component/nested-list.tsx b/lib/list/src/component/nested-list.tsx index ad39a53b52..0147536710 100644 --- a/lib/list/src/component/nested-list.tsx +++ b/lib/list/src/component/nested-list.tsx @@ -169,6 +169,9 @@ export class NestedList

x.key!), true); + } else if (items?.some((x) => x.checked)) { + this._needInitChecks = true; + this.forceUpdate(); } return state; } From bb2633c637cfba469f27b94e88d8a1e7fe632903 Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 13:31:31 +0800 Subject: [PATCH 014/250] * dtable: optimize UI for sorting cols by dnd. --- lib/dtable/dev.ts | 2 +- lib/dtable/src/plugins/sort-col/index.tsx | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/dtable/dev.ts b/lib/dtable/dev.ts index a67345653b..e52c5c64d3 100644 --- a/lib/dtable/dev.ts +++ b/lib/dtable/dev.ts @@ -37,7 +37,7 @@ onPageUpdate(() => { const customColsTable = new DTable('#customColsTable', { cols: [ {name: 'id', title: 'ID', width: 80, fixed: 'left', sortType: 'desc', checkbox: true}, - {name: 'name', title: '项目名称', minWidth: 200, flex: 1, sortType: true, nestedToggle: true, childLabel: '子'}, + {name: 'name', title: '项目名称', minWidth: 200, fixed: 'left', flex: 1, sortType: true, nestedToggle: true, childLabel: '子'}, {name: 'manager', title: '负责人', sortType: true, border: true, width: 200}, {name: 'storyScale', title: '需求规模', sortType: true}, {name: 'executionCount', title: '执行数', sortType: true}, diff --git a/lib/dtable/src/plugins/sort-col/index.tsx b/lib/dtable/src/plugins/sort-col/index.tsx index 1f978f110b..d626f29421 100644 --- a/lib/dtable/src/plugins/sort-col/index.tsx +++ b/lib/dtable/src/plugins/sort-col/index.tsx @@ -173,21 +173,17 @@ const sortColPlugin: DTableSorColPlugin = { return; } - const {from, element, offset} = sortColInfo; + const {from, element} = sortColInfo; const $cells = $(element).closest('.dtable-cells'); const bounding = $cells[0]!.getBoundingClientRect(); - const width = bounding.width; - const pos = event.clientX - bounding.left - offset; - if ((pos + from.width) < 0 || (pos - from.width) > width) { - return sortColInfo.state; - } + const pos = event.clientX - bounding.left; const {cols, scrollLeft} = this.layout; const sideCols = cols[from.side].list; if (sideCols.length <= 1) { return sortColInfo.state; } const left = scrollLeft + pos; - const to = sideCols.find(col => col.name !== from.name && col.visible && col.left <= left && (col.left + col.width) > left); + const to = sideCols.find(col => col.visible && col.left <= left && (col.left + col.width) > left); if (!to) { return sortColInfo.state; } From c53cb6283e3ba9d1b926ab9f0971dee7afb2fe30 Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 13:34:49 +0800 Subject: [PATCH 015/250] * dtable: change default speed of auto scrolling. --- lib/dtable/src/plugins/autoscroll/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dtable/src/plugins/autoscroll/index.ts b/lib/dtable/src/plugins/autoscroll/index.ts index 8f55ae6688..ea546136fd 100644 --- a/lib/dtable/src/plugins/autoscroll/index.ts +++ b/lib/dtable/src/plugins/autoscroll/index.ts @@ -137,7 +137,7 @@ const autoscrollPlugin: DTablePlugin Date: Mon, 29 Jul 2024 15:13:48 +0800 Subject: [PATCH 016/250] * dtable: limit fixed left width for resizing cols. --- lib/dtable/src/helpers/layout.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/dtable/src/helpers/layout.ts b/lib/dtable/src/helpers/layout.ts index f2b8dd879c..d75097b2a1 100644 --- a/lib/dtable/src/helpers/layout.ts +++ b/lib/dtable/src/helpers/layout.ts @@ -2,11 +2,15 @@ import {parseNumber, clamp} from './number'; import type {ColInfo, ColSetting, DTableColsLayout, DTableColsSectionLayout, DTableOptions, DTablePlugin} from '../types'; import type {DTable} from '../components'; -function initSectionColsLayout(cols: DTableColsSectionLayout, fixed = false) { +function initSectionColsLayout(cols: DTableColsSectionLayout, fixed = false, maxWidth = 0) { if (!cols.list.length) { return; } + if (maxWidth && !cols.widthSetting && cols.width > maxWidth) { + cols.widthSetting = maxWidth; + } + if (cols.widthSetting && cols.width !== cols.widthSetting) { cols.width = cols.widthSetting; const extraWidth = cols.width - cols.totalWidth; @@ -164,8 +168,9 @@ export function initColsLayout(dtable: DTable, options: DTableOptions, plugins: } /* Layout columns. */ - initSectionColsLayout(leftCols, true); initSectionColsLayout(rightCols, true); + const maxLeftWidth = width - rightCols.width - Math.max(40, minColWidth); + initSectionColsLayout(leftCols, true, maxLeftWidth); centerCols.widthSetting = width - leftCols.width - rightCols.width; initSectionColsLayout(centerCols); From 9679723f6cc70cdf77b075f8c97f1a00866f6886 Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2024 15:14:18 +0800 Subject: [PATCH 017/250] * dtable: support for resizing last col in left section. --- lib/dtable/src/plugins/resize/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dtable/src/plugins/resize/index.tsx b/lib/dtable/src/plugins/resize/index.tsx index 90994d4bc1..a5b8f37ac4 100644 --- a/lib/dtable/src/plugins/resize/index.tsx +++ b/lib/dtable/src/plugins/resize/index.tsx @@ -145,7 +145,7 @@ const resizePlugin: DTablePlugin = { if (!col) { return; } - if (col.sideIndex === this.layout.cols[col.side].list.length - 1) { + if (col.side !== 'left' && col.sideIndex === this.layout.cols[col.side].list.length - 1) { return; } let colResize = col.setting.colResize ?? this.options.colResize; From 3d84515d69a3a57e0d549d72892410772db83495 Mon Sep 17 00:00:00 2001 From: sunhao Date: Tue, 30 Jul 2024 11:41:20 +0800 Subject: [PATCH 018/250] * list: change list dev example. --- lib/list/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/list/README.md b/lib/list/README.md index a804298f84..934e71fcd5 100644 --- a/lib/list/README.md +++ b/lib/list/README.md @@ -8,6 +8,12 @@

``` +### 仅根节点 + +```html:example +
+``` + ### 远程数据 ```html:example From e41c2cb414c616bab442c97e3e267181bc795143 Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 2 Aug 2024 10:59:11 +0800 Subject: [PATCH 019/250] * dtable: refactor. --- lib/dtable/src/components/dtable.tsx | 2 +- lib/dtable/src/plugins/nested/index.tsx | 2 +- lib/dtable/src/plugins/sort-col/index.tsx | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/dtable/src/components/dtable.tsx b/lib/dtable/src/components/dtable.tsx index 26771b4bbb..91990a830c 100644 --- a/lib/dtable/src/components/dtable.tsx +++ b/lib/dtable/src/components/dtable.tsx @@ -421,7 +421,7 @@ export class DTable extends Component { } this.#layout = undefined; } - this.setState(state ?? ((preState) => ({renderCount: preState.renderCount + 1})), callback); + this.setState(state || ((preState) => ({renderCount: preState.renderCount + 1})), callback); } getPointerInfo(event: Event): DTablePointerInfo | undefined { diff --git a/lib/dtable/src/plugins/nested/index.tsx b/lib/dtable/src/plugins/nested/index.tsx index 92d08d1704..9cacf27756 100644 --- a/lib/dtable/src/plugins/nested/index.tsx +++ b/lib/dtable/src/plugins/nested/index.tsx @@ -209,7 +209,7 @@ const nestedPlugin: DTablePlugin = asParentKey: 'asParent', nestedIndent: 20, canSortTo(from, to) { - const {nestedMap} = this.data; + const {nestedMap} = (this as unknown as DTableNested).data; const fromInfo = nestedMap.get(from.id); const toInfo = nestedMap.get(to.id); return fromInfo?.parent === toInfo?.parent; diff --git a/lib/dtable/src/plugins/sort-col/index.tsx b/lib/dtable/src/plugins/sort-col/index.tsx index d626f29421..97e37bcb2b 100644 --- a/lib/dtable/src/plugins/sort-col/index.tsx +++ b/lib/dtable/src/plugins/sort-col/index.tsx @@ -26,13 +26,13 @@ export type DTableSortColTypes = { onSortColEnd: (this: DTableSortCol, from: ColInfo, to: ColInfo | undefined, sortingSide: SortingColSide | undefined, orders: string[] | undefined) => void; onSortCol: (this: DTableSortCol, from: ColInfo, to: ColInfo, sortingSide: SortingColSide, orders: string[]) => void | false; }>; - state: Partial<{ - colOrders: Record; - sortColFrom: ColInfo; - sortingColPos: number; + state: { + colOrders?: Record; + sortColFrom?: ColInfo; + sortingColPos?: number; sortingColTo?: ColInfo; sortingColSide?: SortingColSide; - }>; + }; data: { sortColInfo?: {from: ColInfo, element: HTMLElement, offset: number, state?: SortingColState, startMouseX: number, lastMouseX: number, colOffsetMap?: Record}; }, @@ -205,8 +205,8 @@ const sortColPlugin: DTableSorColPlugin = { }, }, onAddCol(col) { - const {colOrders} = this.state; - const order = colOrders?.[col.name]; + const {colOrders = {}} = this.state; + const order = colOrders[col.name]; if (order !== undefined) { col.order = order; } From 218549224a0c1dbbaf3b813b216d0a6c62254727 Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 2 Aug 2024 11:03:07 +0800 Subject: [PATCH 020/250] * stable: add requireAfter property to plugin. --- lib/dtable/src/helpers/shared-plugins.ts | 25 +++++++++++++++++++++++- lib/dtable/src/types/plugin.ts | 1 + 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/dtable/src/helpers/shared-plugins.ts b/lib/dtable/src/helpers/shared-plugins.ts index 8c41cf0d9c..087fd87a65 100644 --- a/lib/dtable/src/helpers/shared-plugins.ts +++ b/lib/dtable/src/helpers/shared-plugins.ts @@ -82,5 +82,28 @@ export function initPlugins(pluginsLike: DTablePluginLike[] = [], includeBuildIn return []; } - return initPluginsInner([], pluginsLike, new Set()); + const plugins = initPluginsInner([], pluginsLike, new Set()); + const pluginRequireList: DTablePlugin[] = []; + const pluginOrder = plugins.reduce((order, plugin, index) => { + order.set(plugin.name, index * 1000); + if (plugin.requireAfter?.length) { + pluginRequireList.push(plugin); + } + return order; + }, new Map()); + if (pluginRequireList.length) { + pluginRequireList.forEach(plugin => { + const requireAfterOrders = plugin.requireAfter!.reduce((orders, name) => { + if (pluginOrder.has(name)) { + orders.push(pluginOrder.get(name)!); + } + return orders; + }, [] as number[]); + if (requireAfterOrders.length) { + pluginOrder.set(plugin.name, Math.max(...requireAfterOrders) + 1); + } + }); + plugins.sort((a, b) => pluginOrder.get(a.name)! - pluginOrder.get(b.name)!); + } + return plugins; } diff --git a/lib/dtable/src/types/plugin.ts b/lib/dtable/src/types/plugin.ts index 8859aa0a38..4b8b24f201 100644 --- a/lib/dtable/src/types/plugin.ts +++ b/lib/dtable/src/types/plugin.ts @@ -59,6 +59,7 @@ export type DTablePlugin boolean, + requireAfter: DTablePluginName[], defaultOptions: Partial; colTypes: Record | PluginColSettingModifier>; events: DTablePluginEvents | ((this: PluginTable) => DTablePluginEvents); From f0e4806cb48167c30e473a6f252fc3cadc1aadba Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 2 Aug 2024 11:04:54 +0800 Subject: [PATCH 021/250] * dtable: ensure that nested load after sortable. --- lib/dtable/src/plugins/nested/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/dtable/src/plugins/nested/index.tsx b/lib/dtable/src/plugins/nested/index.tsx index 9cacf27756..345f072cae 100644 --- a/lib/dtable/src/plugins/nested/index.tsx +++ b/lib/dtable/src/plugins/nested/index.tsx @@ -203,6 +203,7 @@ const nestedToggleClass = 'dtable-nested-toggle'; const nestedPlugin: DTablePlugin = { name: 'nested', plugins: [store], + requireAfter: ['sortable'], defaultOptions: { nested: 'auto', nestedParentKey: 'parent', From c972bdf84daaa39adf704efdf4e507eb9aaf4eea Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 2 Aug 2024 11:06:00 +0800 Subject: [PATCH 022/250] * dtable: remove unused canSortTo callback from sortable plugin. --- lib/dtable/src/plugins/sortable/index.tsx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/dtable/src/plugins/sortable/index.tsx b/lib/dtable/src/plugins/sortable/index.tsx index c585d95a9d..601eee15c6 100644 --- a/lib/dtable/src/plugins/sortable/index.tsx +++ b/lib/dtable/src/plugins/sortable/index.tsx @@ -7,7 +7,6 @@ import './style.css'; import type {DTableWithPlugin, DTablePlugin} from '../../types/plugin'; import type {DTableMousemoveTypes} from '../mousemove'; import type {DTableAutoscrollTypes} from '../autoscroll'; -import type {DTableNestedTypes, DTableNested} from '../nested'; import type {RowInfo} from '../../types/row'; export type SortingSide = 'before' | 'after'; @@ -45,18 +44,12 @@ export type DTableSortableTypes = { } }; -export type DTableSortable = DTableWithPlugin; +export type DTableSortable = DTableWithPlugin; -const sortablePlugin: DTablePlugin = { +const sortablePlugin: DTablePlugin = { name: 'sortable', defaultOptions: { sortable: true, - canSortTo(this: DTableSortable, from: RowInfo, to: RowInfo) { - if (!this.options.nested) { - return true; - } - return (this as unknown as DTableNested).getNestedRowInfo(from.id).parent === (this as unknown as DTableNested).getNestedRowInfo(to.id).parent; - }, }, when: options => !!options.sortable, plugins: [mousemove, autoscroll], From 6976e82948533f8639bd22b04262badc500871ca Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 2 Aug 2024 11:06:36 +0800 Subject: [PATCH 023/250] * dtable: refactor sorting rows in nested plugin. --- lib/dtable/src/plugins/nested/index.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/dtable/src/plugins/nested/index.tsx b/lib/dtable/src/plugins/nested/index.tsx index 345f072cae..139324b992 100644 --- a/lib/dtable/src/plugins/nested/index.tsx +++ b/lib/dtable/src/plugins/nested/index.tsx @@ -313,11 +313,16 @@ const nestedPlugin: DTablePlugin = } }); - rows = rows.filter(row => this.getNestedRowInfo(row.id).state !== NestedRowState.hidden); - updateNestedMapOrders(this.data.nestedMap); + const nestedStateMap = new Map(); + rows = rows.filter(row => { + const info = this.getNestedRowInfo(row.id)!; + nestedStateMap.set(row.id, info); + return info.state !== NestedRowState.hidden; + }); + updateNestedMapOrders(nestedStateMap); rows.sort((rowA, rowB) => { - const infoA = this.getNestedRowInfo(rowA.id); - const infoB = this.getNestedRowInfo(rowB.id); + const infoA = nestedStateMap.get(rowA.id)!; + const infoB = nestedStateMap.get(rowB.id)!; const result = (infoA.order ?? 0) - (infoB.order ?? 0); return result === 0 ? (rowA.index - rowB.index) : result; }); @@ -355,6 +360,7 @@ const nestedPlugin: DTablePlugin = result.push(
); } } + return result; }, onRenderHeaderCell(result, {row, col}) { From 72c2169fcca047715e16bcf0a87f10dc0a398dea Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 2 Aug 2024 13:30:06 +0800 Subject: [PATCH 024/250] * dtable: fix ignoreNextClick not work. --- lib/dtable/src/plugins/mousemove/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dtable/src/plugins/mousemove/index.ts b/lib/dtable/src/plugins/mousemove/index.ts index f6120fd42f..9e33d2906e 100644 --- a/lib/dtable/src/plugins/mousemove/index.ts +++ b/lib/dtable/src/plugins/mousemove/index.ts @@ -57,7 +57,7 @@ const mousemovePlugin: DTablePlugin = { }, methods: { ignoreNextClick(timeout = 10) { - window.setTimeout(() => { + this.data.ignoreNextClick = window.setTimeout(() => { this.data.ignoreNextClick = undefined; }, timeout); }, From 4bed039692fe69bbfc55d505e7c5ba7fe5a70b2a Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 5 Aug 2024 14:32:07 +0800 Subject: [PATCH 025/250] * core: fix js error in firefox. --- lib/core/src/component/creator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core/src/component/creator.ts b/lib/core/src/component/creator.ts index efaf85cc62..59cc081a39 100644 --- a/lib/core/src/component/creator.ts +++ b/lib/core/src/component/creator.ts @@ -310,7 +310,7 @@ function checkComponents(delay = 100) { } function autoDestroyComponents() { - if (takeData(document.body, '_autoDestoryMob')) { + if (!document.body || takeData(document.body, '_autoDestoryMob')) { return; } const mob = new MutationObserver((mutations) => { From 566943c445768ab8505b2a13afc95c5e09bf7815 Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 5 Aug 2024 14:37:21 +0800 Subject: [PATCH 026/250] * popover: support for setting footer to popover panel. --- lib/popover/src/component/popover-panel.tsx | 9 ++++++++- lib/popover/src/types/popover-panel-options.ts | 2 ++ lib/popover/src/vanilla/popover.ts | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/popover/src/component/popover-panel.tsx b/lib/popover/src/component/popover-panel.tsx index 19e2525511..68aec47c82 100644 --- a/lib/popover/src/component/popover-panel.tsx +++ b/lib/popover/src/component/popover-panel.tsx @@ -20,6 +20,8 @@ export class PopoverPanel extends Component { contentClass, arrowStyle, onlyInner, + footer, + footerClass, } = props; let contentView = ; @@ -27,6 +29,11 @@ export class PopoverPanel extends Component { contentView =
{contentView}
; } + let footerView = ; + if (footerClass || title) { + footerView =
{footerView}
; + } + const views: ComponentChild[] = []; const closeBtnView = closeBtn ? : null; if (title) { @@ -37,7 +44,7 @@ export class PopoverPanel extends Component { } else { views.push(closeBtnView); } - views.push(contentView); + views.push(contentView, footerView); if (arrow) { views.push(
); } diff --git a/lib/popover/src/types/popover-panel-options.ts b/lib/popover/src/types/popover-panel-options.ts index 9ec1e2b577..c5b98dfc3d 100644 --- a/lib/popover/src/types/popover-panel-options.ts +++ b/lib/popover/src/types/popover-panel-options.ts @@ -15,4 +15,6 @@ export type PopoverPanelOptions = { closeBtn?: boolean; arrow?: boolean | string; arrowStyle?: JSX.CSSProperties; + footer?: CustomContentType; + footerClass?: string; }; diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index 58453500a8..d2922374c2 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -471,6 +471,8 @@ export class Popover Date: Mon, 5 Aug 2024 14:37:59 +0800 Subject: [PATCH 027/250] * popover: add minWidth and minHeight props to popover. --- lib/popover/src/types/popover-options.ts | 2 ++ lib/popover/src/vanilla/popover.ts | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/popover/src/types/popover-options.ts b/lib/popover/src/types/popover-options.ts index fd3afa6a79..b2a4350561 100644 --- a/lib/popover/src/types/popover-options.ts +++ b/lib/popover/src/types/popover-options.ts @@ -11,6 +11,8 @@ export type PopoverOptions = Omit number | 'auto'); + minWidth?: string; + minHeight?: string; height?: number | (() => number | 'auto'); limitSize?: boolean; container?: Selector; diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index d2922374c2..0a0f13f10f 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -309,7 +309,7 @@ export class Popover { - const {animation, name = 'popover'} = this.options; + const {animation, name = 'popover', minWidth, minHeight} = this.options; if (!this._virtual) { const style: JSX.CSSProperties = {}; const {width, height} = this.options; @@ -332,6 +332,8 @@ export class Popover Date: Mon, 5 Aug 2024 14:38:54 +0800 Subject: [PATCH 028/250] * popover: add new prop elementShowClass to custom class in trigger element on show. --- lib/popover/src/types/popover-options.ts | 1 + lib/popover/src/vanilla/popover.ts | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/popover/src/types/popover-options.ts b/lib/popover/src/types/popover-options.ts index b2a4350561..d4ec23f901 100644 --- a/lib/popover/src/types/popover-options.ts +++ b/lib/popover/src/types/popover-options.ts @@ -10,6 +10,7 @@ export type PopoverOptions = Omit number | 'auto'); minWidth?: string; minHeight?: string; diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index 0a0f13f10f..6f6978b672 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -33,6 +33,7 @@ export class Popover { @@ -233,7 +234,7 @@ export class Popover Date: Mon, 5 Aug 2024 14:39:46 +0800 Subject: [PATCH 029/250] * dtable: support for reseting state for resize plugin and sortable plugin. --- lib/dtable/src/plugins/resize/index.tsx | 8 ++++++++ lib/dtable/src/plugins/sortable/index.tsx | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/lib/dtable/src/plugins/resize/index.tsx b/lib/dtable/src/plugins/resize/index.tsx index a5b8f37ac4..6401a8c43d 100644 --- a/lib/dtable/src/plugins/resize/index.tsx +++ b/lib/dtable/src/plugins/resize/index.tsx @@ -68,6 +68,14 @@ const resizePlugin: DTablePlugin = { name: 'resize', when: options => !!options.colResize, plugins: [mousemove], + resetState(props) { + return {colsSizes: props.cols?.reduce((sizes, col) => { + if (col.extraWidth !== undefined) { + sizes[col.name] = col.extraWidth as number; + } + return sizes; + }, {} as Record)}; + }, state() { return {colsSizes: this.props.cols?.reduce((sizes, col) => { if (col.extraWidth !== undefined) { diff --git a/lib/dtable/src/plugins/sortable/index.tsx b/lib/dtable/src/plugins/sortable/index.tsx index 601eee15c6..bb0195aea3 100644 --- a/lib/dtable/src/plugins/sortable/index.tsx +++ b/lib/dtable/src/plugins/sortable/index.tsx @@ -53,6 +53,16 @@ const sortablePlugin: DTablePlugin !!options.sortable, plugins: [mousemove, autoscroll], + resetState: true, + state() { + return { + rowOrders: undefined, + sortingFrom: undefined, + sortingPos: undefined, + sortingTo: undefined, + sortingSide: undefined, + }; + }, events: { click(event) { if ((event.target as HTMLElement).closest('.dtable-sort-link')) { From 5b294c41d6c953aadc062b64c9b14d7bef81c57d Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 5 Aug 2024 14:43:40 +0800 Subject: [PATCH 030/250] * dtable: fix sorting col not work. --- lib/dtable/src/plugins/sort-col/index.tsx | 55 ++++++++++++++--------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/lib/dtable/src/plugins/sort-col/index.tsx b/lib/dtable/src/plugins/sort-col/index.tsx index 97e37bcb2b..15f02a354d 100644 --- a/lib/dtable/src/plugins/sort-col/index.tsx +++ b/lib/dtable/src/plugins/sort-col/index.tsx @@ -67,6 +67,16 @@ const sortColPlugin: DTableSorColPlugin = { name: 'sort-col', when: options => !!options.sortCol, plugins: [mousemove, autoscroll], + resetState: true, + state() { + return { + colOrders: {}, + sortColFrom: undefined, + sortingColPos: undefined, + sortingColTo: undefined, + sortingColSide: undefined, + }; + }, events: { mousedown(event) { if (this.data.disableSortCol) { @@ -101,27 +111,30 @@ const sortColPlugin: DTableSorColPlugin = { let colOrders: Record | undefined; let orders: string[] | undefined; const {from, to, side} = sortingState; - if (to && side) { - const sideCols = this.layout.cols[from.side].list; - const fromIndex = from.sideIndex; - const toIndex = to.sideIndex; - const col = sideCols.splice(fromIndex, 1); - sideCols.splice(toIndex + (side === 'after' ? 1 : 0), 0, col[0]); - colOrders = {}; - orders = []; - sideCols.forEach(({name}, index) => { - colOrders![name] = index + 1; - orders!.push(name); - }); - - if (this.options.onSortCol?.call(this, from, to, side, orders) === false) { - colOrders = undefined; - orders = undefined; - } - } + if (to) { + if (from.name === to.name) { + colOrders = {}; + } else if (side) { + const sideCols = this.layout.cols[from.side].list; + const fromIndex = from.sideIndex; + const toIndex = to.sideIndex; + const col = sideCols.splice(fromIndex, 1); + sideCols.splice(toIndex + (side === 'after' ? 1 : 0), 0, col[0]); + colOrders = {}; + orders = []; + sideCols.forEach(({name}, index) => { + colOrders![name] = index + 1; + orders!.push(name); + }); - if (to || Math.abs(sortColInfo.lastMouseX - sortColInfo.startMouseX) > 4) { - this.ignoreNextClick(); + if (this.options.onSortCol?.call(this, from, to, side, orders) === false) { + colOrders = undefined; + orders = undefined; + } + } + if (Math.abs(sortColInfo.lastMouseX - sortColInfo.startMouseX) > 4) { + this.ignoreNextClick(); + } } this.disableAnimation(); @@ -194,7 +207,7 @@ const sortColPlugin: DTableSorColPlugin = { from, pos: pos + scrollLeft, to, - side, + side: from.name !== to.name ? side : undefined, } : { from, pos, From 94acc2593778c3a695aac62121e7628a71342e9b Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 5 Aug 2024 14:46:10 +0800 Subject: [PATCH 031/250] * list: remove option nestedTrigger from nested list. --- lib/list/src/component/nested-list.tsx | 103 ++++++++---------------- lib/list/src/types/nested-list-props.ts | 2 - 2 files changed, 35 insertions(+), 70 deletions(-) diff --git a/lib/list/src/component/nested-list.tsx b/lib/list/src/component/nested-list.tsx index 0147536710..cc4b107ee6 100644 --- a/lib/list/src/component/nested-list.tsx +++ b/lib/list/src/component/nested-list.tsx @@ -98,8 +98,6 @@ export class NestedList

; @@ -142,7 +140,6 @@ export class NestedList

{ - if (!newNestedShow[key] || !key.startsWith(`${keyPath}:`)) { - return; - } - parentKeys(keyPath).forEach(k => { - newNestedShow[k] = true; - }); - }); - } return { nestedShow: newNestedShow, } as Partial; @@ -573,74 +556,59 @@ export class NestedList

{ - this._hoverInfo = undefined; - this._toggleFromEvent(info); - }, info.hover ? 0 : 200), - }; + return info; } protected _handleNestedCheck(change: Record) { @@ -651,7 +619,7 @@ export class NestedList

extends indent?: number; level?: number; preserve?: string; - nestedTrigger?: 'click' | 'hover', accordion?: boolean; nestedShow?: boolean | Record; defaultNestedShow?: boolean | Record; @@ -20,5 +19,4 @@ export interface NestedListProps extends checkedState?: Record; toggleOnActive?: boolean; onToggle?: (key: ItemKey, toggle: boolean) => false | void; - onHoverItem?: (info: {hover: boolean, item: T, index: number, event: MouseEvent}) => void; } From 6ac6edda0c3c0ae86f3f82f1810f5b2a0b1b111e Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 5 Aug 2024 14:49:50 +0800 Subject: [PATCH 032/250] * list: add option "expandChildrenOnCheck". --- lib/list/src/component/nested-list.tsx | 30 ++++++++++++++++++------- lib/list/src/types/nested-list-props.ts | 1 + 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/lib/list/src/component/nested-list.tsx b/lib/list/src/component/nested-list.tsx index cc4b107ee6..5333583d37 100644 --- a/lib/list/src/component/nested-list.tsx +++ b/lib/list/src/component/nested-list.tsx @@ -104,9 +104,9 @@ export class NestedList

; - protected declare _needInitChecks?: boolean; + protected declare _itemMapCache: Map; - protected declare _hoverInfo?: {timer: number, info: MouseEventInfo}; + protected declare _needInitChecks?: boolean; constructor(props: P) { super(props); @@ -169,7 +169,10 @@ export class NestedList

= reduceNestedItems(this._items, this.props.itemKey, (currentMap, info) => { @@ -204,6 +207,7 @@ export class NestedList

((checks, {keyPath, data}) => { + return Array.from(this.getItemMap(true).values()).reduce((checks, {keyPath, data}) => { const checkState = this.state.checked[keyPath]; if ((checkState === true || (data.checked && checkState !== false)) === true) { checks.push(keyPath); @@ -322,11 +327,13 @@ export class NestedList

{ + await this.changeState(({checked: prevChecked, nestedShow: preNestedShow}) => { const isChecked = (item: ItemInfo) => { return change[item.keyPath] ?? prevChecked[item.keyPath] ?? item.data.checked ?? false; }; + const map = this.getItemMap(); + const nestedShow: Record = {}; + const {expandChildrenOnCheck} = this.props; Object.keys(change).forEach(key => { checked = change[key]; const item = map.get(key); @@ -349,12 +356,19 @@ export class NestedList

; }, () => { const checkState = this.state.checked; diff --git a/lib/list/src/types/nested-list-props.ts b/lib/list/src/types/nested-list-props.ts index 3a10c0428d..bd6fb6e41f 100644 --- a/lib/list/src/types/nested-list-props.ts +++ b/lib/list/src/types/nested-list-props.ts @@ -17,6 +17,7 @@ export interface NestedListProps extends nestedToggle?: string; renderCollapsedList?: boolean; checkedState?: Record; + expandChildrenOnCheck?: boolean; toggleOnActive?: boolean; onToggle?: (key: ItemKey, toggle: boolean) => false | void; } From 975c233e2e91cef47ff8a105f0d750d69c05254e Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 5 Aug 2024 14:50:13 +0800 Subject: [PATCH 033/250] * list: add param "reset" to onToggle callback. --- lib/list/src/component/nested-list.tsx | 8 ++++---- lib/list/src/types/nested-list-props.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/list/src/component/nested-list.tsx b/lib/list/src/component/nested-list.tsx index 5333583d37..03031a06a6 100644 --- a/lib/list/src/component/nested-list.tsx +++ b/lib/list/src/component/nested-list.tsx @@ -236,16 +236,16 @@ export class NestedList

{ let newNestedShow: Record = { - ...prevState.nestedShow, + ...(reset ? {} : prevState.nestedShow), [keyPath]: toggle!, }; if (toggle && accordion) { diff --git a/lib/list/src/types/nested-list-props.ts b/lib/list/src/types/nested-list-props.ts index bd6fb6e41f..5854b8f9da 100644 --- a/lib/list/src/types/nested-list-props.ts +++ b/lib/list/src/types/nested-list-props.ts @@ -19,5 +19,5 @@ export interface NestedListProps extends checkedState?: Record; expandChildrenOnCheck?: boolean; toggleOnActive?: boolean; - onToggle?: (key: ItemKey, toggle: boolean) => false | void; + onToggle?: (key: ItemKey, toggle: boolean, reset?: boolean) => false | void; } From 975b479fa3a572668afcbdd205e99d460903cc4d Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 5 Aug 2024 14:51:17 +0800 Subject: [PATCH 034/250] * list: skip to check item whithout any checkbox. --- lib/list/src/component/list.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/list/src/component/list.tsx b/lib/list/src/component/list.tsx index 9c41a1b923..69313393d7 100644 --- a/lib/list/src/component/list.tsx +++ b/lib/list/src/component/list.tsx @@ -268,9 +268,11 @@ export class List

Date: Tue, 6 Aug 2024 13:36:28 +0800 Subject: [PATCH 035/250] * menu: add new option "nestedTrigger" for expand nested list on mouse hover. --- lib/menu/src/component/menu.tsx | 77 +++++++++++++++++++++++++++++- lib/menu/src/types/menu-options.ts | 1 + 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/lib/menu/src/component/menu.tsx b/lib/menu/src/component/menu.tsx index 3a77e38e53..6e6e2f5c47 100644 --- a/lib/menu/src/component/menu.tsx +++ b/lib/menu/src/component/menu.tsx @@ -23,6 +23,17 @@ export class Menu): ClassNameLike { return [super._getClassName(props), this._hasNestedItems ? 'menu-nested' : '', props.className, props.wrap ? {'scrollbar-thin': props.scrollbarThin, 'scrollbar-hover': props.scrollbarHover} : {popup: props.popup, compact: props.compact}]; } @@ -32,8 +43,17 @@ export class Menu): Record { - const {wrapAttrs, height, maxHeight} = props; - const wrapProps = mergeProps({}, wrapAttrs, (height || maxHeight) ? {style: {height, maxHeight}} : null); + const {wrapAttrs, height, maxHeight, parentKey} = props; + const wrapProps = mergeProps( + {'z-list-wrapper': parentKey}, + wrapAttrs, + (height || maxHeight) ? {style: {height, maxHeight}} : null, + this.isRoot && this.isHoverTrigger ? { + onMouseEnter: this._handleHover, + onMouseLeave: this._handleHover, + onMouseOver: this._handleHover, + } : null, + ); wrapProps.className = classes(this._getWrapClass(props), wrapProps.className as ClassNameLike); return wrapProps; } @@ -46,6 +66,59 @@ export class Menu; } + protected _handleHover(event: MouseEvent) { + const target = event.target; + if (!(target instanceof HTMLElement) || !this.isHoverTrigger) { + return; + } + + let keyPath: string | null | undefined; + if (event.type !== 'mouseleave') { + const itemEle = target.closest('[z-item]'); + if (itemEle) { + keyPath = itemEle.getAttribute('z-key-path') as string; + if (!itemEle.classList.contains('is-nested')) { + keyPath = itemEle.getAttribute('z-parent') as string; + } + } else { + const listEle = target.closest('[z-list-wrapper]'); + keyPath = listEle?.getAttribute('z-list-wrapper'); + } + } + + const lastInfo = this._hoverInfo; + const lastKeyPath = lastInfo?.keyPath; + if (lastKeyPath === keyPath) { + return; + } + if (lastInfo?.timer) { + clearTimeout(lastInfo.timer); + } + const hasKey = typeof keyPath === 'string'; + const lastHasKey = typeof lastKeyPath === 'string'; + const delay = hasKey ? ((lastHasKey && lastInfo?.shown) ? 50 : 200) : (lastInfo?.shown ? 100 : 200); + this._hoverInfo = { + keyPath, + timer: window.setTimeout(() => { + if (hasKey) { + this.toggle(keyPath!, true, true); + this._hoverInfo!.shown = true; + } else { + this.toggleAll(false); + this._hoverInfo = undefined; + } + }, delay), + }; + } + + componentWillUnmount(): void { + super.componentWillUnmount(); + const timer = this._hoverInfo?.timer; + if (timer) { + clearTimeout(timer); + } + } + render(props: RenderableProps) { const menuView = super.render(props); if (props.wrap) { diff --git a/lib/menu/src/types/menu-options.ts b/lib/menu/src/types/menu-options.ts index 94cae43a70..73d801ed17 100644 --- a/lib/menu/src/types/menu-options.ts +++ b/lib/menu/src/types/menu-options.ts @@ -14,4 +14,5 @@ export interface MenuOptions extends compact?: boolean; scrollbarThin?: boolean; scrollbarHover?: boolean; + nestedTrigger?: 'click' | 'hover', } From ac73ebc3930946a937d704265344a5410ff4f865 Mon Sep 17 00:00:00 2001 From: sunhao Date: Tue, 6 Aug 2024 13:37:55 +0800 Subject: [PATCH 036/250] * menu: support for showing independent searchbox in nested menu. --- lib/menu/src/component/search-menu.tsx | 38 ++++++++++++++--------- lib/menu/src/types/search-menu-options.ts | 1 + 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/lib/menu/src/component/search-menu.tsx b/lib/menu/src/component/search-menu.tsx index 5c3297318a..c114c2d57b 100644 --- a/lib/menu/src/component/search-menu.tsx +++ b/lib/menu/src/component/search-menu.tsx @@ -1,4 +1,4 @@ -import {$, classes} from '@zui/core'; +import {$, classes, mergeProps} from '@zui/core'; import {SearchBox} from '@zui/search-box/src/components'; import {Menu} from './menu'; @@ -10,12 +10,14 @@ import type {SearchBoxOptions} from '@zui/search-box'; import type {SearchMenuOptions, SearchMenuState} from '../types'; export class SearchMenu extends Menu { - static inheritNestedProps = [...Menu.inheritNestedProps, 'isItemMatch', 'search', 'underlineKeys']; + static inheritNestedProps = [...Menu.inheritNestedProps, 'isItemMatch', 'search', 'underlineKeys', 'nestedSearch']; static defaultProps: Partial = { ...Menu.defaultProps, defaultNestedShow: true, wrap: true, + nestedSearch: true, + underlineKeys: true, }; protected declare _searchKeys: string[]; @@ -72,9 +74,9 @@ export class SearchMenu extends }; protected _isItemMatch(props: RenderableProps, item: NestedItem, index: number, parentKey: ItemKey | undefined) { - const {isItemMatch} = props; + const {isItemMatch, nestedSearch} = props; const isMatch = isItemMatch ? isItemMatch.call(this, item, this._searchKeys, index, parentKey) : (this.constructor as typeof SearchMenu).isItemMatch(item, this._searchKeys, props.searchProps); - if (this.isRoot && isMatch && parentKey !== undefined) { + if ((nestedSearch && this.isRoot) && isMatch && parentKey !== undefined) { let key = ''; String(parentKey).split(':').forEach(x => { key += `${key.length ? ':' : ''}${x}`; @@ -90,9 +92,11 @@ export class SearchMenu extends protected _getNestedProps(props: RenderableProps, items: ListItemsSetting, item: NestedItem, expanded: boolean): NestedListProps { const nestedProps = super._getNestedProps(props, items, item, expanded) as SearchMenuOptions; - if (this.isRoot) { + if (this.isRoot && props.nestedSearch) { nestedProps.isItemMatch = this._isNestedItemMatch; nestedProps.search = this._searchKeys.join(' '); + } else if (!props.nestedSearch) { + mergeProps(nestedProps as Record, {search: undefined, defaultSearch: undefined}, item.listProps); } return nestedProps; } @@ -129,29 +133,32 @@ export class SearchMenu extends return classes(super._getWrapClass(props), 'search-menu', props.searchBox ? `search-menu-on-${props.searchPlacement || 'top'}` : '', isSearchMode ? 'is-search-mode' : '', isSearchMode && props.expandOnSearch ? 'no-toggle-on-search' : ''); } - protected _renderSearchBox(props: RenderableProps): ComponentChildren { + protected _getSearchBoxProps(props: RenderableProps): SearchBoxOptions { const {searchBox} = props; - if (!searchBox || !this.isRoot) { - return null; - } const searchOptions: SearchBoxOptions = { compact: true, + className: 'not-nested-toggle', onChange: this._handleSearchChange, }; if (typeof searchBox === 'object') { - $.extend(searchOptions, searchBox); + mergeProps(searchOptions, searchBox); } if (props.search !== undefined) { searchOptions.value = this._searchKeys.join(' '); searchOptions.disabled = true; } - return ; + return searchOptions; + } + + protected _renderSearchBox(props: RenderableProps): ComponentChildren { + const searchBoxOptions = this._getSearchBoxProps(props); + return ; } protected _renderWrapperHeader(props: RenderableProps): ComponentChildren { const hasHeader = props.header; - const hasTopSearchBox = this.isRoot && props.searchBox && props.searchPlacement !== 'bottom'; - const {noMatchHint} = props; + const {noMatchHint, searchBox, searchPlacement, nestedSearch} = props; + const hasTopSearchBox = (!nestedSearch || this.isRoot) && searchBox && searchPlacement !== 'bottom'; if (!hasHeader && !hasTopSearchBox && !noMatchHint) { return null; } @@ -166,14 +173,15 @@ export class SearchMenu extends protected _renderWrapperFooter(props: RenderableProps): ComponentChildren { const hasFooter = props.footer; - const hasBottomSearchBox = this.isRoot && props.searchBox && props.searchPlacement === 'bottom'; + const {searchBox, searchPlacement, nestedSearch} = props; + const hasBottomSearchBox = (!nestedSearch || this.isRoot) && searchBox && searchPlacement === 'bottom'; if (!hasFooter && !hasBottomSearchBox) { return null; } return (

{hasFooter ? super._renderWrapperFooter(props) : null} - {this._renderSearchBox(props)} + {hasBottomSearchBox ? this._renderSearchBox(props) : null}
); } diff --git a/lib/menu/src/types/search-menu-options.ts b/lib/menu/src/types/search-menu-options.ts index e8297ed64d..22458688fd 100644 --- a/lib/menu/src/types/search-menu-options.ts +++ b/lib/menu/src/types/search-menu-options.ts @@ -7,6 +7,7 @@ export interface SearchMenuOptions extend searchBox?: SearchBoxOptions | boolean; searchPlacement?: 'bottom' | 'top'; search?: string; + nestedSearch?: boolean; defaultSearch?: string; expandOnSearch?: boolean; underlineKeys?: boolean; From 2f6e35063089a1e7e67b91dc80ee393f6545e093 Mon Sep 17 00:00:00 2001 From: sunhao Date: Tue, 6 Aug 2024 13:38:21 +0800 Subject: [PATCH 037/250] * menu: optimize style of header and footer in nested menu. --- lib/menu/src/style/menu-nested.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/menu/src/style/menu-nested.css b/lib/menu/src/style/menu-nested.css index e319e4427c..a663866834 100644 --- a/lib/menu/src/style/menu-nested.css +++ b/lib/menu/src/style/menu-nested.css @@ -7,3 +7,7 @@ .menu-nested .menu-item > .item-inner { @apply -pl-0; } +.menu-nested .search-menu-header, +.menu-nested .search-menu-footer { + @apply -ml-[--menu-indent] --mt-0.5 -mb-1 -pr-px; +} From 126948d85a0a4d9752b7e32db9bca9e89df36bd5 Mon Sep 17 00:00:00 2001 From: sunhao Date: Tue, 6 Aug 2024 13:38:37 +0800 Subject: [PATCH 038/250] * menu: change dev example. --- lib/menu/README.md | 22 +++++++++++----------- lib/menu/dev.ts | 4 ++++ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/menu/README.md b/lib/menu/README.md index e5e7f688d4..026b6e92d8 100644 --- a/lib/menu/README.md +++ b/lib/menu/README.md @@ -115,23 +115,23 @@ console.log('> menu', menu); ```html:example - - - + + + ``` -## 选中 +## 激活与选中 ```html:example - - - - - - - + + + + + + + ``` diff --git a/lib/menu/dev.ts b/lib/menu/dev.ts index 539d52ebd0..cf4c1e8e9f 100644 --- a/lib/menu/dev.ts +++ b/lib/menu/dev.ts @@ -17,6 +17,7 @@ onPageUpdate(() => { { text: '导入', icon: 'icon-upload-alt', + listProps: {compact: true, searchBox: true}, items: [ {text: '从本地导入'}, {text: '从网络导入'}, @@ -29,6 +30,7 @@ onPageUpdate(() => { items: [ {text: '保存到云端'}, { + listProps: {searchBox: true}, text: '下载到本地', items: [ {text: '下载为 PDF'}, @@ -45,12 +47,14 @@ onPageUpdate(() => { searchPlacement: 'bottom', underlineKeys: true, items: searchMenuItems, + nestedSearch: false, maxHeight: 200, onClickItem: (info) => { console.log('> menu.onClickItem', info); }, }); console.log('> searchMenu1', searchMenu1); + const searchMenu2 = new SearchMenu('#searchMenu2', { popup: true, searchBox: true, From 1e6f1833394b27663c362c39d220e0ee32e54245 Mon Sep 17 00:00:00 2001 From: sunhao Date: Tue, 6 Aug 2024 13:39:12 +0800 Subject: [PATCH 039/250] * dropdown: fix search-menu bg in dropdown nested menu. --- lib/dropdown/src/style/dropdown.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/dropdown/src/style/dropdown.css b/lib/dropdown/src/style/dropdown.css index dcd3eff13c..0b598d5695 100644 --- a/lib/dropdown/src/style/dropdown.css +++ b/lib/dropdown/src/style/dropdown.css @@ -20,6 +20,9 @@ .dropdown > .dropdown-menu { @apply -relative; } +.popup .popup.search-menu { + @apply -bg-[--menu-bg]; +} .show > .menu-wrapper { @apply -flex; From a0c59d678e8b2e17976fcde49f52bfff1098457d Mon Sep 17 00:00:00 2001 From: sunhao Date: Tue, 6 Aug 2024 13:41:54 +0800 Subject: [PATCH 040/250] * dropdown: support for showing independent searchbox in nested menu. --- lib/dropdown/dev.ts | 3 +++ lib/dropdown/src/component/dropdown-menu.tsx | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/dropdown/dev.ts b/lib/dropdown/dev.ts index a9033bc816..9fea3d70ad 100644 --- a/lib/dropdown/dev.ts +++ b/lib/dropdown/dev.ts @@ -22,6 +22,9 @@ onPageUpdate(() => { { text: '导出', icon: 'icon-download-alt', + listProps: { + searchBox: true, + }, items: [ {text: '导出为 PDF'}, {text: '导出为 PNG'}, diff --git a/lib/dropdown/src/component/dropdown-menu.tsx b/lib/dropdown/src/component/dropdown-menu.tsx index af6753c96b..a87085477b 100644 --- a/lib/dropdown/src/component/dropdown-menu.tsx +++ b/lib/dropdown/src/component/dropdown-menu.tsx @@ -1,12 +1,12 @@ -import {$, mergeProps} from '@zui/core'; +import {$, mergeProps, parseSize} from '@zui/core'; import {flip, computePosition, shift, size, offset} from '@floating-ui/dom'; import {SearchMenu} from '@zui/menu/src/component'; import type {ClassNameLike} from '@zui/core'; import type {ListItemsSetting, NestedItem, NestedListProps} from '@zui/list'; import {type ComponentChildren, type RenderableProps, type ComponentChild} from 'preact'; -import type {DropdownMenuOptions} from '../types/dropdown-menu-options'; import type {MouseEventInfo} from '@zui/list/src/component'; +import type {DropdownMenuOptions} from '../types/dropdown-menu-options'; export class DropdownMenu extends SearchMenu { static defaultProps: Partial = { @@ -15,6 +15,7 @@ export class DropdownMenu e placement: 'right-start', defaultNestedShow: false, expandOnSearch: false, + nestedSearch: false, }; static inheritNestedProps = [...SearchMenu.inheritNestedProps, 'container', 'tree']; @@ -47,7 +48,7 @@ export class DropdownMenu e }, })], }).then(({x, y}) => { - $(element).css({ + $element.css({ left: x, top: y, }); From 816753654691c3584e2dd62d124ff5363d29f209 Mon Sep 17 00:00:00 2001 From: sunhao Date: Tue, 6 Aug 2024 13:42:19 +0800 Subject: [PATCH 041/250] * dropdown: preserve dropdown nested menu position on searchbox focus. --- lib/dropdown/src/component/dropdown-menu.tsx | 38 ++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/dropdown/src/component/dropdown-menu.tsx b/lib/dropdown/src/component/dropdown-menu.tsx index a87085477b..56d95b6f3f 100644 --- a/lib/dropdown/src/component/dropdown-menu.tsx +++ b/lib/dropdown/src/component/dropdown-menu.tsx @@ -3,6 +3,7 @@ import {flip, computePosition, shift, size, offset} from '@floating-ui/dom'; import {SearchMenu} from '@zui/menu/src/component'; import type {ClassNameLike} from '@zui/core'; +import type {SearchBoxOptions} from '@zui/search-box'; import type {ListItemsSetting, NestedItem, NestedListProps} from '@zui/list'; import {type ComponentChildren, type RenderableProps, type ComponentChild} from 'preact'; import type {MouseEventInfo} from '@zui/list/src/component'; @@ -22,6 +23,10 @@ export class DropdownMenu e protected declare _nestedContextMenu: ComponentChild[]; + protected declare _searchFocused: boolean; + + protected declare _position: {left: number, top: number, width: number, height: number}; + get isHoverTrigger(): boolean { const {nestedTrigger, tree} = this.props; return nestedTrigger ? nestedTrigger === 'hover' : !tree; @@ -33,18 +38,30 @@ export class DropdownMenu e } const element = this.element?.parentElement; - const $menu = $(element).parent().children('.dropdown-menu'); + const $element = $(element); + if (element && this._searchFocused && this._position) { + $element.css(this._position); + } + + const $menu = $element.parent().children('.dropdown-menu'); const $trigger = $menu.children(`[z-key-path="${this.props.parentKey}"]`); const trigger = $trigger[0]; if (!element || !trigger) { return; } + let {maxHeight} = this.props; computePosition(trigger, element, { placement: this.props.placement, middleware: [flip(), shift(), offset(1), size({ apply({availableWidth, availableHeight}) { - $(element).css({maxHeight: availableHeight - 2, maxWidth: availableWidth - 2}); + if (maxHeight) { + const [maxHeightVal, unit] = parseSize(maxHeight); + maxHeight = Math.min(unit === '%' ? (maxHeightVal * window.innerHeight) : maxHeightVal, availableHeight - 2); + } else { + maxHeight = availableHeight; + } + $element.css({maxHeight, maxWidth: availableWidth - 2}); }, })], }).then(({x, y}) => { @@ -52,6 +69,7 @@ export class DropdownMenu e left: x, top: y, }); + this._position = {left: x, top: y, width: element.offsetWidth, height: element.offsetHeight}; }); } @@ -119,6 +137,22 @@ export class DropdownMenu e return ; } + protected _handleSearchFocus = () => { + this._searchFocused = true; + }; + + protected _handleSearchBlur = () => { + this._searchFocused = false; + }; + + protected _getSearchBoxProps(props: RenderableProps): SearchBoxOptions { + return { + ...super._getSearchBoxProps(props), + onFocus: this._handleSearchFocus, + onBlur: this._handleSearchBlur, + }; + } + protected _beforeRender(props: RenderableProps): void | RenderableProps | undefined { this._nestedContextMenu = []; return super._beforeRender(props); From bc70ebb5b3d7b0fe5808b9cc66ac35facc83b6a7 Mon Sep 17 00:00:00 2001 From: sunhao Date: Wed, 7 Aug 2024 08:32:59 +0800 Subject: [PATCH 042/250] * search-box: register searchbox component. --- lib/search-box/src/vanilla/search-box.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/search-box/src/vanilla/search-box.ts b/lib/search-box/src/vanilla/search-box.ts index e188bf2614..364d85d366 100644 --- a/lib/search-box/src/vanilla/search-box.ts +++ b/lib/search-box/src/vanilla/search-box.ts @@ -7,3 +7,5 @@ export class SearchBox extends ComponentFromReact Date: Wed, 7 Aug 2024 14:17:45 +0800 Subject: [PATCH 043/250] * docs: change doc nav. --- docs/_/.vitepress/theme-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_/.vitepress/theme-config.ts b/docs/_/.vitepress/theme-config.ts index 6756a18345..0bf05d4a3d 100644 --- a/docs/_/.vitepress/theme-config.ts +++ b/docs/_/.vitepress/theme-config.ts @@ -63,7 +63,7 @@ export const extLibs = [...zuiLib.reduce((set, lib) => { function createNav() { return [ - {text: '指引', link: '/guide/start/', activeMatch: '/guide/'}, + {text: '文档', link: '/guide/start/', activeMatch: '/guide/'}, {text: 'CSS 工具类', link: '/utilities/skin/utilities/solid', activeMatch: '/utilities/'}, {text: '组件', link: '/lib/components/button/', activeMatch: '/lib/'}, {text: 'ZUI1', link: 'https://openzui.com/1/'}, From 3961c8200a2a7e2af9faf6fd69fdccf090df1ea6 Mon Sep 17 00:00:00 2001 From: sunhao Date: Wed, 7 Aug 2024 14:18:21 +0800 Subject: [PATCH 044/250] * popover: update nav options from element on open again. --- lib/popover/src/vanilla/popover.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index 6f6978b672..ac56baaeaa 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -1,5 +1,5 @@ import {arrow, computePosition, flip, shift, size, autoUpdate, offset, VirtualElement, ReferenceElement, ComputePositionConfig} from '@floating-ui/dom'; -import {Component, $, ComponentEvents, JSX} from '@zui/core'; +import {Component, $, ComponentEvents, JSX, evalValue} from '@zui/core'; import {PopoverEvents, PopoverOptions, PopoverPanelOptions} from '../types'; import {PopoverPanel} from './popover-panel'; import {isElementDetached} from '@zui/core/src/dom'; @@ -105,9 +105,13 @@ export class Popover); + if (!this.shown) { + let options = $triggerElement.dataset(); + const toggleOptions = $triggerElement.attr(`zui-toggle-${this.constructor.ZUI}`); + if (toggleOptions) { + options = $.extend(options, evalValue(toggleOptions)); + } + this.setOptions(options as Partial); } this.toggle({event, delay: true}); event.preventDefault(); From db5dcc0a7cc8d4f371eeb76746fdc0759dfff613 Mon Sep 17 00:00:00 2001 From: sunhao Date: Wed, 7 Aug 2024 21:58:55 +0800 Subject: [PATCH 045/250] * dtable: prevent to select text on dragging for sorting. --- lib/dtable/src/plugins/sortable/index.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/dtable/src/plugins/sortable/index.tsx b/lib/dtable/src/plugins/sortable/index.tsx index bb0195aea3..fb355e3677 100644 --- a/lib/dtable/src/plugins/sortable/index.tsx +++ b/lib/dtable/src/plugins/sortable/index.tsx @@ -87,9 +87,7 @@ const sortablePlugin: DTablePlugin Date: Wed, 7 Aug 2024 21:59:14 +0800 Subject: [PATCH 046/250] * dtable: fix sortable orders. --- lib/dtable/src/plugins/sortable/index.tsx | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/dtable/src/plugins/sortable/index.tsx b/lib/dtable/src/plugins/sortable/index.tsx index fb355e3677..afaccee7bf 100644 --- a/lib/dtable/src/plugins/sortable/index.tsx +++ b/lib/dtable/src/plugins/sortable/index.tsx @@ -129,12 +129,17 @@ const sortablePlugin: DTablePlugin { + return $.extend({ + sortingFrom: undefined, + sortingPos: undefined, + sortingTo: undefined, + sortingSide: undefined, + }, rowOrders ? {rowOrders: { + ...(preState.rowOrders as Record), + ...rowOrders, + }} : null); + }, }, () => { this.options.onSortEnd?.call(this, sortingFrom, sortingTo, sortingSide, orders); setTimeout(() => { @@ -211,8 +216,11 @@ const sortablePlugin: DTablePlugin { - return rowOrders[row1.id] - rowOrders[row2.id]; + const order1 = rowOrders[row1.id] ?? (undefinedOrder + row1.index); + const order2 = rowOrders[row2.id] ?? (undefinedOrder + row2.index); + return order1 - order2; }); return rows; }, From f87ce1b5168da0e003c84cc64ff850583104e378 Mon Sep 17 00:00:00 2001 From: sunhao Date: Wed, 7 Aug 2024 21:59:45 +0800 Subject: [PATCH 047/250] * dtable: fix sorting nested rows. --- lib/dtable/src/plugins/nested/index.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/dtable/src/plugins/nested/index.tsx b/lib/dtable/src/plugins/nested/index.tsx index 139324b992..365c4eb3f7 100644 --- a/lib/dtable/src/plugins/nested/index.tsx +++ b/lib/dtable/src/plugins/nested/index.tsx @@ -150,7 +150,7 @@ function isAllCollapsed(this: DTableNested): boolean { return true; } -function updateNestedMapOrders(map: Map, lastOrder = 0, ids?: string[], level = 0): number { +function updateNestedMapOrders(map: Map, lastOrder = 1, ids?: string[], level = 0): number { if (!ids) { ids = [...map.keys()]; } @@ -314,17 +314,17 @@ const nestedPlugin: DTablePlugin = }); const nestedStateMap = new Map(); - rows = rows.filter(row => { + const undefinedOrder = rows.length * 100; + rows = rows.filter((row) => { const info = this.getNestedRowInfo(row.id)!; nestedStateMap.set(row.id, info); return info.state !== NestedRowState.hidden; }); updateNestedMapOrders(nestedStateMap); rows.sort((rowA, rowB) => { - const infoA = nestedStateMap.get(rowA.id)!; - const infoB = nestedStateMap.get(rowB.id)!; - const result = (infoA.order ?? 0) - (infoB.order ?? 0); - return result === 0 ? (rowA.index - rowB.index) : result; + const infoA = nestedStateMap.get(rowA.id); + const infoB = nestedStateMap.get(rowB.id); + return (infoA?.order ?? (undefinedOrder + rowA.index)) - (infoB?.order ?? (undefinedOrder + rowB.index)); }); return rows; }, From d9d3cbc332a71c8d0a2c8250934da490b9ada465 Mon Sep 17 00:00:00 2001 From: sunhao Date: Thu, 8 Aug 2024 08:32:45 +0800 Subject: [PATCH 048/250] * dtable: prevent to call callback when orders not change. --- lib/dtable/src/plugins/sortable/index.tsx | 27 +++++++++++++---------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/dtable/src/plugins/sortable/index.tsx b/lib/dtable/src/plugins/sortable/index.tsx index afaccee7bf..bec0489889 100644 --- a/lib/dtable/src/plugins/sortable/index.tsx +++ b/lib/dtable/src/plugins/sortable/index.tsx @@ -104,21 +104,24 @@ const sortablePlugin: DTablePlugin row.id); + const oldOrders = [...ids]; const fromIndex = sortingFrom.index; const toIndex = sortingTo.index; - const row = rows.splice(fromIndex, 1); - rows.splice(toIndex, 0, row[0]); - rowOrders = {}; - orders = []; - rows.forEach(({id}, index) => { - rowOrders![id] = index; - orders!.push(id); - }); + if (!(fromIndex === (toIndex + 1) && sortingSide === 'after') && !(fromIndex === (toIndex - 1) && sortingSide === 'before')) { + const row = ids.splice(fromIndex, 1); + ids.splice(toIndex, 0, row[0]); + rowOrders = {}; + orders = []; + ids.forEach((id, index) => { + rowOrders![id] = index; + orders!.push(id); + }); - if (this.options.onSort?.call(this, sortingFrom, sortingTo, sortingSide, orders) === false) { - rowOrders = undefined; - orders = undefined; + if (oldOrders.join() === orders.join() || this.options.onSort?.call(this, sortingFrom, sortingTo, sortingSide, orders) === false) { + rowOrders = undefined; + orders = undefined; + } } } From b86d61f50a2269e33cbabd33cf59368cb8775361 Mon Sep 17 00:00:00 2001 From: sunhao Date: Thu, 8 Aug 2024 13:42:56 +0800 Subject: [PATCH 049/250] * popover: update options on show from hover trigger. --- lib/popover/src/vanilla/popover.ts | 56 ++++++++++++++++-------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index ac56baaeaa..0e7bb7a953 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -87,35 +87,37 @@ export class Popover { - if ($triggerElement.is('[disabled],.disabled')) { - return; + if (trigger) { + const setOptionsFromTrigger = () => { + let options = $triggerElement.dataset(); + const toggleOptions = $triggerElement.attr(`zui-toggle-${this.constructor.ZUI}`); + if (toggleOptions) { + options = $.extend(options, evalValue(toggleOptions)); } - const target = $triggerElement.dataset('target'); - if (target) { - this.setOptions({target} as Partial); - } - this.show({delay: true, event}); - }).on(`pointerleave${namespace} pointercancel${namespace}`, () => { - this.delayHide(); - }); - } else if (trigger) { - $triggerElement.on(`${trigger}${namespace}`, (event: Event) => { - if ($triggerElement.is('[disabled],.disabled')) { - return; - } - if (!this.shown) { - let options = $triggerElement.dataset(); - const toggleOptions = $triggerElement.attr(`zui-toggle-${this.constructor.ZUI}`); - if (toggleOptions) { - options = $.extend(options, evalValue(toggleOptions)); + this.setOptions(options as Partial); + }; + if (trigger === 'hover') { + $triggerElement.on(`pointerenter${namespace}`, (event: MouseEvent) => { + if ($triggerElement.is('[disabled],.disabled')) { + return; } - this.setOptions(options as Partial); - } - this.toggle({event, delay: true}); - event.preventDefault(); - }); + setOptionsFromTrigger(); + this.show({delay: true, event}); + }).on(`pointerleave${namespace} pointercancel${namespace}`, () => { + this.delayHide(); + }); + } else { + $triggerElement.on(`${trigger}${namespace}`, (event: Event) => { + if ($triggerElement.is('[disabled],.disabled')) { + return; + } + if (!this.shown) { + setOptionsFromTrigger(); + } + this.toggle({event, delay: true}); + event.preventDefault(); + }); + } } } const {show} = this.options; From c9db1021db4fe0bd88526377e4b58ef6a2fdb909 Mon Sep 17 00:00:00 2001 From: sunhao Date: Thu, 8 Aug 2024 15:46:41 +0800 Subject: [PATCH 050/250] * core: store data on occur error. --- lib/core/src/ajax/ajax.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/core/src/ajax/ajax.ts b/lib/core/src/ajax/ajax.ts index 5f3b00c25a..f04a2b9153 100644 --- a/lib/core/src/ajax/ajax.ts +++ b/lib/core/src/ajax/ajax.ts @@ -290,6 +290,9 @@ export class Ajax { throw new Error(statusText); } } catch (err) { + if (this.data === undefined && data !== undefined) { + this.data = data as T; + } error = err as Error; let skipTriggerError = false; if (error.name === 'AbortError') { From a9c6d75ac075e393262ed8ac52d8c5f9dd935116 Mon Sep 17 00:00:00 2001 From: sunhao Date: Thu, 8 Aug 2024 18:39:43 +0800 Subject: [PATCH 051/250] * dtable: refactor private fields in dtable class. --- lib/dtable/src/components/dtable.tsx | 144 +++++++++++++-------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/lib/dtable/src/components/dtable.tsx b/lib/dtable/src/components/dtable.tsx index 91990a830c..e666070bd5 100644 --- a/lib/dtable/src/components/dtable.tsx +++ b/lib/dtable/src/components/dtable.tsx @@ -22,40 +22,40 @@ export class DTable extends Component { ref = createRef(); - #rafId = 0; + _rafId = 0; - #id: string; + _id: string; - #needRender = false; + _needRender = false; - #options?: DTableOptions; + _options?: DTableOptions; - #allPlugins: readonly DTablePlugin[]; + _allPlugins: readonly DTablePlugin[]; - #plugins: DTablePlugin[] = []; + _plugins: DTablePlugin[] = []; - #layout?: DTableLayout; + _layout?: DTableLayout; - #events: Map = new Map(); + _events: Map = new Map(); - #data: Record = {}; + _data: Record = {}; - #rob?: ResizeObserver; + _rob?: ResizeObserver; - #i18nMaps: Record>[] = []; + _i18nMaps: Record>[] = []; - #hover: {in: boolean; row?: RowID; col?: ColName} = {in: false}; + _hover: {in: boolean; row?: RowID; col?: ColName} = {in: false}; _noAnimation?: number; constructor(props: DTableOptions) { super(props); - this.#id = props.id ?? `dtable-${nextGid()}`; + this._id = props.id ?? `dtable-${nextGid()}`; this.state = {scrollTop: 0, scrollLeft: 0, renderCount: 0}; - this.#allPlugins = Object.freeze(initPlugins(props.plugins)); - this.#allPlugins.forEach(plugin => { + this._allPlugins = Object.freeze(initPlugins(props.plugins)); + this._allPlugins.forEach(plugin => { const {methods, data, state} = plugin; if (methods) { Object.entries(methods).forEach(([methodName, method]) => { @@ -65,7 +65,7 @@ export class DTable extends Component { }); } if (data) { - Object.assign(this.#data, data.call(this)); + Object.assign(this._data, data.call(this)); } if (state) { Object.assign(this.state, state.call(this)); @@ -73,29 +73,29 @@ export class DTable extends Component { }); this.#initOptions(); - this.#plugins.forEach(plugin => { + this._plugins.forEach(plugin => { plugin.onCreate?.call(this, plugin); }); } get options() { - return this.#layout?.options || this.#options || getDefaultOptions() as DTableOptions; + return this._layout?.options || this._options || getDefaultOptions() as DTableOptions; } get plugins() { - return this.#plugins; + return this._plugins; } get layout(): DTableLayout { - return this.#layout as DTableLayout; + return this._layout as DTableLayout; } get id() { - return this.#id; + return this._id; } get data() { - return this.#data; + return this._data; } get element() { @@ -107,15 +107,15 @@ export class DTable extends Component { } get hoverInfo() { - return this.#hover; + return this._hover; } componentWillReceiveProps(): void { - this.#options = undefined; + this._options = undefined; } componentDidMount() { - if (this.#needRender) { + if (this._needRender) { this.forceUpdate(); } else { this.#afterRender(); @@ -139,7 +139,7 @@ export class DTable extends Component { if (typeof ResizeObserver !== 'undefined') { const responsiveEvents: string[] = []; const rob = new ResizeObserver(this.updateLayout); - this.#rob = rob; + this._rob = rob; const {parent} = this; responsiveSelectors.forEach(selector => { if (selector === 'window') { @@ -164,7 +164,7 @@ export class DTable extends Component { } } - this.#plugins.forEach(plugin => { + this._plugins.forEach(plugin => { let {events} = plugin; if (events) { if (typeof events === 'function') { @@ -183,17 +183,17 @@ export class DTable extends Component { componentDidUpdate() { this.#afterRender(); - this.#plugins.forEach(plugin => { + this._plugins.forEach(plugin => { plugin.onUpdated?.call(this); }); } componentWillUnmount() { - this.#rob?.disconnect(); + this._rob?.disconnect(); const {element} = this; if (element) { - for (const event of this.#events.keys()) { + for (const event of this._events.keys()) { if (event.startsWith('window_')) { window.removeEventListener(event.replace('window_', ''), this.#handleWindowEvent); } else if (event.startsWith('document_')) { @@ -204,16 +204,16 @@ export class DTable extends Component { } } - this.#plugins.forEach(plugin => { + this._plugins.forEach(plugin => { plugin.onUnmounted?.call(this); }); - this.#allPlugins.forEach(plugin => { + this._allPlugins.forEach(plugin => { plugin.onDestory?.call(this); }); - this.#data = {}; - this.#events.clear(); + this._data = {}; + this._events.clear(); if (this._noAnimation) { clearTimeout(this._noAnimation); @@ -221,12 +221,12 @@ export class DTable extends Component { } resetState(props?: DTableOptions, init?: boolean) { - this.#options = undefined; - this.#layout = undefined; + this._options = undefined; + this._layout = undefined; props = props || this.props; const newState: Partial = {}; - this.#plugins.forEach(plugin => { + this._plugins.forEach(plugin => { const {resetState, state: pluginState} = plugin; if (resetState) { if (typeof resetState === 'function') { @@ -245,11 +245,11 @@ export class DTable extends Component { if (target) { event = `${target}_${event}`; } - const eventCallbacks = this.#events.get(event); + const eventCallbacks = this._events.get(event); if (eventCallbacks) { eventCallbacks.push(callback); } else { - this.#events.set(event, [callback]); + this._events.set(event, [callback]); if (event.startsWith('window_')) { window.addEventListener(event.replace('window_', ''), this.#handleWindowEvent); } else if (event.startsWith('document_')) { @@ -264,7 +264,7 @@ export class DTable extends Component { if (target) { event = `${target}_${event}`; } - const eventCallbacks = this.#events.get(event); + const eventCallbacks = this._events.get(event); if (!eventCallbacks) { return; } @@ -273,7 +273,7 @@ export class DTable extends Component { eventCallbacks.splice(index, 1); } if (!eventCallbacks.length) { - this.#events.delete(event); + this._events.delete(event); if (event.startsWith('window_')) { window.removeEventListener(event.replace('window_', ''), this.#handleWindowEvent); } else if (event.startsWith('document_')) { @@ -404,7 +404,7 @@ export class DTable extends Component { } update(options: {dirtyType?: 'options' | 'layout', state?: Partial | ((prevState: Readonly) => void)} | (() => void) = {}, callback?: () => void) { - if (!this.#options) { + if (!this._options) { return; } if (typeof options === 'function') { @@ -413,13 +413,13 @@ export class DTable extends Component { } const {dirtyType, state} = options; if (dirtyType === 'layout') { - this.#layout = undefined; + this._layout = undefined; } else if (dirtyType === 'options') { - this.#options = undefined; - if (!this.#layout) { + this._options = undefined; + if (!this._layout) { return; } - this.#layout = undefined; + this._layout = undefined; } this.setState(state || ((preState) => ({renderCount: preState.renderCount + 1})), callback); } @@ -447,19 +447,19 @@ export class DTable extends Component { } updateLayout = () => { - if (this.#rafId) { - cancelAnimationFrame(this.#rafId); + if (this._rafId) { + cancelAnimationFrame(this._rafId); } - this.#rafId = requestAnimationFrame(() => { + this._rafId = requestAnimationFrame(() => { this.update({dirtyType: 'layout'}); - this.#rafId = 0; + this._rafId = 0; }); }; i18n(key: string, defaultValue?: string): string; i18n(key: string, args?: (string | number)[] | Record, defaultValue?: string): string; i18n(key: string, args?: string | (string | number)[] | Record, defaultValue?: string): string { - return i18n(this.#i18nMaps, key, args as string, defaultValue, this.options.lang) ?? `{i18n:${key}}`; + return i18n(this._i18nMaps, key, args as string, defaultValue, this.options.lang) ?? `{i18n:${key}}`; } getPlugin(pluginName: string): DTablePlugin | undefined { @@ -468,7 +468,7 @@ export class DTable extends Component { #handleEvent = (event: Event, type?: string) => { type = type || event.type; - const callbacks = this.#events.get(type); + const callbacks = this._events.get(type); if (!callbacks?.length) { return; } @@ -608,8 +608,8 @@ export class DTable extends Component { } #afterRender() { - this.#needRender = false; - this.#plugins.forEach(plugin => plugin.afterRender?.call(this)); + this._needRender = false; + this._plugins.forEach(plugin => plugin.afterRender?.call(this)); this.options.afterRender?.call(this); } @@ -621,7 +621,7 @@ export class DTable extends Component { if (col.setting[renderCallbackName]) { result = (col.setting[renderCallbackName] as CellRenderCallback).call(this, result, data, cellProps, h); } - this.#plugins.forEach(plugin => { + this._plugins.forEach(plugin => { if (plugin[renderCallbackName]) { result = (plugin[renderCallbackName] as CellRenderCallback).call(this, result, data, cellProps, h); } @@ -649,7 +649,7 @@ export class DTable extends Component { if (rowID === 'HEADER') { if (cellElement) { this.options.onHeaderCellClick?.call(this, event, {colName, element: cellElement}); - this.#plugins.forEach(plugin => { + this._plugins.forEach(plugin => { plugin.onHeaderCellClick?.call(this, event, {colName, element: cellElement}); }); } @@ -659,7 +659,7 @@ export class DTable extends Component { if (this.options.onCellClick?.call(this, event, {colName, rowID, rowInfo, element: cellElement}) === true) { return; } - for (const plugin of this.#plugins) { + for (const plugin of this._plugins) { if (plugin.onCellClick?.call(this, event, {colName, rowID, rowInfo, element: cellElement}) === true) { return; } @@ -697,7 +697,7 @@ export class DTable extends Component { if (options.colHover === 'header' && newInfo.row !== 'HEADER') { newInfo.col = undefined; } - const oldInfo = this.#hover; + const oldInfo = this._hover; if (newInfo.in !== oldInfo.in) { $element.toggleClass('dtable-hover', newInfo.in); } @@ -713,25 +713,25 @@ export class DTable extends Component { $element.find(`.dtable-cell[data-col="${newInfo.col}"]`).addClass('is-hover-col'); } } - this.#hover = newInfo; + this._hover = newInfo; } #initOptions(): boolean { - if (this.#options) { + if (this._options) { return false; } const defaultOptions = getDefaultOptions(); - const options = {...defaultOptions, ...this.#allPlugins.reduce((currentOptions, plugin) => { + const options = {...defaultOptions, ...this._allPlugins.reduce((currentOptions, plugin) => { const {defaultOptions: pluginOptions} = plugin; if (pluginOptions) { Object.assign(currentOptions, pluginOptions); } return currentOptions; }, {}), ...this.props} as DTableOptions; - this.#options = options; + this._options = options; - this.#plugins = this.#allPlugins.reduce((list, plugin) => { + this._plugins = this._allPlugins.reduce((list, plugin) => { const {options: optionsModifier} = plugin; let pluginModifyOptions = options; if (optionsModifier) { @@ -747,7 +747,7 @@ export class DTable extends Component { return !when || when.call(this, options); }); - this.#i18nMaps = [this.options.i18n, ...this.plugins.map(x => x.i18n)].filter(Boolean) as Record>[]; + this._i18nMaps = [this.options.i18n, ...this.plugins.map(x => x.i18n)].filter(Boolean) as Record>[]; return true; } @@ -755,7 +755,7 @@ export class DTable extends Component { #initLayout() { const {plugins} = this; - let options = this.#options as DTableOptions; + let options = this._options as DTableOptions; const footerGenerators: Record> = { flex:
, divider:
, @@ -779,7 +779,7 @@ export class DTable extends Component { if (parentElement) { width = parentElement.clientWidth; } else { - this.#needRender = true; + this._needRender = true; return; } } @@ -862,7 +862,7 @@ export class DTable extends Component { height = parentElement.clientHeight; } else { height = 0; - this.#needRender = true; + this._needRender = true; return; } } else { @@ -902,11 +902,11 @@ export class DTable extends Component { } }); - this.#layout = layout; + this._layout = layout; } #getLayout(): DTableLayout | undefined { - if (this.#initOptions() || !this.#layout) { + if (this.#initOptions() || !this._layout) { this.#initLayout(); } @@ -984,7 +984,7 @@ export class DTable extends Component { } } - this.#plugins.forEach(plugin => { + this._plugins.forEach(plugin => { const newLayout = plugin.beforeRender?.call(this, layout!); if (newLayout) { layout = newLayout; @@ -1028,7 +1028,7 @@ export class DTable extends Component { } } - this.#plugins.forEach(plugin => { + this._plugins.forEach(plugin => { const result = plugin.onRender?.call(this, layout!); if (!result) { return; @@ -1047,7 +1047,7 @@ export class DTable extends Component { return (
Date: Fri, 9 Aug 2024 11:10:22 +0800 Subject: [PATCH 052/250] * dtable: check plugins state after each render. --- lib/dtable/src/components/dtable.tsx | 52 ++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/lib/dtable/src/components/dtable.tsx b/lib/dtable/src/components/dtable.tsx index e666070bd5..5839573957 100644 --- a/lib/dtable/src/components/dtable.tsx +++ b/lib/dtable/src/components/dtable.tsx @@ -34,6 +34,8 @@ export class DTable extends Component { _plugins: DTablePlugin[] = []; + _lastUsedPlugins: Map = new Map(); + _layout?: DTableLayout; _events: Map = new Map(); @@ -164,25 +166,12 @@ export class DTable extends Component { } } - this._plugins.forEach(plugin => { - let {events} = plugin; - if (events) { - if (typeof events === 'function') { - events = events.call(this); - } - Object.entries(events).forEach(([eventType, callback]) => { - if (callback) { - this.on(eventType, callback as DTableEventListener); - } - }); - } - - plugin.onMounted?.call(this); - }); + this._checkPluginsState(); } componentDidUpdate() { this.#afterRender(); + this._checkPluginsState(); this._plugins.forEach(plugin => { plugin.onUpdated?.call(this); }); @@ -466,6 +455,39 @@ export class DTable extends Component { return this.plugins.find(x => x.name === pluginName); } + _checkPluginsState() { + const lastUsedPluginsNames = new Set(this._lastUsedPlugins.keys()); + this._plugins.forEach(plugin => { + if (lastUsedPluginsNames.has(plugin.name)) { + lastUsedPluginsNames.delete(plugin.name); + return; + } + + let {events} = plugin; + if (events) { + if (typeof events === 'function') { + events = events.call(this); + } + Object.entries(events).forEach(([eventType, callback]) => { + if (callback) { + this.on(eventType, callback as DTableEventListener); + } + }); + } + + plugin.onMounted?.call(this); + this._lastUsedPlugins.set(plugin.name, plugin); + }); + + if (lastUsedPluginsNames.size) { + lastUsedPluginsNames.forEach(name => { + const plugin = this._lastUsedPlugins.get(name); + plugin?.onUnmounted?.call(this); + this._lastUsedPlugins.delete(name); + }); + } + } + #handleEvent = (event: Event, type?: string) => { type = type || event.type; const callbacks = this._events.get(type); From 17014b801bacbeb75e11c7483daf30eeeb81a6b9 Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 9 Aug 2024 11:10:44 +0800 Subject: [PATCH 053/250] * utilities: add bg-opacity-25 helper. --- lib/utilities/src/backgrounds/background-opacity.css | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/utilities/src/backgrounds/background-opacity.css b/lib/utilities/src/backgrounds/background-opacity.css index d2bf7bb95c..bb7ba3b53b 100644 --- a/lib/utilities/src/backgrounds/background-opacity.css +++ b/lib/utilities/src/backgrounds/background-opacity.css @@ -2,6 +2,7 @@ .bg-opacity-5 {--tw-bg-opacity: .05;} .bg-opacity-10 {--tw-bg-opacity: .1;} .bg-opacity-20 {--tw-bg-opacity: .2;} +.bg-opacity-25 {--tw-bg-opacity: .25;} .bg-opacity-30 {--tw-bg-opacity: .3;} .bg-opacity-40 {--tw-bg-opacity: .4;} .bg-opacity-50 {--tw-bg-opacity: .5;} From 2e6dfc584f37ae5e14848f1e430565c7305f4c24 Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 9 Aug 2024 11:30:05 +0800 Subject: [PATCH 054/250] * dtable: fix col resizing not work with fixedLeftWidth. --- lib/dtable/src/helpers/layout.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/dtable/src/helpers/layout.ts b/lib/dtable/src/helpers/layout.ts index d75097b2a1..ca6f55c3c6 100644 --- a/lib/dtable/src/helpers/layout.ts +++ b/lib/dtable/src/helpers/layout.ts @@ -7,7 +7,11 @@ function initSectionColsLayout(cols: DTableColsSectionLayout, fixed = false, max return; } - if (maxWidth && !cols.widthSetting && cols.width > maxWidth) { + if (fixed && cols.widthSetting) { + cols.widthSetting = Math.min(cols.widthSetting, cols.width); + } + + if (maxWidth && (!cols.widthSetting || cols.widthSetting > maxWidth) && cols.width > maxWidth) { cols.widthSetting = maxWidth; } From f5f9fcfbba6ab3fcf4cae127167ea078f7efe00f Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 9 Aug 2024 15:11:50 +0800 Subject: [PATCH 055/250] * kanban: fix links editor not show. --- lib/kanban/src/component/kanban.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/kanban/src/component/kanban.tsx b/lib/kanban/src/component/kanban.tsx index 45a87ae5ca..78b11db4c9 100644 --- a/lib/kanban/src/component/kanban.tsx +++ b/lib/kanban/src/component/kanban.tsx @@ -774,11 +774,12 @@ export class Kanban

) { const {links = []} = this.data; - if (!links.length) { + const {editLinks} = props; + if (!editLinks && !links.length) { return; } - const {editLinks, showLinkOnHover, showLinkOnSelected} = props; + const {showLinkOnHover, showLinkOnSelected} = props; let filters: string[] | undefined; if (showLinkOnSelected || showLinkOnHover) { filters = []; From 8adc347ab68419d66dc9f0aa91af63d13025076b Mon Sep 17 00:00:00 2001 From: sunhao Date: Sat, 10 Aug 2024 18:39:51 +0800 Subject: [PATCH 056/250] * popover: fix dismiss button not work in inherit class. --- lib/popover/src/vanilla/popover.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/popover/src/vanilla/popover.ts b/lib/popover/src/vanilla/popover.ts index 0e7bb7a953..d1f0f3c982 100644 --- a/lib/popover/src/vanilla/popover.ts +++ b/lib/popover/src/vanilla/popover.ts @@ -595,7 +595,7 @@ $(() => { const clickedPopover = gid ? SHOWN_POPOVERS.get(gid) : null; if (clickedPopover) { const name = clickedPopover.options.name ?? clickedPopover.constructor.ZUI; - if ($target.closest(`[data-dismiss="${name}"]`).length) { + if ($target.closest(`[data-dismiss="popover"],[data-dismiss="${name}"]`).length) { clickedPopover.hide(); return; } From 13325654232f422d6c1f5aad2b1d930f8696f329 Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 12 Aug 2024 21:24:50 +0800 Subject: [PATCH 057/250] * dtable: fix group plugin not work. --- lib/dtable/src/plugins/group/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/dtable/src/plugins/group/index.tsx b/lib/dtable/src/plugins/group/index.tsx index 112a5fd4a6..de8c073de2 100644 --- a/lib/dtable/src/plugins/group/index.tsx +++ b/lib/dtable/src/plugins/group/index.tsx @@ -16,10 +16,10 @@ const applyGroupDivider = (cols: ColInfo[]) => { return; } cols.forEach((col, index) => { - if (!index || col.setting.border || col.setting.group === cols[index - 1].setting.group) { + if (!index || col.border !== undefined || col.setting.group === cols[index - 1].setting.group) { return; } - col.setting.border = 'left'; + col.border = 'left'; }); }; From bc65c78c6563b5d737fd787f347fdc9abe7f4bd3 Mon Sep 17 00:00:00 2001 From: sunhao Date: Tue, 13 Aug 2024 13:27:24 +0800 Subject: [PATCH 058/250] * list: prevent to toggle on click form controls. --- lib/list/src/component/nested-list.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/list/src/component/nested-list.tsx b/lib/list/src/component/nested-list.tsx index 03031a06a6..b0c3da3a8d 100644 --- a/lib/list/src/component/nested-list.tsx +++ b/lib/list/src/component/nested-list.tsx @@ -616,7 +616,7 @@ export class NestedList

Date: Wed, 14 Aug 2024 17:28:07 +0800 Subject: [PATCH 059/250] * form: fix horz form style. --- lib/form/src/style/form-horz.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/form/src/style/form-horz.css b/lib/form/src/style/form-horz.css index 050d9deeb7..1f7fdc4536 100644 --- a/lib/form/src/style/form-horz.css +++ b/lib/form/src/style/form-horz.css @@ -3,7 +3,10 @@ } .form-horz .form-group { - @apply -flex -flex-row -items-start -relative -min-h-[32px] -flex-wrap -pl-[--form-horz-label-width] -min-w-0 -flex-grow; + @apply -flex -flex-row -items-start -relative -min-h-[32px] -flex-wrap -pl-[--form-horz-label-width] -min-w-0 -flex-none; +} +.form-horz .form-row .form-group { + @apply -flex-grow; } .form-horz .form-group[class^="w-"], .form-horz .form-group[class*=" w-"] { From 48779a05a78f789f2b176247c2fc4035336c36a4 Mon Sep 17 00:00:00 2001 From: sunhao Date: Wed, 14 Aug 2024 17:32:11 +0800 Subject: [PATCH 060/250] * list: fix modifier class no-nested-items never work. --- lib/list/src/component/nested-list.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/list/src/component/nested-list.tsx b/lib/list/src/component/nested-list.tsx index b0c3da3a8d..76e6b59725 100644 --- a/lib/list/src/component/nested-list.tsx +++ b/lib/list/src/component/nested-list.tsx @@ -563,7 +563,7 @@ export class NestedList

, renderedItem: NestedItem, index: number): ComponentChildren { - if (this._hasNestedItems && renderedItem.type === 'item' && renderedItem.toggleIcon === undefined) { + if ((this._hasNestedItems || !this.isRoot) && renderedItem.type === 'item' && renderedItem.toggleIcon === undefined) { renderedItem.toggleIcon = this._renderNestedToggle(props, renderedItem.expanded as boolean | undefined); } const nestedListContent = renderedItem.items ? this._renderNestedList(props, renderedItem.items, renderedItem, renderedItem.expanded as boolean) : null; @@ -644,7 +644,7 @@ export class NestedList

): void | RenderableProps

| undefined { this._renderedItemMap.clear(); this._hasIcons = false; - this._hasNestedItems = !this.isRoot; + this._hasNestedItems = false; return super._beforeRender(props); } } From 3b865323fb480a0cf2f5d6d7be5a1ce36b4b91b9 Mon Sep 17 00:00:00 2001 From: sunhao Date: Thu, 15 Aug 2024 14:19:55 +0800 Subject: [PATCH 061/250] * list: fix checkOnClick not work as expected. --- lib/list/src/component/list.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/list/src/component/list.tsx b/lib/list/src/component/list.tsx index 69313393d7..5cf892743b 100644 --- a/lib/list/src/component/list.tsx +++ b/lib/list/src/component/list.tsx @@ -317,9 +317,13 @@ export class List

Date: Thu, 15 Aug 2024 14:28:53 +0800 Subject: [PATCH 062/250] * datetime-picker: fix setValue not work as expected in datetime pickers. --- lib/datetime-picker/src/component/date-picker.tsx | 12 +++++++++++- lib/datetime-picker/src/component/time-picker.tsx | 13 +++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/datetime-picker/src/component/date-picker.tsx b/lib/datetime-picker/src/component/date-picker.tsx index 02c355ac33..f28a1286fb 100644 --- a/lib/datetime-picker/src/component/date-picker.tsx +++ b/lib/datetime-picker/src/component/date-picker.tsx @@ -39,11 +39,21 @@ export class DatePicker extends } const newValue = this._calcValue(value); - this.setState({value: newValue}, () => { + return this.changeState({value: newValue}, () => { this._afterSetDate(); }); }; + setValue(value: string, silent?: boolean) { + if (silent) { + const trigger = this._trigger.current; + if (trigger) { + trigger._skipTriggerChange = value; + } + } + return this.setDate(value) as Promise; + } + _calcValue(value: string): string { const {onInvalid, defaultValue = '', required, allowInvalid, format} = this.props; let date = this._parseDate(value); diff --git a/lib/datetime-picker/src/component/time-picker.tsx b/lib/datetime-picker/src/component/time-picker.tsx index 502f5c87b3..e99c1096e0 100644 --- a/lib/datetime-picker/src/component/time-picker.tsx +++ b/lib/datetime-picker/src/component/time-picker.tsx @@ -1,4 +1,3 @@ -import {ComponentChildren, RenderableProps} from 'preact'; import {Icon, classes} from '@zui/core'; import {formatDate, createDate} from '@zui/helpers'; import {Pick} from '@zui/pick/src/components/pick'; @@ -69,13 +68,23 @@ export class TimePicker extends Pick { const date = parseTime(valueString); const {onInvalid, required, defaultValue} = this.props; - this.setState({value: date ? formatDate(date, this.props.format) : (required ? defaultValue : '')}, () => { + return this.changeState({value: date ? formatDate(date, this.props.format) : (required ? defaultValue : '')}, () => { if (!date && onInvalid) { onInvalid(valueString); } }); } + setValue(value: string, silent?: boolean) { + if (silent) { + const trigger = this._trigger.current; + if (trigger) { + trigger._skipTriggerChange = value; + } + } + return this.setTime(value) as Promise; + } + getTime(): [hour: number, minute: number] | null { const date = parseTime(this.state.value); return date ? [date.getHours(), date.getMinutes()] : null; From fc4ca50bc4cd92a090be1110c5c3298124bb2d5e Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 16 Aug 2024 16:34:03 +0800 Subject: [PATCH 063/250] * picker: fix search param when no search keys. --- lib/picker/src/component/picker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/picker/src/component/picker.tsx b/lib/picker/src/component/picker.tsx index fc3690778d..dc1f8a6304 100644 --- a/lib/picker/src/component/picker.tsx +++ b/lib/picker/src/component/picker.tsx @@ -174,7 +174,7 @@ export class Picker Date: Fri, 16 Aug 2024 16:34:25 +0800 Subject: [PATCH 064/250] * list: fix toggleIcons not work with icon name. --- lib/list/src/component/nested-list.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/list/src/component/nested-list.tsx b/lib/list/src/component/nested-list.tsx index 76e6b59725..a00ed3fa6b 100644 --- a/lib/list/src/component/nested-list.tsx +++ b/lib/list/src/component/nested-list.tsx @@ -1,4 +1,4 @@ -import {Icon, classes, mergeProps, $} from '@zui/core'; +import {Icon, classes, mergeProps, $, isValidElement} from '@zui/core'; import {store} from '@zui/store'; import {List} from './list'; import '@zui/css-icons/src/icons/caret.css'; @@ -519,6 +519,9 @@ export class NestedList

) : (toggleIcons.collapsed || ); toggleClass = `state is-${isExpanded ? 'expanded' : 'collapsed'}`; + if (!isValidElement(toggleIcon)) { + toggleIcon = ; + } } else { toggleIcon = ; toggleClass = 'is-empty'; From 9d97d61ef3b165a8468a7455738ccafcd0ccb93b Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 16 Aug 2024 16:34:43 +0800 Subject: [PATCH 065/250] * menu: add headerClass and footerClass to searchMenu. --- lib/menu/src/component/search-menu.tsx | 8 ++++---- lib/menu/src/types/search-menu-options.ts | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/menu/src/component/search-menu.tsx b/lib/menu/src/component/search-menu.tsx index c114c2d57b..80a1473df7 100644 --- a/lib/menu/src/component/search-menu.tsx +++ b/lib/menu/src/component/search-menu.tsx @@ -157,14 +157,14 @@ export class SearchMenu extends protected _renderWrapperHeader(props: RenderableProps): ComponentChildren { const hasHeader = props.header; - const {noMatchHint, searchBox, searchPlacement, nestedSearch} = props; + const {noMatchHint, searchBox, searchPlacement, nestedSearch, headerClass} = props; const hasTopSearchBox = (!nestedSearch || this.isRoot) && searchBox && searchPlacement !== 'bottom'; if (!hasHeader && !hasTopSearchBox && !noMatchHint) { return null; } return [ noMatchHint ?

{noMatchHint}
: null, - (hasHeader || hasTopSearchBox) ? (
+ (hasHeader || hasTopSearchBox) ? (
{hasHeader ? super._renderWrapperHeader(props) : null} {hasTopSearchBox ? this._renderSearchBox(props) : null}
) : null, @@ -173,13 +173,13 @@ export class SearchMenu extends protected _renderWrapperFooter(props: RenderableProps): ComponentChildren { const hasFooter = props.footer; - const {searchBox, searchPlacement, nestedSearch} = props; + const {searchBox, searchPlacement, nestedSearch, footerClass} = props; const hasBottomSearchBox = (!nestedSearch || this.isRoot) && searchBox && searchPlacement === 'bottom'; if (!hasFooter && !hasBottomSearchBox) { return null; } return ( -