Skip to content

Commit d4f96f8

Browse files
authored
Render root as child (#475)
1 parent 63936d1 commit d4f96f8

File tree

6 files changed

+142
-128
lines changed

6 files changed

+142
-128
lines changed

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lenis",
3-
"version": "1.3.8",
3+
"version": "1.3.9-dev.1",
44
"description": "How smooth scroll should be",
55
"type": "module",
66
"sideEffects": false,
@@ -39,8 +39,9 @@
3939
"version:minor": "npm version minor --force --no-git-tag-version",
4040
"version:major": "npm version major --force --no-git-tag-version",
4141
"postversion": "pnpm build && pnpm readme",
42-
"publish:main": "npm publish",
43-
"publish:dev": "npm publish --tag dev"
42+
"publish:dev": "npm publish --tag dev",
43+
"publish:main": "npm publish"
44+
4445
},
4546
"files": [
4647
"dist"

packages/react/src/provider.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,13 @@ export const ReactLenis = forwardRef<LenisRef, LenisProps>(
3030
children,
3131
root = false,
3232
options = {},
33-
className,
3433
autoRaf = true,
35-
style,
36-
props,
34+
...props
3735
}: LenisProps,
3836
ref
3937
) => {
40-
const wrapperRef = useRef<HTMLDivElement | null>(null)
41-
const contentRef = useRef<HTMLDivElement | null>(null)
38+
const wrapperRef = useRef<HTMLDivElement>(null)
39+
const contentRef = useRef<HTMLDivElement>(null)
4240

4341
const [lenis, setLenis] = useState<Lenis | undefined>(undefined)
4442

@@ -57,10 +55,11 @@ export const ReactLenis = forwardRef<LenisRef, LenisProps>(
5755
useEffect(() => {
5856
const lenis = new Lenis({
5957
...options,
60-
...(!root && {
61-
wrapper: wrapperRef.current!,
62-
content: contentRef.current!,
63-
}),
58+
...(wrapperRef.current &&
59+
contentRef.current && {
60+
wrapper: wrapperRef.current!,
61+
content: contentRef.current!,
62+
}),
6463
autoRaf: options?.autoRaf ?? autoRaf, // this is to avoid breaking the autoRaf prop if it's still used (require breaking change)
6564
})
6665

@@ -70,7 +69,7 @@ export const ReactLenis = forwardRef<LenisRef, LenisProps>(
7069
lenis.destroy()
7170
setLenis(undefined)
7271
}
73-
}, [root, JSON.stringify(options)])
72+
}, [root, JSON.stringify({ ...options, wrapper: null, content: null })])
7473

7574
// Handle callbacks
7675
const callbacksRefs = useRef<
@@ -123,14 +122,16 @@ export const ReactLenis = forwardRef<LenisRef, LenisProps>(
123122
}
124123
}, [lenis])
125124

