mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
109 lines
2.8 KiB
Vue
109 lines
2.8 KiB
Vue
<template>
|
|
<button
|
|
ref="_ref"
|
|
:class="[
|
|
ns.b(),
|
|
ns.m(_type),
|
|
ns.m(_size),
|
|
ns.is('disabled', _disabled),
|
|
ns.is('loading', loading),
|
|
ns.is('plain', plain),
|
|
ns.is('round', round),
|
|
ns.is('circle', circle),
|
|
]"
|
|
:disabled="_disabled || loading"
|
|
:autofocus="autofocus"
|
|
:type="nativeType"
|
|
:style="buttonStyle"
|
|
@click="handleClick"
|
|
>
|
|
<template v-if="loading">
|
|
<slot v-if="$slots.loading" name="loading" />
|
|
<el-icon v-else :class="ns.is('loading')">
|
|
<component :is="loadingIcon" />
|
|
</el-icon>
|
|
</template>
|
|
<el-icon v-else-if="icon || $slots.icon">
|
|
<component :is="icon" v-if="icon" />
|
|
<slot v-else name="icon" />
|
|
</el-icon>
|
|
<span
|
|
v-if="$slots.default"
|
|
:class="{ [ns.em('text', 'expand')]: shouldAddSpace }"
|
|
>
|
|
<slot />
|
|
</span>
|
|
</button>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { Text, computed, inject, ref, useSlots } from 'vue'
|
|
import { ElIcon } from '@element-plus/components/icon'
|
|
import {
|
|
useDisabled,
|
|
useFormItem,
|
|
useGlobalConfig,
|
|
useNamespace,
|
|
useSize,
|
|
} from '@element-plus/hooks'
|
|
import { buttonGroupContextKey } from '@element-plus/tokens'
|
|
import { buttonEmits, buttonProps } from './button'
|
|
import { useButtonCustomStyle } from './button-custom'
|
|
|
|
defineOptions({
|
|
name: 'ElButton',
|
|
})
|
|
|
|
const props = defineProps(buttonProps)
|
|
const emit = defineEmits(buttonEmits)
|
|
const slots = useSlots()
|
|
|
|
const buttonGroupContext = inject(buttonGroupContextKey, undefined)
|
|
const globalConfig = useGlobalConfig('button')
|
|
const ns = useNamespace('button')
|
|
const { form } = useFormItem()
|
|
const _size = useSize(computed(() => buttonGroupContext?.size))
|
|
const _disabled = useDisabled()
|
|
const _ref = ref<HTMLButtonElement>()
|
|
|
|
const _type = computed(() => props.type || buttonGroupContext?.type || '')
|
|
const autoInsertSpace = computed(
|
|
() => props.autoInsertSpace ?? globalConfig.value?.autoInsertSpace ?? false
|
|
)
|
|
|
|
// add space between two characters in Chinese
|
|
const shouldAddSpace = computed(() => {
|
|
const defaultSlot = slots.default?.()
|
|
if (autoInsertSpace.value && defaultSlot?.length === 1) {
|
|
const slot = defaultSlot[0]
|
|
if (slot?.type === Text) {
|
|
const text = slot.children as string
|
|
return /^\p{Unified_Ideograph}{2}$/u.test(text.trim())
|
|
}
|
|
}
|
|
return false
|
|
})
|
|
|
|
const buttonStyle = useButtonCustomStyle(props)
|
|
|
|
const handleClick = (evt: MouseEvent) => {
|
|
if (props.nativeType === 'reset') {
|
|
form?.resetFields()
|
|
}
|
|
emit('click', evt)
|
|
}
|
|
|
|
defineExpose({
|
|
/** @description button html element */
|
|
ref: _ref,
|
|
/** @description button size */
|
|
size: _size,
|
|
/** @description button type */
|
|
type: _type,
|
|
/** @description button disabled */
|
|
disabled: _disabled,
|
|
/** @description whether adding space */
|
|
shouldAddSpace,
|
|
})
|
|
</script>
|