define some interfaces
This commit is contained in:
parent
528b02d172
commit
9ff2fc7d3e
|
@ -1,7 +1,10 @@
|
|||
import type { App } from 'vue';
|
||||
import FButton from './src/button.component';
|
||||
import FButtonGroup from './src/button-group.component';
|
||||
|
||||
export * from './src/button.props';
|
||||
export * from './src/button-group.props';
|
||||
|
||||
|
||||
export { FButton };
|
||||
|
||||
|
|
|
@ -1,28 +1,37 @@
|
|||
// import { defineComponent, computed } from 'vue';
|
||||
// import type { SetupContext } from 'vue';
|
||||
// import { buttonGroupProps, ButtonGroupProps } from './button.props';
|
||||
// import { useButtonGroup } from './composition/use-button-group';
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import type { SetupContext } from 'vue';
|
||||
import { buttonGroupProps, ButtonGroupProps } from './button-group.props';
|
||||
import { useButtonGroup } from './composition/use-button-group';
|
||||
|
||||
// export default defineComponent({
|
||||
// name: 'FButtonGroup',
|
||||
// props: buttonGroupProps,
|
||||
// emits: ['click'],
|
||||
// setup(props: ButtonGroupProps, context: SetupContext) {
|
||||
// // const { onClickButton } = useButtonGroup(props, context);
|
||||
// // const fButtonSize = computed(() => ({
|
||||
// // 'btn-lg': props.size === 'large',
|
||||
// // 'btn-sm': props.size === 'small',
|
||||
// // }));
|
||||
// // const fButtonType = computed(() => ({
|
||||
// // 'btn-primary': props.buttonType === 'primary',
|
||||
// // 'btn-warning': props.buttonType === 'warning',
|
||||
// // 'btn-danger': props.buttonType === 'danger',
|
||||
// // 'btn-success': props.buttonType === 'success',
|
||||
// // 'btn-link': props.buttonType === 'link',
|
||||
// // 'btn-secondary': props.buttonType === 'secondary',
|
||||
// // }));
|
||||
export default defineComponent({
|
||||
name: 'FButtonGroup',
|
||||
props: buttonGroupProps,
|
||||
emits: ['click', 'changeState', 'change', 'clickMenuOut'],
|
||||
setup(props: ButtonGroupProps, context: SetupContext) {
|
||||
// const { onClickButton } = useButtonGroup(props, context);
|
||||
const fButtonGroupSize = computed(() => ({
|
||||
'btn-group-lg': props.size === 'large',
|
||||
'btn-group-sm': props.size === 'small'
|
||||
}));
|
||||
// 样式:
|
||||
// 'btn '+
|
||||
// (btn.type?'btn-'+ btn.type:'btn-link')+
|
||||
// ' '+
|
||||
// (btn.type && btn.type !== 'link' ? 'f-btn-ml' :'')
|
||||
|
||||
// return () => (
|
||||
// );
|
||||
// },
|
||||
// });
|
||||
// btn btn-btn.type f-btn-ml
|
||||
// btn btn-link
|
||||
|
||||
// const fButtonType = computed(() => ({
|
||||
// 'btn-primary': props.buttonType === 'primary',
|
||||
// 'btn-warning': props.buttonType === 'warning',
|
||||
// 'btn-danger': props.buttonType === 'danger',
|
||||
// 'btn-success': props.buttonType === 'success',
|
||||
// 'btn-link': props.buttonType === 'link',
|
||||
// 'btn-secondary': props.buttonType === 'secondary',
|
||||
// }));
|
||||
const theFlatButtons = useButtonGroup(props, context);
|
||||
|
||||
return () => '';
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,26 +1,63 @@
|
|||
// import { ExtractPropTypes, PropType } from 'vue';
|
||||
import { ExtractPropTypes, PropType } from 'vue';
|
||||
|
||||
// type ButtonType = 'primary' | 'warning' | 'danger' | 'success' | 'link' | 'secondary';
|
||||
// type SizeType = 'small' | 'large';
|
||||
// eslint-disable-next-line max-len
|
||||
type PlacementDirection = 'top' | 'top-left' | 'top-right' | 'left' | 'left-top' | 'left-bottom' | 'bottom' | 'bottom-left' | 'bottom-right' | 'right' | 'right-top' | 'right-bottom';
|
||||
|
||||
// export const buttonProps = {
|
||||
// /**
|
||||
// * 组件标识
|
||||
// */
|
||||
// id: String,
|
||||
// /**
|
||||
// * 设置按钮类型
|
||||
// */
|
||||
// buttonType: { type: String as PropType<ButtonType>, default: 'primary' },
|
||||
// /**
|
||||
// * 是否禁用
|
||||
// */
|
||||
// disable: { type: Boolean, default: false },
|
||||
// /**
|
||||
// * 按钮尺寸
|
||||
// */
|
||||
// size: { type: String as PropType<SizeType>, default: 'small' },
|
||||
// // 待确定:text参数
|
||||
// };
|
||||
export const buttonGroupProps = {
|
||||
/**
|
||||
* 组件标识
|
||||
*/
|
||||
id: String,
|
||||
/**
|
||||
* 横向纠正的参照
|
||||
*/
|
||||
rectifyReferenceH: { type: HTMLElement, default: 'referenceEl' },
|
||||
/**
|
||||
* 纵向纠正的参照
|
||||
*/
|
||||
rectifyReferenceV: { type: HTMLElement, default: 'referenceEl' },
|
||||
/**
|
||||
* 是否自动纠正位置
|
||||
*/
|
||||
autoRectify: { type: Boolean, default: 'true' },
|
||||
/**
|
||||
* 计算方向的真正placement
|
||||
*/
|
||||
realPlacement: { type: String, default: 'bottom-right' },
|
||||
/**
|
||||
* 重新计算后的placement
|
||||
*/
|
||||
rectifyPlacement: { type: String, default: 'bottom-right' },
|
||||
/**
|
||||
* 按钮信息
|
||||
*/
|
||||
data: { type: Array },
|
||||
/**
|
||||
* 显示的按钮数量 默认为2
|
||||
*/
|
||||
count: { type: Number, default: 2 },
|
||||
/**
|
||||
* 按钮大小
|
||||
*/
|
||||
size: { type: String, default: 'small' },
|
||||
/**
|
||||
* 按钮样式
|
||||
*/
|
||||
type: { type: String, default: 'primary' },
|
||||
/**
|
||||
* 按钮展示位置
|
||||
*/
|
||||
placement: { type: String, default: 'bottom' }, /**
|
||||
/**
|
||||
* 下拉面板显示
|
||||
*/
|
||||
showPanel: { type: Boolean, default: false },
|
||||
/**
|
||||
* 下拉面板显示标志
|
||||
*/
|
||||
dpFlag: { type: Boolean, default: false },
|
||||
|
||||
// export type ButtonProps = ExtractPropTypes<typeof buttonProps>;
|
||||
};
|
||||
export default buttonGroupProps;
|
||||
|
||||
export type ButtonGroupProps = ExtractPropTypes<typeof buttonGroupProps>;
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// import { ComputedRef } from 'vue';
|
||||
import { ComputedRef } from 'vue';
|
||||
|
||||
// export interface UseButton {
|
||||
// /**
|
||||
// * 附加按钮的Class
|
||||
// */
|
||||
// // buttonClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||
// /**
|
||||
// * 点击附加按钮事件响应函数
|
||||
// */
|
||||
// onClickButton: ($event: Event) => void;
|
||||
export interface UseButtonGroup {
|
||||
/**
|
||||
* 附加按钮的Class
|
||||
*/
|
||||
// buttonClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||
/**
|
||||
* 点击附加按钮事件响应函数
|
||||
*/
|
||||
clickEvent: ($event: Event) => void;
|
||||
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1,24 +1,329 @@
|
|||
// import { UseButton } from './types';
|
||||
// import { ButtonProps } from '../button.props';
|
||||
// import { computed, SetupContext } from 'vue';
|
||||
import { UseButtonGroup } from './types-group';
|
||||
import { ButtonGroupProps } from '../button-group.props';
|
||||
import { computed, SetupContext } from 'vue';
|
||||
|
||||
// export function useButton(props: ButtonProps, context: SetupContext): UseButton {
|
||||
export function useButtonGroup(props: ButtonGroupProps, context: SetupContext): UseButtonGroup {
|
||||
// ngAfterViewChecked() {
|
||||
// if (this.show) {
|
||||
// this.setPosition(this.event)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // const buttonClass = computed(() => ({
|
||||
// // // 'input-group-append': true,
|
||||
// // // 'append-force-show': props.showButtonWhenDisabled && (props.readonly || props.disable),
|
||||
// // }));
|
||||
// function onClickButton($event: Event) {
|
||||
// $event.stopPropagation();
|
||||
// // this.disabled
|
||||
// if (props.disable) {
|
||||
// context.emit('clickButton', $event);
|
||||
// }
|
||||
// }
|
||||
|
||||
// function onClickButton($event: Event) {
|
||||
// $event.stopPropagation();
|
||||
// // this.disabled
|
||||
// if (props.disable) {
|
||||
// context.emit('clickButton', $event);
|
||||
// }
|
||||
// }
|
||||
function clickEvent($event: Event) {
|
||||
$event.stopPropagation();
|
||||
props.showPanel = !props.showPanel;
|
||||
// body添加面板
|
||||
if (props.showPanel) {
|
||||
this.appendBody();
|
||||
this.event = $event;
|
||||
// 绑定相应的事件
|
||||
this.ngZone.runOutsideAngular(() => {
|
||||
this.bindMenuMouseenter();
|
||||
this.bindiMenuMouseleave();
|
||||
this.mouseNotEnterLeave();
|
||||
});
|
||||
}
|
||||
// 面板显示 脏值检测
|
||||
this.changeRef.detectChanges();
|
||||
this.changeRef.markForCheck();
|
||||
context.emit('changeState', props.showPanel);
|
||||
}
|
||||
|
||||
// return {
|
||||
// // buttonClass,
|
||||
// onClickButton
|
||||
// };
|
||||
// }
|
||||
/* 按钮触发事件 */
|
||||
function toggle($event: any, btn) {
|
||||
$event.stopPropagation();
|
||||
if (btn.disabled) return;
|
||||
props.showPanel = false;
|
||||
// 关闭下拉按钮面板 脏值检测
|
||||
this.changeRef.detectChanges();
|
||||
this.changeRef.markForCheck();
|
||||
context.emit('change', btn.id);
|
||||
context.emit('click', btn);
|
||||
}
|
||||
|
||||
/* 显示出来的按钮组 */
|
||||
function flatButtons() {
|
||||
return props.data && props.data.slice(0, this.count);
|
||||
}
|
||||
|
||||
function dpButtons() {
|
||||
return props.data && props.data.slice(this.count);
|
||||
}
|
||||
|
||||
// 下拉按钮显示到body中 可改变面板方向
|
||||
function appendBody() {
|
||||
if (this.dpMenu.nativeElement) {
|
||||
// 添加到body 便于全部显示
|
||||
document.body.appendChild(this.dpMenu.nativeElement);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当下拉超出边界时 转换方向,
|
||||
* 并未处理,边界不够下拉展示的情况
|
||||
* @param btnSize
|
||||
*/
|
||||
function changePlacement(btnSize: any) {
|
||||
if (!props.autoRectify) {
|
||||
return;
|
||||
}
|
||||
const referPosition = this.getReferencePosition();
|
||||
let newPlacement = props.realPlacement;
|
||||
if (newPlacement.indexOf('bottom') > -1) {
|
||||
if (this._menuHeight > referPosition.bottom - btnSize.bottom) {
|
||||
newPlacement = newPlacement.replace('bottom', 'top');
|
||||
}
|
||||
} else if (newPlacement.indexOf('top') > -1) {
|
||||
if (this._menuHeight > btnSize.top - referPosition.top) {
|
||||
newPlacement = newPlacement.replace('top', 'bottom');
|
||||
}
|
||||
}
|
||||
if (newPlacement.indexOf('left') > -1) {
|
||||
if (this._menuWidth > btnSize.left - referPosition.left) {
|
||||
newPlacement = newPlacement.replace('left', 'right');
|
||||
}
|
||||
} else if (newPlacement.indexOf('right') > -1) {
|
||||
if (this._menuWidth > referPosition.right - btnSize.right) {
|
||||
newPlacement = newPlacement.replace('right', 'left');
|
||||
}
|
||||
}
|
||||
this.rectifyPlacement = newPlacement;
|
||||
}
|
||||
/**
|
||||
* 确认参照的边界
|
||||
*/
|
||||
function getReferencePosition() {
|
||||
let rRight = document.documentElement.clientWidth;
|
||||
let rBottom = document.documentElement.clientHeight;
|
||||
let rTop = 0;
|
||||
let rLeft = 0;
|
||||
// 横向参照
|
||||
if (props.rectifyReferenceH) {
|
||||
rRight = props.rectifyReferenceH.getBoundingClientRect().right;
|
||||
rLeft = props.rectifyReferenceH.getBoundingClientRect().left;
|
||||
}
|
||||
// 纵向参照
|
||||
if (props.rectifyReferenceV) {
|
||||
rBottom = props.rectifyReferenceV.getBoundingClientRect().bottom;
|
||||
rTop = props.rectifyReferenceV.getBoundingClientRect().top;
|
||||
}
|
||||
return { top: rTop, left: rLeft, right: rRight, bottom: rBottom };
|
||||
}
|
||||
/**
|
||||
* 变化对应的class
|
||||
* @param position
|
||||
*/
|
||||
function _getClsName(position) {
|
||||
let className = '';
|
||||
switch (position) {
|
||||
case 'top-right':
|
||||
case 'top':
|
||||
// 朝上,朝上-朝右
|
||||
className = 'dropup';
|
||||
break;
|
||||
case 'top-left':
|
||||
// 朝上-朝左
|
||||
className = 'dropup-left';
|
||||
break;
|
||||
case 'left-bottom':
|
||||
case 'left':
|
||||
// 横向——朝左——朝下
|
||||
className = 'dropleft';
|
||||
break;
|
||||
case 'left-top':
|
||||
// 横向——朝左——朝上
|
||||
className = 'dropleft-up';
|
||||
break;
|
||||
case 'right-bottom':
|
||||
case 'right':
|
||||
// 横向——朝右——朝下
|
||||
className = 'dropright';
|
||||
break;
|
||||
case 'right-top':
|
||||
// 横向——朝右——朝上
|
||||
className = 'dropright-up';
|
||||
break;
|
||||
case 'bottom-left':
|
||||
// 朝下——朝左
|
||||
className = 'dropdown-left';
|
||||
break;
|
||||
case 'bottom-right':
|
||||
className = 'dropdown';
|
||||
break;
|
||||
default:
|
||||
// 朝下,朝下——朝右
|
||||
className = 'dropdown';
|
||||
}
|
||||
return className;
|
||||
}
|
||||
|
||||
function getRealPlacement(pment) {
|
||||
let result = 'bottom-right';
|
||||
switch (pment) {
|
||||
case 'top':
|
||||
result = 'top-right';
|
||||
break;
|
||||
case 'left':
|
||||
result = 'left-bottom';
|
||||
break;
|
||||
case 'right':
|
||||
result = 'right-bottom';
|
||||
break;
|
||||
case 'bottom':
|
||||
result = 'bottom-right';
|
||||
break;
|
||||
default:
|
||||
result = pment;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* 计算的位置区分忒细化
|
||||
*/
|
||||
function changePosition(btnSize: any) {
|
||||
let rplacement = '';
|
||||
if (props.autoRectify) {
|
||||
rplacement = this.rectifyPlacement;
|
||||
} else {
|
||||
rplacement = props.realPlacement;
|
||||
}
|
||||
let styleTop = 0;
|
||||
let styleLeft = 0;
|
||||
if (rplacement.indexOf('top') > -1) {
|
||||
styleTop = btnSize.top - this._menuHeight;
|
||||
} else if (rplacement.indexOf('bottom') > -1) {
|
||||
styleTop = btnSize.bottom;
|
||||
}
|
||||
if (rplacement.indexOf('right') > -1) {
|
||||
styleLeft = btnSize.right;
|
||||
} else if (rplacement.indexOf('left') > -1) {
|
||||
styleLeft = btnSize.left - this._menuWidth;
|
||||
}
|
||||
// 开头
|
||||
if (rplacement.indexOf('-top') > -1) {
|
||||
styleTop -= btnSize.height;
|
||||
} else if (rplacement.indexOf('-bottom') > -1) {
|
||||
styleTop += btnSize.height;
|
||||
}
|
||||
this.dpMenu.nativeElement.style.top = styleTop + 'px';
|
||||
this.dpMenu.nativeElement.style.left = styleLeft + 'px';
|
||||
}
|
||||
|
||||
/* 绑定下拉面板鼠标进入事件 */
|
||||
function bindMenuMouseenter() {
|
||||
this.mouseenterEvent = this.changeFlagToTrue.bind(this);
|
||||
this.dpMenu.nativeElement.addEventListener('mouseenter', this.mouseenterEvent);
|
||||
}
|
||||
|
||||
/* 绑定下拉面板鼠标离开事件 */
|
||||
function bindiMenuMouseleave() {
|
||||
this.mouseleaveEvent = this.mouseLeave.bind(this);
|
||||
this.dpMenu.nativeElement.addEventListener('mouseleave', this.mouseleaveEvent);
|
||||
}
|
||||
|
||||
/* 绑定点击面板区域之外触发的事件 */
|
||||
// bindDocClick() {
|
||||
// this.documentClickEvent = this.clickDoc.bind(this);
|
||||
// document.addEventListener('click', this.documentClickEvent);
|
||||
// }
|
||||
|
||||
/* 解绑事件 */
|
||||
function unbindMenuMouseenter() {
|
||||
if (this.mouseenterEvent) {
|
||||
this.dpMenu.nativeElement.removeEventListener('mouseenter', this.mouseenterEvent);
|
||||
}
|
||||
}
|
||||
function unbindiMenuMouseleave() {
|
||||
if (this.mouseleaveEvent) {
|
||||
this.dpMenu.nativeElement.removeEventListener('mouseleave', this.mouseleaveEvent);
|
||||
}
|
||||
}
|
||||
// unbindDocClick() {
|
||||
// if (this.documentClickEvent) {
|
||||
// document.removeEventListener('click', this.documentClickEvent);
|
||||
// }
|
||||
// }
|
||||
|
||||
/* flag true */
|
||||
function changeFlagToTrue() {
|
||||
props.dpFlag = true;
|
||||
}
|
||||
|
||||
/* flag false */
|
||||
function changeFlagToFalse() {
|
||||
props.dpFlag = false;
|
||||
}
|
||||
|
||||
/* 鼠标离开时 关闭menu */
|
||||
function mouseLeave() {
|
||||
if (props.dpFlag) {
|
||||
this.changeFlagToFalse();
|
||||
// this.unbindDocClick();
|
||||
this.unbindiMenuMouseleave();
|
||||
this.unbindMenuMouseenter();
|
||||
this.close();
|
||||
if (this.setTimeObj) {
|
||||
this.ngZone.runOutsideAngular(() => {
|
||||
clearTimeout(this.setTimeObj);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 鼠标没有进入到面板 一段时间后面板自动消失 */
|
||||
function mouseNotEnterLeave() {
|
||||
this.ngZone.runOutsideAngular(() => {
|
||||
this.setTimeObj = setTimeout(() => {
|
||||
if (!props.dpFlag) {
|
||||
this.changeFlagToFalse();
|
||||
// this.unbindDocClick();
|
||||
this.unbindiMenuMouseleave();
|
||||
this.unbindMenuMouseenter();
|
||||
this.close();
|
||||
if (this.setTimeObj) {
|
||||
clearTimeout(this.setTimeObj);
|
||||
}
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
/* 关闭下拉面板 */
|
||||
function close() {
|
||||
props.showPanel = false;
|
||||
// 关闭下拉按钮面板 脏值检测
|
||||
if (!this.changeRef.destroyed) {
|
||||
this.changeRef.detectChanges();
|
||||
this.changeRef.markForCheck();
|
||||
}
|
||||
this.dpBtn.nativeElement.blur();
|
||||
}
|
||||
|
||||
/* 动态指定menu在body中的位置 */
|
||||
function setPosition(e) {
|
||||
// 下拉按钮
|
||||
const btnSize = this.dpBtn.nativeElement.getBoundingClientRect();
|
||||
// 下拉面板
|
||||
const menuRect = this.dpMenu.nativeElement.getBoundingClientRect();
|
||||
this._menuHeight = menuRect.height;
|
||||
this._menuWidth = menuRect.width;
|
||||
// 如果要自动纠正方向
|
||||
if (props.autoRectify) {
|
||||
this.changePlacement(btnSize);
|
||||
}
|
||||
this.changePosition(btnSize);
|
||||
}
|
||||
|
||||
return {
|
||||
clickEvent
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue