Skip to content

Commit

Permalink
feat(Drawer): 限制抽屉可拖拽的最大最小尺寸 (#549)
Browse files Browse the repository at this point in the history
  • Loading branch information
1zumii committed Dec 14, 2023
1 parent 5de7603 commit c47de2d
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 80 deletions.
10 changes: 10 additions & 0 deletions components/drawer/const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import getPrefixCls from '../_util/getPrefixCls';

export const prefixCls = getPrefixCls('drawer');

export const COMPONENT_NAME = 'FDrawer';

/** 抽屉拖拽时,最小的尺寸 */
export const DRAWER_MIN_SIZE = 200;
/** 抽屉拖拽时,距离浏览器窗口边缘的最小距离 */
export const DRAWER_CLIENT_MAX_SPACE = 100;
84 changes: 9 additions & 75 deletions components/drawer/drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ import {
ref,
watch,
nextTick,
type PropType,
type Component,
type CSSProperties,
reactive,
} from 'vue';
import { isNumber } from 'lodash-es';
import getPrefixCls from '../_util/getPrefixCls';
import FButton from '../button';
import FScrollbar from '../scrollbar';
import { CloseOutlined } from '../icon';
Expand All @@ -21,81 +19,17 @@ import useLockScreen from '../_util/use/useLockScreen';
import { useConfig } from '../config-provider';
import { useTheme } from '../_theme/useTheme';
import { useResizable } from './useResizable';
import type { ExtractPublicPropTypes } from '../_util/interface';

const prefixCls = getPrefixCls('drawer');
const UPDATE_SHOW_EVENT = 'update:show';
const OK_EVENT = 'ok';
const CANCEL_EVENT = 'cancel';
const AFTER_LEAVE_EVENT = 'after-leave';

// 通用的属性
export const drawerProps = {
show: Boolean,
displayDirective: {
type: String as PropType<'show' | 'if'>,
default: 'show',
},
closable: {
type: Boolean,
default: true,
},
mask: {
type: Boolean,
default: true,
},
maskClosable: {
type: Boolean,
default: true,
},
title: String,
okText: {
type: String,
default: '确定',
},
okLoading: Boolean,
cancelText: {
type: String,
default: '取消',
},
showCancel: {
type: Boolean,
default: true,
},
width: {
type: [String, Number] as PropType<string | number>,
default: 520,
},
height: {
type: [String, Number] as PropType<string | number>,
default: 520,
},
footer: {
type: Boolean,
default: false,
},
footerBorder: {
type: Boolean,
default: false,
},
getContainer: {
type: Function,
},
placement: {
type: String as PropType<'top' | 'right' | 'bottom' | 'left'>,
default: 'right',
},
contentClass: String,
resizable: {
type: Boolean,
default: false,
},
} as const;

export type DrawerProps = ExtractPublicPropTypes<typeof drawerProps>;
import { COMPONENT_NAME, prefixCls } from './const';
import {
AFTER_LEAVE_EVENT,
CANCEL_EVENT,
OK_EVENT,
UPDATE_SHOW_EVENT,
drawerProps,
} from './props';

const Drawer = defineComponent({
name: 'FDrawer',
name: COMPONENT_NAME,
props: drawerProps,
emits: [UPDATE_SHOW_EVENT, OK_EVENT, CANCEL_EVENT, AFTER_LEAVE_EVENT],
setup(props, ctx) {
Expand Down
4 changes: 2 additions & 2 deletions components/drawer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { SFCWithInstall } from '../_util/interface';
type DrawerType = SFCWithInstall<typeof Drawer>;
export const FDrawer = withInstall<DrawerType>(Drawer as DrawerType);

export { drawerProps } from './drawer';
export type { DrawerProps } from './drawer';
export { drawerProps } from './props';
export type { DrawerProps } from './props';

export default FDrawer;
74 changes: 74 additions & 0 deletions components/drawer/props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { type PropType, type ComponentObjectPropsOptions } from 'vue';
import type { ExtractPublicPropTypes } from '../_util/interface';

export type DrawerPlacement = 'top' | 'right' | 'bottom' | 'left';

// 通用的属性
export const drawerProps = {
show: Boolean,
displayDirective: {
type: String as PropType<'show' | 'if'>,
default: 'show',
},
closable: {
type: Boolean,
default: true,
},
mask: {
type: Boolean,
default: true,
},
maskClosable: {
type: Boolean,
default: true,
},
title: String,
okText: {
type: String,
default: '确定',
},
okLoading: Boolean,
cancelText: {
type: String,
default: '取消',
},
showCancel: {
type: Boolean,
default: true,
},
width: {
type: [String, Number] as PropType<string | number>,
default: 520,
},
height: {
type: [String, Number] as PropType<string | number>,
default: 520,
},
footer: {
type: Boolean,
default: false,
},
footerBorder: {
type: Boolean,
default: false,
},
getContainer: {
type: Function,
},
placement: {
type: String as PropType<DrawerPlacement>,
default: 'right' satisfies DrawerPlacement,
},
contentClass: String,
resizable: {
type: Boolean,
default: false,
},
} as const satisfies ComponentObjectPropsOptions;

export type DrawerProps = ExtractPublicPropTypes<typeof drawerProps>;

export const UPDATE_SHOW_EVENT = 'update:show';
export const OK_EVENT = 'ok';
export const CANCEL_EVENT = 'cancel';
export const AFTER_LEAVE_EVENT = 'after-leave';
39 changes: 36 additions & 3 deletions components/drawer/useResizable.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
import { computed, onMounted, ref, type ComputedRef } from 'vue';
import { useEventListener } from '@vueuse/core';
import { type DrawerPlacement } from './props';
import { DRAWER_CLIENT_MAX_SPACE, DRAWER_MIN_SIZE } from './const';

// 获取抽屉拖拽时距离窗口边缘的距离
const getDrawerClientSpace = (
drawerSize: number,
placement: DrawerPlacement,
): number => {
switch (placement) {
case 'left':
case 'right':
return window.innerWidth - drawerSize;
case 'top':
case 'bottom':
return window.innerHeight - drawerSize;
}
};

export const useResizable = (config: {
propsKey: ComputedRef<'width' | 'height'>;
placement: ComputedRef<string>;
placement: ComputedRef<DrawerPlacement>;
drawerSize: {
width: string | number;
height: string | number;
Expand Down Expand Up @@ -68,14 +85,30 @@ export const useResizable = (config: {
(propsKey.value === 'width' ? event.clientX : event.clientY) -
start;

let nextSize: number;
// 根据 位置 偏移量正负加减
if (['left', 'top'].includes(placement.value)) {
// 鼠标移动时改变宽度或者高度
drawerSize[propsKey.value] = lastSizeValue + offset;
nextSize = lastSizeValue + offset;
} else {
// 鼠标移动时改变宽度或者高度
drawerSize[propsKey.value] = lastSizeValue - offset;
nextSize = lastSizeValue - offset;
}

// 限制抽屉最小、最大可拖拽尺寸
if (nextSize < DRAWER_MIN_SIZE) {
nextSize = DRAWER_MIN_SIZE;
} else if (
getDrawerClientSpace(nextSize, placement.value) <
DRAWER_CLIENT_MAX_SPACE
) {
nextSize =
(['left', 'right'].includes(placement.value)
? window.innerWidth
: window.innerHeight) - DRAWER_CLIENT_MAX_SPACE;
}

drawerSize[propsKey.value] = nextSize;
};

// 拖拽的dom 的位置和样式
Expand Down

0 comments on commit c47de2d

Please sign in to comment.