lenis 1.3.19 → 1.3.20-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,9 +1,9 @@
1
- The MIT License
2
-
3
- Copyright (c) 2024 darkroom.engineering
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
-
7
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
-
1
+ The MIT License
2
+
3
+ Copyright (c) 2024 darkroom.engineering
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
9
  THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,71 +1,68 @@
1
- import * as Lenis from 'lenis';
2
- import Lenis__default, { ScrollCallback, LenisOptions } from 'lenis';
3
- import * as react from 'react';
4
- import { ComponentPropsWithoutRef, ReactNode } from 'react';
1
+ "use client";
2
+ import Lenis, { LenisOptions, ScrollCallback } from "lenis";
3
+ import * as react from "react";
4
+ import { ComponentPropsWithoutRef, ForwardRefExoticComponent, ReactNode, RefAttributes } from "react";
5
5
 
6
+ //#region packages/react/src/types.d.ts
6
7
  type LenisContextValue = {
7
- lenis: Lenis__default;
8
- addCallback: (callback: ScrollCallback, priority: number) => void;
9
- removeCallback: (callback: ScrollCallback) => void;
8
+ lenis: Lenis;
9
+ addCallback: (callback: ScrollCallback, priority: number) => void;
10
+ removeCallback: (callback: ScrollCallback) => void;
10
11
  };
11
12
  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
- * Class name to be applied to the wrapper div
34
- * @default ''
35
- */
36
- className?: string | undefined;
13
+ /**
14
+ * Setup a global instance of Lenis
15
+ * if `asChild`, the component will render wrapper and content divs
16
+ * @default false
17
+ */
18
+ root?: boolean | 'asChild';
19
+ /**
20
+ * Lenis options
21
+ */
22
+ options?: LenisOptions;
23
+ /**
24
+ * Auto-setup requestAnimationFrame
25
+ * @default true
26
+ * @deprecated use options.autoRaf instead
27
+ */
28
+ autoRaf?: boolean;
29
+ /**
30
+ * Children
31
+ */
32
+ children?: ReactNode;
33
+ /**
34
+ * Class name to be applied to the wrapper div
35
+ * @default ''
36
+ */
37
+ className?: string | undefined;
37
38
  };
38
39
  type LenisRef = {
39
- /**
40
- * The wrapper div element
41
- *
42
- * Will only be defined if `root` is `false` or `root` is `asChild`
43
- */
44
- wrapper: HTMLDivElement | null;
45
- /**
46
- * The content div element
47
- *
48
- * Will only be defined if `root` is `false` or `root` is `asChild`
49
- */
50
- content: HTMLDivElement | null;
51
- /**
52
- * The lenis instance
53
- */
54
- lenis?: Lenis__default;
40
+ /**
41
+ * The wrapper div element
42
+ *
43
+ * Will only be defined if `root` is `false` or `root` is `asChild`
44
+ */
45
+ wrapper: HTMLDivElement | null;
46
+ /**
47
+ * The content div element
48
+ *
49
+ * Will only be defined if `root` is `false` or `root` is `asChild`
50
+ */
51
+ content: HTMLDivElement | null;
52
+ /**
53
+ * The lenis instance
54
+ */
55
+ lenis?: Lenis;
55
56
  };
56
-
57
+ //#endregion
58
+ //#region packages/react/src/provider.d.ts
57
59
  declare const LenisContext: react.Context<LenisContextValue | null>;
58
60
  /**
59
61
  * React component to setup a Lenis instance
60
62
  */
