From a4c17ee50f91f575cd90c44658e39a2bd3167549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=B7=BB?= <657454579@qq.com> Date: Fri, 19 Jan 2024 11:46:49 +0800 Subject: [PATCH] feat(components): [tour] target prop add more type (#15578) * feat(components): [tour] target prop add more type * docs(components): [tour] target prop add description * docs(components): [tour] add example and version tag --- docs/en-US/component/tour.md | 40 ++++++++++++++++---------- docs/examples/tour/target.vue | 36 +++++++++++++++++++++++ packages/components/tour/src/helper.ts | 39 +++++++++++++++++++------ packages/components/tour/src/step.ts | 4 ++- packages/components/tour/src/types.ts | 2 +- 5 files changed, 96 insertions(+), 25 deletions(-) create mode 100644 docs/examples/tour/target.vue diff --git a/docs/en-US/component/tour.md b/docs/en-US/component/tour.md index f27b0535dc..34459f9856 100644 --- a/docs/en-US/component/tour.md +++ b/docs/en-US/component/tour.md @@ -57,6 +57,16 @@ tour/indicator ::: +## Target + +Various parameter passing types of target. The string and Function types are supported since ^(2.5.2). + +:::demo + +tour/target + +::: + ## Tour API :::tip @@ -98,21 +108,21 @@ tour-step component configuration with the same name has higher priority ### TourStep Attributes -| Property | Description | Type | Default | -| ------------------------ | ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | -| target | get the element the guide card points to. Empty makes it show in center of screen | `HTMLElement` | - | -| show-arrow | whether to show the arrow | `boolean` | `true` | -| title | title | `string` | - | -| description | description | `string` | - | -| placement | position of the guide card relative to the target element | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | `bottom` | -| content-style | custom style for content | `CSSProperties` | - | -| mask | whether to enable masking, change mask style and fill color by pass custom props | `boolean` \| ^[Object]`{ style?: CSSProperties; color?: string; }` | `true` | -| type | type, affects the background color and text color | `default` \| `primary` | `default` | -| next-button-props | properties of the Next button | ^[Object]`{ children: VueNode \| string; onClick: Function }` | - | -| prev-button-props | properties of the previous button | ^[Object]`{ children: VueNode \| string; onClick: Function }` | - | -| scroll-into-view-options | support pass custom scrollIntoView options, the default follows the `scrollIntoViewOptions` property of Tour | `boolean` \| `ScrollIntoViewOptions` | - | -| show-close | whether to show a close button | `boolean` | `true` | -| close-icon | custom close icon, default is Close | `string` \| `Component` | - | +| Property | Description | Type | Default | +| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | +| target | get the element the guide card points to. Empty makes it show in center of screen. the string and Function types are supported since ^(2.5.2). the string type is selectors of document.querySelector. | `HTMLElement` \| `string` \| ^[Function]`() => HTMLElement` | - | +| show-arrow | whether to show the arrow | `boolean` | `true` | +| title | title | `string` | - | +| description | description | `string` | - | +| placement | position of the guide card relative to the target element | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | `bottom` | +| content-style | custom style for content | `CSSProperties` | - | +| mask | whether to enable masking, change mask style and fill color by pass custom props | `boolean` \| ^[Object]`{ style?: CSSProperties; color?: string; }` | `true` | +| type | type, affects the background color and text color | `default` \| `primary` | `default` | +| next-button-props | properties of the Next button | ^[Object]`{ children: VueNode \| string; onClick: Function }` | - | +| prev-button-props | properties of the previous button | ^[Object]`{ children: VueNode \| string; onClick: Function }` | - | +| scroll-into-view-options | support pass custom scrollIntoView options, the default follows the `scrollIntoViewOptions` property of Tour | `boolean` \| `ScrollIntoViewOptions` | - | +| show-close | whether to show a close button | `boolean` | `true` | +| close-icon | custom close icon, default is Close | `string` \| `Component` | - | ### TourStep slots diff --git a/docs/examples/tour/target.vue b/docs/examples/tour/target.vue new file mode 100644 index 0000000000..402c7b3013 --- /dev/null +++ b/docs/examples/tour/target.vue @@ -0,0 +1,36 @@ + + + diff --git a/packages/components/tour/src/helper.ts b/packages/components/tour/src/helper.ts index fe6d6464ea..583386b134 100644 --- a/packages/components/tour/src/helper.ts +++ b/packages/components/tour/src/helper.ts @@ -18,7 +18,14 @@ import { offset as offsetMiddelware, shift, } from '@floating-ui/dom' -import { hasOwn, isArray, isClient, keysOf } from '@element-plus/utils' +import { + hasOwn, + isArray, + isClient, + isFunction, + isString, + keysOf, +} from '@element-plus/utils' import type { CSSProperties, @@ -40,7 +47,9 @@ import type { } from '@floating-ui/dom' export const useTarget = ( - target: Ref, + target: Ref< + string | HTMLElement | (() => HTMLElement | null) | null | undefined + >, open: Ref, gap: Ref, mergedMask: Ref, @@ -48,15 +57,28 @@ export const useTarget = ( ) => { const posInfo: Ref = ref(null) + const getTargetEl = () => { + let targetEl: HTMLElement | null | undefined + if (isString(target.value)) { + targetEl = document.querySelector(target.value) + } else if (isFunction(target.value)) { + targetEl = target.value() + } else { + targetEl = target.value + } + return targetEl + } + const updatePosInfo = () => { - if (!target.value || !open.value) { + const targetEl = getTargetEl() + if (!targetEl || !open.value) { posInfo.value = null return } - if (!isInViewPort(target.value) && open.value) { - target.value.scrollIntoView(scrollIntoViewOptions.value) + if (!isInViewPort(targetEl) && open.value) { + targetEl.scrollIntoView(scrollIntoViewOptions.value) } - const { left, top, width, height } = target.value.getBoundingClientRect() + const { left, top, width, height } = targetEl.getBoundingClientRect() posInfo.value = { left, top, @@ -104,8 +126,9 @@ export const useTarget = ( }) const triggerTarget = computed(() => { - if (!mergedMask.value || !target.value || !window.DOMRect) { - return target.value || undefined + const targetEl = getTargetEl() + if (!mergedMask.value || !targetEl || !window.DOMRect) { + return targetEl || undefined } return { diff --git a/packages/components/tour/src/step.ts b/packages/components/tour/src/step.ts index b683b0ddbc..9a48108cff 100644 --- a/packages/components/tour/src/step.ts +++ b/packages/components/tour/src/step.ts @@ -8,7 +8,9 @@ export const tourStepProps = buildProps({ * @description get the element the guide card points to. empty makes it show in center of screen */ target: { - type: definePropType(Object), + type: definePropType< + string | HTMLElement | (() => HTMLElement | null) | null + >([String, Object, Function]), }, /** * @description the title of the tour content diff --git a/packages/components/tour/src/types.ts b/packages/components/tour/src/types.ts index ed219a92fe..cd8284d5d2 100644 --- a/packages/components/tour/src/types.ts +++ b/packages/components/tour/src/types.ts @@ -29,7 +29,7 @@ export interface PosInfo { } export interface UsedTourStepProps { - target?: HTMLElement | null + target?: string | HTMLElement | (() => HTMLElement | null) | null showArrow?: boolean placement?: Placement contentStyle?: CSSProperties