mirror of
https://github.com/element-plus/element-plus.git
synced 2024-11-27 02:01:15 +08:00
feat(components): [tooltip-v2] add new component (#6838)
* feat(components): [tooltip-v2] add new component - Init component * Implement trigger and only child * Fix typing issue
This commit is contained in:
parent
f6da924b21
commit
9919e0a867
0
packages/components/tooltip-v2/index.ts
Normal file
0
packages/components/tooltip-v2/index.ts
Normal file
0
packages/components/tooltip-v2/src/arrow.ts
Normal file
0
packages/components/tooltip-v2/src/arrow.ts
Normal file
0
packages/components/tooltip-v2/src/arrow.vue
Normal file
0
packages/components/tooltip-v2/src/arrow.vue
Normal file
0
packages/components/tooltip-v2/src/content.ts
Normal file
0
packages/components/tooltip-v2/src/content.ts
Normal file
0
packages/components/tooltip-v2/src/content.vue
Normal file
0
packages/components/tooltip-v2/src/content.vue
Normal file
38
packages/components/tooltip-v2/src/only-child.tsx
Normal file
38
packages/components/tooltip-v2/src/only-child.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import { Fragment, defineComponent, ref } from 'vue'
|
||||
import {
|
||||
buildProps,
|
||||
composeRefs,
|
||||
definePropType,
|
||||
ensureOnlyChild,
|
||||
} from '@element-plus/utils'
|
||||
|
||||
import type { ExtractPropTypes, VNodeArrayChildren } from 'vue'
|
||||
|
||||
export type RefSetter = (el: HTMLElement | null) => void
|
||||
|
||||
export const forwardRefProps = buildProps({
|
||||
setRef: { type: definePropType<RefSetter>(Function), required: true },
|
||||
} as const)
|
||||
|
||||
export type ForwardRefProps = ExtractPropTypes<typeof forwardRefProps>
|
||||
|
||||
// TODO: consider make this component a reusable component without the only child feature.
|
||||
export default defineComponent({
|
||||
props: forwardRefProps,
|
||||
setup(props, { slots }) {
|
||||
const fragmentRef = ref()
|
||||
const setRef = composeRefs(fragmentRef, (el) => {
|
||||
// vue fragments is represented as a text element.
|
||||
// The first element sibling should be the first element children of fragment.
|
||||
// This is how we get the element.
|
||||
props.setRef((el as HTMLElement).nextElementSibling as HTMLElement | null)
|
||||
})
|
||||
return () => {
|
||||
const [firstChild] = slots.default?.() || []
|
||||
const child = ensureOnlyChild(firstChild.children as VNodeArrayChildren)
|
||||
// Dunno why the ref for jsx complains about the typing issue which was not
|
||||
// in template
|
||||
return <Fragment ref={setRef as any}>{child}</Fragment>
|
||||
}
|
||||
},
|
||||
})
|
0
packages/components/tooltip-v2/src/root.ts
Normal file
0
packages/components/tooltip-v2/src/root.ts
Normal file
0
packages/components/tooltip-v2/src/root.vue
Normal file
0
packages/components/tooltip-v2/src/root.vue
Normal file
0
packages/components/tooltip-v2/src/tooltip.ts
Normal file
0
packages/components/tooltip-v2/src/tooltip.ts
Normal file
9
packages/components/tooltip-v2/src/tooltip.vue
Normal file
9
packages/components/tooltip-v2/src/tooltip.vue
Normal file
@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<slot />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// import { computed, ref } from 'vue'
|
||||
|
||||
// import { useFloating } from '@element-plus/hooks'
|
||||
</script>
|
11
packages/components/tooltip-v2/src/trigger.ts
Normal file
11
packages/components/tooltip-v2/src/trigger.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { buildProps } from '@element-plus/utils'
|
||||
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
|
||||
export const tooltipTriggerV2Props = buildProps({
|
||||
asChild: Boolean,
|
||||
} as const)
|
||||
|
||||
export type TooltipTriggerV2Props = ExtractPropTypes<
|
||||
typeof tooltipTriggerV2Props
|
||||
>
|
20
packages/components/tooltip-v2/src/trigger.vue
Normal file
20
packages/components/tooltip-v2/src/trigger.vue
Normal file
@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<only-child v-if="asChild" :set-ref="setTriggerRef">
|
||||
<slot />
|
||||
</only-child>
|
||||
<button v-else ref="triggerRef">
|
||||
<slot />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import OnlyChild from './only-child'
|
||||
import { tooltipTriggerV2Props } from './trigger'
|
||||
|
||||
defineProps(tooltipTriggerV2Props)
|
||||
const triggerRef = ref<HTMLElement | null>(null)
|
||||
const setTriggerRef = (el: HTMLElement | null) => {
|
||||
triggerRef.value = el
|
||||
}
|
||||
</script>
|
@ -1,9 +1,21 @@
|
||||
import { isFunction } from '@element-plus/utils'
|
||||
|
||||
import type { ComponentPublicInstance, Ref } from 'vue'
|
||||
|
||||
export const composeRefs = (...refs: Ref<HTMLElement | undefined>[]) => {
|
||||
export type RefSetter = (
|
||||
el: Element | ComponentPublicInstance | undefined
|
||||
) => void
|
||||
|
||||
export const composeRefs = (
|
||||
...refs: (Ref<HTMLElement | undefined> | RefSetter)[]
|
||||
) => {
|
||||
return (el: Element | ComponentPublicInstance | null) => {
|
||||
refs.forEach((ref) => {
|
||||
ref.value = el as HTMLElement | undefined
|
||||
if (isFunction(ref)) {
|
||||
ref(el as Element | ComponentPublicInstance)
|
||||
} else {
|
||||
ref.value = el as HTMLElement | undefined
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,15 @@ import {
|
||||
isVNode,
|
||||
openBlock,
|
||||
} from 'vue'
|
||||
import { isArray } from '@vue/shared'
|
||||
import { hasOwn } from '../objects'
|
||||
import { debugWarn } from '../error'
|
||||
import type { VNode, VNodeChild, VNodeNormalizedChildren } from 'vue'
|
||||
import type {
|
||||
VNode,
|
||||
VNodeArrayChildren,
|
||||
VNodeChild,
|
||||
VNodeNormalizedChildren,
|
||||
} from 'vue'
|
||||
|
||||
const SCOPE = 'utils/vue/vnode'
|
||||
|
||||
@ -125,3 +131,10 @@ export const getNormalizedProps = (node: VNode) => {
|
||||
|
||||
return props
|
||||
}
|
||||
|
||||
export const ensureOnlyChild = (children: VNodeArrayChildren | undefined) => {
|
||||
if (!isArray(children) || children.length > 1) {
|
||||
throw new Error('expect to receive a single Vue element child')
|
||||
}
|
||||
return children[0]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user