@fluixi/core 1.0.0-alpha.84 → 1.0.0-alpha.85

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 (49) hide show
  1. package/dist/cdn/core.global.js +2 -2
  2. package/dist/src/cdn/{chunk-VNLCQBFQ.mjs → chunk-MDJLC3PE.mjs} +87 -4
  3. package/dist/src/cdn/core.cjs +91 -5
  4. package/dist/src/cdn/core.mjs +3 -3
  5. package/dist/src/cdn/{router-WMN2AA7E.mjs → router-JYFZP3EZ.mjs} +5 -1
  6. package/dist/src/index.cjs +84 -5
  7. package/dist/src/index.mjs +86 -6
  8. package/dist/src/lib/client/{chunk-2C2KDDQV.mjs → chunk-7IUN2FLI.mjs} +1 -1
  9. package/dist/src/lib/client/index.cjs +92 -6
  10. package/dist/src/lib/client/index.mjs +4 -4
  11. package/dist/src/lib/client/{router-X526HSWQ.mjs → router-NOFEMOEH.mjs} +89 -6
  12. package/dist/src/lib/core.cjs +83 -4
  13. package/dist/src/lib/core.mjs +85 -5
  14. package/dist/src/lib/i18n/index.cjs +1 -1
  15. package/dist/src/lib/i18n/index.mjs +1 -1
  16. package/dist/src/lib/index.cjs +1 -1
  17. package/dist/src/lib/index.mjs +1 -1
  18. package/dist/src/lib/jsx-runtime/index.cjs +1 -1
  19. package/dist/src/lib/jsx-runtime/index.mjs +1 -1
  20. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.cjs +1 -1
  21. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.mjs +1 -1
  22. package/dist/src/lib/plugins/index.cjs +1 -1
  23. package/dist/src/lib/plugins/index.mjs +1 -1
  24. package/dist/src/lib/render/index.cjs +1 -1
  25. package/dist/src/lib/render/index.mjs +1 -1
  26. package/dist/src/lib/render/versions.cjs +1 -1
  27. package/dist/src/lib/render/versions.mjs +1 -1
  28. package/dist/src/lib/router/index.cjs +86 -4
  29. package/dist/src/lib/router/index.d.ts +17 -14
  30. package/dist/src/lib/router/index.d.ts.map +1 -1
  31. package/dist/src/lib/router/index.js +76 -4
  32. package/dist/src/lib/router/index.mjs +88 -5
  33. package/dist/src/lib/router/transition.cjs +75 -0
  34. package/dist/src/lib/router/transition.d.ts +81 -0
  35. package/dist/src/lib/router/transition.d.ts.map +1 -0
  36. package/dist/src/lib/router/transition.js +136 -0
  37. package/dist/src/lib/router/transition.mjs +54 -0
  38. package/dist/src/lib/server/index.cjs +1 -1
  39. package/dist/src/lib/server/index.mjs +1 -1
  40. package/dist/src/routes.cjs +1 -1
  41. package/dist/src/routes.mjs +1 -1
  42. package/dist/src/utils.cjs +1 -1
  43. package/dist/src/utils.mjs +1 -1
  44. package/dist/src/version.generated.cjs +1 -1
  45. package/dist/src/version.generated.d.ts +1 -1
  46. package/dist/src/version.generated.js +1 -1
  47. package/dist/src/version.generated.mjs +1 -1
  48. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  49. package/package.json +11 -11
@@ -20,8 +20,59 @@ import {
20
20
  createEffect,
21
21
  getOwner,
22
22
  onCleanup,
23
- untrack as untrack2
23
+ untrack as untrack2,
24
+ flush
24
25
  } from "@fluixi/reactive/signal";
