naive-ui
Version:
A Vue 3 Component Library. Fairly Complete, Theme Customizable, Uses TypeScript, Fast
479 lines (478 loc) • 24.9 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.XButton = exports.buttonProps = void 0;
const seemly_1 = require("seemly");
const vooks_1 = require("vooks");
const vue_1 = require("vue");
const _internal_1 = require("../../_internal");
const _mixins_1 = require("../../_mixins");
const use_rtl_1 = require("../../_mixins/use-rtl");
const _utils_1 = require("../../_utils");
const index_1 = require("../../_utils/color/index");
const browser_1 = require("../../_utils/env/browser");
const context_1 = require("../../button-group/src/context");
const styles_1 = require("../styles");
const index_cssr_1 = __importDefault(require("./styles/index.cssr"));
exports.buttonProps = Object.assign(Object.assign({}, _mixins_1.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: !browser_1.isSafari
} });
const Button = (0, vue_1.defineComponent)({
name: 'Button',
props: exports.buttonProps,
slots: Object,
setup(props) {
if (process.env.NODE_ENV !== 'production') {
(0, vue_1.watchEffect)(() => {
const { dashed, ghost, text, secondary, tertiary, quaternary } = props;
if ((dashed || ghost || text)
&& (secondary || tertiary || quaternary)) {
(0, _utils_1.warnOnce)('button', '`dashed`, `ghost` and `text` props can\'t be used along with `secondary`, `tertiary` and `quaternary` props.');
}
});
}
const selfElRef = (0, vue_1.ref)(null);
const waveElRef = (0, vue_1.ref)(null);
const enterPressedRef = (0, vue_1.ref)(false);
const showBorderRef = (0, vooks_1.useMemo)(() => {
return (!props.quaternary
&& !props.tertiary
&& !props.secondary
&& !props.text
&& (!props.color || props.ghost || props.dashed)
&& props.bordered);
});
const NButtonGroup = (0, vue_1.inject)(context_1.buttonGroupInjectionKey, {});
const { mergedSizeRef } = (0, _mixins_1.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 = (0, vue_1.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)
(0, _utils_1.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 } = (0, _mixins_1.useConfig)(props);
const themeRef = (0, _mixins_1.useTheme)('Button', '-button', index_cssr_1.default, styles_1.buttonLight, props, mergedClsPrefixRef);
const rtlEnabledRef = (0, use_rtl_1.useRtl)('Button', mergedRtlRef, mergedClsPrefixRef);
const cssVarsRef = (0, vue_1.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[(0, _utils_1.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
? (0, index_1.createHoverColor)(propTextColor)
: self[(0, _utils_1.createKey)('textColorTextHover', mergedType)],
'--n-text-color-pressed': propTextColor
? (0, index_1.createPressedColor)(propTextColor)
: self[(0, _utils_1.createKey)('textColorTextPressed', mergedType)],
'--n-text-color-focus': propTextColor
? (0, index_1.createHoverColor)(propTextColor)
: self[(0, _utils_1.createKey)('textColorTextHover', mergedType)],
'--n-text-color-disabled': propTextColor
|| self[(0, _utils_1.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[(0, _utils_1.createKey)('rippleColor', mergedType)],
'--n-text-color': mergedTextColor || self[(0, _utils_1.createKey)('textColorGhost', mergedType)],
'--n-text-color-hover': mergedTextColor
? (0, index_1.createHoverColor)(mergedTextColor)
: self[(0, _utils_1.createKey)('textColorGhostHover', mergedType)],
'--n-text-color-pressed': mergedTextColor
? (0, index_1.createPressedColor)(mergedTextColor)
: self[(0, _utils_1.createKey)('textColorGhostPressed', mergedType)],
'--n-text-color-focus': mergedTextColor
? (0, index_1.createHoverColor)(mergedTextColor)
: self[(0, _utils_1.createKey)('textColorGhostHover', mergedType)],
'--n-text-color-disabled': mergedTextColor
|| self[(0, _utils_1.createKey)('textColorGhostDisabled', mergedType)]
};
}
else if (secondary) {
const typeTextColor = typeIsDefault
? self.textColor
: typeIsTertiary
? self.textColorTertiary
: self[(0, _utils_1.createKey)('color', mergedType)];
const mergedTextColor = color || typeTextColor;
const isColoredType = type !== 'default' && type !== 'tertiary';
colorProps = {
'--n-color': isColoredType
? (0, seemly_1.changeColor)(mergedTextColor, {
alpha: Number(self.colorOpacitySecondary)
})
: self.colorSecondary,
'--n-color-hover': isColoredType
? (0, seemly_1.changeColor)(mergedTextColor, {
alpha: Number(self.colorOpacitySecondaryHover)
})
: self.colorSecondaryHover,
'--n-color-pressed': isColoredType
? (0, seemly_1.changeColor)(mergedTextColor, {
alpha: Number(self.colorOpacitySecondaryPressed)
})
: self.colorSecondaryPressed,
'--n-color-focus': isColoredType
? (0, seemly_1.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[(0, _utils_1.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[(0, _utils_1.createKey)('color', mergedType)],
'--n-color-hover': color
? (0, index_1.createHoverColor)(color)
: self[(0, _utils_1.createKey)('colorHover', mergedType)],
'--n-color-pressed': color
? (0, index_1.createPressedColor)(color)
: self[(0, _utils_1.createKey)('colorPressed', mergedType)],
'--n-color-focus': color
? (0, index_1.createHoverColor)(color)
: self[(0, _utils_1.createKey)('colorFocus', mergedType)],
'--n-color-disabled': color || self[(0, _utils_1.createKey)('colorDisabled', mergedType)],
'--n-ripple-color': color || self[(0, _utils_1.createKey)('rippleColor', mergedType)],
'--n-text-color': textColor
|| (color
? self.textColorPrimary
: typeIsTertiary
? self.textColorTertiary
: self[(0, _utils_1.createKey)('textColor', mergedType)]),
'--n-text-color-hover': textColor
|| (color
? self.textColorHoverPrimary
: self[(0, _utils_1.createKey)('textColorHover', mergedType)]),
'--n-text-color-pressed': textColor
|| (color
? self.textColorPressedPrimary
: self[(0, _utils_1.createKey)('textColorPressed', mergedType)]),
'--n-text-color-focus': textColor
|| (color
? self.textColorFocusPrimary
: self[(0, _utils_1.createKey)('textColorFocus', mergedType)]),
'--n-text-color-disabled': textColor
|| (color
? self.textColorDisabledPrimary
: self[(0, _utils_1.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[(0, _utils_1.createKey)('border', mergedType)],
'--n-border-hover': self[(0, _utils_1.createKey)('borderHover', mergedType)],
'--n-border-pressed': self[(0, _utils_1.createKey)('borderPressed', mergedType)],
'--n-border-focus': self[(0, _utils_1.createKey)('borderFocus', mergedType)],
'--n-border-disabled': self[(0, _utils_1.createKey)('borderDisabled', mergedType)]
};
}
// size
const { [(0, _utils_1.createKey)('height', size)]: height, [(0, _utils_1.createKey)('fontSize', size)]: fontSize, [(0, _utils_1.createKey)('padding', size)]: padding, [(0, _utils_1.createKey)('paddingRound', size)]: paddingRound, [(0, _utils_1.createKey)('iconSize', size)]: iconSize, [(0, _utils_1.createKey)('borderRadius', size)]: borderRadius, [(0, _utils_1.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
? (0, _mixins_1.useThemeClass)('button', (0, vue_1.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${(0, _utils_1.color2Class)(color)}`;
if (textColor)
hash += `k${(0, _utils_1.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: (0, vue_1.computed)(() => {
const { color } = props;
if (!color)
return null;
const hoverColor = (0, index_1.createHoverColor)(color);
return {
'--n-border-color': color,
'--n-border-color-hover': hoverColor,
'--n-border-color-pressed': (0, index_1.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 = (0, _utils_1.resolveWrappedSlot)(this.$slots.default, children => children && ((0, vue_1.h)("span", { class: `${mergedClsPrefix}-button__content` }, children)));
return ((0, vue_1.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,
(0, vue_1.h)(_internal_1.NFadeInExpandTransition, { width: true }, {
default: () => (0, _utils_1.resolveWrappedSlot)(this.$slots.icon, children => (this.loading || this.renderIcon || children) && ((0, vue_1.h)("span", { class: `${mergedClsPrefix}-button__icon`, style: {
margin: (0, _utils_1.isSlotEmpty)(this.$slots.default) ? '0' : ''
} },
(0, vue_1.h)(_internal_1.NIconSwitchTransition, null, {
default: () => this.loading ? ((0, vue_1.h)(_internal_1.NBaseLoading, { clsPrefix: mergedClsPrefix, key: "loading", class: `${mergedClsPrefix}-icon-slot`, strokeWidth: 20 })) : ((0, vue_1.h)("div", { key: "icon", class: `${mergedClsPrefix}-icon-slot`, role: "none" }, this.renderIcon ? this.renderIcon() : children))
}))))
}),
this.iconPlacement === 'left' && children,
!this.text ? ((0, vue_1.h)(_internal_1.NBaseWave, { ref: "waveElRef", clsPrefix: mergedClsPrefix })) : null,
this.showBorder ? ((0, vue_1.h)("div", { "aria-hidden": true, class: `${mergedClsPrefix}-button__border`, style: this.customColorCssVars })) : null,
this.showBorder ? ((0, vue_1.h)("div", { "aria-hidden": true, class: `${mergedClsPrefix}-button__state-border`, style: this.customColorCssVars })) : null));
}
});
exports.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
exports.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
;