From 631f8cecc19125120e957fadddce4582f5c86a48 Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Fri, 7 Jan 2022 11:38:24 +0100 Subject: [PATCH 1/4] Adding isValidProp to MotionConfig --- CHANGELOG.md | 6 +++++ src/components/MotionConfig/index.tsx | 13 +++++++++- src/projection/node/create-projection-node.ts | 9 +++++++ src/render/dom/utils/filter-props.ts | 26 ++++++++++++------- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b86b2c3469..3115373bea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ Framer Motion adheres to [Semantic Versioning](http://semver.org/). +## [5.6.0] 2022-01-12 + +### Added + +- `isValidProp` prop to `MotionConfig` that allows the injection of custom detection of valid React props. + ## [5.5.8] 2022-01-12 ### Fixed diff --git a/src/components/MotionConfig/index.tsx b/src/components/MotionConfig/index.tsx index 4917b5f6eb..b7ee8e958f 100644 --- a/src/components/MotionConfig/index.tsx +++ b/src/components/MotionConfig/index.tsx @@ -1,10 +1,15 @@ import * as React from "react" import { useContext, useMemo } from "react" import { MotionConfigContext } from "../../context/MotionConfigContext" +import { + loadExternalIsValidProp, + IsValidProp, +} from "../../render/dom/utils/filter-props" import { useConstant } from "../../utils/use-constant" export interface MotionConfigProps extends Partial { children?: React.ReactNode + isValidProp?: IsValidProp } /** @@ -24,7 +29,13 @@ export interface MotionConfigProps extends Partial { * * @public */ -export function MotionConfig({ children, ...config }: MotionConfigProps) { +export function MotionConfig({ + children, + isValidProp, + ...config +}: MotionConfigProps) { + isValidProp && loadExternalIsValidProp(isValidProp) + /** * Inherit props from any parent MotionConfig components */ diff --git a/src/projection/node/create-projection-node.ts b/src/projection/node/create-projection-node.ts index 11a42c9f7e..e17f8d4115 100644 --- a/src/projection/node/create-projection-node.ts +++ b/src/projection/node/create-projection-node.ts @@ -680,6 +680,15 @@ export function createProjectionNode({ measured, actual: this.removeElementScroll(measured), } + + if ((this.instance as any).title) + console.log( + (this.instance as any).title, + "layout", + this.layout.actual, + this.layout.measured + ) + this.layoutCorrected = createBox() this.isLayoutDirty = false this.projectionDelta = undefined diff --git a/src/render/dom/utils/filter-props.ts b/src/render/dom/utils/filter-props.ts index 06184575c2..0ad789df71 100644 --- a/src/render/dom/utils/filter-props.ts +++ b/src/render/dom/utils/filter-props.ts @@ -3,6 +3,16 @@ import { isValidMotionProp } from "../../../motion/utils/valid-prop" let shouldForward = (key: string) => !isValidMotionProp(key) +export type IsValidProp = (key: string) => boolean + +export function loadExternalIsValidProp(emotionIsPropValid?: IsValidProp) { + if (!emotionIsPropValid) return + + // Handle events explicitly as Emotion validates them all as true + shouldForward = (key: string) => + key.startsWith("on") ? !isValidMotionProp(key) : emotionIsPropValid(key) +} + /** * Emotion and Styled Components both allow users to pass through arbitrary props to their components * to dynamically generate CSS. They both use the `@emotion/is-prop-valid` package to determine which @@ -17,16 +27,12 @@ let shouldForward = (key: string) => !isValidMotionProp(key) * actually required. */ try { - const emotionIsPropValid = require("@emotion/is-prop-valid").default - - shouldForward = (key: string) => { - // Handle events explicitly as Emotion validates them all as true - if (key.startsWith("on")) { - return !isValidMotionProp(key) - } else { - return emotionIsPropValid(key) - } - } + /** + * We attempt to import this package but require won't be defined in esm environments, in that case + * isPropValid will have to be provided via `MotionContext`. In a 6.0.0 this should probably be removed + * in favour of explicit injection. + */ + loadExternalIsValidProp(require("@emotion/is-prop-valid").default) } catch { // We don't need to actually do anything here - the fallback is the existing `isPropValid`. } From d3b24d756108e804574406f25759d4eec2a96594 Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Fri, 7 Jan 2022 11:51:33 +0100 Subject: [PATCH 2/4] Removing console.log --- src/projection/node/create-projection-node.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/projection/node/create-projection-node.ts b/src/projection/node/create-projection-node.ts index e17f8d4115..a5812a9fb6 100644 --- a/src/projection/node/create-projection-node.ts +++ b/src/projection/node/create-projection-node.ts @@ -681,14 +681,6 @@ export function createProjectionNode({ actual: this.removeElementScroll(measured), } - if ((this.instance as any).title) - console.log( - (this.instance as any).title, - "layout", - this.layout.actual, - this.layout.measured - ) - this.layoutCorrected = createBox() this.isLayoutDirty = false this.projectionDelta = undefined From 2f7ba170a178b1924595eb30d88dfb4bee6cf0fc Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Fri, 7 Jan 2022 11:59:09 +0100 Subject: [PATCH 3/4] Changing prop --- .../MotionConfig/__tests__/index.test.tsx | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/components/MotionConfig/__tests__/index.test.tsx diff --git a/src/components/MotionConfig/__tests__/index.test.tsx b/src/components/MotionConfig/__tests__/index.test.tsx new file mode 100644 index 0000000000..63920b89e7 --- /dev/null +++ b/src/components/MotionConfig/__tests__/index.test.tsx @@ -0,0 +1,20 @@ +import { render } from "../../../../jest.setup" +import { motion } from "../../../render/dom/motion" +import { MotionConfig } from "../" +import * as React from "react" + +describe("custom properties", () => { + test("renders", () => { + const Component = () => { + return ( + key !== "data-foo"}> + + + ) + } + + const { container } = render() + + expect(container.firstChild).not.toHaveAttribute("data-foo") + }) +}) From 8e7667a3477f6f840a723c25a186da7b6bd13277 Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Wed, 12 Jan 2022 13:08:26 +0100 Subject: [PATCH 4/4] Addressing comments --- src/components/MotionConfig/__tests__/index.test.tsx | 3 ++- src/render/dom/utils/filter-props.ts | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/MotionConfig/__tests__/index.test.tsx b/src/components/MotionConfig/__tests__/index.test.tsx index 63920b89e7..fa1e292eaf 100644 --- a/src/components/MotionConfig/__tests__/index.test.tsx +++ b/src/components/MotionConfig/__tests__/index.test.tsx @@ -8,7 +8,7 @@ describe("custom properties", () => { const Component = () => { return ( key !== "data-foo"}> - + ) } @@ -16,5 +16,6 @@ describe("custom properties", () => { const { container } = render() expect(container.firstChild).not.toHaveAttribute("data-foo") + expect(container.firstChild).toHaveAttribute("data-bar") }) }) diff --git a/src/render/dom/utils/filter-props.ts b/src/render/dom/utils/filter-props.ts index 0ad789df71..15a343cc84 100644 --- a/src/render/dom/utils/filter-props.ts +++ b/src/render/dom/utils/filter-props.ts @@ -5,12 +5,12 @@ let shouldForward = (key: string) => !isValidMotionProp(key) export type IsValidProp = (key: string) => boolean -export function loadExternalIsValidProp(emotionIsPropValid?: IsValidProp) { - if (!emotionIsPropValid) return +export function loadExternalIsValidProp(isValidProp?: IsValidProp) { + if (!isValidProp) return - // Handle events explicitly as Emotion validates them all as true + // Explicitly filter our events shouldForward = (key: string) => - key.startsWith("on") ? !isValidMotionProp(key) : emotionIsPropValid(key) + key.startsWith("on") ? !isValidMotionProp(key) : isValidProp(key) } /**