508 lines
19 KiB
JavaScript
508 lines
19 KiB
JavaScript
|
|
import { changeColor } from 'seemly';
|
||
|
|
import { useMemo } from 'vooks';
|
||
|
|
import { computed, defineComponent, h, inject, ref, watchEffect } from 'vue';
|
||
|
|
import { NBaseLoading, NBaseWave, NFadeInExpandTransition, NIconSwitchTransition } from "../../_internal/index.mjs";
|
||
|
|
import { useConfig, useFormItem, useTheme, useThemeClass } from "../../_mixins/index.mjs";
|
||
|
|
import { useRtl } from "../../_mixins/use-rtl.mjs";
|
||
|
|
import { call, color2Class, createKey, isSlotEmpty, resolveWrappedSlot, warnOnce } from "../../_utils/index.mjs";
|
||
|
|
import { createHoverColor, createPressedColor } from "../../_utils/color/index.mjs";
|
||
|
|
import { isSafari } from "../../_utils/env/browser.mjs";
|
||
|
|
import { buttonGroupInjectionKey } from "../../button-group/src/context.mjs";
|
||
|
|
import { buttonLight } from "../styles/index.mjs";
|
||
|
|
import style from "./styles/index.cssr.mjs";
|
||
|
|
export const buttonProps = Object.assign(Object.assign({}, useTheme.props), {
|
||
|
|
color: String,
|
||
|
|
textColor: String,
|
||
|
|
text: Boolean,
|
||
|
|
block: Boolean,
|
||
|
|
loading: Boolean,
|
||
|
|
disabled: Boolean,
|
||
|
|
circle: Boolean,
|
||
|
|
size: String,
|
||
|
|
ghost: Boolean,
|
||
|
|
round: Boolean,
|
||
|
|
secondary: Boolean,
|
||
|
|
tertiary: Boolean,
|
||
|
|
quaternary: Boolean,
|
||
|
|
strong: Boolean,
|
||
|
|
focusable: {
|
||
|
|
type: Boolean,
|
||
|
|
default: true
|
||
|
|
},
|
||
|
|
keyboard: {
|
||
|
|
type: Boolean,
|
||
|
|
default: true
|
||
|
|
},
|
||
|
|
tag: {
|
||
|
|
type: String,
|
||
|
|
default: 'button'
|
||
|
|
},
|
||
|
|
type: {
|
||
|
|
type: String,
|
||
|
|
default: 'default'
|
||
|
|
},
|
||
|
|
dashed: Boolean,
|
||
|
|
renderIcon: Function,
|
||
|
|
iconPlacement: {
|
||
|
|
type: String,
|
||
|
|
default: 'left'
|
||
|
|
},
|
||
|
|
attrType: {
|
||
|
|
type: String,
|
||
|
|
default: 'button'
|
||
|
|
},
|
||
|
|
bordered: {
|
||
|
|
type: Boolean,
|
||
|
|
default: true
|
||
|
|
},
|
||
|
|
onClick: [Function, Array],
|
||
|
|
nativeFocusBehavior: {
|
||
|
|
type: Boolean,
|
||
|
|
default: !isSafari
|
||
|
|
}
|
||
|
|
});
|
||
|
|
const Button = defineComponent({
|
||
|
|
name: 'Button',
|
||
|
|
props: buttonProps,
|
||
|
|
slots: Object,
|
||
|
|
setup(props) {
|
||
|
|
if (process.env.NODE_ENV !== 'production') {
|
||
|
|
watchEffect(() => {
|
||
|
|
const {
|
||
|
|
dashed,
|
||
|
|
ghost,
|
||
|
|
text,
|
||
|
|
secondary,
|
||
|
|
tertiary,
|
||
|
|
quaternary
|
||
|
|
} = props;
|
||
|
|
if ((dashed || ghost || text) && (secondary || tertiary || quaternary)) {
|
||
|
|
warnOnce('button', '`dashed`, `ghost` and `text` props can\'t be used along with `secondary`, `tertiary` and `quaternary` props.');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
const selfElRef = ref(null);
|
||
|
|
const waveElRef = ref(null);
|
||
|
|
const enterPressedRef = ref(false);
|
||
|
|
const showBorderRef = useMemo(() => {
|
||
|
|
return !props.quaternary && !props.tertiary && !props.secondary && !props.text && (!props.color || props.ghost || props.dashed) && props.bordered;
|
||
|
|
});
|
||
|
|
const NButtonGroup = inject(buttonGroupInjectionKey, {});
|
||
|
|
const {
|
||
|
|
mergedSizeRef
|
||
|
|
} = useFormItem({}, {
|
||
|
|
defaultSize: 'medium',
|
||
|
|
mergedSize: NFormItem => {
|
||
|
|
const {
|
||
|
|
size
|
||
|
|
} = props;
|
||
|
|
if (size) return size;
|
||
|
|
const {
|
||
|
|
size: buttonGroupSize
|
||
|
|
} = NButtonGroup;
|
||
|
|
if (buttonGroupSize) return buttonGroupSize;
|
||
|
|
const {
|
||
|
|
mergedSize: formItemSize
|
||
|
|
} = NFormItem || {};
|
||
|
|
if (formItemSize) {
|
||
|
|
return formItemSize.value;
|
||
|
|
}
|
||
|
|
return 'medium';
|
||
|
|
}
|
||
|
|
});
|
||
|
|
const mergedFocusableRef = computed(() => {
|
||
|
|
return props.focusable && !props.disabled;
|
||
|
|
});
|
||
|
|
const handleMousedown = e => {
|
||
|
|
var _a;
|
||
|
|
if (!mergedFocusableRef.value) {
|
||
|
|
e.preventDefault();
|
||
|
|
}
|
||
|
|
if (props.nativeFocusBehavior) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
e.preventDefault();
|
||
|
|
// normally this won't be called if disabled (when tag is button)
|
||
|
|
// if not, we try to make it behave like a button
|
||
|
|
if (props.disabled) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (mergedFocusableRef.value) {
|
||
|
|
(_a = selfElRef.value) === null || _a === void 0 ? void 0 : _a.focus({
|
||
|
|
preventScroll: true
|
||
|
|
});
|
||
|
|
}
|
||
|
|
};
|
||
|
|
const handleClick = e => {
|
||
|
|
var _a;
|
||
|
|
if (!props.disabled && !props.loading) {
|
||
|
|
const {
|
||
|
|
onClick
|
||
|
|
} = props;
|
||
|
|
if (onClick) call(onClick, e);
|
||
|
|
if (!props.text) {
|
||
|
|
(_a = waveElRef.value) === null || _a === void 0 ? void 0 : _a.play();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
const handleKeyup = e => {
|
||
|
|
switch (e.key) {
|
||
|
|
case 'Enter':
|
||
|
|
if (!props.keyboard) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
enterPressedRef.value = false;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
const handleKeydown = e => {
|
||
|
|
switch (e.key) {
|
||
|
|
case 'Enter':
|
||
|
|
if (!props.keyboard || props.loading) {
|
||
|
|
e.preventDefault();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
enterPressedRef.value = true;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
const handleBlur = () => {
|
||
|
|
enterPressedRef.value = false;
|
||
|
|
};
|
||
|
|
const {
|
||
|
|
inlineThemeDisabled,
|
||
|
|
mergedClsPrefixRef,
|
||
|
|
mergedRtlRef
|
||
|
|
} = useConfig(props);
|
||
|
|
const themeRef = useTheme('Button', '-button', style, buttonLight, props, mergedClsPrefixRef);
|
||
|
|
const rtlEnabledRef = useRtl('Button', mergedRtlRef, mergedClsPrefixRef);
|
||
|
|
const cssVarsRef = computed(() => {
|
||
|
|
const theme = themeRef.value;
|
||
|
|
const {
|
||
|
|
common: {
|
||
|
|
cubicBezierEaseInOut,
|
||
|
|
cubicBezierEaseOut
|
||
|
|
},
|
||
|
|
self
|
||
|
|
} = theme;
|
||
|
|
const {
|
||
|
|
rippleDuration,
|
||
|
|
opacityDisabled,
|
||
|
|
fontWeight,
|
||
|
|
fontWeightStrong
|
||
|
|
} = self;
|
||
|
|
const size = mergedSizeRef.value;
|
||
|
|
const {
|
||
|
|
dashed,
|
||
|
|
type,
|
||
|
|
ghost,
|
||
|
|
text,
|
||
|
|
color,
|
||
|
|
round,
|
||
|
|
circle,
|
||
|
|
textColor,
|
||
|
|
secondary,
|
||
|
|
tertiary,
|
||
|
|
quaternary,
|
||
|
|
strong
|
||
|
|
} = props;
|
||
|
|
// font
|
||
|
|
const fontProps = {
|
||
|
|
'--n-font-weight': strong ? fontWeightStrong : fontWeight
|
||
|
|
};
|
||
|
|
// color
|
||
|
|
let colorProps = {
|
||
|
|
'--n-color': 'initial',
|
||
|
|
'--n-color-hover': 'initial',
|
||
|
|
'--n-color-pressed': 'initial',
|
||
|
|
'--n-color-focus': 'initial',
|
||
|
|
'--n-color-disabled': 'initial',
|
||
|
|
'--n-ripple-color': 'initial',
|
||
|
|
'--n-text-color': 'initial',
|
||
|
|
'--n-text-color-hover': 'initial',
|
||
|
|
'--n-text-color-pressed': 'initial',
|
||
|
|
'--n-text-color-focus': 'initial',
|
||
|
|
'--n-text-color-disabled': 'initial'
|
||
|
|
};
|
||
|
|
const typeIsTertiary = type === 'tertiary';
|
||
|
|
const typeIsDefault = type === 'default';
|
||
|
|
const mergedType = typeIsTertiary ? 'default' : type;
|
||
|
|
if (text) {
|
||
|
|
const propTextColor = textColor || color;
|
||
|
|
const mergedTextColor = propTextColor || self[createKey('textColorText', mergedType)];
|
||
|
|
colorProps = {
|
||
|
|
'--n-color': '#0000',
|
||
|
|
'--n-color-hover': '#0000',
|
||
|
|
'--n-color-pressed': '#0000',
|
||
|
|
'--n-color-focus': '#0000',
|
||
|
|
'--n-color-disabled': '#0000',
|
||
|
|
'--n-ripple-color': '#0000',
|
||
|
|
'--n-text-color': mergedTextColor,
|
||
|
|
'--n-text-color-hover': propTextColor ? createHoverColor(propTextColor) : self[createKey('textColorTextHover', mergedType)],
|
||
|
|
'--n-text-color-pressed': propTextColor ? createPressedColor(propTextColor) : self[createKey('textColorTextPressed', mergedType)],
|
||
|
|
'--n-text-color-focus': propTextColor ? createHoverColor(propTextColor) : self[createKey('textColorTextHover', mergedType)],
|
||
|
|
'--n-text-color-disabled': propTextColor || self[createKey('textColorTextDisabled', mergedType)]
|
||
|
|
};
|
||
|
|
} else if (ghost || dashed) {
|
||
|
|
const mergedTextColor = textColor || color;
|
||
|
|
colorProps = {
|
||
|
|
'--n-color': '#0000',
|
||
|
|
'--n-color-hover': '#0000',
|
||
|
|
'--n-color-pressed': '#0000',
|
||
|
|
'--n-color-focus': '#0000',
|
||
|
|
'--n-color-disabled': '#0000',
|
||
|
|
'--n-ripple-color': color || self[createKey('rippleColor', mergedType)],
|
||
|
|
'--n-text-color': mergedTextColor || self[createKey('textColorGhost', mergedType)],
|
||
|
|
'--n-text-color-hover': mergedTextColor ? createHoverColor(mergedTextColor) : self[createKey('textColorGhostHover', mergedType)],
|
||
|
|
'--n-text-color-pressed': mergedTextColor ? createPressedColor(mergedTextColor) : self[createKey('textColorGhostPressed', mergedType)],
|
||
|
|
'--n-text-color-focus': mergedTextColor ? createHoverColor(mergedTextColor) : self[createKey('textColorGhostHover', mergedType)],
|
||
|
|
'--n-text-color-disabled': mergedTextColor || self[createKey('textColorGhostDisabled', mergedType)]
|
||
|
|
};
|
||
|
|
} else if (secondary) {
|
||
|
|
const typeTextColor = typeIsDefault ? self.textColor : typeIsTertiary ? self.textColorTertiary : self[createKey('color', mergedType)];
|
||
|
|
const mergedTextColor = color || typeTextColor;
|
||
|
|
const isColoredType = type !== 'default' && type !== 'tertiary';
|
||
|
|
colorProps = {
|
||
|
|
'--n-color': isColoredType ? changeColor(mergedTextColor, {
|
||
|
|
alpha: Number(self.colorOpacitySecondary)
|
||
|
|
}) : self.colorSecondary,
|
||
|
|
'--n-color-hover': isColoredType ? changeColor(mergedTextColor, {
|
||
|
|
alpha: Number(self.colorOpacitySecondaryHover)
|
||
|
|
}) : self.colorSecondaryHover,
|
||
|
|
'--n-color-pressed': isColoredType ? changeColor(mergedTextColor, {
|
||
|
|
alpha: Number(self.colorOpacitySecondaryPressed)
|
||
|
|
}) : self.colorSecondaryPressed,
|
||
|
|
'--n-color-focus': isColoredType ? changeColor(mergedTextColor, {
|
||
|
|
alpha: Number(self.colorOpacitySecondaryHover)
|
||
|
|
}) : self.colorSecondaryHover,
|
||
|
|
'--n-color-disabled': self.colorSecondary,
|
||
|
|
'--n-ripple-color': '#0000',
|
||
|
|
'--n-text-color': mergedTextColor,
|
||
|
|
'--n-text-color-hover': mergedTextColor,
|
||
|
|
'--n-text-color-pressed': mergedTextColor,
|
||
|
|
'--n-text-color-focus': mergedTextColor,
|
||
|
|
'--n-text-color-disabled': mergedTextColor
|
||
|
|
};
|
||
|
|
} else if (tertiary || quaternary) {
|
||
|
|
const typeColor = typeIsDefault ? self.textColor : typeIsTertiary ? self.textColorTertiary : self[createKey('color', mergedType)];
|
||
|
|
const mergedColor = color || typeColor;
|
||
|
|
if (tertiary) {
|
||
|
|
colorProps['--n-color'] = self.colorTertiary;
|
||
|
|
colorProps['--n-color-hover'] = self.colorTertiaryHover;
|
||
|
|
colorProps['--n-color-pressed'] = self.colorTertiaryPressed;
|
||
|
|
colorProps['--n-color-focus'] = self.colorSecondaryHover;
|
||
|
|
colorProps['--n-color-disabled'] = self.colorTertiary;
|
||
|
|
} else {
|
||
|
|
colorProps['--n-color'] = self.colorQuaternary;
|
||
|
|
colorProps['--n-color-hover'] = self.colorQuaternaryHover;
|
||
|
|
colorProps['--n-color-pressed'] = self.colorQuaternaryPressed;
|
||
|
|
colorProps['--n-color-focus'] = self.colorQuaternaryHover;
|
||
|
|
colorProps['--n-color-disabled'] = self.colorQuaternary;
|
||
|
|
}
|
||
|
|
colorProps['--n-ripple-color'] = '#0000';
|
||
|
|
colorProps['--n-text-color'] = mergedColor;
|
||
|
|
colorProps['--n-text-color-hover'] = mergedColor;
|
||
|
|
colorProps['--n-text-color-pressed'] = mergedColor;
|
||
|
|
colorProps['--n-text-color-focus'] = mergedColor;
|
||
|
|
colorProps['--n-text-color-disabled'] = mergedColor;
|
||
|
|
} else {
|
||
|
|
colorProps = {
|
||
|
|
'--n-color': color || self[createKey('color', mergedType)],
|
||
|
|
'--n-color-hover': color ? createHoverColor(color) : self[createKey('colorHover', mergedType)],
|
||
|
|
'--n-color-pressed': color ? createPressedColor(color) : self[createKey('colorPressed', mergedType)],
|
||
|
|
'--n-color-focus': color ? createHoverColor(color) : self[createKey('colorFocus', mergedType)],
|
||
|
|
'--n-color-disabled': color || self[createKey('colorDisabled', mergedType)],
|
||
|
|
'--n-ripple-color': color || self[createKey('rippleColor', mergedType)],
|
||
|
|
'--n-text-color': textColor || (color ? self.textColorPrimary : typeIsTertiary ? self.textColorTertiary : self[createKey('textColor', mergedType)]),
|
||
|
|
'--n-text-color-hover': textColor || (color ? self.textColorHoverPrimary : self[createKey('textColorHover', mergedType)]),
|
||
|
|
'--n-text-color-pressed': textColor || (color ? self.textColorPressedPrimary : self[createKey('textColorPressed', mergedType)]),
|
||
|
|
'--n-text-color-focus': textColor || (color ? self.textColorFocusPrimary : self[createKey('textColorFocus', mergedType)]),
|
||
|
|
'--n-text-color-disabled': textColor || (color ? self.textColorDisabledPrimary : self[createKey('textColorDisabled', mergedType)])
|
||
|
|
};
|
||
|
|
}
|
||
|
|
// border
|
||
|
|
let borderProps = {
|
||
|
|
'--n-border': 'initial',
|
||
|
|
'--n-border-hover': 'initial',
|
||
|
|
'--n-border-pressed': 'initial',
|
||
|
|
'--n-border-focus': 'initial',
|
||
|
|
'--n-border-disabled': 'initial'
|
||
|
|
};
|
||
|
|
if (text) {
|
||
|
|
borderProps = {
|
||
|
|
'--n-border': 'none',
|
||
|
|
'--n-border-hover': 'none',
|
||
|
|
'--n-border-pressed': 'none',
|
||
|
|
'--n-border-focus': 'none',
|
||
|
|
'--n-border-disabled': 'none'
|
||
|
|
};
|
||
|
|
} else {
|
||
|
|
borderProps = {
|
||
|
|
'--n-border': self[createKey('border', mergedType)],
|
||
|
|
'--n-border-hover': self[createKey('borderHover', mergedType)],
|
||
|
|
'--n-border-pressed': self[createKey('borderPressed', mergedType)],
|
||
|
|
'--n-border-focus': self[createKey('borderFocus', mergedType)],
|
||
|
|
'--n-border-disabled': self[createKey('borderDisabled', mergedType)]
|
||
|
|
};
|
||
|
|
}
|
||
|
|
// size
|
||
|
|
const {
|
||
|
|
[createKey('height', size)]: height,
|
||
|
|
[createKey('fontSize', size)]: fontSize,
|
||
|
|
[createKey('padding', size)]: padding,
|
||
|
|
[createKey('paddingRound', size)]: paddingRound,
|
||
|
|
[createKey('iconSize', size)]: iconSize,
|
||
|
|
[createKey('borderRadius', size)]: borderRadius,
|
||
|
|
[createKey('iconMargin', size)]: iconMargin,
|
||
|
|
waveOpacity
|
||
|
|
} = self;
|
||
|
|
const sizeProps = {
|
||
|
|
'--n-width': circle && !text ? height : 'initial',
|
||
|
|
'--n-height': text ? 'initial' : height,
|
||
|
|
'--n-font-size': fontSize,
|
||
|
|
'--n-padding': circle ? 'initial' : text ? 'initial' : round ? paddingRound : padding,
|
||
|
|
'--n-icon-size': iconSize,
|
||
|
|
'--n-icon-margin': iconMargin,
|
||
|
|
'--n-border-radius': text ? 'initial' : circle || round ? height : borderRadius
|
||
|
|
};
|
||
|
|
return Object.assign(Object.assign(Object.assign(Object.assign({
|
||
|
|
'--n-bezier': cubicBezierEaseInOut,
|
||
|
|
'--n-bezier-ease-out': cubicBezierEaseOut,
|
||
|
|
'--n-ripple-duration': rippleDuration,
|
||
|
|
'--n-opacity-disabled': opacityDisabled,
|
||
|
|
'--n-wave-opacity': waveOpacity
|
||
|
|
}, fontProps), colorProps), borderProps), sizeProps);
|
||
|
|
});
|
||
|
|
const themeClassHandle = inlineThemeDisabled ? useThemeClass('button', computed(() => {
|
||
|
|
let hash = '';
|
||
|
|
const {
|
||
|
|
dashed,
|
||
|
|
type,
|
||
|
|
ghost,
|
||
|
|
text,
|
||
|
|
color,
|
||
|
|
round,
|
||
|
|
circle,
|
||
|
|
textColor,
|
||
|
|
secondary,
|
||
|
|
tertiary,
|
||
|
|
quaternary,
|
||
|
|
strong
|
||
|
|
} = props;
|
||
|
|
if (dashed) hash += 'a';
|
||
|
|
if (ghost) hash += 'b';
|
||
|
|
if (text) hash += 'c';
|
||
|
|
if (round) hash += 'd';
|
||
|
|
if (circle) hash += 'e';
|
||
|
|
if (secondary) hash += 'f';
|
||
|
|
if (tertiary) hash += 'g';
|
||
|
|
if (quaternary) hash += 'h';
|
||
|
|
if (strong) hash += 'i';
|
||
|
|
if (color) hash += `j${color2Class(color)}`;
|
||
|
|
if (textColor) hash += `k${color2Class(textColor)}`;
|
||
|
|
const {
|
||
|
|
value: size
|
||
|
|
} = mergedSizeRef;
|
||
|
|
hash += `l${size[0]}`;
|
||
|
|
hash += `m${type[0]}`;
|
||
|
|
return hash;
|
||
|
|
}), cssVarsRef, props) : undefined;
|
||
|
|
return {
|
||
|
|
selfElRef,
|
||
|
|
waveElRef,
|
||
|
|
mergedClsPrefix: mergedClsPrefixRef,
|
||
|
|
mergedFocusable: mergedFocusableRef,
|
||
|
|
mergedSize: mergedSizeRef,
|
||
|
|
showBorder: showBorderRef,
|
||
|
|
enterPressed: enterPressedRef,
|
||
|
|
rtlEnabled: rtlEnabledRef,
|
||
|
|
handleMousedown,
|
||
|
|
handleKeydown,
|
||
|
|
handleBlur,
|
||
|
|
handleKeyup,
|
||
|
|
handleClick,
|
||
|
|
customColorCssVars: computed(() => {
|
||
|
|
const {
|
||
|
|
color
|
||
|
|
} = props;
|
||
|
|
if (!color) return null;
|
||
|
|
const hoverColor = createHoverColor(color);
|
||
|
|
return {
|
||
|
|
'--n-border-color': color,
|
||
|
|
'--n-border-color-hover': hoverColor,
|
||
|
|
'--n-border-color-pressed': createPressedColor(color),
|
||
|
|
'--n-border-color-focus': hoverColor,
|
||
|
|
'--n-border-color-disabled': color
|
||
|
|
};
|
||
|
|
}),
|
||
|
|
cssVars: inlineThemeDisabled ? undefined : cssVarsRef,
|
||
|
|
themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
|
||
|
|
onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender
|
||
|
|
};
|
||
|
|
},
|
||
|
|
render() {
|
||
|
|
const {
|
||
|
|
mergedClsPrefix,
|
||
|
|
tag: Component,
|
||
|
|
onRender
|
||
|
|
} = this;
|
||
|
|
onRender === null || onRender === void 0 ? void 0 : onRender();
|
||
|
|
const children = resolveWrappedSlot(this.$slots.default, children => children && h("span", {
|
||
|
|
class: `${mergedClsPrefix}-button__content`
|
||
|
|
}, children));
|
||
|
|
return h(Component, {
|
||
|
|
ref: "selfElRef",
|
||
|
|
class: [this.themeClass, `${mergedClsPrefix}-button`, `${mergedClsPrefix}-button--${this.type}-type`, `${mergedClsPrefix}-button--${this.mergedSize}-type`, this.rtlEnabled && `${mergedClsPrefix}-button--rtl`, this.disabled && `${mergedClsPrefix}-button--disabled`, this.block && `${mergedClsPrefix}-button--block`, this.enterPressed && `${mergedClsPrefix}-button--pressed`, !this.text && this.dashed && `${mergedClsPrefix}-button--dashed`, this.color && `${mergedClsPrefix}-button--color`, this.secondary && `${mergedClsPrefix}-button--secondary`, this.loading && `${mergedClsPrefix}-button--loading`, this.ghost && `${mergedClsPrefix}-button--ghost` // required for button group border collapse
|
||
|
|
],
|
||
|
|
tabindex: this.mergedFocusable ? 0 : -1,
|
||
|
|
type: this.attrType,
|
||
|
|
style: this.cssVars,
|
||
|
|
disabled: this.disabled,
|
||
|
|
onClick: this.handleClick,
|
||
|
|
onBlur: this.handleBlur,
|
||
|
|
onMousedown: this.handleMousedown,
|
||
|
|
onKeyup: this.handleKeyup,
|
||
|
|
onKeydown: this.handleKeydown
|
||
|
|
}, this.iconPlacement === 'right' && children, h(NFadeInExpandTransition, {
|
||
|
|
width: true
|
||
|
|
}, {
|
||
|
|
default: () => resolveWrappedSlot(this.$slots.icon, children => (this.loading || this.renderIcon || children) && h("span", {
|
||
|
|
class: `${mergedClsPrefix}-button__icon`,
|
||
|
|
style: {
|
||
|
|
margin: isSlotEmpty(this.$slots.default) ? '0' : ''
|
||
|
|
}
|
||
|
|
}, h(NIconSwitchTransition, null, {
|
||
|
|
default: () => this.loading ? h(NBaseLoading, {
|
||
|
|
clsPrefix: mergedClsPrefix,
|
||
|
|
key: "loading",
|
||
|
|
class: `${mergedClsPrefix}-icon-slot`,
|
||
|
|
strokeWidth: 20
|
||
|
|
}) : h("div", {
|
||
|
|
key: "icon",
|
||
|
|
class: `${mergedClsPrefix}-icon-slot`,
|
||
|
|
role: "none"
|
||
|
|
}, this.renderIcon ? this.renderIcon() : children)
|
||
|
|
})))
|
||
|
|
}), this.iconPlacement === 'left' && children, !this.text ? h(NBaseWave, {
|
||
|
|
ref: "waveElRef",
|
||
|
|
clsPrefix: mergedClsPrefix
|
||
|
|
}) : null, this.showBorder ? h("div", {
|
||
|
|
"aria-hidden": true,
|
||
|
|
class: `${mergedClsPrefix}-button__border`,
|
||
|
|
style: this.customColorCssVars
|
||
|
|
}) : null, this.showBorder ? h("div", {
|
||
|
|
"aria-hidden": true,
|
||
|
|
class: `${mergedClsPrefix}-button__state-border`,
|
||
|
|
style: this.customColorCssVars
|
||
|
|
}) : null);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
export default Button;
|
||
|
|
// XButton is for tsx type checking
|
||
|
|
// It's not compatible with render function `h`
|
||
|
|
// Currently we don't expose it as public
|
||
|
|
// If there's any issue about this, we may expose it
|
||
|
|
// Since most people use template, the type checking phase doesn't work as tsx
|
||
|
|
export const XButton = Button;
|
||
|
|
// Also, we may make XButton a generic type which support `tag` prop
|
||
|
|
// but currently vue doesn't export IntrinsicElementAttributes from runtime-dom
|
||
|
|
// so we can't easily make an attr map by hand
|
||
|
|
// just leave it for later
|