From b4e5d8584e0046ea08daadd332b0f4466b71385e Mon Sep 17 00:00:00 2001 From: WK Wong Date: Tue, 28 May 2024 21:34:44 +0800 Subject: [PATCH 1/4] fix(avatar): avoid passing `disableAnimation` prop to a DOM element --- .changeset/hungry-garlics-kiss.md | 5 ++++ packages/components/avatar/src/use-avatar.ts | 27 ++++++++++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 .changeset/hungry-garlics-kiss.md diff --git a/.changeset/hungry-garlics-kiss.md b/.changeset/hungry-garlics-kiss.md new file mode 100644 index 0000000000..d4253321e2 --- /dev/null +++ b/.changeset/hungry-garlics-kiss.md @@ -0,0 +1,5 @@ +--- +"@nextui-org/avatar": patch +--- + +avoid passing `disableAnimation` prop to a DOM element (#3109) diff --git a/packages/components/avatar/src/use-avatar.ts b/packages/components/avatar/src/use-avatar.ts index a7a89be77b..ea35a47212 100644 --- a/packages/components/avatar/src/use-avatar.ts +++ b/packages/components/avatar/src/use-avatar.ts @@ -196,14 +196,25 @@ export function useAvatar(originalProps: UseAvatarProps = {}) { ); const getImageProps = useCallback( - (props = {}) => ({ - ref: imgRef, - src: src, - disableAnimation, - "data-loaded": dataAttr(isImgLoaded), - className: slots.img({class: classNames?.img}), - ...mergeProps(imgProps, props), - }), + (props = {}) => { + let allowDisableAnimation = false; + + if ( + typeof ImgComponent !== "string" && + (ImgComponent as any)?.render?.displayName === "NextUI.Image" + ) { + allowDisableAnimation = true; + } + + return { + ref: imgRef, + src: src, + ...(allowDisableAnimation && {disableAnimation}), + "data-loaded": dataAttr(isImgLoaded), + className: slots.img({class: classNames?.img}), + ...mergeProps(imgProps, props), + }; + }, [slots, isImgLoaded, imgProps, disableAnimation, src, imgRef], ); From d482b61982440cf1b6defbe7a779045245ec8162 Mon Sep 17 00:00:00 2001 From: WK Wong Date: Wed, 29 May 2024 11:18:54 +0800 Subject: [PATCH 2/4] refactor(avatar): use filterDOMProps approach --- packages/components/avatar/src/use-avatar.ts | 47 ++++++++++---------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/packages/components/avatar/src/use-avatar.ts b/packages/components/avatar/src/use-avatar.ts index ea35a47212..b8eb80a2a1 100644 --- a/packages/components/avatar/src/use-avatar.ts +++ b/packages/components/avatar/src/use-avatar.ts @@ -1,11 +1,16 @@ import type {AvatarSlots, AvatarVariantProps, SlotsToClasses} from "@nextui-org/theme"; import {avatar} from "@nextui-org/theme"; -import {HTMLNextUIProps, PropGetter, useProviderContext} from "@nextui-org/system"; +import { + DOMAttributes, + DOMElement, + HTMLNextUIProps, + PropGetter, + useProviderContext, +} from "@nextui-org/system"; import {mergeProps} from "@react-aria/utils"; -import {useDOMRef} from "@nextui-org/react-utils"; +import {ReactRef, useDOMRef, filterDOMProps} from "@nextui-org/react-utils"; import {clsx, safeText, dataAttr} from "@nextui-org/shared-utils"; -import {ReactRef} from "@nextui-org/react-utils"; import {useFocusRing} from "@react-aria/focus"; import {useMemo, useCallback} from "react"; import {useImage} from "@nextui-org/use-image"; @@ -141,6 +146,8 @@ export function useAvatar(originalProps: UseAvatarProps = {}) { const isImgLoaded = imageStatus === "loaded"; + const shouldFilterDOMProps = typeof ImgComponent === "string"; + /** * Fallback avatar applies under 2 conditions: * - If `src` was passed and the image has not loaded or failed to load @@ -196,26 +203,20 @@ export function useAvatar(originalProps: UseAvatarProps = {}) { ); const getImageProps = useCallback( - (props = {}) => { - let allowDisableAnimation = false; - - if ( - typeof ImgComponent !== "string" && - (ImgComponent as any)?.render?.displayName === "NextUI.Image" - ) { - allowDisableAnimation = true; - } - - return { - ref: imgRef, - src: src, - ...(allowDisableAnimation && {disableAnimation}), - "data-loaded": dataAttr(isImgLoaded), - className: slots.img({class: classNames?.img}), - ...mergeProps(imgProps, props), - }; - }, - [slots, isImgLoaded, imgProps, disableAnimation, src, imgRef], + (props = {}) => ({ + ref: imgRef, + src: src, + "data-loaded": dataAttr(isImgLoaded), + className: slots.img({class: classNames?.img}), + ...mergeProps( + imgProps, + props, + filterDOMProps({disableAnimation} as DOMAttributes, { + enabled: shouldFilterDOMProps, + }), + ), + }), + [slots, isImgLoaded, imgProps, disableAnimation, src, imgRef, filterDOMProps], ); return { From 09d10f0a11ac6ba36d4098a4f12db990d4d3cdd9 Mon Sep 17 00:00:00 2001 From: WK Wong Date: Wed, 29 May 2024 11:29:34 +0800 Subject: [PATCH 3/4] chore(avatar): remove to type import --- packages/components/avatar/src/use-avatar.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/components/avatar/src/use-avatar.ts b/packages/components/avatar/src/use-avatar.ts index b8eb80a2a1..d297c85caa 100644 --- a/packages/components/avatar/src/use-avatar.ts +++ b/packages/components/avatar/src/use-avatar.ts @@ -1,13 +1,8 @@ import type {AvatarSlots, AvatarVariantProps, SlotsToClasses} from "@nextui-org/theme"; +import type {DOMElement, DOMAttributes, HTMLNextUIProps, PropGetter} from "@nextui-org/system"; import {avatar} from "@nextui-org/theme"; -import { - DOMAttributes, - DOMElement, - HTMLNextUIProps, - PropGetter, - useProviderContext, -} from "@nextui-org/system"; +import {useProviderContext} from "@nextui-org/system"; import {mergeProps} from "@react-aria/utils"; import {ReactRef, useDOMRef, filterDOMProps} from "@nextui-org/react-utils"; import {clsx, safeText, dataAttr} from "@nextui-org/shared-utils"; From a972ecceffe52589bb8c8f7b6293e9c9047b95f8 Mon Sep 17 00:00:00 2001 From: WK Wong Date: Thu, 30 May 2024 10:12:51 +0800 Subject: [PATCH 4/4] chore(avatar): change to shouldFilterDOMProps --- packages/components/avatar/src/use-avatar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/avatar/src/use-avatar.ts b/packages/components/avatar/src/use-avatar.ts index d297c85caa..e7f2b93757 100644 --- a/packages/components/avatar/src/use-avatar.ts +++ b/packages/components/avatar/src/use-avatar.ts @@ -211,7 +211,7 @@ export function useAvatar(originalProps: UseAvatarProps = {}) { }), ), }), - [slots, isImgLoaded, imgProps, disableAnimation, src, imgRef, filterDOMProps], + [slots, isImgLoaded, imgProps, disableAnimation, src, imgRef, shouldFilterDOMProps], ); return {