Skip to content
This repository has been archived by the owner on Nov 12, 2024. It is now read-only.

Update SolidJS implementation #208

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@rollup/plugin-replace": "^5.0.1",
"@types/jest": "^27.0.3",
"bundlesize": "^0.18.1",
"babel-preset-solid": "^1.7.7",
"concurrently": "^7.3.0",
"jest": "^27.4.4",
"lerna": "^4.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const baseConfig = require("config/jest.config")
const config = {
...baseConfig,
preset: "solid-jest/preset/browser",
setupFilesAfterEnv: ["<rootDir>/../jest.setup.js"],
setupFilesAfterEnv: ["<rootDir>/../jest.setup.cjs"],
testPathIgnorePatterns: ["/node_modules/", "ssr"],
}

Expand Down
33 changes: 18 additions & 15 deletions packages/solid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@
"files": [
"dist"
],
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"types": "dist/types/index.d.ts",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/types/index.d.ts",
"type": "module",
"exports": {
".": {
"solid": "./dist/source/index.jsx",
"import": "./dist/esm/index.js",
"browser": "./dist/esm/index.js",
"require": "./dist/cjs/index.js",
"node": "./dist/cjs/index.js"
"solid": "./dist/source/index.jsx",
"import": {
"types": "./dist/types/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/types/index.d.ts",
"default": "./dist/cjs/index.js"
}
},
"bundlesize": [
Expand All @@ -32,23 +35,23 @@
"scripts": {
"build": "rimraf dist && rollup -c",
"test": "yarn test:browser && yarn test:ssr",
"test:browser": "jest --coverage --config jest.config.js",
"test:ssr": "jest --config jest.ssrconfig.js",
"test:browser": "jest --coverage --config jest.config.cjs",
"test:ssr": "jest --config jest.ssrconfig.cjs",
"measure": "bundlesize"
},
"dependencies": {
"@motionone/dom": "^10.16.2",
"@motionone/utils": "^10.15.1",
"@solid-primitives/props": "^3.1.1",
"@solid-primitives/refs": "^1.0.0",
"@solid-primitives/transition-group": "^1.0.0"
"@solid-primitives/props": "^3.1.8",
"@solid-primitives/refs": "^1.0.5",
"@solid-primitives/transition-group": "^1.0.3"
},
"devDependencies": {
"@babel/preset-env": "7.20.2",
"@babel/preset-typescript": "^7.18.6",
"rollup-preset-solid": "^1.4.0",
"solid-jest": "^0.2.0",
"solid-js": "^1.6.11",
"solid-js": "^1.7.9",
"solid-testing-library": "^0.5.1"
},
"peerDependencies": {
Expand Down
139 changes: 113 additions & 26 deletions packages/solid/src/__tests__/presence.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { mountedStates } from "@motionone/dom"
import { createRoot, createSignal, Show } from "solid-js"
import { children, createRoot, createSignal, Show } from "solid-js"
import { screen, render } from "solid-testing-library"
import { Presence, Motion, VariantDefinition } from ".."
import type { RefProps } from "@solid-primitives/refs"

const TestComponent = (
props: {
Expand Down Expand Up @@ -36,7 +37,7 @@ describe("Presence", () => {
<TestComponent show initial={false} animate={{ opacity: 0.5 }} />
))
expect(wrapper.container.outerHTML).toEqual(
`<div><div data-testid="child" style="opacity: 0.5;"></div></div>`
`<div><div style="opacity: 0.5;" data-testid="child"></div></div>`
)
})

Expand Down Expand Up @@ -67,37 +68,123 @@ describe("Presence", () => {
})
}))

