From 69388270af582110293d4c7dccc61b93cb91a969 Mon Sep 17 00:00:00 2001 From: aibayanyu Date: Sat, 18 Mar 2023 20:48:10 +0800 Subject: [PATCH] feat: add wave --- components/_util/wave/index.tsx | 54 +++++++++++++++++++++++++-- components/_util/wave/use-wave.ts | 11 ++++++ components/_util/wave/wave-effect.tsx | 32 ++++++++++++++++ package.json | 2 +- pnpm-lock.yaml | 8 ++-- 5 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 components/_util/wave/use-wave.ts create mode 100644 components/_util/wave/wave-effect.tsx diff --git a/components/_util/wave/index.tsx b/components/_util/wave/index.tsx index 6af4c35..b18fb5f 100644 --- a/components/_util/wave/index.tsx +++ b/components/_util/wave/index.tsx @@ -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({ 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 slots.default?.() + const children = slots.default?.() + const child = filterEmpty(children)[0] + if (!child) return null + return cloneVNode(child as VNode, { ref: containerRef }) } } }) diff --git a/components/_util/wave/use-wave.ts b/components/_util/wave/use-wave.ts new file mode 100644 index 0000000..f18a73e --- /dev/null +++ b/components/_util/wave/use-wave.ts @@ -0,0 +1,11 @@ +import type { ComputedRef, Ref } from 'vue' +import showWaveEffect from './wave-effect' + +export default function useWave(nodeRef: Ref, className: ComputedRef): VoidFunction { + function showWave() { + // const node = nodeRef.va! + showWaveEffect(nodeRef, className) + } + + return showWave +} diff --git a/components/_util/wave/wave-effect.tsx b/components/_util/wave/wave-effect.tsx new file mode 100644 index 0000000..7a08a7e --- /dev/null +++ b/components/_util/wave/wave-effect.tsx @@ -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() + }, + setup() { + return () => null + } +}) + +export default function showWaveEffect(nodeRef: Ref, className: ComputedRef) { + 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( + , + holder + ) +} diff --git a/package.json b/package.json index 65dc9b8..4cf8689 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@ant-design/colors": "^7.0.0", "@antd-tiny-vue/cssinjs": "^0.0.4", "@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.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 25c46ef..568b67d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ specifiers: '@mistjs/tsconfig': ^1.0.0 '@mistjs/tsconfig-vue': ^0.0.3 '@types/node': ^18.13.0 - '@v-c/utils': ^0.0.5 + '@v-c/utils': ^0.0.12 '@vitejs/plugin-vue-jsx': ^3.0.0 '@vueuse/core': ^9.13.0 eslint: ^8.34.0 @@ -28,7 +28,7 @@ dependencies: '@ant-design/colors': 7.0.0 '@antd-tiny-vue/cssinjs': 0.0.4_vue@3.2.47 '@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 vue: 3.2.47 @@ -1280,8 +1280,8 @@ packages: eslint-visitor-keys: 3.3.0 dev: true - /@v-c/utils/0.0.5: - resolution: {integrity: sha512-HiK9iupJ3YIl4AO8VxvQMVh5G7pkTYo7wMhWdsWr6XOPw86p5MgWdQRLhQNX1WbDjA9BsbpjuO7I5PyEhGYoFw==} + /@v-c/utils/0.0.12: + resolution: {integrity: sha512-onwjLSQpH6SG78WJnKiw8XgJfCgYtq59zFW19yiT22ik7ncaLkjojjCU0cAZDA6j6zY6li5U0VuZk91KbOrw2A==} dependencies: lodash.clonedeep: 4.5.0 vue: 3.2.47