refactor: menu
parent
a887ec5b8f
commit
9bb16977a9
|
@ -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 };
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -88,7 +88,6 @@ export default defineComponent({
|
|||
watch(
|
||||
() => props.openKeys,
|
||||
(openKeys = mergedOpenKeys.value) => {
|
||||
console.log('mergedOpenKeys', openKeys);
|
||||
mergedOpenKeys.value = openKeys;
|
||||
},
|
||||
{ immediate: true },
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -239,7 +239,6 @@ a {
|
|||
&[disabled] {
|
||||
color: @disabled-color;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
@import 'motion/move';
|
||||
@import 'motion/other';
|
||||
@import 'motion/slide';
|
||||
@import 'motion/swing';
|
||||
@import 'motion/zoom';
|
||||
|
||||
// For common/openAnimation
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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% {
|
||||
|
|
|
@ -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
2
v2-doc
|
@ -1 +1 @@
|
|||
Subproject commit d197053285b81e77718621c0b5b94cb3b21831a2
|
||||
Subproject commit a7013ae87f69dcbcf547f4b023255b8a7a775557
|
Loading…
Reference in New Issue