Skip to content

Commit cb5434c

Browse files
authored
Version 2.0 (#10)
* completely new * updated methods * updated readme and updated packages * clean up * more props * lint * testing page
1 parent c17a7eb commit cb5434c

File tree

9 files changed

+5080
-3670
lines changed

9 files changed

+5080
-3670
lines changed

README.md

Lines changed: 137 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,166 @@
11
# Nuxt Lenis
22

3-
This is a Nuxt wrapper for [Lenis](https://lenis.studiofreight.com/) by [Studio Freight](https://studiofreight.com/). Thank them for the incredible tool.
3+
This is a Nuxt wrapper for [Lenis](https://lenis.studiofreight.com/) (by [Studio Freight](https://studiofreight.com/)) – providing smooth scrolling with support for multiple instances in a type-safe and reactive way.
44

5+
> **Version 2 Notice:**
6+
> In version 2, the module has been refactored to centrally manage multiple Lenis instances via a Nuxt plugin. Use the provided composable (`useLenis`) for accessing instance methods and reactive scroll state. The component expects an `onScroll` prop for scroll callbacks (instead of using emits).
57
6-
### Please Note
7-
Because of how Vue/Nuxt `useState` works, we have to recreate the `ScrollState` to a new object. We are porting over all fields we find necessary as you can also grab `Lenis` for all methods and attributes.
8-
8+
---
99

1010
## Getting Started
1111

12-
1. `yarn add nuxt-lenis`
13-
2. Add `nuxt-lenis` to your modules in nuxt.config
14-
3. In your `app.vue` file, wrap the nuxt page in the lenis component
12+
1. **Install the package:**
13+
14+
```bash
15+
yarn add nuxt-lenis
16+
```
17+
18+
2. **Add the module in your `nuxt.config`:**
19+
20+
```js
21+
export default {
22+
modules: [
23+
'nuxt-lenis'
24+
]
25+
}
1526
```
27+
28+
3. **Wrap your page with the Lenis component in `app.vue`:**
29+
30+
```vue
31+
<template>
1632
<lenis
1733
:options="LenisOptions"
18-
@initiated="foo"
19-
@scroll="fooBar"
34+
onScroll="handleScroll"
2035
>
2136
<NuxtPage />
2237
</lenis>
38+
</template>
39+
40+
<script setup lang="ts">
41+
const handleScroll = (scrollData: any) => {
42+
console.log("Scroll event:", scrollData);
43+
}
44+
</script>
2345
```
2446

25-
## Composable
47+
---
48+
49+
## Component Usage
2650

51+
The `<lenis>` component (located at `src/runtime/components/Lenis.vue`) accepts the following props:
52+
53+
- **id** (String, default: `"default"`): A unique identifier for your Lenis instance.
54+
- **root** (Boolean, default: `true`): Determines if the window should be used as the scroll container.
55+
- **options** (Object): Lenis options (e.g., `duration`, `autoRaf`, `direction`).
56+
- **onScroll** (Function): Callback fired whenever a scrolling event is received.
57+
58+
Example:
59+
60+
```vue
61+
<template>
62+
<lenis id="default" :options="LenisOptions" onScroll="handleScroll">
63+
<NuxtPage />
64+
</lenis>
65+
</template>
66+
67+
<script setup lang="ts">
68+
const LenisOptions = {
69+
smooth: true,
70+
duration: 1.2,
71+
autoRaf: true,
72+
direction: 'vertical'
73+
}
74+
75+
const handleScroll = (data: any) => {
76+
console.log("Scroll detected:", data);
77+
}
78+
</script>
2779
```
28-
<!-- You can pass in true or false into useLenis if you want to use more than one lenis instance. Defaults to single instance (true) -->
29-
const {scrollState, lenis} = useLenis()
3080

31-
watch(scrollState, (val) => {
32-
console.log("scrollState", val);
33-
},{deep:true});
81+
---
82+
83+
## Composable Usage
84+
85+
Access the reactive Lenis API via the composable. By default, `useLenis()` returns the following properties:
3486

87+
- **createLenis**: Function to create and register a Lenis instance.
88+
- **getLenis**: Function that returns the Lenis instance (or `null` if not found).
89+
- **destroyLenis**: Function to destroy an instance.
90+
- **scrollState**: Function to access the reactive scroll state of an instance.
91+
- **watchScrollState**: Function to watch changes to the scroll state.
92+
93+
### Single Instance Usage
94+
95+
For many cases, a single instance is sufficient:
96+
97+
```vue
98+
<script setup lang="ts">
99+
import { watch } from 'vue';
100+
import { useLenis } from '#imports';
101+
102+
const { scrollState, getLenis } = useLenis();
103+
104+
// Example: retrieve default instance
105+
const instance = getLenis(); // returns the Lenis instance or null
106+
107+
// Watch scroll state changes
108+
watch(scrollState, (state) => {
109+
console.log("Scroll state:", state);
110+
}, { deep: true });
111+
</script>
35112
```
113+
36114
### Multiple Instances
37-
If you have multiple instances of Lenis you can get each one via an ID set ont he Lenis component
38-
```
39-
<lenis id="base" >
115+
116+
If you need multiple instances, pass `false` (or use different IDs on each `<lenis>` component) and access them by ID:
117+
118+
```vue
119+
<template>
120+
<lenis id="main">
40121
<NuxtPage />
41122
</lenis>
42-
43-
<lenis id="modal" >
123+
<lenis id="modal">
44124
<NuxtPage />
45125
</lenis>
126+
</template>
127+
128+
<script setup lang="ts">
129+
import { useLenis } from '#imports';
46130
47-
<!-- script -->
48-
const {scrollState, lenis} = useLenis(false)
131+
// Using multiple instance mode:
132+
const { scrollState, getLenis } = useLenis(false);
49133
50-
scrollState.value.base
51-
lenis.base
52-
scrollState.value.modal
53-
lenis.modal
134+
// Access the instances by ID
135+
const mainInstance = getLenis("main");
136+
const modalInstance = getLenis("modal");
54137
138+
// Example: Log scroll states for each instance
139+
console.log("Main scroll state:", scrollState("main"));
140+
console.log("Modal scroll state:", scrollState("modal"));
141+
</script>
55142
```
143+
144+
---
145+
146+
## Plugin API
147+
148+
The Nuxt plugin (located at `src/runtime/plugin.ts`) exposes the following methods:
149+
150+
- **createLenis(id, options?)**
151+
Creates a new Lenis instance for a given ID and registers it.
152+
153+
- **getLenis(id?)**
154+
Retrieves a Lenis instance by its ID (or the default instance if none is specified).
155+
156+
- **destroyLenis(id)**
157+
Destroys the specified Lenis instance and cleans up its associated state.
158+
159+
- **getScrollState(id?)**
160+
Returns the current scroll state for the specified instance, which is updated reactively.
161+
162+
The composable (`useLenis`) wraps these methods and provides a streamlined API for your components.
163+
164+
---
165+
166+
Happy scrolling!

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nuxt-lenis",
3-
"version": "1.2.9",
3+
"version": "2.1.2",
44
"license": "MIT",
55
"type": "module",
66
"repository": {
@@ -40,12 +40,12 @@
4040
"test:watch": "vitest watch"
4141
},
4242
"dependencies": {
43-
"@nuxt/kit": "^3.6.5",
44-
"lenis": "^1.1.11"
43+
"lenis": "^1.2.3"
4544
},
4645
"devDependencies": {
4746
"@nuxt/devtools": "^0.8.5",
4847
"@nuxt/eslint-config": "^0.1.1",
48+
"@nuxt/kit": "^3.6.5",
4949
"@nuxt/module-builder": "^0.4.0",
5050
"@nuxt/schema": "^3.6.5",
5151
"@nuxt/test-utils": "^3.6.5",

playground/nuxt.config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import MyModule from '..'
33

44
export default defineNuxtConfig({
55
modules: [MyModule],
6+
67
myModule: {
78
addPlugin: true
8-
}
9+
},
10+
11+
compatibilityDate: '2025-02-08'
912
})

playground/pages/index.vue

Lines changed: 49 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,69 @@
11
<template>
2-
<lenis
3-
id="wrapper"
4-
ref="lenisRef"
5-
@scroll="scrollEmitter"
6-
@initiated="initiated"
7-
@click="handleClick"
8-
>
9-
<!-- <div id="content"> -->
10-
<div>
11-
<h2 @click="stop">STOP</h2>
12-
<h2 @click="start">START</h2>
13-
<h2 @click="changeOptions">CHANGE</h2>
14-
<p>Playground for lenis scroll plugin for nuxt</p>
15-
</div>
2+
<lenis id="wrapper" ref="lenisRef" @click="handleClick">
3+
<!-- <div id="content"> -->
4+
<div>
5+
<h2 @click="stop">
6+
STOP
7+
</h2>
8+
<h2 @click="start">
9+
START
10+
</h2>
11+
<h2 @click="changeOptions">
12+
CHANGE
13+
</h2>
14+
<p>Playground for lenis scroll plugin for nuxt</p>
15+
</div>
1616

17-
<div />
18-
<div />
19-
<div />
20-
<div />
21-
<div />
22-
<div />
23-
<!-- </div> -->
24-
</lenis>
17+
<div />
18+
<div />
19+
<div />
20+
<div />
21+
<div />
22+
<div />
23+
<!-- </div> -->
24+
</lenis>
2525
</template>
2626

2727
<script setup>
28-
import { ref, reactive, watch, onMounted, computed } from "vue";
29-
import { useLenis } from "#imports";
28+
import { ref, reactive, watch, onMounted, computed } from 'vue'
29+
import { useLenis } from '#imports'
3030
// import { useLenis } from "#app";
31-
const { scrollState, lenis: lenisN, lenisInstance } = useLenis();
32-
const lenisRef = ref(null);
33-
var lenisLocalVS = null;
34-
const vsOptions = reactive({});
3531
36-
watch(
37-
()=>scrollState,
38-
({ scroll, ...props }) => {
39-
console.log("WATCHER", props);
40-
},
41-
{ deep: true }
42-
);
32+
// const scrollEmitter = (val) => {
33+
// console.log("scrollEmitter", val);
34+
// };
35+
const { scrollState, getLenis } = useLenis()
36+
const lenisRef = ref(null)
37+
const vsOptions = reactive({})
4338
44-
watch(vsOptions, (newVal) => {
45-
// console.log("vsOptions newVal", newVal);
46-
});
39+
watch(
40+
scrollState,
41+
(scroll) => {
42+
console.log('WATCHER- SCROLL', scroll)
43+
// console.log("WATCHER", val);
44+
},
45+
{ deep: true }
46+
)
4747
48-
const scrollEmitter = (val) => {
49-
// console.log("scrollEmitter", val);
50-
};
5148
const stop = (val) => {
52-
// lenisN.wrapper.stop();
53-
lenisN.value.stop();
54-
// lenisLocalVS.stop();
55-
};
49+
getLenis().stop();
50+
}
5651
const start = (val) => {
57-
// console.log("lenisVs", lenisVs.value);
58-
// lenisN.wrapper.start();
59-
lenisN.value.start();
60-
console.log(lenisN);
61-
62-
// lenisLocalVS.start();
63-
};
52+
getLenis().start();
53+
}
6454
6555
const handleClick = () => {
66-
console.log("scrollState------", lenisN);
67-
};
56+
console.log('handleClick------', lenisRef.value)
57+
}
6858
69-
const initiated = ({ lenis }) => (lenisLocalVS = lenis);
7059
const changeOptions = () => {
71-
// console.log("🐯 changing options");
72-
vsOptions.duration = vsOptions.duration > 5 ? 0.1 : 10;
73-
};
60+
// console.log("🐯 changing options");
61+
vsOptions.duration = vsOptions.duration > 5 ? 0.1 : 10
62+
}
7463
7564
onMounted(() => {
76-
// console.log("Lenis Component ref :", lenisRef.value);
77-
// console.log("lenisTest------", lenisInstance("wrapper").isStopped);
78-
console.log("lenisN------", lenisN.value);
79-
console.log("scrollState------", scrollState.value);
80-
});
65+
console.log('handleClick------')
66+
})
8167
</script>
8268

8369
<style>
@@ -113,7 +99,4 @@ onMounted(() => {
11399
align-items: flex-end;
114100
}
115101
116-
.nopointer {
117-
pointer-events: none;
118-
}
119102
</style>

0 commit comments

Comments
 (0)