@neveranyart/weaver 1.0.9 → 1.0.10
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/README.md +2 -7
- package/dist/routing.d.mts +2 -2
- package/dist/routing.d.ts +2 -2
- package/dist/routing.js +6 -6
- package/dist/routing.js.map +1 -1
- package/dist/routing.mjs +6 -6
- package/dist/routing.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ function Root() {
|
|
|
50
50
|
|
|
51
51
|
function Home() {
|
|
52
52
|
return (
|
|
53
|
-
<Pipeline title={'Home'} debugName={'Home'}
|
|
53
|
+
<Pipeline title={'Home'} debugName={'Home'}>
|
|
54
54
|
<p>Home</p>
|
|
55
55
|
<Link to="/projects">Navigate</Link>
|
|
56
56
|
</Pipeline>
|
|
@@ -74,12 +74,7 @@ const router = createBrowserRouter([
|
|
|
74
74
|
path: '/projects/*',
|
|
75
75
|
element: (
|
|
76
76
|
<Suspense>
|
|
77
|
-
<Pipeline
|
|
78
|
-
title={'Projects'}
|
|
79
|
-
debugName={'Projects'}
|
|
80
|
-
{/* The `parentPath` is required and must match the actual route path */}
|
|
81
|
-
parentPath={'/projects'}
|
|
82
|
-
>
|
|
77
|
+
<Pipeline title={'Projects'} debugName={'Projects'}>
|
|
83
78
|
<p>Projects</p>
|
|
84
79
|
<Link to="/">Navigate</Link>
|
|
85
80
|
</Pipeline>
|
package/dist/routing.d.mts
CHANGED
|
@@ -52,9 +52,9 @@ interface PipelineProps {
|
|
|
52
52
|
*/
|
|
53
53
|
title: string;
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
55
|
+
* If provided, `Pipeline` will log the current phase to console.
|
|
56
56
|
*/
|
|
57
|
-
debugName
|
|
57
|
+
debugName?: string;
|
|
58
58
|
/**
|
|
59
59
|
* This is the only feature where weaver will use lenis to directly manipulate scrolling behaviour.
|
|
60
60
|
*
|
package/dist/routing.d.ts
CHANGED
|
@@ -52,9 +52,9 @@ interface PipelineProps {
|
|
|
52
52
|
*/
|
|
53
53
|
title: string;
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
55
|
+
* If provided, `Pipeline` will log the current phase to console.
|
|
56
56
|
*/
|
|
57
|
-
debugName
|
|
57
|
+
debugName?: string;
|
|
58
58
|
/**
|
|
59
59
|
* This is the only feature where weaver will use lenis to directly manipulate scrolling behaviour.
|
|
60
60
|
*
|
package/dist/routing.js
CHANGED
|
@@ -173,9 +173,6 @@ function Pipeline(props) {
|
|
|
173
173
|
() => getParentRoute(window.location.pathname),
|
|
174
174
|
[]
|
|
175
175
|
);
|
|
176
|
-
(0, import_react5.useLayoutEffect)(() => {
|
|
177
|
-
console.log(parentPath);
|
|
178
|
-
}, [parentPath]);
|
|
179
176
|
return /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement(RouteHandler, { ...restOfProps, parentPath }), children);
|
|
180
177
|
}
|
|
181
178
|
function RouteHandler(props) {
|
|
@@ -191,7 +188,8 @@ function RouteHandler(props) {
|
|
|
191
188
|
document.title = props.title;
|
|
192
189
|
setActivePipeline(props.parentPath);
|
|
193
190
|
if (props.contentReady !== void 0 && !props.contentReady) {
|
|
194
|
-
|
|
191
|
+
if (props.debugName)
|
|
192
|
+
console.log(`[${props.debugName}] Renderer status: Loading scene`);
|
|
195
193
|
return;
|
|
196
194
|
}
|
|
197
195
|
if (!navigating && (!pageRendered || activeParent !== props.parentPath)) {
|
|
@@ -200,7 +198,8 @@ function RouteHandler(props) {
|
|
|
200
198
|
}
|
|
201
199
|
setPageRendered(true);
|
|
202
200
|
setActiveParent(props.parentPath);
|
|
203
|
-
|
|
201
|
+
if (props.debugName)
|
|
202
|
+
console.log(`[${props.debugName}] Renderer status: Mounted`);
|
|
204
203
|
}
|
|
205
204
|
}, [
|
|
206
205
|
activeParent,
|
|
@@ -224,7 +223,8 @@ function RouteHandler(props) {
|
|
|
224
223
|
force: true
|
|
225
224
|
});
|
|
226
225
|
}
|
|
227
|
-
|
|
226
|
+
if (props.debugName)
|
|
227
|
+
console.log(`[${props.debugName}] Renderer status: Unmounted`);
|
|
228
228
|
};
|
|
229
229
|
});
|
|
230
230
|
return null;
|
package/dist/routing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routing/index.ts","../src/routing/context.ts","../src/routing/DelayedOutlet.tsx","../src/hooks/routeNormalizer.ts","../src/utils/getParentRoute.ts","../src/routing/Pipeline.tsx","../src/hooks/effectOnce.ts","../src/setup.ts"],"sourcesContent":["import { useWeaverContext, WeaverContextGetter } from './context';\nimport DelayedOutlet from './DelayedOutlet';\nimport Pipeline from './Pipeline';\n\n/// A read-only state for reacting with changes reflected by weaver.\nexport const useWeaverState = (givenState: keyof WeaverContextGetter) => {\n const state = useWeaverContext((state) => state[givenState]);\n return state;\n};\n\nexport { DelayedOutlet, Pipeline };\n","import { create } from 'zustand/react';\n\nexport interface WeaverContextGetter {\n /**\n * Current active parent, **AFTER** Pipeline has finished rendering, so the `activeParent`\n * will be delayed. Example: \"/\", \"/works\",...\n */\n activeParent: string;\n\n /**\n * Current active Pipeline. Example: \"/\", \"/works\",...\n *\n * This is **not based on URL**, it's based on which `Pipeline` has access to the the site.\n */\n activePipeline: string;\n\n /**\n * `DelayedOutlet` special variable, indicating if the route is current transitioning to a new route or not.\n */\n navigating: boolean;\n\n /**\n * When the page is rendered, it will turns this to true,\n * any parent page navigation will causes this to goes false, set to false in `DelayedOulet`.\n *\n * It's set to `false` right after `navigating` is set to `true`. `true` statement will be handled by `Pipeline`.\n */\n pageRendered: boolean;\n}\n\ninterface WeaverContextSetter {\n setActiveParent: (activeParent: string) => void;\n setActivePipeline: (activePipeline: string) => void;\n setNavigating: (navigating: boolean) => void;\n setPageRendered: (pageRendered: boolean) => void;\n}\n\nexport const useWeaverContext = create<\n WeaverContextSetter & WeaverContextGetter\n>()((set) => ({\n activeParent: '',\n setActiveParent: (activeParent) => set({ activeParent }),\n\n activePipeline: '',\n setActivePipeline: (activePipeline) => set({ activePipeline }),\n\n navigating: true,\n setNavigating: (navigating) => set({ navigating }),\n\n pageRendered: false,\n setPageRendered: (pageRendered) => set({ pageRendered }),\n}));\n","import { type ReactNode, useLayoutEffect, useRef, useState } from 'react';\nimport { useOutlet } from 'react-router';\nimport { useRouteNormalizer } from '../hooks/routeNormalizer';\nimport { getParentRoute } from '../utils/getParentRoute';\nimport { useWeaverContext } from './context';\n\n/**\n * A core part of an in-house tool called `weaver`.\n *\n * Delaying the routing process from `react-router`, handles gracefully between `Pipeline`s\n * while allowing any loading fallback component to listen and react with event changes.\n */\nexport default function DelayedOutlet(props: { delay: number }) {\n // Middleware to detect and replace invalid url.\n useRouteNormalizer({ autoReplace: true });\n\n const activePipeline = useWeaverContext((state) => state.activePipeline);\n const setNavigating = useWeaverContext((state) => state.setNavigating);\n const setPageRendered = useWeaverContext((state) => state.setPageRendered);\n\n const renderPageTask = useRef(setTimeout(() => {}));\n const routerOutlet = useOutlet();\n\n const [renderer, setRenderer] = useState<ReactNode>(null);\n\n // Handle and update new parent page.\n useLayoutEffect(() => {\n /**\n * `pageRendered` should be outside of `renderPageTask`,\n * we alrady have `Pipeline` to correct errors.\n */\n if ('scrollRestoration' in history) {\n history.scrollRestoration = 'manual';\n }\n\n if (getParentRoute(window.location.pathname) === activePipeline) {\n // Avoid while changing page, cancelling before new page pushed in\n // cause `activePipeline` to not change, making `navigating` softlock.\n setNavigating(false);\n return;\n }\n\n setNavigating(true);\n setPageRendered(false);\n\n clearTimeout(renderPageTask.current);\n renderPageTask.current = setTimeout(() => {\n setRenderer(routerOutlet!);\n setNavigating(false);\n }, props.delay);\n\n return () => {\n /**\n * Clear invalid task that were scheduled last effect.\n */\n clearInterval(renderPageTask.current);\n };\n }, [\n activePipeline,\n props.delay,\n routerOutlet,\n setNavigating,\n setPageRendered,\n ]);\n\n return renderer;\n}\n","import { useCallback, useLayoutEffect } from 'react';\nimport { useLocation, useNavigate } from 'react-router';\n\nexport function useRouteNormalizer(options: { autoReplace: boolean }) {\n const { pathname } = useLocation();\n const navigate = useNavigate();\n\n const normalizer = useCallback(\n (input: string) => input.replace(/\\/+\\//g, () => '/'),\n []\n );\n\n useLayoutEffect(() => {\n const result = normalizer(pathname);\n if (options.autoReplace && result !== pathname) {\n window.location.replace(result);\n }\n }, [options.autoReplace, pathname, navigate, normalizer]);\n\n return {\n pathname,\n normalizer,\n };\n}\n","export function getParentRoute(pathname: string) {\n let slashes = 0;\n let sliceAt = 0;\n for (sliceAt; sliceAt < pathname.length; sliceAt++) {\n if (pathname[sliceAt] == '/') {\n slashes++;\n }\n if (slashes === 2) {\n break;\n }\n }\n\n return pathname.slice(0, sliceAt);\n}\n","import React, { useLayoutEffect, useMemo, type ReactNode } from 'react';\nimport { useLayoutEffectOnce } from '../hooks/effectOnce';\nimport { weaverSetup } from '../setup';\nimport { getParentRoute } from '../utils/getParentRoute';\nimport { useWeaverContext } from './context';\n\ninterface PipelineProps {\n children?: ReactNode;\n\n /**\n * A state switch to notifies `Pipeline` that the content and elements of the page is ready to be displayed.\n *\n * Usually, you will need to preload some other external sources, or initialize 3D scene, this state\n * make sure that the loading fallback doesn't mess up and show initializing stuff.\n *\n * Using `BakeScene`, you can ensure that the scene is loaded via its callback, you can then pass the state value that\n * `BakeScene` changes to this variable to hide all the lags behind loading screen.\n */\n contentReady?: boolean;\n\n /**\n * Title for the page.\n */\n title: string;\n\n /**\n * By default, `Pipeline` will log the current phase to console.\n */\n debugName: string;\n\n /**\n * This is the only feature where weaver will use lenis to directly manipulate scrolling behaviour.\n *\n * By default, this value is `true` when a lenis instance is provided.\n *\n * `Pipeline` will stop and start lenis automatically when this variable is `true`.\n *\n * Disable this feature to gains complete control over lenis when mounting/unmounting to handle however you want.\n */\n lenisUsage?: boolean;\n}\n\n/**\n * A core part of an in-house tool called `weaver`.\n *\n * `Pipeline`: Notifies & reflect changes to/from `LoadingFallback`\n * and `DelayedOutlet` about its page loading status.\n *\n * All parent routes must have `Pipeline` in order to work and sync with `DelayedOutlet`.\n */\nexport default function Pipeline(props: PipelineProps) {\n const { children, ...restOfProps } = props;\n const parentPath = useMemo(\n () => getParentRoute(window.location.pathname),\n []\n );\n\n useLayoutEffect(() => {\n console.log(parentPath);\n }, [parentPath]);\n\n return (\n <>\n <RouteHandler {...restOfProps} parentPath={parentPath} />\n {children}\n </>\n );\n}\n\nfunction RouteHandler(\n props: Omit<PipelineProps, 'children'> & { parentPath: string }\n) {\n const navigating = useWeaverContext((state) => state.navigating);\n const pageRendered = useWeaverContext((state) => state.pageRendered);\n const activeParent = useWeaverContext((state) => state.activeParent);\n\n const setActivePipeline = useWeaverContext(\n (state) => state.setActivePipeline\n );\n const setPageRendered = useWeaverContext((state) => state.setPageRendered);\n const setActiveParent = useWeaverContext((state) => state.setActiveParent);\n\n useLayoutEffect(() => {\n document.title = props.title;\n setActivePipeline(props.parentPath);\n\n if (props.contentReady !== undefined && !props.contentReady) {\n console.log(`[${props.debugName}] Renderer status: Loading scene`);\n return;\n }\n\n if (!navigating && (!pageRendered || activeParent !== props.parentPath)) {\n if (props.lenisUsage === undefined || props.lenisUsage) {\n weaverSetup._lenisInstance?.start();\n }\n\n setPageRendered(true);\n setActiveParent(props.parentPath);\n\n console.log(`[${props.debugName}] Renderer status: Mounted`);\n }\n }, [\n activeParent,\n setActivePipeline,\n navigating,\n pageRendered,\n props.lenisUsage,\n props.contentReady,\n props.debugName,\n props.parentPath,\n props.title,\n setActiveParent,\n setPageRendered,\n ]);\n\n useLayoutEffectOnce(() => {\n return () => {\n /**\n * When unmounted, stop lenis to pass control to another Pipline instance.\n *\n * The unmount process only happens when the `<LoadingFallback />` kicks in,\n * so any visual glitches can happen in here, we can now set the scroll position to 0.\n */\n if (props.lenisUsage === undefined || props.lenisUsage) {\n weaverSetup._lenisInstance?.stop();\n weaverSetup._lenisInstance?.scrollTo(0, {\n immediate: true,\n force: true,\n });\n }\n\n console.log(`[${props.debugName}] Renderer status: Unmounted`);\n };\n });\n\n return null;\n}\n","import { useEffect, useLayoutEffect } from 'react';\n\nexport function useEffectOnce(callback: React.EffectCallback) {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(callback, []);\n}\n\nexport function useLayoutEffectOnce(callback: React.EffectCallback) {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(callback, []);\n}\n","import Lenis from 'lenis';\nimport { ReactNode } from 'react';\n\nexport type BasicTunnelIn = ({ children }: { children: ReactNode }) => null;\n\nclass WeaverSetup {\n /**\n * This variable is handled internally by weaver. **Do not use**.\n */\n get _lenisInstance(): Lenis | undefined {\n return (globalThis as any).__weaverLenis;\n }\n set _lenisInstance(val: Lenis | undefined) {\n (globalThis as any).__weaverLenis = val;\n }\n\n /**\n * This variable is handled internally by weaver. **Do not use**.\n */\n get _Default3DTunnelIn(): BasicTunnelIn | undefined {\n return (globalThis as any).__weaver3DTunnel;\n }\n set _Default3DTunnelIn(val: BasicTunnelIn | undefined) {\n (globalThis as any).__weaver3DTunnel = val;\n }\n\n setLenisInstance(instance: Lenis) {\n this._lenisInstance = instance;\n }\n set3DTunnel(tunnelIn: BasicTunnelIn) {\n this._Default3DTunnelIn = tunnelIn;\n }\n}\n\nexport const weaverSetup = new WeaverSetup();\n"],"mappings":"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","names":["import_react","import_react_router","import_react","import_react","import_react","React","state"]}
|
|
1
|
+
{"version":3,"sources":["../src/routing/index.ts","../src/routing/context.ts","../src/routing/DelayedOutlet.tsx","../src/hooks/routeNormalizer.ts","../src/utils/getParentRoute.ts","../src/routing/Pipeline.tsx","../src/hooks/effectOnce.ts","../src/setup.ts"],"sourcesContent":["import { useWeaverContext, WeaverContextGetter } from './context';\nimport DelayedOutlet from './DelayedOutlet';\nimport Pipeline from './Pipeline';\n\n/// A read-only state for reacting with changes reflected by weaver.\nexport const useWeaverState = (givenState: keyof WeaverContextGetter) => {\n const state = useWeaverContext((state) => state[givenState]);\n return state;\n};\n\nexport { DelayedOutlet, Pipeline };\n","import { create } from 'zustand/react';\n\nexport interface WeaverContextGetter {\n /**\n * Current active parent, **AFTER** Pipeline has finished rendering, so the `activeParent`\n * will be delayed. Example: \"/\", \"/works\",...\n */\n activeParent: string;\n\n /**\n * Current active Pipeline. Example: \"/\", \"/works\",...\n *\n * This is **not based on URL**, it's based on which `Pipeline` has access to the the site.\n */\n activePipeline: string;\n\n /**\n * `DelayedOutlet` special variable, indicating if the route is current transitioning to a new route or not.\n */\n navigating: boolean;\n\n /**\n * When the page is rendered, it will turns this to true,\n * any parent page navigation will causes this to goes false, set to false in `DelayedOulet`.\n *\n * It's set to `false` right after `navigating` is set to `true`. `true` statement will be handled by `Pipeline`.\n */\n pageRendered: boolean;\n}\n\ninterface WeaverContextSetter {\n setActiveParent: (activeParent: string) => void;\n setActivePipeline: (activePipeline: string) => void;\n setNavigating: (navigating: boolean) => void;\n setPageRendered: (pageRendered: boolean) => void;\n}\n\nexport const useWeaverContext = create<\n WeaverContextSetter & WeaverContextGetter\n>()((set) => ({\n activeParent: '',\n setActiveParent: (activeParent) => set({ activeParent }),\n\n activePipeline: '',\n setActivePipeline: (activePipeline) => set({ activePipeline }),\n\n navigating: true,\n setNavigating: (navigating) => set({ navigating }),\n\n pageRendered: false,\n setPageRendered: (pageRendered) => set({ pageRendered }),\n}));\n","import { type ReactNode, useLayoutEffect, useRef, useState } from 'react';\nimport { useOutlet } from 'react-router';\nimport { useRouteNormalizer } from '../hooks/routeNormalizer';\nimport { getParentRoute } from '../utils/getParentRoute';\nimport { useWeaverContext } from './context';\n\n/**\n * A core part of an in-house tool called `weaver`.\n *\n * Delaying the routing process from `react-router`, handles gracefully between `Pipeline`s\n * while allowing any loading fallback component to listen and react with event changes.\n */\nexport default function DelayedOutlet(props: { delay: number }) {\n // Middleware to detect and replace invalid url.\n useRouteNormalizer({ autoReplace: true });\n\n const activePipeline = useWeaverContext((state) => state.activePipeline);\n const setNavigating = useWeaverContext((state) => state.setNavigating);\n const setPageRendered = useWeaverContext((state) => state.setPageRendered);\n\n const renderPageTask = useRef(setTimeout(() => {}));\n const routerOutlet = useOutlet();\n\n const [renderer, setRenderer] = useState<ReactNode>(null);\n\n // Handle and update new parent page.\n useLayoutEffect(() => {\n /**\n * `pageRendered` should be outside of `renderPageTask`,\n * we alrady have `Pipeline` to correct errors.\n */\n if ('scrollRestoration' in history) {\n history.scrollRestoration = 'manual';\n }\n\n if (getParentRoute(window.location.pathname) === activePipeline) {\n // Avoid while changing page, cancelling before new page pushed in\n // cause `activePipeline` to not change, making `navigating` softlock.\n setNavigating(false);\n return;\n }\n\n setNavigating(true);\n setPageRendered(false);\n\n clearTimeout(renderPageTask.current);\n renderPageTask.current = setTimeout(() => {\n setRenderer(routerOutlet!);\n setNavigating(false);\n }, props.delay);\n\n return () => {\n /**\n * Clear invalid task that were scheduled last effect.\n */\n clearInterval(renderPageTask.current);\n };\n }, [\n activePipeline,\n props.delay,\n routerOutlet,\n setNavigating,\n setPageRendered,\n ]);\n\n return renderer;\n}\n","import { useCallback, useLayoutEffect } from 'react';\nimport { useLocation, useNavigate } from 'react-router';\n\nexport function useRouteNormalizer(options: { autoReplace: boolean }) {\n const { pathname } = useLocation();\n const navigate = useNavigate();\n\n const normalizer = useCallback(\n (input: string) => input.replace(/\\/+\\//g, () => '/'),\n []\n );\n\n useLayoutEffect(() => {\n const result = normalizer(pathname);\n if (options.autoReplace && result !== pathname) {\n window.location.replace(result);\n }\n }, [options.autoReplace, pathname, navigate, normalizer]);\n\n return {\n pathname,\n normalizer,\n };\n}\n","export function getParentRoute(pathname: string) {\n let slashes = 0;\n let sliceAt = 0;\n for (sliceAt; sliceAt < pathname.length; sliceAt++) {\n if (pathname[sliceAt] == '/') {\n slashes++;\n }\n if (slashes === 2) {\n break;\n }\n }\n\n return pathname.slice(0, sliceAt);\n}\n","import React, { useLayoutEffect, useMemo, type ReactNode } from 'react';\nimport { useLayoutEffectOnce } from '../hooks/effectOnce';\nimport { weaverSetup } from '../setup';\nimport { getParentRoute } from '../utils/getParentRoute';\nimport { useWeaverContext } from './context';\n\ninterface PipelineProps {\n children?: ReactNode;\n\n /**\n * A state switch to notifies `Pipeline` that the content and elements of the page is ready to be displayed.\n *\n * Usually, you will need to preload some other external sources, or initialize 3D scene, this state\n * make sure that the loading fallback doesn't mess up and show initializing stuff.\n *\n * Using `BakeScene`, you can ensure that the scene is loaded via its callback, you can then pass the state value that\n * `BakeScene` changes to this variable to hide all the lags behind loading screen.\n */\n contentReady?: boolean;\n\n /**\n * Title for the page.\n */\n title: string;\n\n /**\n * If provided, `Pipeline` will log the current phase to console.\n */\n debugName?: string;\n\n /**\n * This is the only feature where weaver will use lenis to directly manipulate scrolling behaviour.\n *\n * By default, this value is `true` when a lenis instance is provided.\n *\n * `Pipeline` will stop and start lenis automatically when this variable is `true`.\n *\n * Disable this feature to gains complete control over lenis when mounting/unmounting to handle however you want.\n */\n lenisUsage?: boolean;\n}\n\n/**\n * A core part of an in-house tool called `weaver`.\n *\n * `Pipeline`: Notifies & reflect changes to/from `LoadingFallback`\n * and `DelayedOutlet` about its page loading status.\n *\n * All parent routes must have `Pipeline` in order to work and sync with `DelayedOutlet`.\n */\nexport default function Pipeline(props: PipelineProps) {\n const { children, ...restOfProps } = props;\n const parentPath = useMemo(\n () => getParentRoute(window.location.pathname),\n []\n );\n\n return (\n <>\n <RouteHandler {...restOfProps} parentPath={parentPath} />\n {children}\n </>\n );\n}\n\nfunction RouteHandler(\n props: Omit<PipelineProps, 'children'> & { parentPath: string }\n) {\n const navigating = useWeaverContext((state) => state.navigating);\n const pageRendered = useWeaverContext((state) => state.pageRendered);\n const activeParent = useWeaverContext((state) => state.activeParent);\n\n const setActivePipeline = useWeaverContext(\n (state) => state.setActivePipeline\n );\n const setPageRendered = useWeaverContext((state) => state.setPageRendered);\n const setActiveParent = useWeaverContext((state) => state.setActiveParent);\n\n useLayoutEffect(() => {\n document.title = props.title;\n setActivePipeline(props.parentPath);\n\n if (props.contentReady !== undefined && !props.contentReady) {\n if (props.debugName)\n console.log(`[${props.debugName}] Renderer status: Loading scene`);\n return;\n }\n\n if (!navigating && (!pageRendered || activeParent !== props.parentPath)) {\n if (props.lenisUsage === undefined || props.lenisUsage) {\n weaverSetup._lenisInstance?.start();\n }\n\n setPageRendered(true);\n setActiveParent(props.parentPath);\n\n if (props.debugName)\n console.log(`[${props.debugName}] Renderer status: Mounted`);\n }\n }, [\n activeParent,\n setActivePipeline,\n navigating,\n pageRendered,\n props.lenisUsage,\n props.contentReady,\n props.debugName,\n props.parentPath,\n props.title,\n setActiveParent,\n setPageRendered,\n ]);\n\n useLayoutEffectOnce(() => {\n return () => {\n /**\n * When unmounted, stop lenis to pass control to another Pipline instance.\n *\n * The unmount process only happens when the `<LoadingFallback />` kicks in,\n * so any visual glitches can happen in here, we can now set the scroll position to 0.\n */\n if (props.lenisUsage === undefined || props.lenisUsage) {\n weaverSetup._lenisInstance?.stop();\n weaverSetup._lenisInstance?.scrollTo(0, {\n immediate: true,\n force: true,\n });\n }\n\n if (props.debugName)\n console.log(`[${props.debugName}] Renderer status: Unmounted`);\n };\n });\n\n return null;\n}\n","import { useEffect, useLayoutEffect } from 'react';\n\nexport function useEffectOnce(callback: React.EffectCallback) {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(callback, []);\n}\n\nexport function useLayoutEffectOnce(callback: React.EffectCallback) {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(callback, []);\n}\n","import Lenis from 'lenis';\nimport { ReactNode } from 'react';\n\nexport type BasicTunnelIn = ({ children }: { children: ReactNode }) => null;\n\nclass WeaverSetup {\n /**\n * This variable is handled internally by weaver. **Do not use**.\n */\n get _lenisInstance(): Lenis | undefined {\n return (globalThis as any).__weaverLenis;\n }\n set _lenisInstance(val: Lenis | undefined) {\n (globalThis as any).__weaverLenis = val;\n }\n\n /**\n * This variable is handled internally by weaver. **Do not use**.\n */\n get _Default3DTunnelIn(): BasicTunnelIn | undefined {\n return (globalThis as any).__weaver3DTunnel;\n }\n set _Default3DTunnelIn(val: BasicTunnelIn | undefined) {\n (globalThis as any).__weaver3DTunnel = val;\n }\n\n setLenisInstance(instance: Lenis) {\n this._lenisInstance = instance;\n }\n set3DTunnel(tunnelIn: BasicTunnelIn) {\n this._Default3DTunnelIn = tunnelIn;\n }\n}\n\nexport const weaverSetup = new WeaverSetup();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAAuB;AAqChB,IAAM,uBAAmB,qBAE9B,EAAE,CAAC,SAAS;AAAA,EACZ,cAAc;AAAA,EACd,iBAAiB,CAAC,iBAAiB,IAAI,EAAE,aAAa,CAAC;AAAA,EAEvD,gBAAgB;AAAA,EAChB,mBAAmB,CAAC,mBAAmB,IAAI,EAAE,eAAe,CAAC;AAAA,EAE7D,YAAY;AAAA,EACZ,eAAe,CAAC,eAAe,IAAI,EAAE,WAAW,CAAC;AAAA,EAEjD,cAAc;AAAA,EACd,iBAAiB,CAAC,iBAAiB,IAAI,EAAE,aAAa,CAAC;AACzD,EAAE;;;ACnDF,IAAAA,gBAAkE;AAClE,IAAAC,uBAA0B;;;ACD1B,IAAAC,gBAA6C;AAC7C,0BAAyC;AAElC,SAAS,mBAAmB,SAAmC;AACpE,QAAM,EAAE,SAAS,QAAI,iCAAY;AACjC,QAAM,eAAW,iCAAY;AAE7B,QAAM,iBAAa;AAAA,IACjB,CAAC,UAAkB,MAAM,QAAQ,UAAU,MAAM,GAAG;AAAA,IACpD,CAAC;AAAA,EACH;AAEA,qCAAgB,MAAM;AACpB,UAAM,SAAS,WAAW,QAAQ;AAClC,QAAI,QAAQ,eAAe,WAAW,UAAU;AAC9C,aAAO,SAAS,QAAQ,MAAM;AAAA,IAChC;AAAA,EACF,GAAG,CAAC,QAAQ,aAAa,UAAU,UAAU,UAAU,CAAC;AAExD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;;;ACvBO,SAAS,eAAe,UAAkB;AAC/C,MAAI,UAAU;AACd,MAAI,UAAU;AACd,OAAK,SAAS,UAAU,SAAS,QAAQ,WAAW;AAClD,QAAI,SAAS,OAAO,KAAK,KAAK;AAC5B;AAAA,IACF;AACA,QAAI,YAAY,GAAG;AACjB;AAAA,IACF;AAAA,EACF;AAEA,SAAO,SAAS,MAAM,GAAG,OAAO;AAClC;;;AFDe,SAAR,cAA+B,OAA0B;AAE9D,qBAAmB,EAAE,aAAa,KAAK,CAAC;AAExC,QAAM,iBAAiB,iBAAiB,CAAC,UAAU,MAAM,cAAc;AACvE,QAAM,gBAAgB,iBAAiB,CAAC,UAAU,MAAM,aAAa;AACrE,QAAM,kBAAkB,iBAAiB,CAAC,UAAU,MAAM,eAAe;AAEzE,QAAM,qBAAiB,sBAAO,WAAW,MAAM;AAAA,EAAC,CAAC,CAAC;AAClD,QAAM,mBAAe,gCAAU;AAE/B,QAAM,CAAC,UAAU,WAAW,QAAI,wBAAoB,IAAI;AAGxD,qCAAgB,MAAM;AAKpB,QAAI,uBAAuB,SAAS;AAClC,cAAQ,oBAAoB;AAAA,IAC9B;AAEA,QAAI,eAAe,OAAO,SAAS,QAAQ,MAAM,gBAAgB;AAG/D,oBAAc,KAAK;AACnB;AAAA,IACF;AAEA,kBAAc,IAAI;AAClB,oBAAgB,KAAK;AAErB,iBAAa,eAAe,OAAO;AACnC,mBAAe,UAAU,WAAW,MAAM;AACxC,kBAAY,YAAa;AACzB,oBAAc,KAAK;AAAA,IACrB,GAAG,MAAM,KAAK;AAEd,WAAO,MAAM;AAIX,oBAAc,eAAe,OAAO;AAAA,IACtC;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;AGlEA,IAAAC,gBAAgE;;;ACAhE,IAAAC,gBAA2C;AAOpC,SAAS,oBAAoB,UAAgC;AAElE,qCAAgB,UAAU,CAAC,CAAC;AAC9B;;;ACLA,IAAM,cAAN,MAAkB;AAAA;AAAA;AAAA;AAAA,EAIhB,IAAI,iBAAoC;AACtC,WAAQ,WAAmB;AAAA,EAC7B;AAAA,EACA,IAAI,eAAe,KAAwB;AACzC,IAAC,WAAmB,gBAAgB;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,qBAAgD;AAClD,WAAQ,WAAmB;AAAA,EAC7B;AAAA,EACA,IAAI,mBAAmB,KAAgC;AACrD,IAAC,WAAmB,mBAAmB;AAAA,EACzC;AAAA,EAEA,iBAAiB,UAAiB;AAChC,SAAK,iBAAiB;AAAA,EACxB;AAAA,EACA,YAAY,UAAyB;AACnC,SAAK,qBAAqB;AAAA,EAC5B;AACF;AAEO,IAAM,cAAc,IAAI,YAAY;;;AFgB5B,SAAR,SAA0B,OAAsB;AACrD,QAAM,EAAE,UAAU,GAAG,YAAY,IAAI;AACrC,QAAM,iBAAa;AAAA,IACjB,MAAM,eAAe,OAAO,SAAS,QAAQ;AAAA,IAC7C,CAAC;AAAA,EACH;AAEA,SACE,8BAAAC,QAAA,4BAAAA,QAAA,gBACE,8BAAAA,QAAA,cAAC,gBAAc,GAAG,aAAa,YAAwB,GACtD,QACH;AAEJ;AAEA,SAAS,aACP,OACA;AACA,QAAM,aAAa,iBAAiB,CAAC,UAAU,MAAM,UAAU;AAC/D,QAAM,eAAe,iBAAiB,CAAC,UAAU,MAAM,YAAY;AACnE,QAAM,eAAe,iBAAiB,CAAC,UAAU,MAAM,YAAY;AAEnE,QAAM,oBAAoB;AAAA,IACxB,CAAC,UAAU,MAAM;AAAA,EACnB;AACA,QAAM,kBAAkB,iBAAiB,CAAC,UAAU,MAAM,eAAe;AACzE,QAAM,kBAAkB,iBAAiB,CAAC,UAAU,MAAM,eAAe;AAEzE,qCAAgB,MAAM;AACpB,aAAS,QAAQ,MAAM;AACvB,sBAAkB,MAAM,UAAU;AAElC,QAAI,MAAM,iBAAiB,UAAa,CAAC,MAAM,cAAc;AAC3D,UAAI,MAAM;AACR,gBAAQ,IAAI,IAAI,MAAM,SAAS,kCAAkC;AACnE;AAAA,IACF;AAEA,QAAI,CAAC,eAAe,CAAC,gBAAgB,iBAAiB,MAAM,aAAa;AACvE,UAAI,MAAM,eAAe,UAAa,MAAM,YAAY;AACtD,oBAAY,gBAAgB,MAAM;AAAA,MACpC;AAEA,sBAAgB,IAAI;AACpB,sBAAgB,MAAM,UAAU;AAEhC,UAAI,MAAM;AACR,gBAAQ,IAAI,IAAI,MAAM,SAAS,4BAA4B;AAAA,IAC/D;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF,CAAC;AAED,sBAAoB,MAAM;AACxB,WAAO,MAAM;AAOX,UAAI,MAAM,eAAe,UAAa,MAAM,YAAY;AACtD,oBAAY,gBAAgB,KAAK;AACjC,oBAAY,gBAAgB,SAAS,GAAG;AAAA,UACtC,WAAW;AAAA,UACX,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAEA,UAAI,MAAM;AACR,gBAAQ,IAAI,IAAI,MAAM,SAAS,8BAA8B;AAAA,IACjE;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;ALlIO,IAAM,iBAAiB,CAAC,eAA0C;AACvE,QAAM,QAAQ,iBAAiB,CAACC,WAAUA,OAAM,UAAU,CAAC;AAC3D,SAAO;AACT;","names":["import_react","import_react_router","import_react","import_react","import_react","React","state"]}
|
package/dist/routing.mjs
CHANGED
|
@@ -135,9 +135,6 @@ function Pipeline(props) {
|
|
|
135
135
|
() => getParentRoute(window.location.pathname),
|
|
136
136
|
[]
|
|
137
137
|
);
|
|
138
|
-
useLayoutEffect4(() => {
|
|
139
|
-
console.log(parentPath);
|
|
140
|
-
}, [parentPath]);
|
|
141
138
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(RouteHandler, { ...restOfProps, parentPath }), children);
|
|
142
139
|
}
|
|
143
140
|
function RouteHandler(props) {
|
|
@@ -153,7 +150,8 @@ function RouteHandler(props) {
|
|
|
153
150
|
document.title = props.title;
|
|
154
151
|
setActivePipeline(props.parentPath);
|
|
155
152
|
if (props.contentReady !== void 0 && !props.contentReady) {
|
|
156
|
-
|
|
153
|
+
if (props.debugName)
|
|
154
|
+
console.log(`[${props.debugName}] Renderer status: Loading scene`);
|
|
157
155
|
return;
|
|
158
156
|
}
|
|
159
157
|
if (!navigating && (!pageRendered || activeParent !== props.parentPath)) {
|
|
@@ -162,7 +160,8 @@ function RouteHandler(props) {
|
|
|
162
160
|
}
|
|
163
161
|
setPageRendered(true);
|
|
164
162
|
setActiveParent(props.parentPath);
|
|
165
|
-
|
|
163
|
+
if (props.debugName)
|
|
164
|
+
console.log(`[${props.debugName}] Renderer status: Mounted`);
|
|
166
165
|
}
|
|
167
166
|
}, [
|
|
168
167
|
activeParent,
|
|
@@ -186,7 +185,8 @@ function RouteHandler(props) {
|
|
|
186
185
|
force: true
|
|
187
186
|
});
|
|
188
187
|
}
|
|
189
|
-
|
|
188
|
+
if (props.debugName)
|
|
189
|
+
console.log(`[${props.debugName}] Renderer status: Unmounted`);
|
|
190
190
|
};
|
|
191
191
|
});
|
|
192
192
|
return null;
|
package/dist/routing.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routing/context.ts","../src/routing/DelayedOutlet.tsx","../src/hooks/routeNormalizer.ts","../src/utils/getParentRoute.ts","../src/routing/Pipeline.tsx","../src/hooks/effectOnce.ts","../src/setup.ts","../src/routing/index.ts"],"sourcesContent":["import { create } from 'zustand/react';\n\nexport interface WeaverContextGetter {\n /**\n * Current active parent, **AFTER** Pipeline has finished rendering, so the `activeParent`\n * will be delayed. Example: \"/\", \"/works\",...\n */\n activeParent: string;\n\n /**\n * Current active Pipeline. Example: \"/\", \"/works\",...\n *\n * This is **not based on URL**, it's based on which `Pipeline` has access to the the site.\n */\n activePipeline: string;\n\n /**\n * `DelayedOutlet` special variable, indicating if the route is current transitioning to a new route or not.\n */\n navigating: boolean;\n\n /**\n * When the page is rendered, it will turns this to true,\n * any parent page navigation will causes this to goes false, set to false in `DelayedOulet`.\n *\n * It's set to `false` right after `navigating` is set to `true`. `true` statement will be handled by `Pipeline`.\n */\n pageRendered: boolean;\n}\n\ninterface WeaverContextSetter {\n setActiveParent: (activeParent: string) => void;\n setActivePipeline: (activePipeline: string) => void;\n setNavigating: (navigating: boolean) => void;\n setPageRendered: (pageRendered: boolean) => void;\n}\n\nexport const useWeaverContext = create<\n WeaverContextSetter & WeaverContextGetter\n>()((set) => ({\n activeParent: '',\n setActiveParent: (activeParent) => set({ activeParent }),\n\n activePipeline: '',\n setActivePipeline: (activePipeline) => set({ activePipeline }),\n\n navigating: true,\n setNavigating: (navigating) => set({ navigating }),\n\n pageRendered: false,\n setPageRendered: (pageRendered) => set({ pageRendered }),\n}));\n","import { type ReactNode, useLayoutEffect, useRef, useState } from 'react';\nimport { useOutlet } from 'react-router';\nimport { useRouteNormalizer } from '../hooks/routeNormalizer';\nimport { getParentRoute } from '../utils/getParentRoute';\nimport { useWeaverContext } from './context';\n\n/**\n * A core part of an in-house tool called `weaver`.\n *\n * Delaying the routing process from `react-router`, handles gracefully between `Pipeline`s\n * while allowing any loading fallback component to listen and react with event changes.\n */\nexport default function DelayedOutlet(props: { delay: number }) {\n // Middleware to detect and replace invalid url.\n useRouteNormalizer({ autoReplace: true });\n\n const activePipeline = useWeaverContext((state) => state.activePipeline);\n const setNavigating = useWeaverContext((state) => state.setNavigating);\n const setPageRendered = useWeaverContext((state) => state.setPageRendered);\n\n const renderPageTask = useRef(setTimeout(() => {}));\n const routerOutlet = useOutlet();\n\n const [renderer, setRenderer] = useState<ReactNode>(null);\n\n // Handle and update new parent page.\n useLayoutEffect(() => {\n /**\n * `pageRendered` should be outside of `renderPageTask`,\n * we alrady have `Pipeline` to correct errors.\n */\n if ('scrollRestoration' in history) {\n history.scrollRestoration = 'manual';\n }\n\n if (getParentRoute(window.location.pathname) === activePipeline) {\n // Avoid while changing page, cancelling before new page pushed in\n // cause `activePipeline` to not change, making `navigating` softlock.\n setNavigating(false);\n return;\n }\n\n setNavigating(true);\n setPageRendered(false);\n\n clearTimeout(renderPageTask.current);\n renderPageTask.current = setTimeout(() => {\n setRenderer(routerOutlet!);\n setNavigating(false);\n }, props.delay);\n\n return () => {\n /**\n * Clear invalid task that were scheduled last effect.\n */\n clearInterval(renderPageTask.current);\n };\n }, [\n activePipeline,\n props.delay,\n routerOutlet,\n setNavigating,\n setPageRendered,\n ]);\n\n return renderer;\n}\n","import { useCallback, useLayoutEffect } from 'react';\nimport { useLocation, useNavigate } from 'react-router';\n\nexport function useRouteNormalizer(options: { autoReplace: boolean }) {\n const { pathname } = useLocation();\n const navigate = useNavigate();\n\n const normalizer = useCallback(\n (input: string) => input.replace(/\\/+\\//g, () => '/'),\n []\n );\n\n useLayoutEffect(() => {\n const result = normalizer(pathname);\n if (options.autoReplace && result !== pathname) {\n window.location.replace(result);\n }\n }, [options.autoReplace, pathname, navigate, normalizer]);\n\n return {\n pathname,\n normalizer,\n };\n}\n","export function getParentRoute(pathname: string) {\n let slashes = 0;\n let sliceAt = 0;\n for (sliceAt; sliceAt < pathname.length; sliceAt++) {\n if (pathname[sliceAt] == '/') {\n slashes++;\n }\n if (slashes === 2) {\n break;\n }\n }\n\n return pathname.slice(0, sliceAt);\n}\n","import React, { useLayoutEffect, useMemo, type ReactNode } from 'react';\nimport { useLayoutEffectOnce } from '../hooks/effectOnce';\nimport { weaverSetup } from '../setup';\nimport { getParentRoute } from '../utils/getParentRoute';\nimport { useWeaverContext } from './context';\n\ninterface PipelineProps {\n children?: ReactNode;\n\n /**\n * A state switch to notifies `Pipeline` that the content and elements of the page is ready to be displayed.\n *\n * Usually, you will need to preload some other external sources, or initialize 3D scene, this state\n * make sure that the loading fallback doesn't mess up and show initializing stuff.\n *\n * Using `BakeScene`, you can ensure that the scene is loaded via its callback, you can then pass the state value that\n * `BakeScene` changes to this variable to hide all the lags behind loading screen.\n */\n contentReady?: boolean;\n\n /**\n * Title for the page.\n */\n title: string;\n\n /**\n * By default, `Pipeline` will log the current phase to console.\n */\n debugName: string;\n\n /**\n * This is the only feature where weaver will use lenis to directly manipulate scrolling behaviour.\n *\n * By default, this value is `true` when a lenis instance is provided.\n *\n * `Pipeline` will stop and start lenis automatically when this variable is `true`.\n *\n * Disable this feature to gains complete control over lenis when mounting/unmounting to handle however you want.\n */\n lenisUsage?: boolean;\n}\n\n/**\n * A core part of an in-house tool called `weaver`.\n *\n * `Pipeline`: Notifies & reflect changes to/from `LoadingFallback`\n * and `DelayedOutlet` about its page loading status.\n *\n * All parent routes must have `Pipeline` in order to work and sync with `DelayedOutlet`.\n */\nexport default function Pipeline(props: PipelineProps) {\n const { children, ...restOfProps } = props;\n const parentPath = useMemo(\n () => getParentRoute(window.location.pathname),\n []\n );\n\n useLayoutEffect(() => {\n console.log(parentPath);\n }, [parentPath]);\n\n return (\n <>\n <RouteHandler {...restOfProps} parentPath={parentPath} />\n {children}\n </>\n );\n}\n\nfunction RouteHandler(\n props: Omit<PipelineProps, 'children'> & { parentPath: string }\n) {\n const navigating = useWeaverContext((state) => state.navigating);\n const pageRendered = useWeaverContext((state) => state.pageRendered);\n const activeParent = useWeaverContext((state) => state.activeParent);\n\n const setActivePipeline = useWeaverContext(\n (state) => state.setActivePipeline\n );\n const setPageRendered = useWeaverContext((state) => state.setPageRendered);\n const setActiveParent = useWeaverContext((state) => state.setActiveParent);\n\n useLayoutEffect(() => {\n document.title = props.title;\n setActivePipeline(props.parentPath);\n\n if (props.contentReady !== undefined && !props.contentReady) {\n console.log(`[${props.debugName}] Renderer status: Loading scene`);\n return;\n }\n\n if (!navigating && (!pageRendered || activeParent !== props.parentPath)) {\n if (props.lenisUsage === undefined || props.lenisUsage) {\n weaverSetup._lenisInstance?.start();\n }\n\n setPageRendered(true);\n setActiveParent(props.parentPath);\n\n console.log(`[${props.debugName}] Renderer status: Mounted`);\n }\n }, [\n activeParent,\n setActivePipeline,\n navigating,\n pageRendered,\n props.lenisUsage,\n props.contentReady,\n props.debugName,\n props.parentPath,\n props.title,\n setActiveParent,\n setPageRendered,\n ]);\n\n useLayoutEffectOnce(() => {\n return () => {\n /**\n * When unmounted, stop lenis to pass control to another Pipline instance.\n *\n * The unmount process only happens when the `<LoadingFallback />` kicks in,\n * so any visual glitches can happen in here, we can now set the scroll position to 0.\n */\n if (props.lenisUsage === undefined || props.lenisUsage) {\n weaverSetup._lenisInstance?.stop();\n weaverSetup._lenisInstance?.scrollTo(0, {\n immediate: true,\n force: true,\n });\n }\n\n console.log(`[${props.debugName}] Renderer status: Unmounted`);\n };\n });\n\n return null;\n}\n","import { useEffect, useLayoutEffect } from 'react';\n\nexport function useEffectOnce(callback: React.EffectCallback) {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(callback, []);\n}\n\nexport function useLayoutEffectOnce(callback: React.EffectCallback) {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(callback, []);\n}\n","import Lenis from 'lenis';\nimport { ReactNode } from 'react';\n\nexport type BasicTunnelIn = ({ children }: { children: ReactNode }) => null;\n\nclass WeaverSetup {\n /**\n * This variable is handled internally by weaver. **Do not use**.\n */\n get _lenisInstance(): Lenis | undefined {\n return (globalThis as any).__weaverLenis;\n }\n set _lenisInstance(val: Lenis | undefined) {\n (globalThis as any).__weaverLenis = val;\n }\n\n /**\n * This variable is handled internally by weaver. **Do not use**.\n */\n get _Default3DTunnelIn(): BasicTunnelIn | undefined {\n return (globalThis as any).__weaver3DTunnel;\n }\n set _Default3DTunnelIn(val: BasicTunnelIn | undefined) {\n (globalThis as any).__weaver3DTunnel = val;\n }\n\n setLenisInstance(instance: Lenis) {\n this._lenisInstance = instance;\n }\n set3DTunnel(tunnelIn: BasicTunnelIn) {\n this._Default3DTunnelIn = tunnelIn;\n }\n}\n\nexport const weaverSetup = new WeaverSetup();\n","import { useWeaverContext, WeaverContextGetter } from './context';\nimport DelayedOutlet from './DelayedOutlet';\nimport Pipeline from './Pipeline';\n\n/// A read-only state for reacting with changes reflected by weaver.\nexport const useWeaverState = (givenState: keyof WeaverContextGetter) => {\n const state = useWeaverContext((state) => state[givenState]);\n return state;\n};\n\nexport { DelayedOutlet, Pipeline };\n"],"mappings":"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","names":["useLayoutEffect","useLayoutEffect","useLayoutEffect","useLayoutEffect","useLayoutEffect","useLayoutEffect","state"]}
|
|
1
|
+
{"version":3,"sources":["../src/routing/context.ts","../src/routing/DelayedOutlet.tsx","../src/hooks/routeNormalizer.ts","../src/utils/getParentRoute.ts","../src/routing/Pipeline.tsx","../src/hooks/effectOnce.ts","../src/setup.ts","../src/routing/index.ts"],"sourcesContent":["import { create } from 'zustand/react';\n\nexport interface WeaverContextGetter {\n /**\n * Current active parent, **AFTER** Pipeline has finished rendering, so the `activeParent`\n * will be delayed. Example: \"/\", \"/works\",...\n */\n activeParent: string;\n\n /**\n * Current active Pipeline. Example: \"/\", \"/works\",...\n *\n * This is **not based on URL**, it's based on which `Pipeline` has access to the the site.\n */\n activePipeline: string;\n\n /**\n * `DelayedOutlet` special variable, indicating if the route is current transitioning to a new route or not.\n */\n navigating: boolean;\n\n /**\n * When the page is rendered, it will turns this to true,\n * any parent page navigation will causes this to goes false, set to false in `DelayedOulet`.\n *\n * It's set to `false` right after `navigating` is set to `true`. `true` statement will be handled by `Pipeline`.\n */\n pageRendered: boolean;\n}\n\ninterface WeaverContextSetter {\n setActiveParent: (activeParent: string) => void;\n setActivePipeline: (activePipeline: string) => void;\n setNavigating: (navigating: boolean) => void;\n setPageRendered: (pageRendered: boolean) => void;\n}\n\nexport const useWeaverContext = create<\n WeaverContextSetter & WeaverContextGetter\n>()((set) => ({\n activeParent: '',\n setActiveParent: (activeParent) => set({ activeParent }),\n\n activePipeline: '',\n setActivePipeline: (activePipeline) => set({ activePipeline }),\n\n navigating: true,\n setNavigating: (navigating) => set({ navigating }),\n\n pageRendered: false,\n setPageRendered: (pageRendered) => set({ pageRendered }),\n}));\n","import { type ReactNode, useLayoutEffect, useRef, useState } from 'react';\nimport { useOutlet } from 'react-router';\nimport { useRouteNormalizer } from '../hooks/routeNormalizer';\nimport { getParentRoute } from '../utils/getParentRoute';\nimport { useWeaverContext } from './context';\n\n/**\n * A core part of an in-house tool called `weaver`.\n *\n * Delaying the routing process from `react-router`, handles gracefully between `Pipeline`s\n * while allowing any loading fallback component to listen and react with event changes.\n */\nexport default function DelayedOutlet(props: { delay: number }) {\n // Middleware to detect and replace invalid url.\n useRouteNormalizer({ autoReplace: true });\n\n const activePipeline = useWeaverContext((state) => state.activePipeline);\n const setNavigating = useWeaverContext((state) => state.setNavigating);\n const setPageRendered = useWeaverContext((state) => state.setPageRendered);\n\n const renderPageTask = useRef(setTimeout(() => {}));\n const routerOutlet = useOutlet();\n\n const [renderer, setRenderer] = useState<ReactNode>(null);\n\n // Handle and update new parent page.\n useLayoutEffect(() => {\n /**\n * `pageRendered` should be outside of `renderPageTask`,\n * we alrady have `Pipeline` to correct errors.\n */\n if ('scrollRestoration' in history) {\n history.scrollRestoration = 'manual';\n }\n\n if (getParentRoute(window.location.pathname) === activePipeline) {\n // Avoid while changing page, cancelling before new page pushed in\n // cause `activePipeline` to not change, making `navigating` softlock.\n setNavigating(false);\n return;\n }\n\n setNavigating(true);\n setPageRendered(false);\n\n clearTimeout(renderPageTask.current);\n renderPageTask.current = setTimeout(() => {\n setRenderer(routerOutlet!);\n setNavigating(false);\n }, props.delay);\n\n return () => {\n /**\n * Clear invalid task that were scheduled last effect.\n */\n clearInterval(renderPageTask.current);\n };\n }, [\n activePipeline,\n props.delay,\n routerOutlet,\n setNavigating,\n setPageRendered,\n ]);\n\n return renderer;\n}\n","import { useCallback, useLayoutEffect } from 'react';\nimport { useLocation, useNavigate } from 'react-router';\n\nexport function useRouteNormalizer(options: { autoReplace: boolean }) {\n const { pathname } = useLocation();\n const navigate = useNavigate();\n\n const normalizer = useCallback(\n (input: string) => input.replace(/\\/+\\//g, () => '/'),\n []\n );\n\n useLayoutEffect(() => {\n const result = normalizer(pathname);\n if (options.autoReplace && result !== pathname) {\n window.location.replace(result);\n }\n }, [options.autoReplace, pathname, navigate, normalizer]);\n\n return {\n pathname,\n normalizer,\n };\n}\n","export function getParentRoute(pathname: string) {\n let slashes = 0;\n let sliceAt = 0;\n for (sliceAt; sliceAt < pathname.length; sliceAt++) {\n if (pathname[sliceAt] == '/') {\n slashes++;\n }\n if (slashes === 2) {\n break;\n }\n }\n\n return pathname.slice(0, sliceAt);\n}\n","import React, { useLayoutEffect, useMemo, type ReactNode } from 'react';\nimport { useLayoutEffectOnce } from '../hooks/effectOnce';\nimport { weaverSetup } from '../setup';\nimport { getParentRoute } from '../utils/getParentRoute';\nimport { useWeaverContext } from './context';\n\ninterface PipelineProps {\n children?: ReactNode;\n\n /**\n * A state switch to notifies `Pipeline` that the content and elements of the page is ready to be displayed.\n *\n * Usually, you will need to preload some other external sources, or initialize 3D scene, this state\n * make sure that the loading fallback doesn't mess up and show initializing stuff.\n *\n * Using `BakeScene`, you can ensure that the scene is loaded via its callback, you can then pass the state value that\n * `BakeScene` changes to this variable to hide all the lags behind loading screen.\n */\n contentReady?: boolean;\n\n /**\n * Title for the page.\n */\n title: string;\n\n /**\n * If provided, `Pipeline` will log the current phase to console.\n */\n debugName?: string;\n\n /**\n * This is the only feature where weaver will use lenis to directly manipulate scrolling behaviour.\n *\n * By default, this value is `true` when a lenis instance is provided.\n *\n * `Pipeline` will stop and start lenis automatically when this variable is `true`.\n *\n * Disable this feature to gains complete control over lenis when mounting/unmounting to handle however you want.\n */\n lenisUsage?: boolean;\n}\n\n/**\n * A core part of an in-house tool called `weaver`.\n *\n * `Pipeline`: Notifies & reflect changes to/from `LoadingFallback`\n * and `DelayedOutlet` about its page loading status.\n *\n * All parent routes must have `Pipeline` in order to work and sync with `DelayedOutlet`.\n */\nexport default function Pipeline(props: PipelineProps) {\n const { children, ...restOfProps } = props;\n const parentPath = useMemo(\n () => getParentRoute(window.location.pathname),\n []\n );\n\n return (\n <>\n <RouteHandler {...restOfProps} parentPath={parentPath} />\n {children}\n </>\n );\n}\n\nfunction RouteHandler(\n props: Omit<PipelineProps, 'children'> & { parentPath: string }\n) {\n const navigating = useWeaverContext((state) => state.navigating);\n const pageRendered = useWeaverContext((state) => state.pageRendered);\n const activeParent = useWeaverContext((state) => state.activeParent);\n\n const setActivePipeline = useWeaverContext(\n (state) => state.setActivePipeline\n );\n const setPageRendered = useWeaverContext((state) => state.setPageRendered);\n const setActiveParent = useWeaverContext((state) => state.setActiveParent);\n\n useLayoutEffect(() => {\n document.title = props.title;\n setActivePipeline(props.parentPath);\n\n if (props.contentReady !== undefined && !props.contentReady) {\n if (props.debugName)\n console.log(`[${props.debugName}] Renderer status: Loading scene`);\n return;\n }\n\n if (!navigating && (!pageRendered || activeParent !== props.parentPath)) {\n if (props.lenisUsage === undefined || props.lenisUsage) {\n weaverSetup._lenisInstance?.start();\n }\n\n setPageRendered(true);\n setActiveParent(props.parentPath);\n\n if (props.debugName)\n console.log(`[${props.debugName}] Renderer status: Mounted`);\n }\n }, [\n activeParent,\n setActivePipeline,\n navigating,\n pageRendered,\n props.lenisUsage,\n props.contentReady,\n props.debugName,\n props.parentPath,\n props.title,\n setActiveParent,\n setPageRendered,\n ]);\n\n useLayoutEffectOnce(() => {\n return () => {\n /**\n * When unmounted, stop lenis to pass control to another Pipline instance.\n *\n * The unmount process only happens when the `<LoadingFallback />` kicks in,\n * so any visual glitches can happen in here, we can now set the scroll position to 0.\n */\n if (props.lenisUsage === undefined || props.lenisUsage) {\n weaverSetup._lenisInstance?.stop();\n weaverSetup._lenisInstance?.scrollTo(0, {\n immediate: true,\n force: true,\n });\n }\n\n if (props.debugName)\n console.log(`[${props.debugName}] Renderer status: Unmounted`);\n };\n });\n\n return null;\n}\n","import { useEffect, useLayoutEffect } from 'react';\n\nexport function useEffectOnce(callback: React.EffectCallback) {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(callback, []);\n}\n\nexport function useLayoutEffectOnce(callback: React.EffectCallback) {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(callback, []);\n}\n","import Lenis from 'lenis';\nimport { ReactNode } from 'react';\n\nexport type BasicTunnelIn = ({ children }: { children: ReactNode }) => null;\n\nclass WeaverSetup {\n /**\n * This variable is handled internally by weaver. **Do not use**.\n */\n get _lenisInstance(): Lenis | undefined {\n return (globalThis as any).__weaverLenis;\n }\n set _lenisInstance(val: Lenis | undefined) {\n (globalThis as any).__weaverLenis = val;\n }\n\n /**\n * This variable is handled internally by weaver. **Do not use**.\n */\n get _Default3DTunnelIn(): BasicTunnelIn | undefined {\n return (globalThis as any).__weaver3DTunnel;\n }\n set _Default3DTunnelIn(val: BasicTunnelIn | undefined) {\n (globalThis as any).__weaver3DTunnel = val;\n }\n\n setLenisInstance(instance: Lenis) {\n this._lenisInstance = instance;\n }\n set3DTunnel(tunnelIn: BasicTunnelIn) {\n this._Default3DTunnelIn = tunnelIn;\n }\n}\n\nexport const weaverSetup = new WeaverSetup();\n","import { useWeaverContext, WeaverContextGetter } from './context';\nimport DelayedOutlet from './DelayedOutlet';\nimport Pipeline from './Pipeline';\n\n/// A read-only state for reacting with changes reflected by weaver.\nexport const useWeaverState = (givenState: keyof WeaverContextGetter) => {\n const state = useWeaverContext((state) => state[givenState]);\n return state;\n};\n\nexport { DelayedOutlet, Pipeline };\n"],"mappings":"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","names":["useLayoutEffect","useLayoutEffect","useLayoutEffect","useLayoutEffect","useLayoutEffect","useLayoutEffect","state"]}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "neveranyart",
|
|
3
3
|
"license": "GPL-3.0-or-later",
|
|
4
4
|
"name": "@neveranyart/weaver",
|
|
5
|
-
"version": "1.0.
|
|
5
|
+
"version": "1.0.10",
|
|
6
6
|
"description": "An in-house package by neverany for making interactive React CSR.",
|
|
7
7
|
"packageManager": "yarn@4.10.3",
|
|
8
8
|
"publishConfig": {
|