125+
if (!children) return null
126+
126127
return (
127128
<LenisContext.Provider
128129
value={{ lenis: lenis!, addCallback, removeCallback }}
129130
>
130-
{root ? (
131+
{root && root !== 'asChild' ? (
131132
children
132133
) : (
133-
<div ref={wrapperRef} className={className} style={style} {...props}>
134+
<div ref={wrapperRef} {...props}>
134135
<div ref={contentRef}>{children}</div>
135136
</div>
136137
)}

packages/react/src/types.ts

Lines changed: 51 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,51 @@
1-
import type Lenis from 'lenis'
2-
import type { LenisOptions, ScrollCallback } from 'lenis'
3-
import type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from 'react'
4-
5-
export type LenisContextValue = {
6-
lenis: Lenis
7-
addCallback: (callback: ScrollCallback, priority: number) => void
8-
removeCallback: (callback: ScrollCallback) => void
9-
}
10-
11-
export type LenisProps = {
12-
/**
13-
* Setup a global instance of Lenis
14-
* @default false
15-
*/
16-
root?: boolean
17-
/**
18-
* Lenis options
19-
*/
20-
options?: LenisOptions
21-
/**
22-
* Auto-setup requestAnimationFrame
23-
* @default true
24-
* @deprecated use options.autoRaf instead
25-
*/
26-
autoRaf?: boolean
27-
/**
28-
* Children
29-
*/
30-
children?: ReactNode
31-
/**
32-
* Class name for the wrapper div
33-
*
34-
* When `root` is `false`, this will be applied to the wrapper div
35-
*/
36-
className?: string
37-
/**
38-
* Style for the wrapper div
39-
*
40-
* When `root` is `false`, this will be applied to the wrapper div
41-
*/
42-
style?: CSSProperties
43-
/**
44-
* Additional props for the wrapper div
45-
*
46-
* When `root` is `false`, this will be applied to the wrapper div
47-
*/
48-
props?: Omit<ComponentPropsWithoutRef<'div'>, 'children' | 'className'>
49-
}
50-
51-
export type LenisRef = {
52-
/**
53-
* The wrapper div element
54-
*
55-
* Will only be defined if `root` is `false`
56-
*/
57-
wrapper: HTMLDivElement | null
58-
/**
59-
* The content div element
60-
*
61-
* Will only be defined if `root` is `false`
62-
*/
63-
content: HTMLDivElement | null
64-
/**
65-
* The lenis instance
66-
*/
67-
lenis?: Lenis
68-
}
1+
import type Lenis from 'lenis'
2+
import type { LenisOptions, ScrollCallback } from 'lenis'
3+
import type { ComponentPropsWithoutRef, ReactNode } from 'react'
4+
5+
export type LenisContextValue = {
6+
lenis: Lenis
7+
addCallback: (callback: ScrollCallback, priority: number) => void
8+
removeCallback: (callback: ScrollCallback) => void
9+
}
10+
11+
export type LenisProps = ComponentPropsWithoutRef<'div'> & {
12+
/**
13+
* Setup a global instance of Lenis
14+
* if `asChild`, the component will render wrapper and content divs
15+
* @default false
16+
*/
17+
root?: boolean | 'asChild'
18+
/**
19+
* Lenis options
20+
*/
21+
options?: LenisOptions
22+
/**
23+
* Auto-setup requestAnimationFrame
24+
* @default true
25+
* @deprecated use options.autoRaf instead
26+
*/
27+
autoRaf?: boolean
28+
/**
29+
* Children
30+
*/
31+
children?: ReactNode
32+
}
33+
34+
export type LenisRef = {
35+
/**
36+
* The wrapper div element
37+
*
38+
* Will only be defined if `root` is `false` or `root` is `asChild`
39+
*/
40+
wrapper: HTMLDivElement | null
41+
/**
42+
* The content div element
43+
*
44+
* Will only be defined if `root` is `false` or `root` is `asChild`
45+
*/
46+
content: HTMLDivElement | null
47+
/**
48+
* The lenis instance
49+
*/
50+
lenis?: Lenis
51+
}

playground/react/app.tsx

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,45 @@
1-
import { ReactLenis, useLenis } from 'lenis/react'
2-
import { LoremIpsum } from 'lorem-ipsum'
3-
import { useRef, useState } from 'react'
4-
5-
function App() {
6-
const [lorem] = useState(() => new LoremIpsum().generateParagraphs(200))
7-
8-
const lenis = useLenis((lenis) => {
9-
// console.log('lenis in callback', lenis)
10-
})
11-
12-
const lenisRef = useRef()
13-
14-
// useEffect(() => {
15-
// console.log('lenis ref', lenisRef.current)
16-
17-
// function raf(time: number) {
18-
// lenisRef.current?.lenis?.raf(time)
19-
// }
20-
21-
// const rafId = requestAnimationFrame(raf)
22-
23-
// return () => cancelAnimationFrame(rafId)
24-
// }, [lenis])
25-
26-
return (
27-
<>
28-
{/* <ReactLenis root /> */}
29-
<ReactLenis
30-
className="wrapper"
31-
// root
32-
ref={lenisRef}
33-
style={{ height: '100vh', overflowY: 'auto' }}
34-
>
35-
{lorem}
36-
</ReactLenis>
37-
</>
38-
)
39-
}
40-
41-
export default App
1+
import { ReactLenis, useLenis, type LenisRef } from 'lenis/react'
2+
import { LoremIpsum } from 'lorem-ipsum'
3+
import { useEffect, useRef, useState } from 'react'
4+
5+
function App() {
6+
const [lorem] = useState(() => new LoremIpsum().generateParagraphs(200))
7+
8+
const lenis = useLenis((lenis) => {
9+
console.log('lenis in callback', lenis)
10+
})
11+
12+
const lenisRef = useRef<LenisRef>(null)
13+
14+
useEffect(() => {
15+
console.log('lenis ref', lenisRef.current)
16+
}, [lenisRef])
17+
18+
// useEffect(() => {
19+
// console.log('lenis ref', lenisRef.current)
20+
21+
// function raf(time: number) {
22+
// lenisRef.current?.lenis?.raf(time)
23+
// }
24+
25+
// const rafId = requestAnimationFrame(raf)
26+
27+
// return () => cancelAnimationFrame(rafId)
28+
// }, [lenis])
29+
30+
return (
31+
<>
32+
{/* <ReactLenis root /> */}
33+
<ReactLenis
34+
className="wrapper"
35+
root="asChild"
36+
sfsdfdsf="dssdfs"
37+
ref={lenisRef}
38+
>
39+
{lorem}
40+
</ReactLenis>
41+
</>
42+
)
43+
}
44+
45+
export default App

playground/react/style.css

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
1-
/* .lenis {
2-
height: 100vh;
3-
overflow-y: auto;
4-
} */
1+
html:not(.lenis) {
2+
body,
3+
& {
4+
margin: 0;
5+
padding: 0;
6+
width: 100%;
7+
height: 100%;
8+
overflow: hidden;
9+
}
10+
body {
11+
position: fixed;
12+
overscroll-behavior-y: none;
13+
overscroll-behavior-x: none;
14+
}
15+
16+
.lenis {
17+
position: absolute;
18+
top: 0;
19+
left: 0;
20+
width: 100%;
21+
height: 100%;
22+
overflow: hidden;
23+
overflow-y: scroll;
24+
-ms-scroll-chaining: none;
25+
overscroll-behavior: contain;
26+
background: #0b41cd;
27+
}
28+
}

playground/www/layouts/Layout.astro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ const { title } = Astro.props
7878
height: 3rem;
7979
display: flex;
8080
gap: 2px;
81+
z-index: 1;
8182
}
8283

8384
a {

0 commit comments

Comments
 (0)