feat: add loading icon

This commit is contained in:
aibayanyu 2023-04-19 08:30:24 +08:00
parent 786877b629
commit 6096c28669
4 changed files with 71 additions and 15 deletions

View File

@ -21,6 +21,7 @@ import {
isUnBorderedButtonType, isUnBorderedButtonType,
spaceChildren spaceChildren
} from './button-helper' } from './button-helper'
import LoadingIcon from './loading-icon'
type Loading = number | boolean type Loading = number | boolean
function getLoadingConfig(loading: ButtonProps['loading']): LoadingConfigType { function getLoadingConfig(loading: ButtonProps['loading']): LoadingConfigType {
@ -183,7 +184,17 @@ const Button = defineComponent({
compactItemClassnames.value, compactItemClassnames.value,
rootClassName rootClassName
) )
const iconNode = icon && (!innerLoading.value ? icon?.() : <>L</>) const iconNode =
icon &&
(!innerLoading.value ? (
icon?.()
) : (
<LoadingIcon
existIcon={!!icon}
prefixCls={prefixCls.value}
loading={!!innerLoading.value}
/>
))
const kids = const kids =
children || children === 0 children || children === 0

View File

@ -1,4 +1,4 @@
import { defineComponent } from 'vue' import { Transition, defineComponent, nextTick } from 'vue'
import { booleanType, someType, stringType } from '@v-c/utils' import { booleanType, someType, stringType } from '@v-c/utils'
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined' import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined'
@ -13,25 +13,33 @@ export const loadingIconProps = {
loading: someType<boolean | object>([Boolean, Object]) loading: someType<boolean | object>([Boolean, Object])
} }
// const getCollapsedWidth = (): CSSProperties => ({ const getCollapsedWidth = (el: Element) => {
// width: 0, const node: HTMLElement = el as HTMLElement
// opacity: 0, if (node) {
// transform: 'scale(0)' node.style.width = '0'
// }) node.style.opacity = '0'
// node.style.transform = 'scale(0)'
// const getRealWidth = (node: HTMLElement): CSSProperties => ({ }
// width: node.scrollWidth, }
// opacity: 1,
// transform: 'scale(1)' const getRealWidth = (el: Element) => {
// }) const node: HTMLElement = el as HTMLElement
nextTick(() => {
if (node) {
node.style.width = `${node.scrollWidth}px`
node.style.opacity = '1'
node.style.transform = 'scale(1)'
}
}).then()
}
const LoadingIcon = defineComponent({ const LoadingIcon = defineComponent({
name: 'LoadingIcon', name: 'LoadingIcon',
props: loadingIconProps, props: loadingIconProps,
setup(props) { setup(props) {
return () => { return () => {
const { existIcon, prefixCls } = props const { loading, existIcon, prefixCls } = props
// const visible = !!loading const visible = !!loading
if (existIcon) { if (existIcon) {
return ( return (
<span class={`${prefixCls}-loading-icon`}> <span class={`${prefixCls}-loading-icon`}>
@ -39,6 +47,19 @@ const LoadingIcon = defineComponent({
</span> </span>
) )
} }
return (
<Transition
name={`${prefixCls}-loading-icon-motion`}
onBeforeEnter={getCollapsedWidth}
onEnter={getRealWidth}
>
{visible ? (
<span class={`${prefixCls}-loading-icon`}>
<LoadingOutlined />
</span>
) : null}
</Transition>
)
} }
} }
}) })

View File

@ -23,6 +23,7 @@
}, },
"dependencies": { "dependencies": {
"@ant-design/colors": "^7.0.0", "@ant-design/colors": "^7.0.0",
"@ant-design/icons-vue": "^6.1.0",
"@antd-tiny-vue/cssinjs": "0.0.8", "@antd-tiny-vue/cssinjs": "0.0.8",
"@ctrl/tinycolor": "^3.6.0", "@ctrl/tinycolor": "^3.6.0",
"@v-c/utils": "^0.0.22", "@v-c/utils": "^0.0.22",

View File

@ -4,6 +4,9 @@ dependencies:
'@ant-design/colors': '@ant-design/colors':
specifier: ^7.0.0 specifier: ^7.0.0
version: 7.0.0 version: 7.0.0
'@ant-design/icons-vue':
specifier: ^6.1.0
version: 6.1.0(vue@3.2.47)
'@antd-tiny-vue/cssinjs': '@antd-tiny-vue/cssinjs':
specifier: 0.0.8 specifier: 0.0.8
version: 0.0.8(vue@3.2.47) version: 0.0.8(vue@3.2.47)
@ -196,12 +199,32 @@ packages:
'@jridgewell/trace-mapping': 0.3.18 '@jridgewell/trace-mapping': 0.3.18
dev: true dev: true
/@ant-design/colors@6.0.0:
resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==}
dependencies:
'@ctrl/tinycolor': 3.6.0
dev: false
/@ant-design/colors@7.0.0: /@ant-design/colors@7.0.0:
resolution: {integrity: sha512-iVm/9PfGCbC0dSMBrz7oiEXZaaGH7ceU40OJEfKmyuzR9R5CRimJYPlRiFtMQGQcbNMea/ePcoIebi4ASGYXtg==} resolution: {integrity: sha512-iVm/9PfGCbC0dSMBrz7oiEXZaaGH7ceU40OJEfKmyuzR9R5CRimJYPlRiFtMQGQcbNMea/ePcoIebi4ASGYXtg==}
dependencies: dependencies:
'@ctrl/tinycolor': 3.6.0 '@ctrl/tinycolor': 3.6.0
dev: false dev: false
/@ant-design/icons-svg@4.2.1:
resolution: {integrity: sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw==}
dev: false
/@ant-design/icons-vue@6.1.0(vue@3.2.47):
resolution: {integrity: sha512-EX6bYm56V+ZrKN7+3MT/ubDkvJ5rK/O2t380WFRflDcVFgsvl3NLH7Wxeau6R8DbrO5jWR6DSTC3B6gYFp77AA==}
peerDependencies:
vue: '>=3.0.3'
dependencies:
'@ant-design/colors': 6.0.0
'@ant-design/icons-svg': 4.2.1
vue: 3.2.47
dev: false
/@antd-tiny-vue/cssinjs@0.0.8(vue@3.2.47): /@antd-tiny-vue/cssinjs@0.0.8(vue@3.2.47):
resolution: {integrity: sha512-Q5/4ugRfaIn0jfG/D5eXu2DtGfmMbsNAvAcx6M0aRjY3gfvd4h/W7YDIfI4N9lfighnvJ8A4CgW6d9xAHlP5pw==} resolution: {integrity: sha512-Q5/4ugRfaIn0jfG/D5eXu2DtGfmMbsNAvAcx6M0aRjY3gfvd4h/W7YDIfI4N9lfighnvJ8A4CgW6d9xAHlP5pw==}
peerDependencies: peerDependencies: