2024-08-02 18:19:39 +08:00

209 lines
6.7 KiB
JavaScript

import { computed, defineComponent, h, inject, ref, toRef, withDirectives } from 'vue';
import { useMergedState } from 'vooks';
import { mousemoveoutside } from 'vdirs';
import { floatButtonGroupInjectionKey } from "../../float-button-group/src/FloatButtonGroup.mjs";
import { call, formatLength, resolveSlot, resolveWrappedSlot } from "../../_utils/index.mjs";
import useConfig from "../../_mixins/use-config.mjs";
import { useTheme, useThemeClass } from "../../_mixins/index.mjs";
import { floatButtonLight } from "../styles/index.mjs";
import { NBaseIcon } from "../../_internal/index.mjs";
import { CloseIcon } from "../../_internal/icons/index.mjs";
import style from "./styles/index.cssr.mjs";
export const floatButtonProps = Object.assign(Object.assign({}, useTheme.props), {
width: {
type: [Number, String],
default: 40
},
height: {
type: [Number, String],
default: 40
},
left: [Number, String],
right: [Number, String],
top: [Number, String],
bottom: [Number, String],
shape: {
type: String,
default: 'circle'
},
position: {
type: String,
default: 'fixed'
},
type: {
type: String,
default: 'default'
},
menuTrigger: String,
showMenu: {
type: Boolean,
default: undefined
},
onUpdateShowMenu: {
type: [Function, Array],
default: undefined
},
'onUpdate:showMenu': {
type: [Function, Array],
default: undefined
}
});
export default defineComponent({
name: 'FloatButton',
props: floatButtonProps,
setup(props) {
const {
mergedClsPrefixRef,
inlineThemeDisabled
} = useConfig(props);
const themeRef = useTheme('FloatButton', '-float-button', style, floatButtonLight, props, mergedClsPrefixRef);
const floatButtonGroupInjection = inject(floatButtonGroupInjectionKey, null);
const uncontrolledShowMenuRef = ref(false);
const controlledShoeMenuRef = toRef(props, 'showMenu');
const mergedShowMenuRef = useMergedState(controlledShoeMenuRef, uncontrolledShowMenuRef);
function doUpdateShowMenu(value) {
const {
onUpdateShowMenu,
'onUpdate:showMenu': _onUpdateShowMenu
} = props;
uncontrolledShowMenuRef.value = value;
if (onUpdateShowMenu) {
call(onUpdateShowMenu, value);
}
if (_onUpdateShowMenu) {
call(_onUpdateShowMenu, value);
}
}
const cssVarsRef = computed(() => {
const {
self: {
color,
textColor,
boxShadow,
boxShadowHover,
boxShadowPressed,
colorHover,
colorPrimary,
colorPrimaryHover,
textColorPrimary,
borderRadiusSquare,
colorPressed,
colorPrimaryPressed
},
common: {
cubicBezierEaseInOut
}
} = themeRef.value;
const {
type
} = props;
return {
'--n-bezier': cubicBezierEaseInOut,
'--n-box-shadow': boxShadow,
'--n-box-shadow-hover': boxShadowHover,
'--n-box-shadow-pressed': boxShadowPressed,
'--n-color': type === 'primary' ? colorPrimary : color,
'--n-text-color': type === 'primary' ? textColorPrimary : textColor,
'--n-color-hover': type === 'primary' ? colorPrimaryHover : colorHover,
'--n-color-pressed': type === 'primary' ? colorPrimaryPressed : colorPressed,
'--n-border-radius-square': borderRadiusSquare
};
});
const inlineStyle = computed(() => {
const {
width,
height
} = props;
return Object.assign({
position: floatButtonGroupInjection ? undefined : props.position,
width: formatLength(width),
minHeight: formatLength(height)
}, floatButtonGroupInjection ? null : {
left: formatLength(props.left),
right: formatLength(props.right),
top: formatLength(props.top),
bottom: formatLength(props.bottom)
});
});
const mergedShapeRef = computed(() => {
return floatButtonGroupInjection ? floatButtonGroupInjection.shapeRef.value : props.shape;
});
const Mouseenter = () => {
if (props.menuTrigger === 'hover') {
doUpdateShowMenu(true);
}
};
const handleMouseleave = () => {
if (props.menuTrigger === 'hover' && mergedShowMenuRef.value) {
doUpdateShowMenu(false);
}
};
const handleClick = () => {
if (props.menuTrigger === 'click') {
doUpdateShowMenu(!mergedShowMenuRef.value);
}
};
const themeClassHandle = inlineThemeDisabled ? useThemeClass('float-button', computed(() => props.type[0]), cssVarsRef, props) : undefined;
return {
inlineStyle,
cssVars: inlineThemeDisabled ? undefined : cssVarsRef,
mergedClsPrefix: mergedClsPrefixRef,
mergedShape: mergedShapeRef,
mergedShowMenu: mergedShowMenuRef,
themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender,
Mouseenter,
handleMouseleave,
handleClick
};
},
render() {
var _a;
const {
mergedClsPrefix,
cssVars,
mergedShape,
type,
menuTrigger,
mergedShowMenu,
themeClass,
$slots,
inlineStyle,
onRender
} = this;
const dirs = [[mousemoveoutside, this.handleMouseleave]];
onRender === null || onRender === void 0 ? void 0 : onRender();
return withDirectives(h("div", {
class: [`${mergedClsPrefix}-float-button`, `${mergedClsPrefix}-float-button--${mergedShape}-shape`, `${mergedClsPrefix}-float-button--${type}-type`, mergedShowMenu && `${mergedClsPrefix}-float-button--show-menu`, themeClass],
style: [cssVars, inlineStyle],
onMouseenter: this.Mouseenter,
onMouseleave: this.handleMouseleave,
onClick: this.handleClick,
role: "button"
}, h("div", {
class: `${mergedClsPrefix}-float-button__fill`,
"aria-hidden": true
}), h("div", {
class: `${mergedClsPrefix}-float-button__body`
}, (_a = $slots.default) === null || _a === void 0 ? void 0 : _a.call($slots), resolveWrappedSlot($slots.description, children => {
if (children) {
return h("div", {
class: `${mergedClsPrefix}-float-button__description`
}, children);
}
return null;
})), menuTrigger ? h("div", {
class: `${mergedClsPrefix}-float-button__close`
}, h(NBaseIcon, {
clsPrefix: mergedClsPrefix
}, {
default: () => h(CloseIcon, null)
})) : null, menuTrigger ? h("div", {
onClick: e => {
e.stopPropagation();
},
"data-float-button-menu": true,
class: `${mergedClsPrefix}-float-button__menu`
}, resolveSlot($slots.menu, () => [])) : null), dirs);
}
});