61
- declare const ReactLenis: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
62
- root?: boolean | "asChild";
63
- options?: Lenis.LenisOptions;
64
- autoRaf?: boolean;
65
- children?: react.ReactNode;
66
- className?: string | undefined;
67
- } & react.RefAttributes<LenisRef>>;
68
-
63
+ declare const ReactLenis: ForwardRefExoticComponent<LenisProps & RefAttributes<LenisRef>>;
64
+ //#endregion
65
+ //#region packages/react/src/use-lenis.d.ts
69
66
  /**
70
67
  * Hook to access the Lenis instance and its methods
71
68
  *
@@ -106,6 +103,7 @@ declare const ReactLenis: react.ForwardRefExoticComponent<Omit<react.DetailedHTM
106
103
  * })
107
104
  * }
108
105
  */
109
- declare function useLenis(callback?: ScrollCallback, deps?: unknown[], priority?: number): Lenis.default | undefined;
110
-
111
- export { ReactLenis as Lenis, LenisContext, type LenisContextValue, type LenisProps, type LenisRef, ReactLenis, ReactLenis as default, useLenis };
106
+ declare function useLenis(callback?: ScrollCallback, deps?: unknown[], priority?: number): Lenis | undefined;
107
+ //#endregion
108
+ export { ReactLenis as Lenis, ReactLenis, ReactLenis as default, LenisContext, LenisContextValue, LenisProps, LenisRef, useLenis };
109
+ //# sourceMappingURL=lenis-react.d.ts.map
@@ -1,165 +1,194 @@
1
1
  "use client";
2
-
3
- // packages/react/src/provider.tsx
4
2
  import Lenis from "lenis";
5
- import {
6
- createContext,
7
- forwardRef,
8
- useCallback,
9
- useEffect as useEffect2,
10
- useImperativeHandle,
11
- useRef,
12
- useState as useState2
13
- } from "react";
14
-
15
- // packages/react/src/store.ts
16
- import { useEffect, useState } from "react";
3
+ import { createContext, forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useRef, useState } from "react";
4
+ import { jsx } from "react/jsx-runtime";
5
+ //#region packages/react/src/store.ts
17
6
  var Store = class {
18
- constructor(state) {
19
- this.state = state;
20
- }
21
- listeners = [];
22
- set(state) {
23
- this.state = state;
24
- for (const listener of this.listeners) {
25
- listener(this.state);
26
- }
27
- }
28
- subscribe(listener) {
29
- this.listeners = [...this.listeners, listener];
30
- return () => {
31
- this.listeners = this.listeners.filter((l) => l !== listener);
32
- };
33
- }
34
- get() {
35
- return this.state;
36
- }
7
+ listeners = [];
8
+ constructor(state) {
9
+ this.state = state;
10
+ }
11
+ set(state) {
12
+ this.state = state;
13
+ for (const listener of this.listeners) listener(this.state);
14
+ }
15
+ subscribe(listener) {
16
+ this.listeners = [...this.listeners, listener];
17
+ return () => {
18
+ this.listeners = this.listeners.filter((l) => l !== listener);
19
+ };
20
+ }
21
+ get() {
22
+ return this.state;
23
+ }
37
24
  };
38
25
  function useStore(store) {
39
- const [state, setState] = useState(store.get());
40
- useEffect(() => {
41
- return store.subscribe((state2) => setState(state2));
42
- }, [store]);
43
- return state;
26
+ const [state, setState] = useState(store.get());
27
+ useEffect(() => {
28
+ return store.subscribe((state) => setState(state));
29
+ }, [store]);
30
+ return state;
44
31
  }
