@coreui/vue-pro
Version:
UI Components Library for Vue.js
99 lines (91 loc) • 2.29 kB
text/typescript
import { defineComponent, h, ref, watch } from 'vue'
import { CButton } from '../button/CButton'
import { CSpinner } from '../spinner/CSpinner'
import type { ComponentProps } from '../../utils/ComponentProps'
interface CLoadingButtonProps extends ComponentProps<typeof CButton> {
disabledOnLoading?: boolean
loading?: boolean
spinnerType?: 'border' | 'grow'
timeout?: number
}
const CLoadingButton = defineComponent({
name: 'CLoadingButton',
props: {
/**
* Makes button disabled when loading.
*/
disabledOnLoading: Boolean,
/**
* Loading state (set to true to start animation).
*/
loading: {
type: Boolean,
default: false,
required: false,
},
/**
* Sets type of spinner.
*
* @values 'border', 'grow'
* @default 'border'
*/
spinnerType: {
type: String,
default: 'border',
required: false,
validator: (value: string) => {
return ['border', 'grow'].includes(value)
},
},
/**
* Automatically starts loading animation and stops after a determined amount of milliseconds.
*/
timeout: {
type: Number,
default: undefined,
required: false,
},
...CButton.props,
},
emits: [
/**
* Event called when the user clicks on a component.
*/
'click',
],
setup(props: CLoadingButtonProps, { emit, slots }) {
const loading = ref(props.loading)
watch(
() => props.loading,
() => {
loading.value = props.loading
},
)
const handleOnClick = () => {
emit('click')
if (props.timeout) {
loading.value = true
setTimeout(() => {
loading.value = false
}, props.timeout)
}
}
return () =>
h(
CButton,
{
...props,
class: ['btn-loading', { ['is-loading']: loading.value }],
...(props.disabledOnLoading && loading.value && { disabled: true }),
onClick: () => handleOnClick(),
},
{
default: () => [
h(CSpinner, { class: 'btn-loading-spinner', size: 'sm', variant: props.spinnerType }),
slots.default && slots.default(),
],
},
)
},
})
export { CLoadingButton }