@rcaferati/react-awesome-slider 5.0.0 → 5.0.2
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 +212 -51
- package/dist/autoplay.js +25 -9
- package/dist/autoplay.js.map +1 -1
- package/dist/autoplay.mjs +25 -9
- package/dist/autoplay.mjs.map +1 -1
- package/dist/captioned.js +25 -9
- package/dist/captioned.js.map +1 -1
- package/dist/captioned.mjs +25 -9
- package/dist/captioned.mjs.map +1 -1
- package/dist/custom-animations/cube-animation.css +1 -1
- package/dist/custom-animations/cube-animation.d.mts +3 -0
- package/dist/custom-animations/cube-animation.d.ts +3 -0
- package/dist/custom-animations/cube-animation.js +13 -0
- package/dist/custom-animations/cube-animation.mjs +10 -0
- package/dist/custom-animations/fall-animation.d.mts +3 -0
- package/dist/custom-animations/fall-animation.d.ts +3 -0
- package/dist/custom-animations/fall-animation.js +11 -0
- package/dist/custom-animations/fall-animation.mjs +8 -0
- package/dist/custom-animations/fold-out-animation.d.mts +3 -0
- package/dist/custom-animations/fold-out-animation.d.ts +3 -0
- package/dist/custom-animations/fold-out-animation.js +12 -0
- package/dist/custom-animations/fold-out-animation.mjs +9 -0
- package/dist/custom-animations/open-animation.d.mts +3 -0
- package/dist/custom-animations/open-animation.d.ts +3 -0
- package/dist/custom-animations/open-animation.js +12 -0
- package/dist/custom-animations/open-animation.mjs +9 -0
- package/dist/custom-animations/scale-out-animation.d.mts +3 -0
- package/dist/custom-animations/scale-out-animation.d.ts +3 -0
- package/dist/custom-animations/scale-out-animation.js +11 -0
- package/dist/custom-animations/scale-out-animation.mjs +8 -0
- package/dist/index.js +25 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +25 -9
- package/dist/index.mjs.map +1 -1
- package/dist/lettering.js +25 -9
- package/dist/lettering.js.map +1 -1
- package/dist/lettering.mjs +25 -9
- package/dist/lettering.mjs.map +1 -1
- package/dist/navigation.d.mts +1 -0
- package/dist/navigation.d.ts +1 -0
- package/dist/navigation.js +45 -31
- package/dist/navigation.js.map +1 -1
- package/dist/navigation.mjs +45 -31
- package/dist/navigation.mjs.map +1 -1
- package/package.json +14 -4
package/dist/navigation.js
CHANGED
|
@@ -40,7 +40,7 @@ module.exports = __toCommonJS(navigation_exports);
|
|
|
40
40
|
// src/hoc/navigation/context.tsx
|
|
41
41
|
var import_react = __toESM(require("react"));
|
|
42
42
|
var Context = (0, import_react.createContext)([
|
|
43
|
-
{ slug: "", goto: "", navigating: false, pop: false },
|
|
43
|
+
{ slug: "", goto: "", navigating: false, pop: false, defaultSlug: "" },
|
|
44
44
|
() => {
|
|
45
45
|
}
|
|
46
46
|
]);
|
|
@@ -58,15 +58,16 @@ var Provider = ({
|
|
|
58
58
|
slug: cleanPage,
|
|
59
59
|
goto: cleanPage,
|
|
60
60
|
navigating: false,
|
|
61
|
-
pop: false
|
|
61
|
+
pop: false,
|
|
62
|
+
defaultSlug
|
|
62
63
|
}));
|
|
63
64
|
(0, import_react.useEffect)(() => {
|
|
64
|
-
if (!cleanPage) return;
|
|
65
65
|
setState((prev) => {
|
|
66
66
|
if (prev.navigating === true) {
|
|
67
67
|
return {
|
|
68
68
|
...prev,
|
|
69
|
-
slug: cleanPage
|
|
69
|
+
slug: cleanPage,
|
|
70
|
+
defaultSlug
|
|
70
71
|
// keep goto as-is while navigating; end-handler will reconcile
|
|
71
72
|
};
|
|
72
73
|
}
|
|
@@ -75,10 +76,11 @@ var Provider = ({
|
|
|
75
76
|
slug: cleanPage,
|
|
76
77
|
goto: cleanPage,
|
|
77
78
|
navigating: false,
|
|
78
|
-
pop: false
|
|
79
|
+
pop: false,
|
|
80
|
+
defaultSlug
|
|
79
81
|
};
|
|
80
82
|
});
|
|
81
|
-
}, [cleanPage]);
|
|
83
|
+
}, [cleanPage, defaultSlug]);
|
|
82
84
|
const setNavigation = (0, import_react.useCallback)(
|
|
83
85
|
(params) => {
|
|
84
86
|
if (params && typeof params === "object") {
|
|
@@ -176,6 +178,19 @@ var getUrlSlug = () => {
|
|
|
176
178
|
if (typeof window === "undefined") return "";
|
|
177
179
|
return getCleanPath2(window.location.pathname) || "";
|
|
178
180
|
};
|
|
181
|
+
var getDefaultSlug = (navigation) => (navigation == null ? void 0 : navigation.defaultSlug) || "";
|
|
182
|
+
var resolveUrlSlug = (rawSlug, navigation) => {
|
|
183
|
+
return rawSlug === "" ? getDefaultSlug(navigation) : rawSlug;
|
|
184
|
+
};
|
|
185
|
+
var getHistoryPath = (slug) => {
|
|
186
|
+
return slug === "" ? "/" : `/${slug}`;
|
|
187
|
+
};
|
|
188
|
+
var getMediaSlug = (media) => {
|
|
189
|
+
return typeof (media == null ? void 0 : media.slug) === "string" ? media.slug : void 0;
|
|
190
|
+
};
|
|
191
|
+
var firstDefined = (...values) => {
|
|
192
|
+
return values.find((value) => value !== void 0);
|
|
193
|
+
};
|
|
179
194
|
function withNavigationHandlers(Component) {
|
|
180
195
|
function WithNavigationHandlers(props) {
|
|
181
196
|
const {
|
|
@@ -215,8 +230,6 @@ function withNavigationHandlers(Component) {
|
|
|
215
230
|
async (reason) => {
|
|
216
231
|
void reason;
|
|
217
232
|
if (typeof window === "undefined") return;
|
|
218
|
-
const initialUrlSlug = getUrlSlug();
|
|
219
|
-
if (!initialUrlSlug) return;
|
|
220
233
|
if (syncRunningRef.current) {
|
|
221
234
|
syncSeqRef.current += 1;
|
|
222
235
|
}
|
|
@@ -235,8 +248,7 @@ function withNavigationHandlers(Component) {
|
|
|
235
248
|
navigating: false,
|
|
236
249
|
pop: false
|
|
237
250
|
};
|
|
238
|
-
const urlNow = getUrlSlug();
|
|
239
|
-
if (!urlNow) continue;
|
|
251
|
+
const urlNow = resolveUrlSlug(getUrlSlug(), nav);
|
|
240
252
|
if (nav.goto !== urlNow) {
|
|
241
253
|
urlDrivenStartLatchRef.current = true;
|
|
242
254
|
safeNavigate(
|
|
@@ -288,7 +300,6 @@ function withNavigationHandlers(Component) {
|
|
|
288
300
|
}, [handlePopState]);
|
|
289
301
|
const handleTransitionStart = (0, import_react4.useCallback)(
|
|
290
302
|
(element) => {
|
|
291
|
-
var _a;
|
|
292
303
|
if (typeof window === "undefined") return;
|
|
293
304
|
const nav = navRef.current || {
|
|
294
305
|
slug: "",
|
|
@@ -297,18 +308,18 @@ function withNavigationHandlers(Component) {
|
|
|
297
308
|
pop: false
|
|
298
309
|
};
|
|
299
310
|
const cleanPath = getUrlSlug();
|
|
300
|
-
const nextSlug = (
|
|
311
|
+
const nextSlug = getMediaSlug(element == null ? void 0 : element.nextMedia);
|
|
301
312
|
txInFlightRef.current = true;
|
|
302
313
|
const urlDrivenStart = urlDrivenStartLatchRef.current === true;
|
|
303
314
|
urlDrivenStartLatchRef.current = false;
|
|
304
|
-
if (nextSlug && cleanPath !== nextSlug && !urlDrivenStart) {
|
|
305
|
-
window.history.pushState({}, "",
|
|
315
|
+
if (nextSlug !== void 0 && cleanPath !== nextSlug && !urlDrivenStart) {
|
|
316
|
+
window.history.pushState({}, "", getHistoryPath(nextSlug));
|
|
306
317
|
}
|
|
307
318
|
safeNavigate(
|
|
308
319
|
{
|
|
309
320
|
...nav,
|
|
310
|
-
goto: nextSlug
|
|
311
|
-
slug: nav.slug
|
|
321
|
+
goto: nextSlug !== void 0 ? nextSlug : nav.goto,
|
|
322
|
+
slug: nav.slug,
|
|
312
323
|
navigating: true,
|
|
313
324
|
pop: urlDrivenStart ? true : false
|
|
314
325
|
},
|
|
@@ -320,7 +331,6 @@ function withNavigationHandlers(Component) {
|
|
|
320
331
|
);
|
|
321
332
|
const handleTransitionEnd = (0, import_react4.useCallback)(
|
|
322
333
|
(element) => {
|
|
323
|
-
var _a;
|
|
324
334
|
if (typeof window === "undefined") return;
|
|
325
335
|
const nav = navRef.current || {
|
|
326
336
|
slug: "",
|
|
@@ -328,18 +338,18 @@ function withNavigationHandlers(Component) {
|
|
|
328
338
|
navigating: false,
|
|
329
339
|
pop: false
|
|
330
340
|
};
|
|
331
|
-
const currentSlug = ((
|
|
332
|
-
const urlSlug = getUrlSlug();
|
|
341
|
+
const currentSlug = firstDefined(getMediaSlug(element == null ? void 0 : element.currentMedia), nav.goto, nav.slug) || "";
|
|
342
|
+
const urlSlug = resolveUrlSlug(getUrlSlug(), nav);
|
|
333
343
|
txInFlightRef.current = false;
|
|
334
|
-
|
|
335
|
-
const mismatch =
|
|
344
|
+
landedSlugRef.current = currentSlug;
|
|
345
|
+
const mismatch = urlSlug !== currentSlug;
|
|
336
346
|
safeNavigate(
|
|
337
347
|
{
|
|
338
348
|
...nav,
|
|
339
349
|
navigating: false,
|
|
340
350
|
pop: mismatch ? true : false,
|
|
341
|
-
slug: currentSlug
|
|
342
|
-
goto: mismatch ? urlSlug : currentSlug
|
|
351
|
+
slug: currentSlug,
|
|
352
|
+
goto: mismatch ? urlSlug : currentSlug
|
|
343
353
|
},
|
|
344
354
|
mismatch ? "onTransitionEnd:mismatch(set-goto=url)" : "onTransitionEnd"
|
|
345
355
|
);
|
|
@@ -354,7 +364,6 @@ function withNavigationHandlers(Component) {
|
|
|
354
364
|
);
|
|
355
365
|
const handleTransitionReject = (0, import_react4.useCallback)(
|
|
356
366
|
(element) => {
|
|
357
|
-
var _a, _b;
|
|
358
367
|
if (typeof window === "undefined") return;
|
|
359
368
|
const nav = navRef.current || {
|
|
360
369
|
slug: "",
|
|
@@ -362,23 +371,28 @@ function withNavigationHandlers(Component) {
|
|
|
362
371
|
navigating: false,
|
|
363
372
|
pop: false
|
|
364
373
|
};
|
|
365
|
-
const urlSlug = getUrlSlug();
|
|
374
|
+
const urlSlug = resolveUrlSlug(getUrlSlug(), nav);
|
|
366
375
|
armForceRetry(element == null ? void 0 : element.forceTransition);
|
|
367
|
-
const currentSlug = (
|
|
368
|
-
|
|
369
|
-
|
|
376
|
+
const currentSlug = firstDefined(
|
|
377
|
+
getMediaSlug(element == null ? void 0 : element.currentMedia),
|
|
378
|
+
nav.slug,
|
|
379
|
+
landedSlugRef.current,
|
|
380
|
+
nav.goto
|
|
381
|
+
) || "";
|
|
382
|
+
const mismatch = urlSlug !== currentSlug;
|
|
383
|
+
const desiredGoto = firstDefined(urlSlug, getMediaSlug(element == null ? void 0 : element.nextMedia), nav.goto, currentSlug) || "";
|
|
370
384
|
safeNavigate(
|
|
371
385
|
{
|
|
372
386
|
...nav,
|
|
373
|
-
slug: currentSlug
|
|
387
|
+
slug: currentSlug,
|
|
374
388
|
goto: desiredGoto,
|
|
375
389
|
navigating: false,
|
|
376
|
-
pop:
|
|
390
|
+
pop: true
|
|
377
391
|
// treat as URL-driven alignment context
|
|
378
392
|
},
|
|
379
393
|
mismatch ? "onTransitionReject:mismatch" : "onTransitionReject"
|
|
380
394
|
);
|
|
381
|
-
if (
|
|
395
|
+
if (landedSlugRef.current !== urlSlug) {
|
|
382
396
|
syncToUrl(
|
|
383
397
|
mismatch ? "onTransitionReject:url-mismatch" : "onTransitionReject:retry"
|
|
384
398
|
);
|
package/dist/navigation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hoc/navigation/index.ts","../src/hoc/navigation/context.tsx","../src/hoc/navigation/link.tsx","../src/hoc/navigation/withNavigationContext.tsx","../src/hoc/navigation/withNavigationHandlers.tsx"],"sourcesContent":["// navigation/index.ts\nexport { Context, Provider } from './context';\nexport { default as Link } from './link';\nexport { default as withNavigationContext } from './withNavigationContext';\nexport { default as withNavigationHandlers } from './withNavigationHandlers';","// navigation/context.tsx\nimport React, {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\n\nexport type NavigationState = {\n slug: string;\n goto: string;\n navigating: boolean;\n pop: boolean;\n};\n\nexport type SetNavigation = (next: Partial<NavigationState> | string) => void;\n\nexport const Context = createContext<[NavigationState, SetNavigation]>([\n { slug: '', goto: '', navigating: false, pop: false },\n () => {},\n]);\n\nconst getCleanPath = (path: unknown) =>\n String(path || '')\n .replace(/^\\//, '')\n .replace(/\\/$/, '');\n\nexport type ProviderProps = {\n slug: string;\n defaultSlug?: string;\n children?: React.ReactNode;\n};\n\nexport const Provider: React.FC<ProviderProps> = ({\n slug,\n defaultSlug = '',\n children,\n}) => {\n const cleanPage = useMemo(() => {\n const cleanPageRaw = getCleanPath(slug);\n return cleanPageRaw || defaultSlug || '';\n }, [slug, defaultSlug]);\n\n const [state, setState] = useState<NavigationState>(() => ({\n slug: cleanPage,\n goto: cleanPage,\n navigating: false,\n pop: false,\n }));\n\n // Re-anchor when slug prop changes, but don't clobber in-flight nav.\n useEffect(() => {\n if (!cleanPage) return;\n\n setState((prev) => {\n // If we're mid-transition, don't force navigating=false or stomp goto.\n if (prev.navigating === true) {\n return {\n ...prev,\n slug: cleanPage,\n // keep goto as-is while navigating; end-handler will reconcile\n };\n }\n\n return {\n ...prev,\n slug: cleanPage,\n goto: cleanPage,\n navigating: false,\n pop: false,\n };\n });\n }, [cleanPage]);\n\n const setNavigation = useCallback<SetNavigation>(\n (params) => {\n if (params && typeof params === 'object') {\n setState((prev) => ({ ...prev, ...params }));\n return;\n }\n\n const nextRaw = getCleanPath(params);\n const next = nextRaw || defaultSlug || '';\n\n setState((prev) => ({ ...prev, goto: next }));\n },\n [defaultSlug]\n );\n\n return (\n <Context.Provider value={[state, setNavigation]}>\n {children}\n </Context.Provider>\n );\n};","// navigation/link.tsx\nimport React, { useCallback, useMemo } from 'react';\nimport withNavigationContext from './withNavigationContext';\nimport type { NavigationState, SetNavigation } from './context';\n\ntype Fullpage = {\n navigation: NavigationState;\n navigate: SetNavigation;\n};\n\nconst isModifiedClick = (e: React.MouseEvent) =>\n e.metaKey || e.altKey || e.ctrlKey || e.shiftKey || e.button !== 0;\n\nconst isExternalHref = (href: unknown) => {\n const h = String(href || '');\n return (\n /^([a-z][a-z0-9+.-]*:)?\\/\\//i.test(h) ||\n /^mailto:/i.test(h) ||\n /^tel:/i.test(h)\n );\n};\n\nconst cleanHrefToGoto = (href: unknown) =>\n String(href || '')\n .replace(/^\\//, '')\n .replace(/\\/$/, '');\n\nexport type LinkProps = Omit<\n React.AnchorHTMLAttributes<HTMLAnchorElement>,\n 'href' | 'className' | 'onClick'\n> & {\n fullpage?: Fullpage;\n href: string;\n className?: string | null;\n onClick?: React.MouseEventHandler<HTMLAnchorElement>;\n children?: React.ReactNode;\n};\n\nexport default withNavigationContext((props: LinkProps) => {\n const { fullpage, children, href, className = null, onClick, ...extra } =\n props;\n\n const navigation = fullpage?.navigation;\n const navigate = fullpage?.navigate;\n\n const goto = useMemo(() => cleanHrefToGoto(href), [href]);\n\n const handleClick = useCallback(\n (event: React.MouseEvent<HTMLAnchorElement>) => {\n // let user handler run first\n if (typeof onClick === 'function') onClick(event);\n if (event.defaultPrevented) return;\n\n // no nav context / no href / external => let browser handle\n if (!navigation || typeof navigate !== 'function' || !href) return;\n if (isExternalHref(href)) return;\n\n // allow middle click / cmd-click / ctrl-click / shift-click etc.\n if (isModifiedClick(event)) return;\n\n event.preventDefault();\n\n // ignore clicks while a transition is in progress\n if (navigation.navigating === true) return;\n\n // IMPORTANT: allow \"/\" to map to empty goto (Provider/handlers decide fallback)\n const nextGoto = goto;\n\n // noop if already targeting same goto\n if (nextGoto === navigation.goto) return;\n\n navigate({\n ...navigation,\n pop: false, // click-driven\n goto: nextGoto,\n });\n },\n [onClick, navigation, navigate, href, goto]\n );\n\n return (\n <a\n className={className || undefined}\n onClick={handleClick}\n href={href}\n {...extra}\n >\n {children}\n </a>\n );\n});","// navigation/withNavigationContext.tsx\nimport React, { useContext, useMemo } from 'react';\nimport { Context } from './context';\nimport type { NavigationState, SetNavigation } from './context';\n\nexport type Fullpage = {\n navigation: NavigationState;\n navigate: SetNavigation;\n};\n\nexport type WithNavigationInjectedProps = {\n fullpage: Fullpage;\n};\n\nconst FALLBACK_NAV: NavigationState = {\n slug: '',\n goto: '',\n navigating: false,\n pop: false,\n};\n\nexport default function withNavigationContext<P extends object>(\n Component: React.ComponentType<P & WithNavigationInjectedProps>\n) {\n function WithNavigationContext(props: P) {\n const value = useContext(Context);\n\n const navigation: NavigationState =\n (value && (value as any)[0]) || FALLBACK_NAV;\n\n const navigate: SetNavigation =\n (value && (value as any)[1]) || ((() => {}) as SetNavigation);\n\n const fullpage = useMemo<Fullpage>(\n () => ({\n navigation,\n navigate,\n }),\n [navigation, navigate]\n );\n\n return <Component {...props} fullpage={fullpage} />;\n }\n\n WithNavigationContext.displayName = `withNavigationContext(${\n (Component as any).displayName || (Component as any).name || 'Component'\n })`;\n\n return WithNavigationContext;\n}\n","// navigation/withNavigationHandlers.tsx (drop-in replacement)\nimport React, { useCallback, useEffect, useRef } from 'react';\nimport { frameThrower } from '@rcaferati/wac';\nimport withNavigationContext, {\n type WithNavigationInjectedProps,\n} from './withNavigationContext';\nimport type { NavigationState } from './context';\n\n// --- helpers -------------------------------------------------------------\n\nconst getCleanPath = (path: unknown) =>\n String(path || '')\n .replace(/^\\//, '')\n .replace(/\\/$/, '');\n\nconst getUrlSlug = (): string => {\n if (typeof window === 'undefined') return '';\n return getCleanPath(window.location.pathname) || '';\n};\n\ntype MediaLike = { slug?: string } | null | undefined;\n\ntype TransitionInfoLike = {\n currentMedia?: MediaLike;\n nextMedia?: MediaLike;\n} & Record<string, any>;\n\ntype TransitionRejectInfoLike = TransitionInfoLike & {\n forceTransition?: () => void;\n};\n\ntype HandlerProps = {\n onTransitionReject?: (info: any) => void;\n onTransitionStart?: (info: any) => void;\n onTransitionEnd?: (info: any) => void;\n};\n\n// -------------------------------------------------------------------------\n\nexport default function withNavigationHandlers<P extends object>(\n Component: React.ComponentType<P>\n) {\n type Props = P & HandlerProps & Partial<WithNavigationInjectedProps>;\n\n function WithNavigationHandlers(props: Props) {\n const {\n fullpage,\n onTransitionReject,\n onTransitionStart,\n onTransitionEnd,\n ...extra\n } = props as any;\n\n const navigation = fullpage?.navigation as NavigationState | undefined;\n const navigate = fullpage?.navigate as ((next: any) => void) | undefined;\n\n const navRef = useRef<NavigationState | undefined>(navigation);\n const navigateRef = useRef<typeof navigate>(navigate);\n\n // keep refs hot synchronously (avoid stale reads in callbacks)\n navRef.current = navigation;\n navigateRef.current = navigate;\n\n // What we *actually* landed on visually (authoritative). Only set on tx:end.\n const landedSlugRef = useRef<string>('');\n\n // Retry hook (available after a reject payload happens)\n const forceRef = useRef<(() => void) | null>(null);\n\n // Real transition lifecycle (engine reality)\n const txInFlightRef = useRef(false);\n\n // One-shot latch: \"next transitionStart is URL-driven (pop/sync), do NOT pushState\"\n // IMPORTANT: this is NOT stored in NavigationState to avoid sticky mode bugs.\n const urlDrivenStartLatchRef = useRef(false);\n\n // sync loop control (latest-wins)\n const syncRunningRef = useRef(false);\n const syncSeqRef = useRef(0);\n\n // ---- navigation -------------------------------------------------------\n\n const safeNavigate = useCallback(\n (next: NavigationState, reason: string) => {\n void reason; // keep callsites readable; avoid unused-param lint\n const fn = navigateRef.current;\n if (typeof fn !== 'function') return;\n fn(next);\n },\n []\n );\n\n const armForceRetry = useCallback((forceTransition?: unknown) => {\n if (typeof forceTransition === 'function') {\n forceRef.current = forceTransition as () => void;\n }\n }, []);\n\n // =========================================================================\n // URL Sync + Retry (latest-wins)\n // =========================================================================\n const syncToUrl = useCallback(\n async (reason: string) => {\n void reason; // retained for callsite intent; no logging\n if (typeof window === 'undefined') return;\n\n const initialUrlSlug = getUrlSlug();\n if (!initialUrlSlug) return;\n\n // latest-wins: cancel older runner\n if (syncRunningRef.current) {\n syncSeqRef.current += 1;\n }\n\n syncRunningRef.current = true;\n const mySeq = ++syncSeqRef.current;\n\n const MAX_TICKS = 240;\n\n try {\n for (let tick = 1; tick <= MAX_TICKS; tick++) {\n await frameThrower(1);\n\n if (mySeq !== syncSeqRef.current) {\n return;\n }\n\n const nav = (navRef.current || {\n slug: '',\n goto: '',\n navigating: false,\n pop: false,\n }) as NavigationState;\n\n const urlNow = getUrlSlug();\n if (!urlNow) continue;\n\n // 1) Ensure the controlled \"selected\" (goto) matches the URL.\n // Mark the next transitionStart as URL-driven so it must NOT pushState.\n if (nav.goto !== urlNow) {\n urlDrivenStartLatchRef.current = true;\n\n safeNavigate(\n {\n ...nav,\n pop: true,\n goto: urlNow,\n navigating: !!nav.navigating, // preserve (not trusted, but keep behavior)\n } as any,\n `syncToUrl:align-goto(tick:${tick})`\n );\n continue;\n }\n\n // 2) Never declare \"done\" while a real engine transition is in-flight.\n if (txInFlightRef.current === true) {\n continue;\n }\n\n // 3) Done when the *actual landed slide* matches the URL.\n if (landedSlugRef.current === urlNow) {\n return;\n }\n\n // 4) Not landed yet, not in-flight, goto matches URL -> re-trigger (if possible).\n const force = forceRef.current;\n if (typeof force === 'function') {\n // Avoid spamming: retry at a modest cadence.\n if (tick % 6 === 0) {\n try {\n force();\n } catch {\n // ignore\n }\n }\n }\n }\n } finally {\n if (syncSeqRef.current === mySeq) {\n syncRunningRef.current = false;\n }\n }\n },\n [safeNavigate]\n );\n\n // ---- popstate ----------------------------------------------------------\n\n const popSeqRef = useRef(0);\n\n const handlePopState = useCallback(() => {\n if (typeof window === 'undefined') return;\n const popSeq = ++popSeqRef.current;\n syncToUrl(`popstate#${popSeq}`);\n }, [syncToUrl]);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n window.addEventListener('popstate', handlePopState);\n return () => window.removeEventListener('popstate', handlePopState);\n }, [handlePopState]);\n\n // ---- transition handlers ----------------------------------------------\n\n const handleTransitionStart = useCallback(\n (element: TransitionInfoLike) => {\n if (typeof window === 'undefined') return;\n\n const nav = (navRef.current || {\n slug: '',\n goto: '',\n navigating: false,\n pop: false,\n }) as NavigationState;\n\n const cleanPath = getUrlSlug();\n const nextSlug = element?.nextMedia?.slug || '';\n\n // Real engine lifecycle\n txInFlightRef.current = true;\n\n // Consume the one-shot latch (URL-driven start => do NOT pushState).\n const urlDrivenStart = urlDrivenStartLatchRef.current === true;\n urlDrivenStartLatchRef.current = false;\n\n // pushState only for click-driven transitions (not URL-driven pop/sync).\n if (nextSlug && cleanPath !== nextSlug && !urlDrivenStart) {\n window.history.pushState({}, '', `/${nextSlug}`);\n }\n\n safeNavigate(\n {\n ...nav,\n goto: nextSlug || nav.goto,\n slug: nav.slug || cleanPath,\n navigating: true,\n pop: urlDrivenStart ? true : false,\n } as any,\n 'onTransitionStart'\n );\n\n if (onTransitionStart) onTransitionStart(element);\n },\n [onTransitionStart, safeNavigate]\n );\n\n const handleTransitionEnd = useCallback(\n (element: TransitionInfoLike) => {\n if (typeof window === 'undefined') return;\n\n const nav = (navRef.current || {\n slug: '',\n goto: '',\n navigating: false,\n pop: false,\n }) as NavigationState;\n\n const currentSlug = element?.currentMedia?.slug || '';\n const urlSlug = getUrlSlug();\n\n // Real engine lifecycle ends here (authoritative)\n txInFlightRef.current = false;\n\n if (currentSlug) landedSlugRef.current = currentSlug;\n\n const mismatch = !!(urlSlug && currentSlug && urlSlug !== currentSlug);\n\n // If mismatch, immediately set goto to URL so controlled selected follows it.\n safeNavigate(\n {\n ...nav,\n navigating: false,\n pop: mismatch ? true : false,\n slug: currentSlug || nav.slug,\n goto: mismatch ? urlSlug : currentSlug || nav.goto,\n } as any,\n mismatch\n ? 'onTransitionEnd:mismatch(set-goto=url)'\n : 'onTransitionEnd'\n );\n\n if (onTransitionEnd) onTransitionEnd(element);\n\n if (mismatch) {\n syncToUrl('onTransitionEnd:url-mismatch');\n } else {\n // Safe point to clear the retry hook only when reality matches the URL.\n forceRef.current = null;\n }\n },\n [onTransitionEnd, safeNavigate, syncToUrl]\n );\n\n const handleTransitionReject = useCallback(\n (element: TransitionRejectInfoLike) => {\n if (typeof window === 'undefined') return;\n\n const nav = (navRef.current || {\n slug: '',\n goto: '',\n navigating: false,\n pop: false,\n }) as NavigationState;\n\n const urlSlug = getUrlSlug();\n\n // NOTE: DO NOT overwrite landedSlugRef here.\n // Rejects can happen during an unrelated in-flight transition (loading churn),\n // and pretending we've \"landed\" breaks sync completion logic.\n\n // Always arm forceTransition when we receive it.\n armForceRetry(element?.forceTransition);\n\n // Best-effort \"where are we\" for nav bookkeeping.\n const currentSlug =\n element?.currentMedia?.slug ||\n nav.slug ||\n landedSlugRef.current ||\n nav.goto ||\n '';\n\n const mismatch = !!(urlSlug && currentSlug && urlSlug !== currentSlug);\n\n // Prefer keeping goto pointing at the URL (authoritative) when available,\n // so controlled selected continues to request the URL target.\n const desiredGoto =\n urlSlug || element?.nextMedia?.slug || nav.goto || currentSlug;\n\n safeNavigate(\n {\n ...nav,\n slug: currentSlug || nav.slug,\n goto: desiredGoto,\n navigating: false,\n pop: !!urlSlug, // treat as URL-driven alignment context\n } as any,\n mismatch ? 'onTransitionReject:mismatch' : 'onTransitionReject'\n );\n\n // If URL says we should be elsewhere, kick sync loop (it will wait if tx is in-flight).\n if (urlSlug && landedSlugRef.current !== urlSlug) {\n syncToUrl(\n mismatch\n ? 'onTransitionReject:url-mismatch'\n : 'onTransitionReject:retry'\n );\n }\n\n if (onTransitionReject) onTransitionReject(element);\n },\n [armForceRetry, onTransitionReject, safeNavigate, syncToUrl]\n );\n\n return (\n <Component\n {...(extra as any)}\n buttons\n fillParent\n bullets={false}\n infinite={false}\n selected={navigation ? navigation.goto : (extra as any).selected}\n onTransitionReject={handleTransitionReject}\n onTransitionStart={handleTransitionStart}\n onTransitionEnd={handleTransitionEnd}\n />\n );\n }\n\n WithNavigationHandlers.displayName = `withNavigationHandlers(${\n (Component as any).displayName || (Component as any).name || 'Component'\n })`;\n\n return withNavigationContext(WithNavigationHandlers as any) as any;\n}\n"],"mappings":"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","names":["React","import_react","import_react","React","React","import_react","getCleanPath","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/hoc/navigation/index.ts","../src/hoc/navigation/context.tsx","../src/hoc/navigation/link.tsx","../src/hoc/navigation/withNavigationContext.tsx","../src/hoc/navigation/withNavigationHandlers.tsx"],"sourcesContent":["// navigation/index.ts\nexport { Context, Provider } from './context';\nexport { default as Link } from './link';\nexport { default as withNavigationContext } from './withNavigationContext';\nexport { default as withNavigationHandlers } from './withNavigationHandlers';","// navigation/context.tsx\nimport React, {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\n\nexport type NavigationState = {\n slug: string;\n goto: string;\n navigating: boolean;\n pop: boolean;\n defaultSlug?: string;\n};\n\nexport type SetNavigation = (next: Partial<NavigationState> | string) => void;\n\nexport const Context = createContext<[NavigationState, SetNavigation]>([\n { slug: '', goto: '', navigating: false, pop: false, defaultSlug: '' },\n () => {},\n]);\n\nconst getCleanPath = (path: unknown) =>\n String(path || '')\n .replace(/^\\//, '')\n .replace(/\\/$/, '');\n\nexport type ProviderProps = {\n slug: string;\n defaultSlug?: string;\n children?: React.ReactNode;\n};\n\nexport const Provider: React.FC<ProviderProps> = ({\n slug,\n defaultSlug = '',\n children,\n}) => {\n const cleanPage = useMemo(() => {\n const cleanPageRaw = getCleanPath(slug);\n return cleanPageRaw || defaultSlug || '';\n }, [slug, defaultSlug]);\n\n const [state, setState] = useState<NavigationState>(() => ({\n slug: cleanPage,\n goto: cleanPage,\n navigating: false,\n pop: false,\n defaultSlug,\n }));\n\n // Re-anchor when slug prop changes, but don't clobber in-flight nav.\n useEffect(() => {\n setState((prev) => {\n // If we're mid-transition, don't force navigating=false or stomp goto.\n if (prev.navigating === true) {\n return {\n ...prev,\n slug: cleanPage,\n defaultSlug,\n // keep goto as-is while navigating; end-handler will reconcile\n };\n }\n\n return {\n ...prev,\n slug: cleanPage,\n goto: cleanPage,\n navigating: false,\n pop: false,\n defaultSlug,\n };\n });\n }, [cleanPage, defaultSlug]);\n\n const setNavigation = useCallback<SetNavigation>(\n (params) => {\n if (params && typeof params === 'object') {\n setState((prev) => ({ ...prev, ...params }));\n return;\n }\n\n const nextRaw = getCleanPath(params);\n const next = nextRaw || defaultSlug || '';\n\n setState((prev) => ({ ...prev, goto: next }));\n },\n [defaultSlug]\n );\n\n return (\n <Context.Provider value={[state, setNavigation]}>\n {children}\n </Context.Provider>\n );\n};\n","// navigation/link.tsx\nimport React, { useCallback, useMemo } from 'react';\nimport withNavigationContext from './withNavigationContext';\nimport type { NavigationState, SetNavigation } from './context';\n\ntype Fullpage = {\n navigation: NavigationState;\n navigate: SetNavigation;\n};\n\nconst isModifiedClick = (e: React.MouseEvent) =>\n e.metaKey || e.altKey || e.ctrlKey || e.shiftKey || e.button !== 0;\n\nconst isExternalHref = (href: unknown) => {\n const h = String(href || '');\n return (\n /^([a-z][a-z0-9+.-]*:)?\\/\\//i.test(h) ||\n /^mailto:/i.test(h) ||\n /^tel:/i.test(h)\n );\n};\n\nconst cleanHrefToGoto = (href: unknown) =>\n String(href || '')\n .replace(/^\\//, '')\n .replace(/\\/$/, '');\n\nexport type LinkProps = Omit<\n React.AnchorHTMLAttributes<HTMLAnchorElement>,\n 'href' | 'className' | 'onClick'\n> & {\n fullpage?: Fullpage;\n href: string;\n className?: string | null;\n onClick?: React.MouseEventHandler<HTMLAnchorElement>;\n children?: React.ReactNode;\n};\n\nexport default withNavigationContext((props: LinkProps) => {\n const { fullpage, children, href, className = null, onClick, ...extra } =\n props;\n\n const navigation = fullpage?.navigation;\n const navigate = fullpage?.navigate;\n\n const goto = useMemo(() => cleanHrefToGoto(href), [href]);\n\n const handleClick = useCallback(\n (event: React.MouseEvent<HTMLAnchorElement>) => {\n // let user handler run first\n if (typeof onClick === 'function') onClick(event);\n if (event.defaultPrevented) return;\n\n // no nav context / no href / external => let browser handle\n if (!navigation || typeof navigate !== 'function' || !href) return;\n if (isExternalHref(href)) return;\n\n // allow middle click / cmd-click / ctrl-click / shift-click etc.\n if (isModifiedClick(event)) return;\n\n event.preventDefault();\n\n // ignore clicks while a transition is in progress\n if (navigation.navigating === true) return;\n\n // IMPORTANT: allow \"/\" to map to empty goto (Provider/handlers decide fallback)\n const nextGoto = goto;\n\n // noop if already targeting same goto\n if (nextGoto === navigation.goto) return;\n\n navigate({\n ...navigation,\n pop: false, // click-driven\n goto: nextGoto,\n });\n },\n [onClick, navigation, navigate, href, goto]\n );\n\n return (\n <a\n className={className || undefined}\n onClick={handleClick}\n href={href}\n {...extra}\n >\n {children}\n </a>\n );\n});","// navigation/withNavigationContext.tsx\nimport React, { useContext, useMemo } from 'react';\nimport { Context } from './context';\nimport type { NavigationState, SetNavigation } from './context';\n\nexport type Fullpage = {\n navigation: NavigationState;\n navigate: SetNavigation;\n};\n\nexport type WithNavigationInjectedProps = {\n fullpage: Fullpage;\n};\n\nconst FALLBACK_NAV: NavigationState = {\n slug: '',\n goto: '',\n navigating: false,\n pop: false,\n};\n\nexport default function withNavigationContext<P extends object>(\n Component: React.ComponentType<P & WithNavigationInjectedProps>\n) {\n function WithNavigationContext(props: P) {\n const value = useContext(Context);\n\n const navigation: NavigationState =\n (value && (value as any)[0]) || FALLBACK_NAV;\n\n const navigate: SetNavigation =\n (value && (value as any)[1]) || ((() => {}) as SetNavigation);\n\n const fullpage = useMemo<Fullpage>(\n () => ({\n navigation,\n navigate,\n }),\n [navigation, navigate]\n );\n\n return <Component {...props} fullpage={fullpage} />;\n }\n\n WithNavigationContext.displayName = `withNavigationContext(${\n (Component as any).displayName || (Component as any).name || 'Component'\n })`;\n\n return WithNavigationContext;\n}\n","// navigation/withNavigationHandlers.tsx (drop-in replacement)\nimport React, { useCallback, useEffect, useRef } from 'react';\nimport { frameThrower } from '@rcaferati/wac';\nimport withNavigationContext, {\n type WithNavigationInjectedProps,\n} from './withNavigationContext';\nimport type { NavigationState } from './context';\n\n// --- helpers -------------------------------------------------------------\n\nconst getCleanPath = (path: unknown) =>\n String(path || '')\n .replace(/^\\//, '')\n .replace(/\\/$/, '');\n\nconst getUrlSlug = (): string => {\n if (typeof window === 'undefined') return '';\n return getCleanPath(window.location.pathname) || '';\n};\n\nconst getDefaultSlug = (navigation?: NavigationState): string =>\n navigation?.defaultSlug || '';\n\nconst resolveUrlSlug = (\n rawSlug: string,\n navigation?: NavigationState\n): string => {\n return rawSlug === '' ? getDefaultSlug(navigation) : rawSlug;\n};\n\nconst getHistoryPath = (slug: string): string => {\n return slug === '' ? '/' : `/${slug}`;\n};\n\nconst getMediaSlug = (media?: MediaLike): string | undefined => {\n return typeof media?.slug === 'string' ? media.slug : undefined;\n};\n\nconst firstDefined = (...values: Array<string | undefined>): string | undefined => {\n return values.find((value) => value !== undefined);\n};\n\ntype MediaLike = { slug?: string } | null | undefined;\n\ntype TransitionInfoLike = {\n currentMedia?: MediaLike;\n nextMedia?: MediaLike;\n} & Record<string, any>;\n\ntype TransitionRejectInfoLike = TransitionInfoLike & {\n forceTransition?: () => void;\n};\n\ntype HandlerProps = {\n onTransitionReject?: (info: any) => void;\n onTransitionStart?: (info: any) => void;\n onTransitionEnd?: (info: any) => void;\n};\n\n// -------------------------------------------------------------------------\n\nexport default function withNavigationHandlers<P extends object>(\n Component: React.ComponentType<P>\n) {\n type Props = P & HandlerProps & Partial<WithNavigationInjectedProps>;\n\n function WithNavigationHandlers(props: Props) {\n const {\n fullpage,\n onTransitionReject,\n onTransitionStart,\n onTransitionEnd,\n ...extra\n } = props as any;\n\n const navigation = fullpage?.navigation as NavigationState | undefined;\n const navigate = fullpage?.navigate as ((next: any) => void) | undefined;\n\n const navRef = useRef<NavigationState | undefined>(navigation);\n const navigateRef = useRef<typeof navigate>(navigate);\n\n // keep refs hot synchronously (avoid stale reads in callbacks)\n navRef.current = navigation;\n navigateRef.current = navigate;\n\n // What we *actually* landed on visually (authoritative). Only set on tx:end.\n const landedSlugRef = useRef<string>('');\n\n // Retry hook (available after a reject payload happens)\n const forceRef = useRef<(() => void) | null>(null);\n\n // Real transition lifecycle (engine reality)\n const txInFlightRef = useRef(false);\n\n // One-shot latch: \"next transitionStart is URL-driven (pop/sync), do NOT pushState\"\n // IMPORTANT: this is NOT stored in NavigationState to avoid sticky mode bugs.\n const urlDrivenStartLatchRef = useRef(false);\n\n // sync loop control (latest-wins)\n const syncRunningRef = useRef(false);\n const syncSeqRef = useRef(0);\n\n // ---- navigation -------------------------------------------------------\n\n const safeNavigate = useCallback(\n (next: NavigationState, reason: string) => {\n void reason; // keep callsites readable; avoid unused-param lint\n const fn = navigateRef.current;\n if (typeof fn !== 'function') return;\n fn(next);\n },\n []\n );\n\n const armForceRetry = useCallback((forceTransition?: unknown) => {\n if (typeof forceTransition === 'function') {\n forceRef.current = forceTransition as () => void;\n }\n }, []);\n\n // =========================================================================\n // URL Sync + Retry (latest-wins)\n // =========================================================================\n const syncToUrl = useCallback(\n async (reason: string) => {\n void reason; // retained for callsite intent; no logging\n if (typeof window === 'undefined') return;\n\n // latest-wins: cancel older runner\n if (syncRunningRef.current) {\n syncSeqRef.current += 1;\n }\n\n syncRunningRef.current = true;\n const mySeq = ++syncSeqRef.current;\n\n const MAX_TICKS = 240;\n\n try {\n for (let tick = 1; tick <= MAX_TICKS; tick++) {\n await frameThrower(1);\n\n if (mySeq !== syncSeqRef.current) {\n return;\n }\n\n const nav = (navRef.current || {\n slug: '',\n goto: '',\n navigating: false,\n pop: false,\n }) as NavigationState;\n\n const urlNow = resolveUrlSlug(getUrlSlug(), nav);\n\n // 1) Ensure the controlled \"selected\" (goto) matches the URL.\n // Mark the next transitionStart as URL-driven so it must NOT pushState.\n if (nav.goto !== urlNow) {\n urlDrivenStartLatchRef.current = true;\n\n safeNavigate(\n {\n ...nav,\n pop: true,\n goto: urlNow,\n navigating: !!nav.navigating, // preserve (not trusted, but keep behavior)\n } as any,\n `syncToUrl:align-goto(tick:${tick})`\n );\n continue;\n }\n\n // 2) Never declare \"done\" while a real engine transition is in-flight.\n if (txInFlightRef.current === true) {\n continue;\n }\n\n // 3) Done when the *actual landed slide* matches the URL.\n if (landedSlugRef.current === urlNow) {\n return;\n }\n\n // 4) Not landed yet, not in-flight, goto matches URL -> re-trigger (if possible).\n const force = forceRef.current;\n if (typeof force === 'function') {\n // Avoid spamming: retry at a modest cadence.\n if (tick % 6 === 0) {\n try {\n force();\n } catch {\n // ignore\n }\n }\n }\n }\n } finally {\n if (syncSeqRef.current === mySeq) {\n syncRunningRef.current = false;\n }\n }\n },\n [safeNavigate]\n );\n\n // ---- popstate ----------------------------------------------------------\n\n const popSeqRef = useRef(0);\n\n const handlePopState = useCallback(() => {\n if (typeof window === 'undefined') return;\n const popSeq = ++popSeqRef.current;\n syncToUrl(`popstate#${popSeq}`);\n }, [syncToUrl]);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n window.addEventListener('popstate', handlePopState);\n return () => window.removeEventListener('popstate', handlePopState);\n }, [handlePopState]);\n\n // ---- transition handlers ----------------------------------------------\n\n const handleTransitionStart = useCallback(\n (element: TransitionInfoLike) => {\n if (typeof window === 'undefined') return;\n\n const nav = (navRef.current || {\n slug: '',\n goto: '',\n navigating: false,\n pop: false,\n }) as NavigationState;\n\n const cleanPath = getUrlSlug();\n const nextSlug = getMediaSlug(element?.nextMedia);\n\n // Real engine lifecycle\n txInFlightRef.current = true;\n\n // Consume the one-shot latch (URL-driven start => do NOT pushState).\n const urlDrivenStart = urlDrivenStartLatchRef.current === true;\n urlDrivenStartLatchRef.current = false;\n\n // pushState only for click-driven transitions (not URL-driven pop/sync).\n if (\n nextSlug !== undefined &&\n cleanPath !== nextSlug &&\n !urlDrivenStart\n ) {\n window.history.pushState({}, '', getHistoryPath(nextSlug));\n }\n\n safeNavigate(\n {\n ...nav,\n goto: nextSlug !== undefined ? nextSlug : nav.goto,\n slug: nav.slug,\n navigating: true,\n pop: urlDrivenStart ? true : false,\n } as any,\n 'onTransitionStart'\n );\n\n if (onTransitionStart) onTransitionStart(element);\n },\n [onTransitionStart, safeNavigate]\n );\n\n const handleTransitionEnd = useCallback(\n (element: TransitionInfoLike) => {\n if (typeof window === 'undefined') return;\n\n const nav = (navRef.current || {\n slug: '',\n goto: '',\n navigating: false,\n pop: false,\n }) as NavigationState;\n\n const currentSlug =\n firstDefined(getMediaSlug(element?.currentMedia), nav.goto, nav.slug) || '';\n const urlSlug = resolveUrlSlug(getUrlSlug(), nav);\n\n // Real engine lifecycle ends here (authoritative)\n txInFlightRef.current = false;\n\n landedSlugRef.current = currentSlug;\n\n const mismatch = urlSlug !== currentSlug;\n\n // If mismatch, immediately set goto to URL so controlled selected follows it.\n safeNavigate(\n {\n ...nav,\n navigating: false,\n pop: mismatch ? true : false,\n slug: currentSlug,\n goto: mismatch ? urlSlug : currentSlug,\n } as any,\n mismatch\n ? 'onTransitionEnd:mismatch(set-goto=url)'\n : 'onTransitionEnd'\n );\n\n if (onTransitionEnd) onTransitionEnd(element);\n\n if (mismatch) {\n syncToUrl('onTransitionEnd:url-mismatch');\n } else {\n // Safe point to clear the retry hook only when reality matches the URL.\n forceRef.current = null;\n }\n },\n [onTransitionEnd, safeNavigate, syncToUrl]\n );\n\n const handleTransitionReject = useCallback(\n (element: TransitionRejectInfoLike) => {\n if (typeof window === 'undefined') return;\n\n const nav = (navRef.current || {\n slug: '',\n goto: '',\n navigating: false,\n pop: false,\n }) as NavigationState;\n\n const urlSlug = resolveUrlSlug(getUrlSlug(), nav);\n\n // NOTE: DO NOT overwrite landedSlugRef here.\n // Rejects can happen during an unrelated in-flight transition (loading churn),\n // and pretending we've \"landed\" breaks sync completion logic.\n\n // Always arm forceTransition when we receive it.\n armForceRetry(element?.forceTransition);\n\n // Best-effort \"where are we\" for nav bookkeeping.\n const currentSlug =\n firstDefined(\n getMediaSlug(element?.currentMedia),\n nav.slug,\n landedSlugRef.current,\n nav.goto\n ) || '';\n\n const mismatch = urlSlug !== currentSlug;\n\n // Prefer keeping goto pointing at the URL (authoritative) when available,\n // so controlled selected continues to request the URL target.\n const desiredGoto =\n firstDefined(urlSlug, getMediaSlug(element?.nextMedia), nav.goto, currentSlug) ||\n '';\n\n safeNavigate(\n {\n ...nav,\n slug: currentSlug,\n goto: desiredGoto,\n navigating: false,\n pop: true, // treat as URL-driven alignment context\n } as any,\n mismatch ? 'onTransitionReject:mismatch' : 'onTransitionReject'\n );\n\n // If URL says we should be elsewhere, kick sync loop (it will wait if tx is in-flight).\n if (landedSlugRef.current !== urlSlug) {\n syncToUrl(\n mismatch\n ? 'onTransitionReject:url-mismatch'\n : 'onTransitionReject:retry'\n );\n }\n\n if (onTransitionReject) onTransitionReject(element);\n },\n [armForceRetry, onTransitionReject, safeNavigate, syncToUrl]\n );\n\n return (\n <Component\n {...(extra as any)}\n buttons\n fillParent\n bullets={false}\n infinite={false}\n selected={navigation ? navigation.goto : (extra as any).selected}\n onTransitionReject={handleTransitionReject}\n onTransitionStart={handleTransitionStart}\n onTransitionEnd={handleTransitionEnd}\n />\n );\n }\n\n WithNavigationHandlers.displayName = `withNavigationHandlers(${\n (Component as any).displayName || (Component as any).name || 'Component'\n })`;\n\n return withNavigationContext(WithNavigationHandlers as any) as any;\n}\n"],"mappings":"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","names":["React","import_react","import_react","React","React","import_react","getCleanPath","React"]}
|
package/dist/navigation.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import React, {
|
|
|
7
7
|
useState
|
|
8
8
|
} from "react";
|
|
9
9
|
var Context = createContext([
|
|
10
|
-
{ slug: "", goto: "", navigating: false, pop: false },
|
|
10
|
+
{ slug: "", goto: "", navigating: false, pop: false, defaultSlug: "" },
|
|
11
11
|
() => {
|
|
12
12
|
}
|
|
13
13
|
]);
|
|
@@ -25,15 +25,16 @@ var Provider = ({
|
|
|
25
25
|
slug: cleanPage,
|
|
26
26
|
goto: cleanPage,
|
|
27
27
|
navigating: false,
|
|
28
|
-
pop: false
|
|
28
|
+
pop: false,
|
|
29
|
+
defaultSlug
|
|
29
30
|
}));
|
|
30
31
|
useEffect(() => {
|
|
31
|
-
if (!cleanPage) return;
|
|
32
32
|
setState((prev) => {
|
|
33
33
|
if (prev.navigating === true) {
|
|
34
34
|
return {
|
|
35
35
|
...prev,
|
|
36
|
-
slug: cleanPage
|
|
36
|
+
slug: cleanPage,
|
|
37
|
+
defaultSlug
|
|
37
38
|
// keep goto as-is while navigating; end-handler will reconcile
|
|
38
39
|
};
|
|
39
40
|
}
|
|
@@ -42,10 +43,11 @@ var Provider = ({
|
|
|
42
43
|
slug: cleanPage,
|
|
43
44
|
goto: cleanPage,
|
|
44
45
|
navigating: false,
|
|
45
|
-
pop: false
|
|
46
|
+
pop: false,
|
|
47
|
+
defaultSlug
|
|
46
48
|
};
|
|
47
49
|
});
|
|
48
|
-
}, [cleanPage]);
|
|
50
|
+
}, [cleanPage, defaultSlug]);
|
|
49
51
|
const setNavigation = useCallback(
|
|
50
52
|
(params) => {
|
|
51
53
|
if (params && typeof params === "object") {
|
|
@@ -143,6 +145,19 @@ var getUrlSlug = () => {
|
|
|
143
145
|
if (typeof window === "undefined") return "";
|
|
144
146
|
return getCleanPath2(window.location.pathname) || "";
|
|
145
147
|
};
|
|
148
|
+
var getDefaultSlug = (navigation) => (navigation == null ? void 0 : navigation.defaultSlug) || "";
|
|
149
|
+
var resolveUrlSlug = (rawSlug, navigation) => {
|
|
150
|
+
return rawSlug === "" ? getDefaultSlug(navigation) : rawSlug;
|
|
151
|
+
};
|
|
152
|
+
var getHistoryPath = (slug) => {
|
|
153
|
+
return slug === "" ? "/" : `/${slug}`;
|
|
154
|
+
};
|
|
155
|
+
var getMediaSlug = (media) => {
|
|
156
|
+
return typeof (media == null ? void 0 : media.slug) === "string" ? media.slug : void 0;
|
|
157
|
+
};
|
|
158
|
+
var firstDefined = (...values) => {
|
|
159
|
+
return values.find((value) => value !== void 0);
|
|
160
|
+
};
|
|
146
161
|
function withNavigationHandlers(Component) {
|
|
147
162
|
function WithNavigationHandlers(props) {
|
|
148
163
|
const {
|
|
@@ -182,8 +197,6 @@ function withNavigationHandlers(Component) {
|
|
|
182
197
|
async (reason) => {
|
|
183
198
|
void reason;
|
|
184
199
|
if (typeof window === "undefined") return;
|
|
185
|
-
const initialUrlSlug = getUrlSlug();
|
|
186
|
-
if (!initialUrlSlug) return;
|
|
187
200
|
if (syncRunningRef.current) {
|
|
188
201
|
syncSeqRef.current += 1;
|
|
189
202
|
}
|
|
@@ -202,8 +215,7 @@ function withNavigationHandlers(Component) {
|
|
|
202
215
|
navigating: false,
|
|
203
216
|
pop: false
|
|
204
217
|
};
|
|
205
|
-
const urlNow = getUrlSlug();
|
|
206
|
-
if (!urlNow) continue;
|
|
218
|
+
const urlNow = resolveUrlSlug(getUrlSlug(), nav);
|
|
207
219
|
if (nav.goto !== urlNow) {
|
|
208
220
|
urlDrivenStartLatchRef.current = true;
|
|
209
221
|
safeNavigate(
|
|
@@ -255,7 +267,6 @@ function withNavigationHandlers(Component) {
|
|
|
255
267
|
}, [handlePopState]);
|
|
256
268
|
const handleTransitionStart = useCallback3(
|
|
257
269
|
(element) => {
|
|
258
|
-
var _a;
|
|
259
270
|
if (typeof window === "undefined") return;
|
|
260
271
|
const nav = navRef.current || {
|
|
261
272
|
slug: "",
|
|
@@ -264,18 +275,18 @@ function withNavigationHandlers(Component) {
|
|
|
264
275
|
pop: false
|
|
265
276
|
};
|
|
266
277
|
const cleanPath = getUrlSlug();
|
|
267
|
-
const nextSlug = (
|
|
278
|
+
const nextSlug = getMediaSlug(element == null ? void 0 : element.nextMedia);
|
|
268
279
|
txInFlightRef.current = true;
|
|
269
280
|
const urlDrivenStart = urlDrivenStartLatchRef.current === true;
|
|
270
281
|
urlDrivenStartLatchRef.current = false;
|
|
271
|
-
if (nextSlug && cleanPath !== nextSlug && !urlDrivenStart) {
|
|
272
|
-
window.history.pushState({}, "",
|
|
282
|
+
if (nextSlug !== void 0 && cleanPath !== nextSlug && !urlDrivenStart) {
|
|
283
|
+
window.history.pushState({}, "", getHistoryPath(nextSlug));
|
|
273
284
|
}
|
|
274
285
|
safeNavigate(
|
|
275
286
|
{
|
|
276
287
|
...nav,
|
|
277
|
-
goto: nextSlug
|
|
278
|
-
slug: nav.slug
|
|
288
|
+
goto: nextSlug !== void 0 ? nextSlug : nav.goto,
|
|
289
|
+
slug: nav.slug,
|
|
279
290
|
navigating: true,
|
|
280
291
|
pop: urlDrivenStart ? true : false
|
|
281
292
|
},
|
|
@@ -287,7 +298,6 @@ function withNavigationHandlers(Component) {
|
|
|
287
298
|
);
|
|
288
299
|
const handleTransitionEnd = useCallback3(
|
|
289
300
|
(element) => {
|
|
290
|
-
var _a;
|
|
291
301
|
if (typeof window === "undefined") return;
|
|
292
302
|
const nav = navRef.current || {
|
|
293
303
|
slug: "",
|
|
@@ -295,18 +305,18 @@ function withNavigationHandlers(Component) {
|
|
|
295
305
|
navigating: false,
|
|
296
306
|
pop: false
|
|
297
307
|
};
|
|
298
|
-
const currentSlug = ((
|
|
299
|
-
const urlSlug = getUrlSlug();
|
|
308
|
+
const currentSlug = firstDefined(getMediaSlug(element == null ? void 0 : element.currentMedia), nav.goto, nav.slug) || "";
|
|
309
|
+
const urlSlug = resolveUrlSlug(getUrlSlug(), nav);
|
|
300
310
|
txInFlightRef.current = false;
|
|
301
|
-
|
|
302
|
-
const mismatch =
|
|
311
|
+
landedSlugRef.current = currentSlug;
|
|
312
|
+
const mismatch = urlSlug !== currentSlug;
|
|
303
313
|
safeNavigate(
|
|
304
314
|
{
|
|
305
315
|
...nav,
|
|
306
316
|
navigating: false,
|
|
307
317
|
pop: mismatch ? true : false,
|
|
308
|
-
slug: currentSlug
|
|
309
|
-
goto: mismatch ? urlSlug : currentSlug
|
|
318
|
+
slug: currentSlug,
|
|
319
|
+
goto: mismatch ? urlSlug : currentSlug
|
|
310
320
|
},
|
|
311
321
|
mismatch ? "onTransitionEnd:mismatch(set-goto=url)" : "onTransitionEnd"
|
|
312
322
|
);
|
|
@@ -321,7 +331,6 @@ function withNavigationHandlers(Component) {
|
|
|
321
331
|
);
|
|
322
332
|
const handleTransitionReject = useCallback3(
|
|
323
333
|
(element) => {
|
|
324
|
-
var _a, _b;
|
|
325
334
|
if (typeof window === "undefined") return;
|
|
326
335
|
const nav = navRef.current || {
|
|
327
336
|
slug: "",
|
|
@@ -329,23 +338,28 @@ function withNavigationHandlers(Component) {
|
|
|
329
338
|
navigating: false,
|
|
330
339
|
pop: false
|
|
331
340
|
};
|
|
332
|
-
const urlSlug = getUrlSlug();
|
|
341
|
+
const urlSlug = resolveUrlSlug(getUrlSlug(), nav);
|
|
333
342
|
armForceRetry(element == null ? void 0 : element.forceTransition);
|
|
334
|
-
const currentSlug = (
|
|
335
|
-
|
|
336
|
-
|
|
343
|
+
const currentSlug = firstDefined(
|
|
344
|
+
getMediaSlug(element == null ? void 0 : element.currentMedia),
|
|
345
|
+
nav.slug,
|
|
346
|
+
landedSlugRef.current,
|
|
347
|
+
nav.goto
|
|
348
|
+
) || "";
|
|
349
|
+
const mismatch = urlSlug !== currentSlug;
|
|
350
|
+
const desiredGoto = firstDefined(urlSlug, getMediaSlug(element == null ? void 0 : element.nextMedia), nav.goto, currentSlug) || "";
|
|
337
351
|
safeNavigate(
|
|
338
352
|
{
|
|
339
353
|
...nav,
|
|
340
|
-
slug: currentSlug
|
|
354
|
+
slug: currentSlug,
|
|
341
355
|
goto: desiredGoto,
|
|
342
356
|
navigating: false,
|
|
343
|
-
pop:
|
|
357
|
+
pop: true
|
|
344
358
|
// treat as URL-driven alignment context
|
|
345
359
|
},
|
|
346
360
|
mismatch ? "onTransitionReject:mismatch" : "onTransitionReject"
|
|
347
361
|
);
|
|
348
|
-
if (
|
|
362
|
+
if (landedSlugRef.current !== urlSlug) {
|
|
349
363
|
syncToUrl(
|
|
350
364
|
mismatch ? "onTransitionReject:url-mismatch" : "onTransitionReject:retry"
|
|
351
365
|
);
|