45
-
46
- // packages/react/src/provider.tsx
47
- import { jsx } from "react/jsx-runtime";
48
- var LenisContext = createContext(null);
49
- var rootLenisContextStore = new Store(null);
50
- var ReactLenis = forwardRef(
51
- ({
52
- children,
53
- root = false,
54
- options = {},
55
- autoRaf = true,
56
- className = "",
57
- ...props
58
- }, ref) => {
59
- const wrapperRef = useRef(null);
60
- const contentRef = useRef(null);
61
- const [lenis, setLenis] = useState2(void 0);
62
- useImperativeHandle(
63
- ref,
64
- () => ({
65
- wrapper: wrapperRef.current,
66
- content: contentRef.current,
67
- lenis
68
- }),
69
- [lenis]
70
- );
71
- useEffect2(() => {
72
- const lenis2 = new Lenis({
73
- ...options,
74
- ...wrapperRef.current && contentRef.current && {
75
- wrapper: wrapperRef.current,
76
- content: contentRef.current
77
- },
78
- autoRaf: options?.autoRaf ?? autoRaf
79
- // this is to avoid breaking the autoRaf prop if it's still used (require breaking change)
80
- });
81
- setLenis(lenis2);
82
- return () => {
83
- lenis2.destroy();
84
- setLenis(void 0);
85
- };
86
- }, [autoRaf, JSON.stringify({ ...options, wrapper: null, content: null })]);
87
- const callbacksRefs = useRef([]);
88
- const addCallback = useCallback(
89
- (callback, priority) => {
90
- callbacksRefs.current.push({ callback, priority });
91
- callbacksRefs.current.sort((a, b) => a.priority - b.priority);
92
- },
93
- []
94
- );
95
- const removeCallback = useCallback(
96
- (callback) => {
97
- callbacksRefs.current = callbacksRefs.current.filter(
98
- (cb) => cb.callback !== callback
99
- );
100
- },
101
- []
102
- );
103
- useEffect2(() => {
104
- if (root && lenis) {
105
- rootLenisContextStore.set({ lenis, addCallback, removeCallback });
106
- return () => rootLenisContextStore.set(null);
107
- }
108
- }, [root, lenis, addCallback, removeCallback]);
109
- useEffect2(() => {
110
- if (!lenis) return;
111
- const onScroll = (data) => {
112
- for (const { callback } of callbacksRefs.current) {
113
- callback(data);
114
- }
115
- };
116
- lenis.on("scroll", onScroll);
117
- return () => {
118
- lenis.off("scroll", onScroll);
119
- };
120
- }, [lenis]);
121
- if (!children) return null;
122
- return /* @__PURE__ */ jsx(
123
- LenisContext.Provider,
124
- {
125
- value: { lenis, addCallback, removeCallback },
126
- children: root && root !== "asChild" ? children : /* @__PURE__ */ jsx(
127
- "div",
128
- {
129
- ref: wrapperRef,
130
- className: `${className} ${lenis?.className ?? ""}`.trim(),
131
- ...props,
132
- children: /* @__PURE__ */ jsx("div", { ref: contentRef, children })
133
- }
134
- )
135
- }
136
- );
137
- }
138
- );
139
-
140
- // packages/react/src/use-lenis.ts
141
- import { useContext, useEffect as useEffect3 } from "react";
142
- var fallbackContext = {};
32
+ //#endregion
33
+ //#region packages/react/src/provider.tsx
34
+ const LenisContext = createContext(null);
35
+ /**
36
+ * The root store for the lenis context
37
+ *
38
+ * This store serves as a fallback for the context if it is not available
39
+ * and allows us to use the global lenis instance above a provider
40
+ */
41
+ const rootLenisContextStore = new Store(null);
42
+ /**
43
+ * React component to setup a Lenis instance
44
+ */
45
+ const ReactLenis = forwardRef(({ children, root = false, options = {}, autoRaf = true, className = "", ...props }, ref) => {
46
+ const wrapperRef = useRef(null);
47
+ const contentRef = useRef(null);
48
+ const [lenis, setLenis] = useState(void 0);
49
+ useImperativeHandle(ref, () => ({
50
+ wrapper: wrapperRef.current,
51
+ content: contentRef.current,
52
+ lenis
53
+ }), [lenis]);
54
+ useEffect(() => {
55
+ const lenis = new Lenis({
56
+ ...options,
57
+ ...wrapperRef.current && contentRef.current && {
58
+ wrapper: wrapperRef.current,
59
+ content: contentRef.current
60
+ },
61
+ autoRaf: options?.autoRaf ?? autoRaf
62
+ });
63
+ setLenis(lenis);
64
+ return () => {
65
+ lenis.destroy();
66
+ setLenis(void 0);
67
+ };
68
+ }, [autoRaf, JSON.stringify({
69
+ ...options,
70
+ wrapper: null,
71
+ content: null
72
+ })]);
73
+ const callbacksRefs = useRef([]);
74
+ const addCallback = useCallback((callback, priority) => {
75
+ callbacksRefs.current.push({
76
+ callback,
77
+ priority
78
+ });
79
+ callbacksRefs.current.sort((a, b) => a.priority - b.priority);
80
+ }, []);
81
+ const removeCallback = useCallback((callback) => {
82
+ callbacksRefs.current = callbacksRefs.current.filter((cb) => cb.callback !== callback);
83
+ }, []);
84
+ useEffect(() => {
85
+ if (root && lenis) {
86
+ rootLenisContextStore.set({
87
+ lenis,
88
+ addCallback,
89
+ removeCallback
90
+ });
91
+ return () => rootLenisContextStore.set(null);
92
+ }
93
+ }, [
94
+ root,
95
+ lenis,
96
+ addCallback,
97
+ removeCallback
98
+ ]);
99
+ useEffect(() => {
100
+ if (!lenis) return;
101
+ const onScroll = (data) => {
102
+ for (const { callback } of callbacksRefs.current) callback(data);
103
+ };
104
+ lenis.on("scroll", onScroll);
105
+ return () => {
106
+ lenis.off("scroll", onScroll);
107
+ };
108
+ }, [lenis]);
109
+ if (!children) return null;
110
+ return /* @__PURE__ */ jsx(LenisContext.Provider, {
111
+ value: {
112
+ lenis,
113
+ addCallback,
114
+ removeCallback
115
+ },
116
+ children: root && root !== "asChild" ? children : /* @__PURE__ */ jsx("div", {
117
+ ref: wrapperRef,
118
+ className: `${className} ${lenis?.className ?? ""}`.trim(),
119
+ ...props,
120
+ children: /* @__PURE__ */ jsx("div", {
121
+ ref: contentRef,
122
+ children
123
+ })
124
+ })
125
+ });
126
+ });
127
+ //#endregion
128
+ //#region packages/react/src/use-lenis.ts
129
+ const fallbackContext = {};
130
+ /**
131
+ * Hook to access the Lenis instance and its methods
132
+ *
133
+ * @example <caption>Scroll callback</caption>
134
+ * useLenis((lenis) => {
135
+ * if (lenis.isScrolling) {
136
+ * console.log('Scrolling...')
137
+ * }
138
+ *
139
+ * if (lenis.progress === 1) {
140
+ * console.log('At the end!')
141
+ * }
142
+ * })
143
+ *
144
+ * @example <caption>Scroll callback with dependencies</caption>
145
+ * useLenis((lenis) => {
146
+ * if (lenis.isScrolling) {
147
+ * console.log('Scrolling...', someDependency)
148
+ * }
149
+ * }, [someDependency])
150
+ * @example <caption>Scroll callback with priority</caption>
151
+ * useLenis((lenis) => {
152
+ * if (lenis.isScrolling) {
153
+ * console.log('Scrolling...')
154
+ * }
155
+ * }, [], 1)
156
+ * @example <caption>Instance access</caption>
157
+ * const lenis = useLenis()
158
+ *
159
+ * handleClick() {
160
+ * lenis.scrollTo(100, {
161
+ * lerp: 0.1,
162
+ * duration: 1,
163
+ * easing: (t) => t,
164
+ * onComplete: () => {
165
+ * console.log('Complete!')
166
+ * }
167
+ * })
168
+ * }
169
+ */
143
170
  function useLenis(callback, deps = [], priority = 0) {
144
- const localContext = useContext(LenisContext);
145
- const rootContext = useStore(rootLenisContextStore);
146
- const currentContext = localContext ?? rootContext ?? fallbackContext;
147
- const { lenis, addCallback, removeCallback } = currentContext;
148
- useEffect3(() => {
149
- if (!(callback && addCallback && removeCallback && lenis)) return;
150
- addCallback(callback, priority);
151
- callback(lenis);
152
- return () => {
153
- removeCallback(callback);
154
- };
155
- }, [lenis, addCallback, removeCallback, priority, ...deps, callback]);
156
- return lenis;
171
+ const localContext = useContext(LenisContext);
172
+ const rootContext = useStore(rootLenisContextStore);
173
+ const { lenis, addCallback, removeCallback } = localContext ?? rootContext ?? fallbackContext;
174
+ useEffect(() => {
175
+ if (!(callback && addCallback && removeCallback && lenis)) return;
176
+ addCallback(callback, priority);
177
+ callback(lenis);
178
+ return () => {
179
+ removeCallback(callback);
180
+ };
181
+ }, [
182
+ lenis,
183
+ addCallback,
184
+ removeCallback,
185
+ priority,
186
+ ...deps,
187
+ callback
188
+ ]);
189
+ return lenis;
157
190
  }
