Skip to content

Commit

Permalink
fix: nav collapse hover will lost open state, #2558
Browse files Browse the repository at this point in the history
  • Loading branch information
pointhalo committed Nov 5, 2024
1 parent 31ca051 commit 76067ba
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
32 changes: 27 additions & 5 deletions packages/semi-foundation/navigation/subNavFoundation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ const removeKeys = function removeKeys(originKeys: (string | number)[] = [], ...
return Array.from(keySet);
};

const hasKeys = function hasKeys(originKeys: (string | number)[] = [], ...willCheckKeys: (string | number)[]) {
const keySet = new Set(originKeys);
return willCheckKeys.some(key => key && keySet.has(key));
};

export interface OnOpenChangeData {
itemKey: string | number;
openKeys: (string | number)[];
Expand All @@ -32,12 +37,12 @@ export interface SubNavAdapter<P = Record<string, any>, S = Record<string, any>>
getOpenKeys(): (string | number)[];
getOpenKeysIsControlled(): boolean;
getCanUpdateOpenKeys(): boolean;
updateOpen(isOpen: boolean): void;
notifyGlobalOpenChange(data: OnOpenChangeData): void;
notifyGlobalOnSelect(data: OnSelectData): void;
notifyGlobalOnClick(data: OnClickData): void;
getIsSelected(itemKey: string | number): boolean;
getIsOpen(): boolean
getIsOpen(): boolean;
updateOpenKeys(openKeys: (string | number)[]): void
}

export default class SubNavFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<SubNavAdapter<P, S>, P, S> {
Expand All @@ -46,10 +51,12 @@ export default class SubNavFoundation<P = Record<string, any>, S = Record<string
}

_timer: number;
_currentHoverAlreadyOpen: null | number | string;

init() {
// this.log('invoke SubNavFoundation init()');
this._timer = null;
this._currentHoverAlreadyOpen = null;
}

destroy() {
Expand All @@ -74,13 +81,28 @@ export default class SubNavFoundation<P = Record<string, any>, S = Record<string
const canUpdateOpenKeys = this._adapter.getCanUpdateOpenKeys();
const rawOpenKeys = this._adapter.getOpenKeys();

const openKeys = visible ? addKeys(rawOpenKeys, itemKey) : removeKeys(rawOpenKeys, itemKey);
let openKeys = rawOpenKeys;

if (visible) {
if (hasKeys(rawOpenKeys, itemKey)) {
// 如果 state.openKeys已经存在,说明他之前就已经处于open态,不需要再次将其写入 state.openKeys中
} else {
// 如果 itemKey 跟 _currentHoverAlreadyOpen 不相同,说明是新的 hover,正常更新 state.openKeys
openKeys = addKeys(rawOpenKeys, itemKey);
}
this._currentHoverAlreadyOpen = itemKey;
} else {
if (itemKey !== this._currentHoverAlreadyOpen) {
openKeys = removeKeys(rawOpenKeys, itemKey);
}
this._currentHoverAlreadyOpen = null;
}

this.clearDelayTimer();

if (!openKeysIsControlled) {
if (canUpdateOpenKeys) {
this._adapter.updateOpen(visible);
this._adapter.updateOpenKeys(openKeys);
}
// this._adapter.updateIsHovered(visible);
}
Expand Down Expand Up @@ -117,7 +139,7 @@ export default class SubNavFoundation<P = Record<string, any>, S = Record<string
const canUpdateOpenKeys = this._adapter.getCanUpdateOpenKeys();

if (!openKeysIsControlled && canUpdateOpenKeys) {
this._adapter.updateOpen(isOpen);
this._adapter.updateOpenKeys(openKeys);
}
this._adapter.notifyGlobalOpenChange(cbVal);
this._adapter.notifyGlobalOnClick(cbVal);
Expand Down
5 changes: 2 additions & 3 deletions packages/semi-ui/navigation/SubNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,15 @@ export default class SubNav extends BaseComponent<SubNavProps, SubNavState> {
getOpenKeys: () => this.context && this.context.openKeys,
getOpenKeysIsControlled: () => this.context && this.context.openKeysIsControlled,
getCanUpdateOpenKeys: () => this.context && this.context.canUpdateOpenKeys,
updateOpen: isOpen =>
this._invokeContextFunc(isOpen ? 'addOpenKeys' : 'removeOpenKeys', this.props.itemKey),
notifyGlobalOpenChange: (...args) => this._invokeContextFunc('onOpenChange', ...args),
notifyGlobalOnSelect: (...args) => this._invokeContextFunc('onSelect', ...args),
notifyGlobalOnClick: (...args) => this._invokeContextFunc('onClick', ...args),
getIsSelected: itemKey => Boolean(!isNullOrUndefined(itemKey) && get(this.context, 'selectedKeys', []).includes(String(itemKey))),
getIsOpen: () => {
const { itemKey } = this.props;
return Boolean(this.context && this.context.openKeys && this.context.openKeys.includes(this.props.itemKey));
}
},
updateOpenKeys: (newOpenKeys) => { this.context.updateOpenKeys(newOpenKeys); }
};
}

Expand Down
5 changes: 4 additions & 1 deletion packages/semi-ui/navigation/nav-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ export interface NavContextType {
renderWrapper?: NavProps['renderWrapper'];
getPopupContainer?: DropdownProps['getPopupContainer'];
tooltipShowDelay?: number;
tooltipHideDelay?: number
tooltipHideDelay?: number;
updateOpenKeys?: (openKeys: ItemKey[]) => void;
addOpenKeys?: (itemKey: ItemKey) => void;
removeOpenKeys?: (itemKey: ItemKey) => void
}

const NavContext = React.createContext<NavContextType>({
Expand Down

0 comments on commit 76067ba

Please sign in to comment.