refactor: menu

feat-new-menu
tanjinzhou 2021-05-19 15:34:25 +08:00
parent a887ec5b8f
commit 9bb16977a9
14 changed files with 106 additions and 86 deletions

View File

@ -3,6 +3,7 @@ import {
CSSProperties,
defineComponent,
nextTick,
Ref,
Transition as T,
TransitionGroup as TG,
} from 'vue';
@ -91,17 +92,17 @@ export declare type MotionEvent = (TransitionEvent | AnimationEvent) & {
deadline?: boolean;
};
export declare type MotionEventHandler = (
element: Element,
done?: () => void,
) => CSSProperties | void;
export declare type MotionEventHandler = (element: Element, done?: () => void) => CSSProperties;
export declare type MotionEndEventHandler = (element: Element, done?: () => void) => boolean | void;
// ================== Collapse Motion ==================
const getCollapsedHeight: MotionEventHandler = () => ({ height: 0, opacity: 0 });
const getRealHeight: MotionEventHandler = node => ({ height: node.scrollHeight, opacity: 1 });
const getCurrentHeight: MotionEventHandler = (node: any) => ({ height: node.offsetHeight });
const getRealHeight: MotionEventHandler = node => ({
height: `${node.scrollHeight}px`,
opacity: 1,
});
const getCurrentHeight: MotionEventHandler = (node: any) => ({ height: `${node.offsetHeight}px` });
// const skipOpacityTransition: MotionEndEventHandler = (_, event) =>
// (event as TransitionEvent).propertyName === 'height';
@ -110,14 +111,38 @@ export interface CSSMotionProps extends Partial<BaseTransitionProps<Element>> {
css?: boolean;
}
const collapseMotion: CSSMotionProps = {
name: 'ant-motion-collapse',
appear: true,
// onAppearStart: getCollapsedHeight,
onBeforeEnter: getCollapsedHeight,
onEnter: getRealHeight,
onBeforeLeave: getCurrentHeight,
onLeave: getCollapsedHeight,
const collapseMotion = (style: Ref<CSSProperties>, className: Ref<string>): CSSMotionProps => {
return {
name: 'ant-motion-collapse',
appear: true,
css: true,
onBeforeEnter: node => {
className.value = 'ant-motion-collapse';
style.value = getCollapsedHeight(node);
},
onEnter: node => {
nextTick(() => {
style.value = getRealHeight(node);
});
},
onAfterEnter: () => {
className.value = '';
style.value = {};
},
onBeforeLeave: node => {
className.value = 'ant-motion-collapse';
style.value = getCurrentHeight(node);
},
onLeave: node => {
window.setTimeout(() => {
style.value = getCollapsedHeight(node);
});
},
onAfterLeave: () => {
className.value = '';
style.value = {};
},
};
};
export { Transition, TransitionGroup, collapseMotion };

View File

@ -1,4 +1,4 @@
import { computed, defineComponent, ref, watch } from '@vue/runtime-core';
import { computed, defineComponent, reactive, ref, watch } from '@vue/runtime-core';
import Transition from 'ant-design-vue/es/_util/transition';
import { useInjectMenu, MenuContextProvider } from './hooks/useMenuContext';
import { MenuMode } from './interface';
@ -31,12 +31,13 @@ export default defineComponent({
},
{ flush: 'post' },
);
const mergedMotion = computed(() => ({
...(motion.value || defaultMotions.value?.[fixedMode]),
appear: props.keyPath.length <= 1,
}));
const style = ref({});
const className = ref('');
const mergedMotion = computed(() => {
const m = motion.value || defaultMotions.value?.[fixedMode];
const res = typeof m === 'function' ? m(style, className) : m;
return { ...res, appear: props.keyPath.length <= 1 };
});
return () => {
if (destroy.value) {
return null;
@ -49,7 +50,12 @@ export default defineComponent({
}}
>
<Transition {...mergedMotion.value}>
<SubMenuList v-show={mergedOpen.value} id={props.id}>
<SubMenuList
v-show={mergedOpen.value}
id={props.id}
style={style.value}
class={className.value}
>
{slots.default?.()}
</SubMenuList>
</Transition>

View File

@ -88,7 +88,6 @@ export default defineComponent({
watch(
() => props.openKeys,
(openKeys = mergedOpenKeys.value) => {
console.log('mergedOpenKeys', openKeys);
mergedOpenKeys.value = openKeys;
},
{ immediate: true },

View File

@ -1,5 +1,14 @@
import { Key } from '../../../_util/type';
import { ComputedRef, defineComponent, inject, InjectionKey, provide, Ref, UnwrapRef } from 'vue';
import {
ComputedRef,
CSSProperties,
defineComponent,
inject,
InjectionKey,
provide,
Ref,
UnwrapRef,
} from 'vue';
import { BuiltinPlacements, MenuMode, MenuTheme, TriggerSubMenuAction } from '../interface';
import { CSSMotionProps } from '../../../_util/transition';
@ -48,7 +57,13 @@ export interface MenuContextProps {
// // Motion
motion?: ComputedRef<CSSMotionProps | null>;
defaultMotions?: ComputedRef<Partial<{ [key in MenuMode | 'other']: CSSMotionProps }> | null>;
defaultMotions?: ComputedRef<Partial<
{
[key in MenuMode | 'other']:
| CSSMotionProps
| ((style: Ref<CSSProperties>, className: Ref<string>) => CSSMotionProps);
}
> | null>;
// // Popup
subMenuOpenDelay: ComputedRef<number>;

View File

@ -239,7 +239,6 @@ a {
&[disabled] {
color: @disabled-color;
cursor: not-allowed;
pointer-events: none;
}
}

View File

@ -3,7 +3,6 @@
@import 'motion/move';
@import 'motion/other';
@import 'motion/slide';
@import 'motion/swing';
@import 'motion/zoom';
// For common/openAnimation

View File

@ -1,11 +1,12 @@
.fade-motion(@className, @keyframeName) {
.make-motion(@className, @keyframeName);
.@{className}-enter,
.@{className}-appear {
@name: ~'@{ant-prefix}-@{className}';
.make-motion(@name, @keyframeName);
.@{name}-enter,
.@{name}-appear {
opacity: 0;
animation-timing-function: linear;
}
.@{className}-leave {
.@{name}-leave {
animation-timing-function: linear;
}
}

View File

@ -1,11 +1,12 @@
.move-motion(@className, @keyframeName) {
.make-motion(@className, @keyframeName);
.@{className}-enter,
.@{className}-appear {
@name: ~'@{ant-prefix}-@{className}';
.make-motion(@name, @keyframeName);
.@{name}-enter,
.@{name}-appear {
opacity: 0;
animation-timing-function: @ease-out-circ;
}
.@{className}-leave {
.@{name}-leave {
animation-timing-function: @ease-in-circ;
}
}

View File

@ -4,17 +4,23 @@
}
}
[ant-click-animating='true'],
[ant-click-animating-without-extra-node='true'] {
@click-animating-true: ~"[@{ant-prefix}-click-animating='true']";
@click-animating-with-extra-node-true: ~"[@{ant-prefix}-click-animating-without-extra-node='true']";
@{click-animating-true},
@{click-animating-with-extra-node-true} {
position: relative;
}
html {
--antd-wave-shadow-color: @primary-color;
--scroll-bar: 0;
}
[ant-click-animating-without-extra-node='true']::after,
.ant-click-animating-node {
@click-animating-with-extra-node-true-after: ~'@{click-animating-with-extra-node-true}::after';
@{click-animating-with-extra-node-true-after},
.@{ant-prefix}-click-animating-node {
position: absolute;
top: 0;
right: 0;

View File

@ -1,11 +1,12 @@
.slide-motion(@className, @keyframeName) {
.make-motion(@className, @keyframeName);
.@{className}-enter,
.@{className}-appear {
@name: ~'@{ant-prefix}-@{className}';
.make-motion(@name, @keyframeName);
.@{name}-enter,
.@{name}-appear {
opacity: 0;
animation-timing-function: @ease-out-quint;
}
.@{className}-leave {
.@{name}-leave {
animation-timing-function: @ease-in-quint;
}
}

View File

@ -1,34 +0,0 @@
.swing-motion(@className, @keyframeName) {
.@{className}-enter,
.@{className}-appear {
.motion-common();
animation-play-state: paused;
}
.@{className}-enter.@{className}-enter-active,
.@{className}-appear.@{className}-appear-active {
animation-name: ~'@{keyframeName}In';
animation-play-state: running;
}
}
.swing-motion(swing, antSwing);
@keyframes antSwingIn {
0%,
100% {
transform: translateX(0);
}
20% {
transform: translateX(-10px);
}
40% {
transform: translateX(10px);
}
60% {
transform: translateX(-5px);
}
80% {
transform: translateX(5px);
}
}

View File

@ -1,15 +1,17 @@
.zoom-motion(@className, @keyframeName, @duration: @animation-duration-base) {
.make-motion(@className, @keyframeName, @duration);
.@{className}-enter,
.@{className}-appear {
@name: ~'@{ant-prefix}-@{className}';
.make-motion(@name, @keyframeName, @duration);
.@{name}-enter,
.@{name}-appear {
transform: scale(0); // need this by yiminghe
opacity: 0;
animation-timing-function: @ease-out-circ;
&-prepare {
transform: none;
}
}
.@{className}-leave {
.@{name}-leave {
animation-timing-function: @ease-in-out-circ;
}
}
@ -54,7 +56,7 @@
opacity: 0;
}
5% {
transform: scale(0.2);
transform: scale(0.8);
opacity: 0;
}
100% {

View File

@ -67,15 +67,15 @@ export default defineComponent({
const selectedKeys = ref<string[]>(['1']);
const openKeys = ref<string[]>(['sub1']);
const handleClick = (e: Event) => {
console.log('click', e);
// console.log('click', e);
};
const titleClick = (e: Event) => {
console.log('titleClick', e);
// console.log('titleClick', e);
};
watch(
() => openKeys,
val => {
console.log('openKeys', val);
// console.log('openKeys', val);
},
);
return {

2
v2-doc

@ -1 +1 @@
Subproject commit d197053285b81e77718621c0b5b94cb3b21831a2
Subproject commit a7013ae87f69dcbcf547f4b023255b8a7a775557