158
- export {
159
- ReactLenis as Lenis,
160
- LenisContext,
161
- ReactLenis,
162
- ReactLenis as default,
163
- useLenis
164
- };
191
+ //#endregion
192
+ export { ReactLenis as Lenis, ReactLenis, ReactLenis as default, LenisContext, useLenis };
193
+
165
194
  //# sourceMappingURL=lenis-react.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../packages/react/src/provider.tsx","../packages/react/src/store.ts","../packages/react/src/use-lenis.ts"],"sourcesContent":["import Lenis, { type ScrollCallback } from 'lenis'\nimport {\n createContext,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react'\nimport { Store } from './store'\nimport type { LenisContextValue, LenisProps, LenisRef } from './types'\n\nexport const LenisContext = createContext<LenisContextValue | null>(null)\n\n/**\n * The root store for the lenis context\n *\n * This store serves as a fallback for the context if it is not available\n * and allows us to use the global lenis instance above a provider\n */\nexport const rootLenisContextStore = new Store<LenisContextValue | null>(null)\n\n/**\n * React component to setup a Lenis instance\n */\nexport const ReactLenis = forwardRef<LenisRef, LenisProps>(\n (\n {\n children,\n root = false,\n options = {},\n autoRaf = true,\n className = '',\n ...props\n }: LenisProps,\n ref\n ) => {\n const wrapperRef = useRef<HTMLDivElement>(null)\n const contentRef = useRef<HTMLDivElement>(null)\n\n const [lenis, setLenis] = useState<Lenis | undefined>(undefined)\n\n // Setup ref\n useImperativeHandle(\n ref,\n () => ({\n wrapper: wrapperRef.current,\n content: contentRef.current,\n lenis,\n }),\n [lenis]\n )\n\n // Setup lenis instance\n useEffect(() => {\n const lenis = new Lenis({\n ...options,\n ...(wrapperRef.current &&\n contentRef.current && {\n wrapper: wrapperRef.current!,\n content: contentRef.current!,\n }),\n autoRaf: options?.autoRaf ?? autoRaf, // this is to avoid breaking the autoRaf prop if it's still used (require breaking change)\n })\n\n setLenis(lenis)\n\n return () => {\n lenis.destroy()\n setLenis(undefined)\n }\n }, [autoRaf, JSON.stringify({ ...options, wrapper: null, content: null })])\n\n // Handle callbacks\n const callbacksRefs = useRef<\n {\n callback: ScrollCallback\n priority: number\n }[]\n >([])\n\n const addCallback: LenisContextValue['addCallback'] = useCallback(\n (callback, priority) => {\n callbacksRefs.current.push({ callback, priority })\n callbacksRefs.current.sort((a, b) => a.priority - b.priority)\n },\n []\n )\n\n const removeCallback: LenisContextValue['removeCallback'] = useCallback(\n (callback) => {\n callbacksRefs.current = callbacksRefs.current.filter(\n (cb) => cb.callback !== callback\n )\n },\n []\n )\n\n // This makes sure to set the global context if the root is true\n useEffect(() => {\n if (root && lenis) {\n rootLenisContextStore.set({ lenis, addCallback, removeCallback })\n\n return () => rootLenisContextStore.set(null)\n }\n }, [root, lenis, addCallback, removeCallback])\n\n // Setup callback listeners\n useEffect(() => {\n if (!lenis) return\n\n const onScroll: ScrollCallback = (data) => {\n for (const { callback } of callbacksRefs.current) {\n callback(data)\n }\n }\n\n lenis.on('scroll', onScroll)\n\n return () => {\n lenis.off('scroll', onScroll)\n }\n }, [lenis])\n\n if (!children) return null\n\n return (\n <LenisContext.Provider\n value={{ lenis: lenis!, addCallback, removeCallback }}\n >\n {root && root !== 'asChild' ? (\n children\n ) : (\n <div\n ref={wrapperRef}\n className={`${className} ${lenis?.className ?? ''}`.trim()}\n {...props}\n >\n <div ref={contentRef}>{children}</div>\n </div>\n )}\n </LenisContext.Provider>\n )\n }\n)\n","import { useEffect, useState } from 'react'\n\ntype Listener<S> = (state: S) => void\n\nexport class Store<S> {\n private listeners: Listener<S>[] = []\n\n constructor(private state: S) {}\n\n set(state: S) {\n this.state = state\n\n for (const listener of this.listeners) {\n listener(this.state)\n }\n }\n\n subscribe(listener: Listener<S>) {\n this.listeners = [...this.listeners, listener]\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener)\n }\n }\n\n get() {\n return this.state\n }\n}\n\nexport function useStore<S>(store: Store<S>) {\n const [state, setState] = useState(store.get())\n\n useEffect(() => {\n return store.subscribe((state) => setState(state))\n }, [store])\n\n return state\n}\n","import type { ScrollCallback } from 'lenis'\nimport { useContext, useEffect } from 'react'\nimport { LenisContext, rootLenisContextStore } from './provider'\nimport { useStore } from './store'\nimport type { LenisContextValue } from './types'\n\n// Fall back to an empty object if both context and store are not available\nconst fallbackContext: Partial<LenisContextValue> = {}\n\n/**\n * Hook to access the Lenis instance and its methods\n *\n * @example <caption>Scroll callback</caption>\n * useLenis((lenis) => {\n * if (lenis.isScrolling) {\n * console.log('Scrolling...')\n * }\n *\n * if (lenis.progress === 1) {\n * console.log('At the end!')\n * }\n * })\n *\n * @example <caption>Scroll callback with dependencies</caption>\n * useLenis((lenis) => {\n * if (lenis.isScrolling) {\n * console.log('Scrolling...', someDependency)\n * }\n * }, [someDependency])\n * @example <caption>Scroll callback with priority</caption>\n * useLenis((lenis) => {\n * if (lenis.isScrolling) {\n * console.log('Scrolling...')\n * }\n * }, [], 1)\n * @example <caption>Instance access</caption>\n * const lenis = useLenis()\n *\n * handleClick() {\n * lenis.scrollTo(100, {\n * lerp: 0.1,\n * duration: 1,\n * easing: (t) => t,\n * onComplete: () => {\n * console.log('Complete!')\n * }\n * })\n * }\n */\nexport function useLenis(\n callback?: ScrollCallback,\n deps: unknown[] = [],\n priority = 0\n) {\n // Try to get the lenis instance from the context first\n const localContext = useContext(LenisContext)\n // Fall back to the root store if the context is not available\n const rootContext = useStore(rootLenisContextStore)\n // Fall back to the fallback context if all else fails\n const currentContext = localContext ?? rootContext ?? fallbackContext\n\n const { lenis, addCallback, removeCallback } = currentContext\n\n useEffect(() => {\n if (!(callback && addCallback && removeCallback && lenis)) return\n\n addCallback(callback, priority)\n callback(lenis)\n\n return () => {\n removeCallback(callback)\n }\n }, [lenis, addCallback, removeCallback, priority, ...deps, callback])\n\n return lenis\n}\n"],"mappings":"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","names":["useEffect","useState","state","useState","useEffect","lenis","useEffect","useEffect"]}
