209 lines
6.7 KiB
JavaScript
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);
|
|
}
|
|
}); |