26
+
27
+ // src/lib/router/transition.ts
28
+ function supportsViewTransitions() {
29
+ return typeof document !== "undefined" && typeof document.startViewTransition === "function";
30
+ }
31
+ function prefersReducedMotion() {
32
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
33
+ return false;
34
+ }
35
+ try {
36
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+ function shouldAnimate(mode) {
42
+ return mode !== "none" && supportsViewTransitions() && !prefersReducedMotion();
43
+ }
44
+ function prepareComponents(components) {
45
+ const pending = [];
46
+ for (const component of components) {
47
+ const preload = component?.preload;
48
+ if (typeof preload === "function") {
49
+ try {
50
+ const result = preload();
51
+ if (result && typeof result.then === "function") {
52
+ pending.push(result.catch(() => void 0));
53
+ }
54
+ } catch {
55
+ }
56
+ }
57
+ }
58
+ return pending.length ? Promise.all(pending).then(() => void 0) : null;
59
+ }
60
+ function runTransition(mode, commit) {
61
+ if (!shouldAnimate(mode)) {
62
+ return Promise.resolve(commit()).then(() => void 0);
63
+ }
64
+ const start = document.startViewTransition;
65
+ try {
66
+ const transition = start.call(document, () => commit());
67
+ transition.finished?.catch(() => void 0);
68
+ transition.ready?.catch(() => void 0);
69
+ return transition.updateCallbackDone.catch(() => void 0);
70
+ } catch {
71
+ return Promise.resolve(commit()).then(() => void 0);
72
+ }
73
+ }
74
+
75
+ // src/lib/router/index.ts
25
76
  import {
26
77
  insert,
27
78
  createComponent as createComponent2,
@@ -422,7 +473,7 @@ function renderChild(ctx) {
422
473
  );
423
474
  createEffect(() => {
424
475
  const c = ctx.matched()[childIdx]?.component;
425
- setChildComp(() => c);
476
+ if (untrack2(childComp) !== c) setChildComp(() => c);
426
477
  });
427
478
  return createMemo2(() => {
428
479
  const component = childComp();
@@ -460,6 +511,7 @@ function buildDefaultNotFound() {
460
511
  el.appendChild(p);
461
512
  return el;
462
513
  }
514
+ var pendingTransitionMode;
463
515
  function Router(props) {
464
516
  const history = props.history ?? createBrowserHistory();
465
517
  const router = createCoreRouter({
@@ -468,10 +520,35 @@ function Router(props) {
468
520
  history
469
521
  });
470
522
  const [state, setState] = createSignal2(router.state());
471
- const unsub = router.subscribe(setState);
523
+ let navigationId = 0;
524
+ const takeMode = () => {
525
+ const mode = pendingTransitionMode ?? (props.transition ?? "auto");
526
+ pendingTransitionMode = void 0;
527
+ return mode;
528
+ };
529
+ const unsub = router.subscribe((next) => {
530
+ const id = ++navigationId;
531
+ const mode = takeMode();
532
+ const prepared = prepareComponents(
533
+ (next.match?.matched ?? []).map((m) => m.component).filter(Boolean)
534
+ );
535
+ const commit = () => {
536
+ setState(next);
537
+ return flush();
538
+ };
539
+ if (!prepared) {
540
+ void runTransition(mode, commit);
541
+ return;
542
+ }
543
+ void prepared.then(() => {
544
+ if (id !== navigationId) return;
545
+ return runTransition(mode, commit);
546
+ });
547
+ });
472
548
  onCleanup(() => {
473
549
  unsub();
474
550
  router.destroy();
551
+ navigationId++;
475
552
  });
476
553
  const matched = createMemo2(
477
554
  () => (state().match?.matched ?? []).filter((m) => m.component)
@@ -604,12 +681,16 @@ function useLinkNavigation(options = {}) {
604
681
  if (url.hash && url.pathname === window.location.pathname && url.search === window.location.search) return;
605
682
  if (options.shouldNavigate && !options.shouldNavigate(url, anchor)) return;
606
683
  event.preventDefault();
684
+ pendingTransitionMode = options.transition;
607
685
  ctx.router.navigate(url.pathname + url.search + url.hash, { replace: options.replace });
608
686
  };
609
687
  }
610
688
  function useNavigate() {
611
689
  const { router } = useRouter();
612
- return (to, options) => router.navigate(to, options);
690
+ return (to, options) => {
691
+ pendingTransitionMode = options?.transition;
692
+ router.navigate(to, options);
693
+ };
613
694
  }
614
695
  function useRouteData() {
615
696
  const acc = useContext2(RouteDataContext2);
@@ -714,6 +795,8 @@ export {
714
795
  setHydrating,
715
796
  deserializeHydrationData,
716
797
  cleanupHydration,
798
+ supportsViewTransitions,
799
+ prefersReducedMotion,
717
800
  cache,
718
801
  revalidate,
719
802
  createAsync,
@@ -245,6 +245,59 @@ var init_hydration = __esm({
245
245
  }
246
246
  });
247
247
 
248
+ // src/lib/router/transition.ts
249
+ function supportsViewTransitions() {
250
+ return typeof document !== "undefined" && typeof document.startViewTransition === "function";
251
+ }
252
+ function prefersReducedMotion() {
253
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
254
+ return false;
255
+ }
256
+ try {
257
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
258
+ } catch {
259
+ return false;
260
+ }
261
+ }
262
+ function shouldAnimate(mode) {
263
+ return mode !== "none" && supportsViewTransitions() && !prefersReducedMotion();
264
+ }
265
+ function prepareComponents(components) {
266
+ const pending = [];
267
+ for (const component of components) {
268
+ const preload = component?.preload;
269
+ if (typeof preload === "function") {
270
+ try {
271
+ const result = preload();
272
+ if (result && typeof result.then === "function") {
273
+ pending.push(result.catch(() => void 0));
274
+ }
275
+ } catch {
276
+ }
277
+ }
278
+ }
279
+ return pending.length ? Promise.all(pending).then(() => void 0) : null;
280
+ }
281
+ function runTransition(mode, commit) {
282
+ if (!shouldAnimate(mode)) {
283
+ return Promise.resolve(commit()).then(() => void 0);
284
+ }
285
+ const start = document.startViewTransition;
286
+ try {
287
+ const transition = start.call(document, () => commit());
288
+ transition.finished?.catch(() => void 0);
289
+ transition.ready?.catch(() => void 0);
290
+ return transition.updateCallbackDone.catch(() => void 0);
291
+ } catch {
292
+ return Promise.resolve(commit()).then(() => void 0);
293
+ }
294
+ }
295
+ var init_transition = __esm({
296
+ "src/lib/router/transition.ts"() {
297
+ "use strict";
298
+ }
299
+ });
300
+
248
301
  // src/lib/router/data.ts
249
302
  function cache(fn, name) {
250
303
  return async (...args) => {
@@ -381,10 +434,12 @@ __export(router_exports, {
381
434
  lazy: () => lazy,
382
435
  matchPath: () => import_router2.matchPath,
383
436
  matchRoutes: () => import_router2.matchRoutes,
437
+ prefersReducedMotion: () => prefersReducedMotion,
384
438
  preloadRoutes: () => preloadRoutes,
385
439
  revalidate: () => revalidate,
386
440
  runWithOwner: () => import_signal16.runWithOwner,
387
441
  select: () => select,
442
+ supportsViewTransitions: () => supportsViewTransitions,
388
443
  useAction: () => useAction,
389
444
  useLevelParams: () => useLevelParams,
390
445
  useLinkNavigation: () => useLinkNavigation,
@@ -443,7 +498,7 @@ function renderChild(ctx) {
443
498
  );
444
499
  (0, import_signal14.createEffect)(() => {
445
500
  const c = ctx.matched()[childIdx]?.component;
446
- setChildComp(() => c);
501
+ if ((0, import_signal14.untrack)(childComp) !== c) setChildComp(() => c);
447
502
  });
448
503
  return (0, import_signal14.createMemo)(() => {
449
504
  const component = childComp();
@@ -489,10 +544,35 @@ function Router(props) {
489
544
  history
490
545
  });
491
546
  const [state, setState] = (0, import_signal14.createSignal)(router.state());
492
- const unsub = router.subscribe(setState);
547
+ let navigationId = 0;
548
+ const takeMode = () => {
549
+ const mode = pendingTransitionMode ?? (props.transition ?? "auto");
550
+ pendingTransitionMode = void 0;
551
+ return mode;
552
+ };
553
+ const unsub = router.subscribe((next) => {
554
+ const id = ++navigationId;
555
+ const mode = takeMode();
556
+ const prepared = prepareComponents(
557
+ (next.match?.matched ?? []).map((m) => m.component).filter(Boolean)
558
+ );
559
+ const commit = () => {
560
+ setState(next);
561
+ return (0, import_signal14.flush)();
562
+ };
563
+ if (!prepared) {
564
+ void runTransition(mode, commit);
565
+ return;
566
+ }
567
+ void prepared.then(() => {
568
+ if (id !== navigationId) return;
569
+ return runTransition(mode, commit);
570
+ });
571
+ });
493
572
  (0, import_signal14.onCleanup)(() => {
494
573
  unsub();
495
574
  router.destroy();
575
+ navigationId++;
496
576
  });
497
577
  const matched = (0, import_signal14.createMemo)(
498
578
  () => (state().match?.matched ?? []).filter((m) => m.component)
@@ -619,12 +699,16 @@ function useLinkNavigation(options = {}) {
619
699
  if (url.hash && url.pathname === window.location.pathname && url.search === window.location.search) return;
620
700
  if (options.shouldNavigate && !options.shouldNavigate(url, anchor)) return;
621
701
  event.preventDefault();
702
+ pendingTransitionMode = options.transition;
622
703
  ctx.router.navigate(url.pathname + url.search + url.hash, { replace: options.replace });
623
704
  };
624
705
  }
625
706
  function useNavigate() {
626
707
  const { router } = useRouter();
627
- return (to, options) => router.navigate(to, options);
708
+ return (to, options) => {
709
+ pendingTransitionMode = options?.transition;
710
+ router.navigate(to, options);
711
+ };
628
712
  }
629
713
  function useRouteData() {
630
714
  const acc = (0, import_signal15.useContext)(RouteDataContext2);
@@ -703,11 +787,12 @@ async function preloadRoutes(routes, pathname) {
703
787
  }
704
788
  await Promise.all(loads);
705
789
  }
706
- var import_signal14, import_dom16, import_signal15, import_object, import_compare, import_router, import_router2, import_signal16, RouterContext, OutletContext, LevelParamsContext, RouteDataContext2, _ssrRouterStub, read, LINK_OWN_PROPS, A;
790
+ var import_signal14, import_dom16, import_signal15, import_object, import_compare, import_router, import_router2, import_signal16, RouterContext, OutletContext, LevelParamsContext, RouteDataContext2, pendingTransitionMode, _ssrRouterStub, read, LINK_OWN_PROPS, A;
707
791
  var init_router = __esm({
708
792
  "src/lib/router/index.ts"() {
709
793
  "use strict";
710
794
  import_signal14 = require("@fluixi/reactive/signal");
795
+ init_transition();
711
796
  import_dom16 = require("@fluixi/dom");
712
797
  import_signal15 = require("@fluixi/reactive/signal");
713
798
  import_object = require("@fluixi/utils/object");
@@ -716,6 +801,7 @@ var init_router = __esm({
716
801
  import_router2 = require("@fluixi/router");
717
802
  init_data();
718
803
  init_lazy();
804
+ init_transition();
719
805
  import_signal16 = require("@fluixi/reactive/signal");
720
806
  RouterContext = (0, import_signal15.createContext)(void 0, "router");
721
807
  OutletContext = (0, import_signal15.createContext)(void 0, "outlet");
@@ -857,7 +943,7 @@ var import_signal6 = require("@fluixi/reactive/signal");
857
943
  var import_dom = require("@fluixi/dom");
858
944
 
859
945
  // src/version.generated.ts
860
- var VERSION = "1.0.0-alpha.84";
946
+ var VERSION = "1.0.0-alpha.85";
861
947
 
862
948
  // src/lib/render/versions.ts
863
949
  var import_dom2 = require("@fluixi/dom");
@@ -25,7 +25,7 @@ import {
25
25
  useProvide,
26
26
  useRouter,
27
27
  useSearchParams
28
- } from "./chunk-VNLCQBFQ.mjs";
28
+ } from "./chunk-MDJLC3PE.mjs";
29
29
 
30
30
  // src/lib/index.ts
31
31
  import {
@@ -59,7 +59,7 @@ import { createRoot as createRoot2 } from "@fluixi/reactive/signal";
59
59
  import { registerCoreVersion } from "@fluixi/dom";
60
60
 
61
61
  // src/version.generated.ts
62
- var VERSION = "1.0.0-alpha.84";
62
+ var VERSION = "1.0.0-alpha.85";
63
63
 
64
64
  // src/lib/render/versions.ts
65
65
  import { stampVersions, warnOnVersionSkew, versions } from "@fluixi/dom";
@@ -508,7 +508,7 @@ async function startClient(App, options = {}) {
508
508
  stripHeadMarker(container);
509
509
  if (shouldHydrate) {
510
510
  if (options.routes && options.routes.length) {
511
- const { preloadRoutes } = await import("./router-WMN2AA7E.mjs");
511
+ const { preloadRoutes } = await import("./router-JYFZP3EZ.mjs");
512
512
  await preloadRoutes(options.routes, window.location.pathname);
513
513
  }
514
514
  deserializeHydrationData();
@@ -13,10 +13,12 @@ import {
13
13
  lazy,
14
14
  matchPath,
15
15
  matchRoutes,
16
+ prefersReducedMotion,
16
17
  preloadRoutes,
17
18
  revalidate,
18
19
  runWithOwner,
19
20
  select,
21
+ supportsViewTransitions,
20
22
  useAction,
21
23
  useLevelParams,
22
24
  useLinkNavigation,
@@ -30,7 +32,7 @@ import {
30
32
  useRouter,
31
33
  useSearchParams,
32
34
  useSubmission
33
- } from "./chunk-VNLCQBFQ.mjs";
35
+ } from "./chunk-MDJLC3PE.mjs";
34
36
  export {
35
37
  A,
36
38
  Form,
@@ -46,10 +48,12 @@ export {
46
48
  lazy,
47
49
  matchPath,
48
50
  matchRoutes,
51
+ prefersReducedMotion,
49
52
  preloadRoutes,
50
53
  revalidate,
51
54
  runWithOwner,
52
55
  select,
56
+ supportsViewTransitions,
53
57
  useAction,
54
58
  useLevelParams,
55
59
  useLinkNavigation,
@@ -1,4 +1,4 @@
1
- /*! @fluixi/core v1.0.0-alpha.84 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/core v1.0.0-alpha.85 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -141,7 +141,7 @@ __export(index_exports, {
141
141
  module.exports = __toCommonJS(index_exports);
142
142
 
143
143
  // src/version.generated.ts
144
- var VERSION = "1.0.0-alpha.84";
144
+ var VERSION = "1.0.0-alpha.85";
145
145
 
146
146
  // src/lib/core.ts
147
147
  var import_signal15 = require("@fluixi/reactive/signal");
@@ -887,6 +887,56 @@ function createTheme(options) {
887
887
 
888
888
  // src/lib/router/index.ts
889
889
  var import_signal12 = require("@fluixi/reactive/signal");
890
+
891
+ // src/lib/router/transition.ts
892
+ function supportsViewTransitions() {
893
+ return typeof document !== "undefined" && typeof document.startViewTransition === "function";
894
+ }
895
+ function prefersReducedMotion() {
896
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
897
+ return false;
898
+ }
899
+ try {
900
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
901
+ } catch {
902
+ return false;
903
+ }
904
+ }
905
+ function shouldAnimate(mode) {
906
+ return mode !== "none" && supportsViewTransitions() && !prefersReducedMotion();
907
+ }
908
+ function prepareComponents(components) {
909
+ const pending = [];
910
+ for (const component of components) {
911
+ const preload = component?.preload;
912
+ if (typeof preload === "function") {
913
+ try {
914
+ const result = preload();
915
+ if (result && typeof result.then === "function") {
916
+ pending.push(result.catch(() => void 0));
917
+ }
918
+ } catch {
919
+ }
920
+ }
921
+ }
922
+ return pending.length ? Promise.all(pending).then(() => void 0) : null;
923
+ }
924
+ function runTransition(mode, commit) {
925
+ if (!shouldAnimate(mode)) {
926
+ return Promise.resolve(commit()).then(() => void 0);
927
+ }
928
+ const start = document.startViewTransition;
929
+ try {
930
+ const transition = start.call(document, () => commit());
931
+ transition.finished?.catch(() => void 0);
932
+ transition.ready?.catch(() => void 0);
933
+ return transition.updateCallbackDone.catch(() => void 0);
934
+ } catch {
935
+ return Promise.resolve(commit()).then(() => void 0);
936
+ }
937
+ }
938
+
939
+ // src/lib/router/index.ts
890
940
  var import_dom15 = require("@fluixi/dom");
891
941
  var import_signal13 = require("@fluixi/reactive/signal");
892
942
  var import_object = require("@fluixi/utils/object");
@@ -989,7 +1039,7 @@ function renderChild(ctx) {
989
1039
  );
990
1040
  (0, import_signal12.createEffect)(() => {
991
1041
  const c = ctx.matched()[childIdx]?.component;
992
- setChildComp(() => c);
1042
+ if ((0, import_signal12.untrack)(childComp) !== c) setChildComp(() => c);
993
1043
  });
994
1044
  return (0, import_signal12.createMemo)(() => {
995
1045
  const component = childComp();
@@ -1027,6 +1077,7 @@ function buildDefaultNotFound() {
1027
1077
  el.appendChild(p);
1028
1078
  return el;
1029
1079
  }
1080
+ var pendingTransitionMode;
1030
1081
  function Router(props) {
1031
1082
  const history = props.history ?? (0, import_router.createBrowserHistory)();
1032
1083
  const router = (0, import_router.createRouter)({
@@ -1035,10 +1086,35 @@ function Router(props) {
1035
1086
  history
1036
1087
  });
1037
1088
  const [state, setState] = (0, import_signal12.createSignal)(router.state());
1038
- const unsub = router.subscribe(setState);
1089
+ let navigationId = 0;
1090
+ const takeMode = () => {
1091
+ const mode = pendingTransitionMode ?? (props.transition ?? "auto");
1092
+ pendingTransitionMode = void 0;
1093
+ return mode;
1094
+ };
1095
+ const unsub = router.subscribe((next) => {
1096
+ const id = ++navigationId;
1097
+ const mode = takeMode();
1098
+ const prepared = prepareComponents(
1099
+ (next.match?.matched ?? []).map((m) => m.component).filter(Boolean)
1100
+ );
1101
+ const commit = () => {
1102
+ setState(next);
1103
+ return (0, import_signal12.flush)();
1104
+ };
1105
+ if (!prepared) {
1106
+ void runTransition(mode, commit);
1107
+ return;
1108
+ }
1109
+ void prepared.then(() => {
1110
+ if (id !== navigationId) return;
1111
+ return runTransition(mode, commit);
1112
+ });
1113
+ });
1039
1114
  (0, import_signal12.onCleanup)(() => {
1040
1115
  unsub();
1041
1116
  router.destroy();
1117
+ navigationId++;
1042
1118
  });
1043
1119
  const matched = (0, import_signal12.createMemo)(
1044
1120
  () => (state().match?.matched ?? []).filter((m) => m.component)
@@ -1093,7 +1169,10 @@ function useLocation() {
1093
1169
  }
1094
1170
  function useNavigate() {
1095
1171
  const { router } = useRouter();
1096
- return (to, options) => router.navigate(to, options);
1172
+ return (to, options) => {
1173
+ pendingTransitionMode = options?.transition;
1174
+ router.navigate(to, options);
1175
+ };
1097
1176
  }
1098
1177
  var read = (v) => typeof v === "function" ? v() : v;
1099
1178
  var LINK_OWN_PROPS = /* @__PURE__ */ new Set([
@@ -1,7 +1,7 @@
1
- /*! @fluixi/core v1.0.0-alpha.84 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/core v1.0.0-alpha.85 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
 
3
3
  // src/version.generated.ts
4
- var VERSION = "1.0.0-alpha.84";
4
+ var VERSION = "1.0.0-alpha.85";
5
5
 
6
6
  // src/lib/core.ts
7
7
  import {
@@ -820,8 +820,59 @@ import {
820
820
  createEffect as createEffect3,
821
821
  getOwner as getOwner2,
822
822
  onCleanup as onCleanup2,
823
- untrack as untrack3
823
+ untrack as untrack3,
824
+ flush
824
825
  } from "@fluixi/reactive/signal";
826
+
827
+ // src/lib/router/transition.ts
828
+ function supportsViewTransitions() {
829
+ return typeof document !== "undefined" && typeof document.startViewTransition === "function";
830
+ }
831
+ function prefersReducedMotion() {
832
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
833
+ return false;
834
+ }
835
+ try {
836
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
837
+ } catch {
838
+ return false;
839
+ }
840
+ }
841
+ function shouldAnimate(mode) {
842
+ return mode !== "none" && supportsViewTransitions() && !prefersReducedMotion();
843
+ }
844
+ function prepareComponents(components) {
845
+ const pending = [];
846
+ for (const component of components) {
847
+ const preload = component?.preload;
848
+ if (typeof preload === "function") {
849
+ try {
850
+ const result = preload();
851
+ if (result && typeof result.then === "function") {
852
+ pending.push(result.catch(() => void 0));
853
+ }
854
+ } catch {
855
+ }
856
+ }
857
+ }
858
+ return pending.length ? Promise.all(pending).then(() => void 0) : null;
859
+ }
860
+ function runTransition(mode, commit) {
861
+ if (!shouldAnimate(mode)) {
862
+ return Promise.resolve(commit()).then(() => void 0);
863
+ }
864
+ const start = document.startViewTransition;
865
+ try {
866
+ const transition = start.call(document, () => commit());
867
+ transition.finished?.catch(() => void 0);
868
+ transition.ready?.catch(() => void 0);
869
+ return transition.updateCallbackDone.catch(() => void 0);
870
+ } catch {
871
+ return Promise.resolve(commit()).then(() => void 0);
872
+ }
873
+ }
874
+
875
+ // src/lib/router/index.ts
825
876
  import {
826
877
  insert as insert2,
827
878
  createComponent as createComponent4,
@@ -942,7 +993,7 @@ function renderChild(ctx) {
942
993
  );
943
994
  createEffect3(() => {
944
995
  const c = ctx.matched()[childIdx]?.component;
945
- setChildComp(() => c);
996
+ if (untrack3(childComp) !== c) setChildComp(() => c);
946
997
  });
947
998
  return createMemo6(() => {
948
999
  const component = childComp();
@@ -980,6 +1031,7 @@ function buildDefaultNotFound() {
980
1031
  el.appendChild(p);
981
1032
  return el;
982
1033
  }
1034
+ var pendingTransitionMode;
983
1035
  function Router(props) {
984
1036
  const history = props.history ?? createBrowserHistory();
985
1037
  const router = createCoreRouter({
@@ -988,10 +1040,35 @@ function Router(props) {
988
1040
  history
989
1041
  });
990
1042
  const [state, setState] = createSignal7(router.state());
991
- const unsub = router.subscribe(setState);
1043
+ let navigationId = 0;
1044
+ const takeMode = () => {
1045
+ const mode = pendingTransitionMode ?? (props.transition ?? "auto");
1046
+ pendingTransitionMode = void 0;
1047
+ return mode;
1048
+ };
1049
+ const unsub = router.subscribe((next) => {
1050
+ const id = ++navigationId;
1051
+ const mode = takeMode();
1052
+ const prepared = prepareComponents(
1053
+ (next.match?.matched ?? []).map((m) => m.component).filter(Boolean)
1054
+ );
1055
+ const commit = () => {
1056
+ setState(next);
1057
+ return flush();
1058
+ };
1059
+ if (!prepared) {
1060
+ void runTransition(mode, commit);
1061
+ return;
1062
+ }
1063
+ void prepared.then(() => {
1064
+ if (id !== navigationId) return;
1065
+ return runTransition(mode, commit);
1066
+ });
1067
+ });
992
1068
  onCleanup2(() => {
993
1069
  unsub();
994
1070
  router.destroy();
1071
+ navigationId++;
995
1072
  });
996
1073
  const matched = createMemo6(
997
1074
  () => (state().match?.matched ?? []).filter((m) => m.component)
@@ -1046,7 +1123,10 @@ function useLocation() {
1046
1123
  }
1047
1124
  function useNavigate() {
1048
1125
  const { router } = useRouter();
1049
- return (to, options) => router.navigate(to, options);
1126
+ return (to, options) => {
1127
+ pendingTransitionMode = options?.transition;
1128
+ router.navigate(to, options);
1129
+ };
1050
1130
  }
1051
1131
  var read = (v) => typeof v === "function" ? v() : v;
1052
1132
  var LINK_OWN_PROPS = /* @__PURE__ */ new Set([
@@ -1,4 +1,4 @@
1
- /*! @fluixi/core v1.0.0-alpha.84 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/core v1.0.0-alpha.85 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
 
3
3
  // src/lib/server/hydration.ts
4
4
  import { isServer as domIsServer } from "@fluixi/dom";