1
+ {"version":3,"file":"lenis-react.mjs","names":[],"sources":["../packages/react/src/store.ts","../packages/react/src/provider.tsx","../packages/react/src/use-lenis.ts"],"sourcesContent":["import { useEffect, useState } from 'react'\n\ntype Listener<S> = (state: S) => void\n\nexport class Store<S> {\n private listeners: Listener<S>[] = []\n\n constructor(private state: S) {}\n\n set(state: S) {\n this.state = state\n\n for (const listener of this.listeners) {\n listener(this.state)\n }\n }\n\n subscribe(listener: Listener<S>) {\n this.listeners = [...this.listeners, listener]\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener)\n }\n }\n\n get() {\n return this.state\n }\n}\n\nexport function useStore<S>(store: Store<S>) {\n const [state, setState] = useState(store.get())\n\n useEffect(() => {\n return store.subscribe((state) => setState(state))\n }, [store])\n\n return state\n}\n","import Lenis, { type ScrollCallback } from 'lenis'\nimport {\n type ForwardRefExoticComponent,\n type RefAttributes,\n createContext,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react'\nimport { Store } from './store'\nimport type { LenisContextValue, LenisProps, LenisRef } from './types'\n\nexport const LenisContext = createContext<LenisContextValue | null>(null)\n\n/**\n * The root store for the lenis context\n *\n * This store serves as a fallback for the context if it is not available\n * and allows us to use the global lenis instance above a provider\n */\nexport const rootLenisContextStore = new Store<LenisContextValue | null>(null)\n\n/**\n * React component to setup a Lenis instance\n */\nexport const ReactLenis: ForwardRefExoticComponent<\n LenisProps & RefAttributes<LenisRef>\n> = forwardRef<LenisRef, LenisProps>(\n (\n {\n children,\n root = false,\n options = {},\n autoRaf = true,\n className = '',\n ...props\n }: LenisProps,\n ref\n ) => {\n const wrapperRef = useRef<HTMLDivElement>(null)\n const contentRef = useRef<HTMLDivElement>(null)\n\n const [lenis, setLenis] = useState<Lenis | undefined>(undefined)\n\n // Setup ref\n useImperativeHandle(\n ref,\n () => ({\n wrapper: wrapperRef.current,\n content: contentRef.current,\n lenis,\n }),\n [lenis]\n )\n\n // Setup lenis instance\n useEffect(() => {\n const lenis = new Lenis({\n ...options,\n ...(wrapperRef.current &&\n contentRef.current && {\n wrapper: wrapperRef.current!,\n content: contentRef.current!,\n }),\n autoRaf: options?.autoRaf ?? autoRaf, // this is to avoid breaking the autoRaf prop if it's still used (require breaking change)\n })\n\n setLenis(lenis)\n\n return () => {\n lenis.destroy()\n setLenis(undefined)\n }\n }, [autoRaf, JSON.stringify({ ...options, wrapper: null, content: null })])\n\n // Handle callbacks\n const callbacksRefs = useRef<\n {\n callback: ScrollCallback\n priority: number\n }[]\n >([])\n\n const addCallback: LenisContextValue['addCallback'] = useCallback(\n (callback, priority) => {\n callbacksRefs.current.push({ callback, priority })\n callbacksRefs.current.sort((a, b) => a.priority - b.priority)\n },\n []\n )\n\n const removeCallback: LenisContextValue['removeCallback'] = useCallback(\n (callback) => {\n callbacksRefs.current = callbacksRefs.current.filter(\n (cb) => cb.callback !== callback\n )\n },\n []\n )\n\n // This makes sure to set the global context if the root is true\n useEffect(() => {\n if (root && lenis) {\n rootLenisContextStore.set({ lenis, addCallback, removeCallback })\n\n return () => rootLenisContextStore.set(null)\n }\n }, [root, lenis, addCallback, removeCallback])\n\n // Setup callback listeners\n useEffect(() => {\n if (!lenis) return\n\n const onScroll: ScrollCallback = (data) => {\n for (const { callback } of callbacksRefs.current) {\n callback(data)\n }\n }\n\n lenis.on('scroll', onScroll)\n\n return () => {\n lenis.off('scroll', onScroll)\n }\n }, [lenis])\n\n if (!children) return null\n\n return (\n <LenisContext.Provider\n value={{ lenis: lenis!, addCallback, removeCallback }}\n >\n {root && root !== 'asChild' ? (\n children\n ) : (\n <div\n ref={wrapperRef}\n className={`${className} ${lenis?.className ?? ''}`.trim()}\n {...props}\n >\n <div ref={contentRef}>{children}</div>\n </div>\n )}\n </LenisContext.Provider>\n )\n }\n)\n","import type Lenis from 'lenis'\nimport type { ScrollCallback } from 'lenis'\nimport { useContext, useEffect } from 'react'\nimport { LenisContext, rootLenisContextStore } from './provider'\nimport { useStore } from './store'\nimport type { LenisContextValue } from './types'\n\n// Fall back to an empty object if both context and store are not available\nconst fallbackContext: Partial<LenisContextValue> = {}\n\n/**\n * Hook to access the Lenis instance and its methods\n *\n * @example <caption>Scroll callback</caption>\n * useLenis((lenis) => {\n * if (lenis.isScrolling) {\n * console.log('Scrolling...')\n * }\n *\n * if (lenis.progress === 1) {\n * console.log('At the end!')\n * }\n * })\n *\n * @example <caption>Scroll callback with dependencies</caption>\n * useLenis((lenis) => {\n * if (lenis.isScrolling) {\n * console.log('Scrolling...', someDependency)\n * }\n * }, [someDependency])\n * @example <caption>Scroll callback with priority</caption>\n * useLenis((lenis) => {\n * if (lenis.isScrolling) {\n * console.log('Scrolling...')\n * }\n * }, [], 1)\n * @example <caption>Instance access</caption>\n * const lenis = useLenis()\n *\n * handleClick() {\n * lenis.scrollTo(100, {\n * lerp: 0.1,\n * duration: 1,\n * easing: (t) => t,\n * onComplete: () => {\n * console.log('Complete!')\n * }\n * })\n * }\n */\nexport function useLenis(\n callback?: ScrollCallback,\n deps: unknown[] = [],\n priority = 0\n): Lenis | undefined {\n // Try to get the lenis instance from the context first\n const localContext = useContext(LenisContext)\n // Fall back to the root store if the context is not available\n const rootContext = useStore(rootLenisContextStore)\n // Fall back to the fallback context if all else fails\n const currentContext = localContext ?? rootContext ?? fallbackContext\n\n const { lenis, addCallback, removeCallback } = currentContext\n\n useEffect(() => {\n if (!(callback && addCallback && removeCallback && lenis)) return\n\n addCallback(callback, priority)\n callback(lenis)\n\n return () => {\n removeCallback(callback)\n }\n }, [lenis, addCallback, removeCallback, priority, ...deps, callback])\n\n return lenis\n}\n"],"mappings":"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"}