@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.
Files changed (45) hide show
  1. package/README.md +212 -51
  2. package/dist/autoplay.js +25 -9
  3. package/dist/autoplay.js.map +1 -1
  4. package/dist/autoplay.mjs +25 -9
  5. package/dist/autoplay.mjs.map +1 -1
  6. package/dist/captioned.js +25 -9
  7. package/dist/captioned.js.map +1 -1
  8. package/dist/captioned.mjs +25 -9
  9. package/dist/captioned.mjs.map +1 -1
  10. package/dist/custom-animations/cube-animation.css +1 -1
  11. package/dist/custom-animations/cube-animation.d.mts +3 -0
  12. package/dist/custom-animations/cube-animation.d.ts +3 -0
  13. package/dist/custom-animations/cube-animation.js +13 -0
  14. package/dist/custom-animations/cube-animation.mjs +10 -0
  15. package/dist/custom-animations/fall-animation.d.mts +3 -0
  16. package/dist/custom-animations/fall-animation.d.ts +3 -0
  17. package/dist/custom-animations/fall-animation.js +11 -0
  18. package/dist/custom-animations/fall-animation.mjs +8 -0
  19. package/dist/custom-animations/fold-out-animation.d.mts +3 -0
  20. package/dist/custom-animations/fold-out-animation.d.ts +3 -0
  21. package/dist/custom-animations/fold-out-animation.js +12 -0
  22. package/dist/custom-animations/fold-out-animation.mjs +9 -0
  23. package/dist/custom-animations/open-animation.d.mts +3 -0
  24. package/dist/custom-animations/open-animation.d.ts +3 -0
  25. package/dist/custom-animations/open-animation.js +12 -0
  26. package/dist/custom-animations/open-animation.mjs +9 -0
  27. package/dist/custom-animations/scale-out-animation.d.mts +3 -0
  28. package/dist/custom-animations/scale-out-animation.d.ts +3 -0
  29. package/dist/custom-animations/scale-out-animation.js +11 -0
  30. package/dist/custom-animations/scale-out-animation.mjs +8 -0
  31. package/dist/index.js +25 -9
  32. package/dist/index.js.map +1 -1
  33. package/dist/index.mjs +25 -9
  34. package/dist/index.mjs.map +1 -1
  35. package/dist/lettering.js +25 -9
  36. package/dist/lettering.js.map +1 -1
  37. package/dist/lettering.mjs +25 -9
  38. package/dist/lettering.mjs.map +1 -1
  39. package/dist/navigation.d.mts +1 -0
  40. package/dist/navigation.d.ts +1 -0
  41. package/dist/navigation.js +45 -31
  42. package/dist/navigation.js.map +1 -1
  43. package/dist/navigation.mjs +45 -31
  44. package/dist/navigation.mjs.map +1 -1
  45. package/package.json +14 -4
@@ -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 = ((_a = element == null ? void 0 : element.nextMedia) == null ? void 0 : _a.slug) || "";
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({}, "", `/${nextSlug}`);
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 || nav.goto,
311
- slug: nav.slug || cleanPath,
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 = ((_a = element == null ? void 0 : element.currentMedia) == null ? void 0 : _a.slug) || "";
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
- if (currentSlug) landedSlugRef.current = currentSlug;
335
- const mismatch = !!(urlSlug && currentSlug && urlSlug !== currentSlug);
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 || nav.slug,
342
- goto: mismatch ? urlSlug : currentSlug || nav.goto
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 = ((_a = element == null ? void 0 : element.currentMedia) == null ? void 0 : _a.slug) || nav.slug || landedSlugRef.current || nav.goto || "";
368
- const mismatch = !!(urlSlug && currentSlug && urlSlug !== currentSlug);
369
- const desiredGoto = urlSlug || ((_b = element == null ? void 0 : element.nextMedia) == null ? void 0 : _b.slug) || nav.goto || currentSlug;
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 || nav.slug,
387
+ slug: currentSlug,
374
388
  goto: desiredGoto,
375
389
  navigating: false,
376
- pop: !!urlSlug
390
+ pop: true
377
391
  // treat as URL-driven alignment context
378
392
  },
379
393
  mismatch ? "onTransitionReject:mismatch" : "onTransitionReject"
380
394
  );
381
- if (urlSlug && landedSlugRef.current !== urlSlug) {
395
+ if (landedSlugRef.current !== urlSlug) {
382
396
  syncToUrl(
383
397
  mismatch ? "onTransitionReject:url-mismatch" : "onTransitionReject:retry"
384
398
  );
@@ -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"]}
@@ -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 = ((_a = element == null ? void 0 : element.nextMedia) == null ? void 0 : _a.slug) || "";
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({}, "", `/${nextSlug}`);
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 || nav.goto,
278
- slug: nav.slug || cleanPath,
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 = ((_a = element == null ? void 0 : element.currentMedia) == null ? void 0 : _a.slug) || "";
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
- if (currentSlug) landedSlugRef.current = currentSlug;
302
- const mismatch = !!(urlSlug && currentSlug && urlSlug !== currentSlug);
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 || nav.slug,
309
- goto: mismatch ? urlSlug : currentSlug || nav.goto
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 = ((_a = element == null ? void 0 : element.currentMedia) == null ? void 0 : _a.slug) || nav.slug || landedSlugRef.current || nav.goto || "";
335
- const mismatch = !!(urlSlug && currentSlug && urlSlug !== currentSlug);
336
- const desiredGoto = urlSlug || ((_b = element == null ? void 0 : element.nextMedia) == null ? void 0 : _b.slug) || nav.goto || currentSlug;
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 || nav.slug,
354
+ slug: currentSlug,
341
355
  goto: desiredGoto,
342
356
  navigating: false,
343
- pop: !!urlSlug
357
+ pop: true
344
358
  // treat as URL-driven alignment context
345
359
  },
346
360
  mismatch ? "onTransitionReject:mismatch" : "onTransitionReject"
347
361
  );
348
- if (urlSlug && landedSlugRef.current !== urlSlug) {
362
+ if (landedSlugRef.current !== urlSlug) {
349
363
  syncToUrl(
350
364
  mismatch ? "onTransitionReject:url-mismatch" : "onTransitionReject:retry"
351
365
  );