mirror of
				https://github.com/antd-tiny-vue/antd-tiny-vue.git
				synced 2025-10-31 16:51:45 +08:00 
			
		
		
		
	feat: add wave
This commit is contained in:
		| @@ -1,10 +1,58 @@ | |||||||
| import { defineComponent } from 'vue' | import type { VNode } from 'vue' | ||||||
|  | import { cloneVNode, computed, defineComponent, shallowRef } from 'vue' | ||||||
|  | import { booleanType, classNames, filterEmpty, isVisible } from '@v-c/utils' | ||||||
|  | import { useEventListener } from '@vueuse/core' | ||||||
|  | import { useProviderConfigState } from '../../config-provider/context' | ||||||
|  | import useStyle from './style' | ||||||
|  | import useWave from './use-wave' | ||||||
|  |  | ||||||
| const Wave = defineComponent({ | const Wave = defineComponent({ | ||||||
|   name: 'Wave', |   name: 'Wave', | ||||||
|   setup(_, { slots }) { |   props: { | ||||||
|  |     disabled: booleanType() | ||||||
|  |   }, | ||||||
|  |   setup(props, { slots }) { | ||||||
|  |     const { getPrefixCls } = useProviderConfigState() | ||||||
|  |     const containerRef = shallowRef() | ||||||
|  |  | ||||||
|  |     // ============================== Style =============================== | ||||||
|  |     const prefixCls = computed(() => getPrefixCls('wave')) | ||||||
|  |     const [, hashId] = useStyle(prefixCls) | ||||||
|  |     const showWave = useWave( | ||||||
|  |       containerRef, | ||||||
|  |       computed(() => classNames(prefixCls, hashId)) | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     const onClick = (e: MouseEvent) => { | ||||||
|  |       const node = containerRef.value | ||||||
|  |       const { disabled } = props | ||||||
|  |       if (!node || node.nodeType !== 1 || disabled) { | ||||||
|  |         return | ||||||
|  |       } | ||||||
|  |       // Fix radio button click twice | ||||||
|  |       if ( | ||||||
|  |         (e.target as HTMLElement).tagName === 'INPUT' || | ||||||
|  |         !isVisible(e.target as HTMLElement) || | ||||||
|  |         // No need wave | ||||||
|  |         !node.getAttribute || | ||||||
|  |         node.getAttribute('disabled') || | ||||||
|  |         (node as HTMLInputElement).disabled || | ||||||
|  |         node.className.includes('disabled') || | ||||||
|  |         node.className.includes('-leave') | ||||||
|  |       ) { | ||||||
|  |         return | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       showWave() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     useEventListener(containerRef, 'click', onClick, true) | ||||||
|  |  | ||||||
|     return () => { |     return () => { | ||||||
|       return slots.default?.() |       const children = slots.default?.() | ||||||
|  |       const child = filterEmpty(children)[0] | ||||||
|  |       if (!child) return null | ||||||
|  |       return cloneVNode(child as VNode, { ref: containerRef }) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								components/_util/wave/use-wave.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								components/_util/wave/use-wave.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | import type { ComputedRef, Ref } from 'vue' | ||||||
|  | import showWaveEffect from './wave-effect' | ||||||
|  |  | ||||||
|  | export default function useWave(nodeRef: Ref<HTMLElement>, className: ComputedRef<string>): VoidFunction { | ||||||
|  |   function showWave() { | ||||||
|  |     // const node = nodeRef.va! | ||||||
|  |     showWaveEffect(nodeRef, className) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return showWave | ||||||
|  | } | ||||||
							
								
								
									
										32
									
								
								components/_util/wave/wave-effect.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								components/_util/wave/wave-effect.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | import type { ComputedRef, Ref } from 'vue' | ||||||
|  | import { unrefElement } from '@vueuse/core' | ||||||
|  | import { defineComponent, render } from 'vue' | ||||||
|  | import { objectType } from '@v-c/utils' | ||||||
|  |  | ||||||
|  | export const WaveEffect = defineComponent({ | ||||||
|  |   name: 'WaveEffect', | ||||||
|  |   props: { | ||||||
|  |     target: objectType<HTMLElement>() | ||||||
|  |   }, | ||||||
|  |   setup() { | ||||||
|  |     return () => null | ||||||
|  |   } | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | export default function showWaveEffect(nodeRef: Ref<HTMLElement>, className: ComputedRef<string>) { | ||||||
|  |   const node = unrefElement(nodeRef) | ||||||
|  |   // Create holder | ||||||
|  |   const holder = document.createElement('div') | ||||||
|  |   holder.style.position = 'absolute' | ||||||
|  |   holder.style.left = `0px` | ||||||
|  |   holder.style.top = `0px` | ||||||
|  |   node?.insertBefore(holder, node?.firstChild) | ||||||
|  |  | ||||||
|  |   render( | ||||||
|  |     <WaveEffect | ||||||
|  |       target={node} | ||||||
|  |       class={className.value} | ||||||
|  |     />, | ||||||
|  |     holder | ||||||
|  |   ) | ||||||
|  | } | ||||||
| @@ -17,7 +17,7 @@ | |||||||
|     "@ant-design/colors": "^7.0.0", |     "@ant-design/colors": "^7.0.0", | ||||||
|     "@antd-tiny-vue/cssinjs": "^0.0.4", |     "@antd-tiny-vue/cssinjs": "^0.0.4", | ||||||
|     "@ctrl/tinycolor": "^3.6.0", |     "@ctrl/tinycolor": "^3.6.0", | ||||||
|     "@v-c/utils": "^0.0.5", |     "@v-c/utils": "^0.0.12", | ||||||
|     "@vueuse/core": "^9.13.0", |     "@vueuse/core": "^9.13.0", | ||||||
|     "vue": "^3.2.0" |     "vue": "^3.2.0" | ||||||
|   }, |   }, | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							| @@ -10,7 +10,7 @@ specifiers: | |||||||
|   '@mistjs/tsconfig': ^1.0.0 |   '@mistjs/tsconfig': ^1.0.0 | ||||||
|   '@mistjs/tsconfig-vue': ^0.0.3 |   '@mistjs/tsconfig-vue': ^0.0.3 | ||||||
|   '@types/node': ^18.13.0 |   '@types/node': ^18.13.0 | ||||||
|   '@v-c/utils': ^0.0.5 |   '@v-c/utils': ^0.0.12 | ||||||
|   '@vitejs/plugin-vue-jsx': ^3.0.0 |   '@vitejs/plugin-vue-jsx': ^3.0.0 | ||||||
|   '@vueuse/core': ^9.13.0 |   '@vueuse/core': ^9.13.0 | ||||||
|   eslint: ^8.34.0 |   eslint: ^8.34.0 | ||||||
| @@ -28,7 +28,7 @@ dependencies: | |||||||
|   '@ant-design/colors': 7.0.0 |   '@ant-design/colors': 7.0.0 | ||||||
|   '@antd-tiny-vue/cssinjs': 0.0.4_vue@3.2.47 |   '@antd-tiny-vue/cssinjs': 0.0.4_vue@3.2.47 | ||||||
|   '@ctrl/tinycolor': 3.6.0 |   '@ctrl/tinycolor': 3.6.0 | ||||||
|   '@v-c/utils': 0.0.5 |   '@v-c/utils': 0.0.12 | ||||||
|   '@vueuse/core': 9.13.0_vue@3.2.47 |   '@vueuse/core': 9.13.0_vue@3.2.47 | ||||||
|   vue: 3.2.47 |   vue: 3.2.47 | ||||||
|  |  | ||||||
| @@ -1280,8 +1280,8 @@ packages: | |||||||
|       eslint-visitor-keys: 3.3.0 |       eslint-visitor-keys: 3.3.0 | ||||||
|     dev: true |     dev: true | ||||||
|  |  | ||||||
|   /@v-c/utils/0.0.5: |   /@v-c/utils/0.0.12: | ||||||
|     resolution: {integrity: sha512-HiK9iupJ3YIl4AO8VxvQMVh5G7pkTYo7wMhWdsWr6XOPw86p5MgWdQRLhQNX1WbDjA9BsbpjuO7I5PyEhGYoFw==} |     resolution: {integrity: sha512-onwjLSQpH6SG78WJnKiw8XgJfCgYtq59zFW19yiT22ik7ncaLkjojjCU0cAZDA6j6zY6li5U0VuZk91KbOrw2A==} | ||||||
|     dependencies: |     dependencies: | ||||||
|       lodash.clonedeep: 4.5.0 |       lodash.clonedeep: 4.5.0 | ||||||
|       vue: 3.2.47 |       vue: 3.2.47 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user