Skip to content

Commit 293e3cd

Browse files
authored
refactor: Align motion with rc-trigger (#350)
* fix: Popup motion * chore: reduce code * chore: bump rc-trigger version * fix lint
1 parent 1796367 commit 293e3cd

File tree

2 files changed

+72
-48
lines changed

2 files changed

+72
-48
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"mini-store": "^3.0.1",
4747
"omit.js": "^2.0.0",
4848
"rc-motion": "^2.0.1",
49-
"rc-trigger": "^5.0.4",
49+
"rc-trigger": "^5.1.2",
5050
"rc-util": "^5.0.1",
5151
"resize-observer-polyfill": "^1.5.0",
5252
"shallowequal": "^1.1.0"

src/SubMenu.tsx

Lines changed: 71 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ export class SubMenu extends React.Component<SubMenuProps> {
197197
* This legacy code that `onKeyDown` is called by parent instead of dom self.
198198
* which need return code to check if this event is handled
199199
*/
200-
onKeyDown: React.KeyboardEventHandler<HTMLElement> = e => {
200+
onKeyDown: React.KeyboardEventHandler<HTMLElement> = (e) => {
201201
const { keyCode } = e;
202202
const menu = this.menuInstance;
203203
const { isOpen, store } = this.props;
@@ -239,15 +239,15 @@ export class SubMenu extends React.Component<SubMenuProps> {
239239
return undefined;
240240
};
241241

242-
onOpenChange: OpenEventHandler = e => {
242+
onOpenChange: OpenEventHandler = (e) => {
243243
this.props.onOpenChange(e);
244244
};
245245

246246
onPopupVisibleChange = (visible: boolean) => {
247247
this.triggerOpenChange(visible, visible ? 'mouseenter' : 'mouseleave');
248248
};
249249

250-
onMouseEnter: React.MouseEventHandler<HTMLElement> = e => {
250+
onMouseEnter: React.MouseEventHandler<HTMLElement> = (e) => {
251251
const { eventKey: key, onMouseEnter, store } = this.props;
252252
updateDefaultActiveFirst(store, this.props.eventKey, false);
253253
onMouseEnter({
@@ -256,7 +256,7 @@ export class SubMenu extends React.Component<SubMenuProps> {
256256
});
257257
};
258258

259-
onMouseLeave: React.MouseEventHandler<HTMLElement> = e => {
259+
onMouseLeave: React.MouseEventHandler<HTMLElement> = (e) => {
260260
const { parentMenu, eventKey, onMouseLeave } = this.props;
261261
parentMenu.subMenuInstance = this;
262262
onMouseLeave({
@@ -265,7 +265,7 @@ export class SubMenu extends React.Component<SubMenuProps> {
265265
});
266266
};
267267

268-
onTitleMouseEnter: React.MouseEventHandler<HTMLElement> = domEvent => {
268+
onTitleMouseEnter: React.MouseEventHandler<HTMLElement> = (domEvent) => {
269269
const { eventKey: key, onItemHover, onTitleMouseEnter } = this.props;
270270
onItemHover({
271271
key,
@@ -277,7 +277,7 @@ export class SubMenu extends React.Component<SubMenuProps> {
277277
});
278278
};
279279

280-
onTitleMouseLeave: React.MouseEventHandler<HTMLElement> = e => {
280+
onTitleMouseLeave: React.MouseEventHandler<HTMLElement> = (e) => {
281281
const { parentMenu, eventKey, onItemHover, onTitleMouseLeave } = this.props;
282282
parentMenu.subMenuInstance = this;
283283
onItemHover({
@@ -313,11 +313,11 @@ export class SubMenu extends React.Component<SubMenuProps> {
313313
}
314314
};
315315

316-
onSelect: SelectEventHandler = info => {
316+
onSelect: SelectEventHandler = (info) => {
317317
this.props.onSelect(info);
318318
};
319319

320-
onDeselect: SelectEventHandler = info => {
320+
onDeselect: SelectEventHandler = (info) => {
321321
this.props.onDeselect(info);
322322
};
323323

@@ -369,6 +369,8 @@ export class SubMenu extends React.Component<SubMenuProps> {
369369

370370
isOpen = () => this.props.openKeys.indexOf(this.props.eventKey) !== -1;
371371

372+
isInlineMode = () => this.props.mode === 'inline';
373+
372374
adjustWidth = () => {
373375
/* istanbul ignore if */
374376
if (!this.subMenuTitle || !this.menuInstance) {
@@ -440,43 +442,55 @@ export class SubMenu extends React.Component<SubMenuProps> {
440442
return mergedMotion;
441443
};
442444

443-
renderChildren(children: React.ReactNode) {
445+
renderPopupMenu(className: string, style?: React.CSSProperties) {
446+
const baseProps = this.getBaseProps();
447+
448+
/**
449+
* zombiej: Why SubPopupMenu here?
450+
* Seems whatever popup or inline mode both will render SubPopupMenu.
451+
* It's controlled by Trigger for popup or not.
452+
*/
453+
return (
454+
<SubPopupMenu
455+
{...baseProps}
456+
id={this.internalMenuId}
457+
className={className}
458+
style={style}
459+
>
460+
{this.props.children}
461+
</SubPopupMenu>
462+
);
463+
}
464+
465+
renderChildren() {
444466
const baseProps = this.getBaseProps();
467+
const { mode, visible, forceSubMenuRender, direction } = baseProps;
445468

446469
// [Legacy] getMotion must be called before `haveRendered`
447-
const mergedMotion = this.getMotion(baseProps.mode, baseProps.visible);
470+
const mergedMotion = this.getMotion(mode, visible);
448471

449472
this.haveRendered = true;
450473

451-
this.haveOpened =
452-
this.haveOpened || baseProps.visible || baseProps.forceSubMenuRender;
474+
this.haveOpened = this.haveOpened || visible || forceSubMenuRender;
453475
// never rendered not planning to, don't render
454476
if (!this.haveOpened) {
455477
return <div />;
456478
}
457479

458-
const { direction } = baseProps;
480+
const sharedClassName = classNames(`${baseProps.prefixCls}-sub`, {
481+
[`${baseProps.prefixCls}-rtl`]: direction === 'rtl',
482+
});
483+
484+
if (!this.isInlineMode()) {
485+
return this.renderPopupMenu(sharedClassName);
486+
}
487+
459488
return (
460489
<CSSMotion visible={baseProps.visible} {...mergedMotion}>
461490
{({ className, style }) => {
462-
const mergedClassName = classNames(
463-
`${baseProps.prefixCls}-sub`,
464-
className,
465-
{
466-
[`${baseProps.prefixCls}-rtl`]: direction === 'rtl',
467-
},
468-
);
469-
470-
return (
471-
<SubPopupMenu
472-
{...baseProps}
473-
id={this.internalMenuId}
474-
className={mergedClassName}
475-
style={style}
476-
>
477-
{children}
478-
</SubPopupMenu>
479-
);
491+
const mergedClassName = classNames(sharedClassName, className);
492+
493+
return this.renderPopupMenu(mergedClassName, style);
480494
}}
481495
</CSSMotion>
482496
);
@@ -486,11 +500,11 @@ export class SubMenu extends React.Component<SubMenuProps> {
486500
const props = { ...this.props };
487501
const { isOpen } = props;
488502
const prefixCls = this.getPrefixCls();
489-
const isInlineMode = props.mode === 'inline';
503+
const inline = this.isInlineMode();
490504
const className = classNames(prefixCls, `${prefixCls}-${props.mode}`, {
491505
[props.className]: !!props.className,
492506
[this.getOpenClassName()]: isOpen,
493-
[this.getActiveClassName()]: props.active || (isOpen && !isInlineMode),
507+
[this.getActiveClassName()]: props.active || (isOpen && !inline),
494508
[this.getDisabledClassName()]: props.disabled,
495509
[this.getSelectedClassName()]: this.isChildrenSelected(),
496510
});
@@ -526,9 +540,10 @@ export class SubMenu extends React.Component<SubMenuProps> {
526540
const style: React.CSSProperties = {};
527541

528542
const { direction } = props;
543+
const isRTL = direction === 'rtl';
529544

530-
if (isInlineMode) {
531-
if (direction === 'rtl') {
545+
if (inline) {
546+
if (isRTL) {
532547
style.paddingRight = props.inlineIndent * props.level;
533548
} else {
534549
style.paddingLeft = props.inlineIndent * props.level;
@@ -574,15 +589,17 @@ export class SubMenu extends React.Component<SubMenuProps> {
574589
</div>
575590
);
576591

577-
const children = this.renderChildren(props.children);
592+
const children = this.renderChildren();
578593

579594
const getPopupContainer = props.parentMenu?.isRootMenu
580595
? props.parentMenu.props.getPopupContainer
581596
: (triggerNode: HTMLElement) => triggerNode.parentNode;
582597
const popupPlacement = popupPlacementMap[props.mode];
583598
const popupAlign = props.popupOffset ? { offset: props.popupOffset } : {};
584-
let popupClassName = props.mode === 'inline' ? '' : props.popupClassName;
585-
popupClassName += direction === 'rtl' ? ` ${prefixCls}-rtl` : '';
599+
const popupClassName = classNames({
600+
[props.popupClassName]: props.popupClassName && !inline,
601+
[`${prefixCls}-rtl`]: isRTL,
602+
});
586603
const {
587604
disabled,
588605
triggerSubMenuAction,
@@ -591,15 +608,21 @@ export class SubMenu extends React.Component<SubMenuProps> {
591608
subMenuCloseDelay,
592609
builtinPlacements,
593610
} = props;
594-
menuAllProps.forEach(key => delete props[key]);
611+
menuAllProps.forEach((key) => delete props[key]);
595612
// Set onClick to null, to ignore propagated onClick event
596613
delete props.onClick;
597-
const placement =
598-
direction === 'rtl'
599-
? Object.assign({}, placementsRtl, builtinPlacements)
600-
: Object.assign({}, placements, builtinPlacements);
614+
const placement = isRTL
615+
? Object.assign({}, placementsRtl, builtinPlacements)
616+
: Object.assign({}, placements, builtinPlacements);
601617
delete props.direction;
602618

619+
// [Legacy] It's a fast fix,
620+
// but we should check if we can refactor this to make code more easy to understand
621+
const baseProps = this.getBaseProps();
622+
const mergedMotion = inline
623+
? null
624+
: this.getMotion(baseProps.mode, baseProps.visible);
625+
603626
return (
604627
<li
605628
{...(props as any)}
@@ -613,18 +636,19 @@ export class SubMenu extends React.Component<SubMenuProps> {
613636
getPopupContainer={getPopupContainer}
614637
builtinPlacements={placement}
615638
popupPlacement={popupPlacement}
616-
popupVisible={isInlineMode ? false : isOpen}
639+
popupVisible={inline ? false : isOpen}
617640
popupAlign={popupAlign}
618-
popup={isInlineMode ? null : children}
619-
action={(disabled || isInlineMode) ? [] : [triggerSubMenuAction]}
641+
popup={inline ? null : children}
642+
action={disabled || inline ? [] : [triggerSubMenuAction]}
620643
mouseEnterDelay={subMenuOpenDelay}
621644
mouseLeaveDelay={subMenuCloseDelay}
622645
onPopupVisibleChange={this.onPopupVisibleChange}
623646
forceRender={forceSubMenuRender}
647+
popupMotion={mergedMotion}
624648
>
625649
{title}
626650
</Trigger>
627-
{isInlineMode ? children : null}
651+
{inline ? children : null}
628652
</li>
629653
);
630654
}

0 commit comments

Comments
 (0)