test("All children run their exit animation", () =>
createRoot(async () => {
const [show, setShow] = createSignal(true)
render(() => (
test("All children run their exit animation", async () => {
const [show, setShow] = createSignal(true)

let ref_1!: HTMLDivElement, ref_2!: HTMLDivElement
let resolve_1: () => void, resolve_2: () => void

const exit_animation: VariantDefinition = {
opacity: 0,
transition: { duration: 0.001 },
}

const rendered = createRoot(() =>
children(() => (
<Presence>
<Show when={show()}>
<Motion.div
data-testid="child1"
exit={{ opacity: 0, transition: { duration: 0.001 } }}
<Motion
ref={ref_1}
exit={exit_animation}
onMotionComplete={() => resolve_1()}
>
<Motion
data-testid="child2"
exit={{ opacity: 0, transition: { duration: 0.001 } }}
></Motion>
</Motion.div>
ref={ref_2}
exit={exit_animation}
onMotionComplete={() => resolve_2()}
/>
</Motion>
</Show>
</Presence>
))
const child1 = await screen.findByTestId("child1")
const child2 = await screen.findByTestId("child2")
)

setShow(false)
expect(rendered()).toContain(ref_1)
expect(ref_1).toContainElement(ref_2)
expect(ref_1.style.opacity).toBe("")
expect(ref_2.style.opacity).toBe("")
expect(mountedStates.has(ref_1)).toBeTruthy()
expect(mountedStates.has(ref_2)).toBeTruthy()

return new Promise<void>((resolve) => {
setTimeout(() => {
expect(child1.style.opacity).toBe("0")
expect(mountedStates.has(child1)).toBeFalsy()
expect(child2.style.opacity).toBe("0")
expect(mountedStates.has(child2)).toBeFalsy()
resolve()
}, 100)
})
}))
setShow(false)

expect(rendered()).toContain(ref_1)
expect(ref_1.style.opacity).toBe("")
expect(ref_2.style.opacity).toBe("")

await new Promise<void>((resolve) => {
let count = 0
resolve_1 = resolve_2 = () => {
if (++count === 2) resolve()
}
})

expect(rendered()).toHaveLength(0)
expect(ref_1.style.opacity).toBe("0")
expect(ref_2.style.opacity).toBe("0")
expect(mountedStates.has(ref_1)).toBeFalsy()
expect(mountedStates.has(ref_2)).toBeFalsy()
})

test("exitBeforeEnter delays enter animation until exit animation is complete", async () => {
const [condition, setCondition] = createSignal(true)

let ref_1!: HTMLDivElement, ref_2!: HTMLDivElement
let resolve_last: (() => void) | undefined

const El = (props: RefProps<HTMLDivElement>) => (
<Motion.div
ref={props.ref}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.001 }}
onMotionComplete={() => resolve_last?.()}
/>
)

const rendered = createRoot(() =>
children(() => (
<Presence exitBeforeEnter>
<Show
when={condition()}
children={<El ref={ref_1} />}
fallback={<El ref={ref_2} />}
/>
</Presence>
))
)

expect(rendered()).toContain(ref_1)
expect(ref_1.style.opacity).toBe("0")

// enter 1
await new Promise<void>((resolve) => (resolve_last = resolve))

expect(rendered()).toContain(ref_1)
expect(ref_1.style.opacity).toBe("1")

setCondition(false)

expect(rendered()).toContain(ref_1)
expect(rendered()).not.toContain(ref_2)
expect(ref_1.style.opacity).toBe("1")
expect(ref_2.style.opacity).toBe("0")

// exit 1
await new Promise<void>((resolve) => (resolve_last = resolve))

expect(rendered()).toContain(ref_2)
expect(rendered()).not.toContain(ref_1)
expect(ref_1.style.opacity).toBe("0")
expect(ref_2.style.opacity).toBe("0")

// enter 2
await new Promise<void>((resolve) => (resolve_last = resolve))

expect(rendered()).toContain(ref_2)
expect(rendered()).not.toContain(ref_1)
expect(ref_1.style.opacity).toBe("0")
expect(ref_2.style.opacity).toBe("1")
})
})
58 changes: 27 additions & 31 deletions packages/solid/src/__tests__/primitives.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ motion

const duration = 0.001

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))

describe("motion directive", () => {
test("Applies initial as style to DOM node", async () => {
await render(() => (
Expand Down Expand Up @@ -47,37 +49,31 @@ describe("motion directive", () => {
})

test("Animation runs when target changes", async () => {
await createRoot(async (dispose) => {
const [animate, setAnimate] = createSignal({ opacity: 0.5 })

const element = await new Promise((resolve) => {
const Component = (props: any) => {
let ref!: HTMLDivElement
setTimeout(() => resolve(ref), 100)
return (
<div
ref={ref}
use:motion={{
initial: { opacity: 0 },
animate: props.animate,
transition: { duration },
}}
/>
)
}
render(() => <Component animate={animate()} />)
})
expect(element).toHaveStyle("opacity: 0.5")

await new Promise<void>((resolve) => {
setAnimate({ opacity: 0.8 })
setTimeout(() => {
expect(element).toHaveStyle("opacity: 0.8")
dispose()
resolve()
}, 100)
})
})
const [opacity, setOpacity] = createSignal(0.5)

const element = createRoot(() => (
<div
use:motion={{
initial: { opacity: 0 },
animate: { opacity: opacity() },
transition: { duration },
}}
/>
)) as HTMLDivElement

expect(element.style.opacity).toBe("0")

await sleep(100)

expect(element.style.opacity).toBe("0.5")

setOpacity(0.8)

expect(element.style.opacity).toBe("0.5")

await sleep(100)

expect(element.style.opacity).toBe("0.8")
})

test("Accepts default transition", async () => {
Expand Down
Loading