@tanstack/solid-router 1.115.3 → 1.117.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const web = require("solid-js/web");
4
+ const Solid = require("solid-js");
5
+ function _interopNamespaceDefault(e) {
6
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
7
+ if (e) {
8
+ for (const k in e) {
9
+ if (k !== "default") {
10
+ const d = Object.getOwnPropertyDescriptor(e, k);
11
+ Object.defineProperty(n, k, d.get ? d : {
12
+ enumerable: true,
13
+ get: () => e[k]
14
+ });
15
+ }
16
+ }
17
+ }
18
+ n.default = e;
19
+ return Object.freeze(n);
20
+ }
21
+ const Solid__namespace = /* @__PURE__ */ _interopNamespaceDefault(Solid);
22
+ function ClientOnly(props) {
23
+ return useHydrated() ? web.memo(() => props.children) : web.memo(() => props.fallback);
24
+ }
25
+ function useHydrated() {
26
+ const [hydrated, setHydrated] = Solid__namespace.createSignal(!web.isServer);
27
+ if (!web.isServer) {
28
+ Solid__namespace.createEffect(() => {
29
+ setHydrated(true);
30
+ });
31
+ }
32
+ return hydrated;
33
+ }
34
+ exports.ClientOnly = ClientOnly;
35
+ exports.useHydrated = useHydrated;
36
+ //# sourceMappingURL=ClientOnly.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClientOnly.cjs","sources":["../../src/ClientOnly.tsx"],"sourcesContent":["import * as Solid from 'solid-js'\nimport { isServer } from 'solid-js/web'\n\nexport interface ClientOnlyProps {\n /**\n * The children to render if the JS is loaded.\n */\n children: Solid.JSX.Element\n /**\n * The fallback component to render if the JS is not yet loaded.\n */\n fallback?: Solid.JSX.Element\n}\n\n/**\n * Render the children only after the JS has loaded client-side. Use an optional\n * fallback component if the JS is not yet loaded.\n *\n * @example\n * Render a Chart component if JS loads, renders a simple FakeChart\n * component server-side or if there is no JS. The FakeChart can have only the\n * UI without the behavior or be a loading spinner or skeleton.\n *\n * ```tsx\n * return (\n * <ClientOnly fallback={<FakeChart />}>\n * <Chart />\n * </ClientOnly>\n * )\n * ```\n */\nexport function ClientOnly(props: ClientOnlyProps) {\n return useHydrated() ? <>{props.children}</> : <>{props.fallback}</>\n}\n\n/**\n * Return a boolean indicating if the JS has been hydrated already.\n * When doing Server-Side Rendering, the result will always be false.\n * When doing Client-Side Rendering, the result will always be false on the\n * first render and true from then on. Even if a new component renders it will\n * always start with true.\n *\n * @example\n * ```tsx\n * // Disable a button that needs JS to work.\n * let hydrated = useHydrated()\n * return (\n * <button type=\"button\" disabled={!hydrated()} onClick={doSomethingCustom}>\n * Click me\n * </button>\n * )\n * ```\n * @returns A signal accessor function that returns true if the JS has been hydrated already, false otherwise.\n */\nexport function useHydrated() {\n const [hydrated, setHydrated] = Solid.createSignal(!isServer)\n\n if (!isServer) {\n Solid.createEffect(() => {\n setHydrated(true)\n })\n }\n\n return hydrated\n}\n"],"names":["ClientOnly","props","useHydrated","_$memo","children","fallback","hydrated","setHydrated","Solid","createSignal","isServer","createEffect"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA+BO,SAASA,WAAWC,OAAwB;AAC1CC,SAAAA,YAAAA,IAAaC,IAAAA,KAAMF,MAAAA,MAAMG,QAAQ,IAAAD,IAAAA,KAAA,MAAUF,MAAMI,QAAQ;AAClE;AAqBO,SAASH,cAAc;AAC5B,QAAM,CAACI,UAAUC,WAAW,IAAIC,iBAAMC,aAAa,CAACC,YAAQ;AAE5D,MAAI,CAACA,IAAAA,UAAU;AACbF,qBAAMG,aAAa,MAAM;AACvBJ,kBAAY,IAAI;AAAA,IAAA,CACjB;AAAA,EAAA;AAGID,SAAAA;AACT;;;"}
@@ -0,0 +1,49 @@
1
+ import * as Solid from 'solid-js';
2
+ export interface ClientOnlyProps {
3
+ /**
4
+ * The children to render if the JS is loaded.
5
+ */
6
+ children: Solid.JSX.Element;
7
+ /**
8
+ * The fallback component to render if the JS is not yet loaded.
9
+ */
10
+ fallback?: Solid.JSX.Element;
11
+ }
12
+ /**
13
+ * Render the children only after the JS has loaded client-side. Use an optional
14
+ * fallback component if the JS is not yet loaded.
15
+ *
16
+ * @example
17
+ * Render a Chart component if JS loads, renders a simple FakeChart
18
+ * component server-side or if there is no JS. The FakeChart can have only the
19
+ * UI without the behavior or be a loading spinner or skeleton.
20
+ *
21
+ * ```tsx
22
+ * return (
23
+ * <ClientOnly fallback={<FakeChart />}>
24
+ * <Chart />
25
+ * </ClientOnly>
26
+ * )
27
+ * ```
28
+ */
29
+ export declare function ClientOnly(props: ClientOnlyProps): Solid.JSX.Element;
30
+ /**
31
+ * Return a boolean indicating if the JS has been hydrated already.
32
+ * When doing Server-Side Rendering, the result will always be false.
33
+ * When doing Client-Side Rendering, the result will always be false on the
34
+ * first render and true from then on. Even if a new component renders it will
35
+ * always start with true.
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * // Disable a button that needs JS to work.
40
+ * let hydrated = useHydrated()
41
+ * return (
42
+ * <button type="button" disabled={!hydrated()} onClick={doSomethingCustom}>
43
+ * Click me
44
+ * </button>
45
+ * )
46
+ * ```
47
+ * @returns A signal accessor function that returns true if the JS has been hydrated already, false otherwise.
48
+ */
49
+ export declare function useHydrated(): Solid.Accessor<boolean>;
@@ -6,6 +6,7 @@ const routerCore = require("@tanstack/router-core");
6
6
  const history = require("@tanstack/history");
7
7
  const awaited = require("./awaited.cjs");
8
8
  const CatchBoundary = require("./CatchBoundary.cjs");
9
+ const ClientOnly = require("./ClientOnly.cjs");
9
10
  const fileRoute = require("./fileRoute.cjs");
10
11
  const lazyRouteComponent = require("./lazyRouteComponent.cjs");
11
12
  const link = require("./link.cjs");
@@ -225,6 +226,7 @@ exports.Await = awaited.Await;
225
226
  exports.useAwaited = awaited.useAwaited;
226
227
  exports.CatchBoundary = CatchBoundary.CatchBoundary;
227
228
  exports.ErrorComponent = CatchBoundary.ErrorComponent;
229
+ exports.ClientOnly = ClientOnly.ClientOnly;
228
230
  exports.FileRoute = fileRoute.FileRoute;
229
231
  exports.FileRouteLoader = fileRoute.FileRouteLoader;
230
232
  exports.LazyRoute = fileRoute.LazyRoute;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -8,6 +8,7 @@ export type { BlockerFn, HistoryLocation, RouterHistory, ParsedPath, HistoryStat
8
8
  export { useAwaited, Await } from './awaited.cjs';
9
9
  export type { AwaitOptions } from './awaited.cjs';
10
10
  export { CatchBoundary, ErrorComponent } from './CatchBoundary.cjs';
11
+ export { ClientOnly } from './ClientOnly.cjs';
11
12
  export { FileRoute, createFileRoute, FileRouteLoader, LazyRoute, createLazyRoute, createLazyFileRoute, } from './fileRoute.cjs';
12
13
  export * from './history.cjs';
13
14
  export { lazyRouteComponent } from './lazyRouteComponent.cjs';
@@ -3,15 +3,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const web = require("solid-js/web");
4
4
  const Solid = require("solid-js");
5
5
  const Match = require("./Match.cjs");
6
+ const ClientOnly = require("./ClientOnly.cjs");
6
7
  function isModuleNotFoundError(error) {
7
8
  return typeof (error == null ? void 0 : error.message) === "string" && /Failed to fetch dynamically imported module/.test(error.message);
8
9
  }
9
- function ClientOnly(props) {
10
- return useHydrated() ? web.memo(() => props.children) : web.memo(() => props.fallback);
11
- }
12
- function useHydrated() {
13
- return web.isServer;
14
- }
15
10
  function lazyRouteComponent(importer, exportName, ssr) {
16
11
  let loadPromise;
17
12
  let comp;
@@ -56,7 +51,7 @@ function lazyRouteComponent(importer, exportName, ssr) {
56
51
  return web.memo(compResource);
57
52
  }
58
53
  if ((ssr == null ? void 0 : ssr()) === false) {
59
- return web.createComponent(ClientOnly, {
54
+ return web.createComponent(ClientOnly.ClientOnly, {
60
55
  get fallback() {
61
56
  return web.createComponent(Match.Outlet, {});
62
57
  },
@@ -74,7 +69,5 @@ function lazyRouteComponent(importer, exportName, ssr) {
74
69
  lazyComp.preload = load;
75
70
  return lazyComp;
76
71
  }
77
- exports.ClientOnly = ClientOnly;
78
72
  exports.lazyRouteComponent = lazyRouteComponent;
79
- exports.useHydrated = useHydrated;
80
73
  //# sourceMappingURL=lazyRouteComponent.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"lazyRouteComponent.cjs","sources":["../../src/lazyRouteComponent.tsx"],"sourcesContent":["import { Dynamic, isServer } from 'solid-js/web'\nimport { createResource } from 'solid-js'\nimport { Outlet } from './Match'\nimport type * as Solid from 'solid-js'\nimport type { AsyncRouteComponent } from './route'\n\n// If the load fails due to module not found, it may mean a new version of\n// the build was deployed and the user's browser is still using an old version.\n// If this happens, the old version in the user's browser would have an outdated\n// URL to the lazy module.\n// In that case, we want to attempt one window refresh to get the latest.\nfunction isModuleNotFoundError(error: any): boolean {\n return (\n typeof error?.message === 'string' &&\n /Failed to fetch dynamically imported module/.test(error.message)\n )\n}\n\nexport function ClientOnly(\n props: Solid.ParentProps<{ fallback?: Solid.JSX.Element }>,\n) {\n return useHydrated() ? <>{props.children}</> : <>{props.fallback}</>\n}\n\nexport function useHydrated() {\n return isServer\n}\n\nexport function lazyRouteComponent<\n T extends Record<string, any>,\n TKey extends keyof T = 'default',\n>(\n importer: () => Promise<T>,\n exportName?: TKey,\n ssr?: () => boolean,\n): T[TKey] extends (props: infer TProps) => any\n ? AsyncRouteComponent<TProps>\n : never {\n let loadPromise: Promise<any> | undefined\n let comp: T[TKey] | T['default']\n let error: any\n\n const load = () => {\n if (typeof document === 'undefined' && ssr?.() === false) {\n comp = (() => null) as any\n return Promise.resolve(comp)\n }\n if (!loadPromise) {\n loadPromise = importer()\n .then((res) => {\n loadPromise = undefined\n comp = res[exportName ?? 'default']\n return comp\n })\n .catch((err) => {\n error = err\n })\n }\n\n return loadPromise\n }\n\n const lazyComp = function Lazy(props: any) {\n // Now that we're out of preload and into actual render path,\n // throw the error if it was a module not found error during preload\n if (error) {\n if (isModuleNotFoundError(error)) {\n // We don't want an error thrown from preload in this case, because\n // there's nothing we want to do about module not found during preload.\n // Record the error, recover the promise with a null return,\n // and we will attempt module not found resolution during the render path.\n\n if (\n error instanceof Error &&\n typeof window !== 'undefined' &&\n typeof sessionStorage !== 'undefined'\n ) {\n // Again, we want to reload one time on module not found error and not enter\n // a reload loop if there is some other issue besides an old deploy.\n // That's why we store our reload attempt in sessionStorage.\n // Use error.message as key because it contains the module path that failed.\n const storageKey = `tanstack_router_reload:${error.message}`\n if (!sessionStorage.getItem(storageKey)) {\n sessionStorage.setItem(storageKey, '1')\n window.location.reload()\n\n // Return empty component while we wait for window to reload\n return {\n default: () => null,\n }\n }\n }\n }\n\n // Otherwise, just throw the error\n throw error\n }\n\n if (!comp) {\n const [compResource] = createResource(load, {\n initialValue: comp,\n ssrLoadFrom: 'initial',\n })\n return <>{compResource()}</>\n }\n\n if (ssr?.() === false) {\n return (\n <ClientOnly fallback={<Outlet />}>\n <Dynamic component={comp} {...props} />\n </ClientOnly>\n )\n }\n return <Dynamic component={comp} {...props} />\n }\n\n ;(lazyComp as any).preload = load\n\n return lazyComp as any\n}\n"],"names":["isModuleNotFoundError","error","message","test","ClientOnly","props","useHydrated","_$memo","children","fallback","isServer","lazyRouteComponent","importer","exportName","ssr","loadPromise","comp","load","document","Promise","resolve","then","res","undefined","catch","err","lazyComp","Lazy","Error","window","sessionStorage","storageKey","getItem","setItem","location","reload","default","compResource","createResource","initialValue","ssrLoadFrom","_$createComponent","Outlet","Dynamic","_$mergeProps","component","preload"],"mappings":";;;;;AAWA,SAASA,sBAAsBC,OAAqB;AAClD,SACE,QAAOA,+BAAOC,aAAY,YAC1B,8CAA8CC,KAAKF,MAAMC,OAAO;AAEpE;AAEO,SAASE,WACdC,OACA;AACOC,SAAAA,YAAAA,IAAaC,IAAAA,KAAMF,MAAAA,MAAMG,QAAQ,IAAAD,IAAAA,KAAA,MAAUF,MAAMI,QAAQ;AAClE;AAEO,SAASH,cAAc;AACrBI,SAAAA,IAAAA;AACT;AAEgBC,SAAAA,mBAIdC,UACAC,YACAC,KAGQ;AACJC,MAAAA;AACAC,MAAAA;AACAf,MAAAA;AAEJ,QAAMgB,OAAOA,MAAM;AACjB,QAAI,OAAOC,aAAa,gBAAeJ,kCAAY,OAAO;AACxDE,aAAQ,MAAM;AACPG,aAAAA,QAAQC,QAAQJ,IAAI;AAAA,IAAA;AAE7B,QAAI,CAACD,aAAa;AACFH,oBAAAA,SAAAA,EACXS,KAAMC,CAAQ,QAAA;AACCC,sBAAAA;AACPD,eAAAA,IAAIT,cAAc,SAAS;AAC3BG,eAAAA;AAAAA,MAAAA,CACR,EACAQ,MAAOC,CAAQ,QAAA;AACNA,gBAAAA;AAAAA,MAAAA,CACT;AAAA,IAAA;AAGEV,WAAAA;AAAAA,EACT;AAEMW,QAAAA,WAAW,SAASC,KAAKtB,OAAY;AAGzC,QAAIJ,OAAO;AACLD,UAAAA,sBAAsBC,KAAK,GAAG;AAMhC,YACEA,iBAAiB2B,SACjB,OAAOC,WAAW,eAClB,OAAOC,mBAAmB,aAC1B;AAKMC,gBAAAA,aAAa,0BAA0B9B,MAAMC,OAAO;AAC1D,cAAI,CAAC4B,eAAeE,QAAQD,UAAU,GAAG;AACxBE,2BAAAA,QAAQF,YAAY,GAAG;AACtCF,mBAAOK,SAASC,OAAO;AAGhB,mBAAA;AAAA,cACLC,SAASA,MAAM;AAAA,YACjB;AAAA,UAAA;AAAA,QACF;AAAA,MACF;AAIInC,YAAAA;AAAAA,IAAAA;AAGR,QAAI,CAACe,MAAM;AACT,YAAM,CAACqB,YAAY,IAAIC,MAAAA,eAAerB,MAAM;AAAA,QAC1CsB,cAAcvB;AAAAA,QACdwB,aAAa;AAAA,MAAA,CACd;AACD,aAAAjC,IAAAA,KAAU8B,YAAY;AAAA,IAAA;AAGpBvB,SAAAA,kCAAY,OAAO;AACrB,aAAA2B,IAAAA,gBACGrC,YAAU;AAAA,QAAA,IAACK,WAAQ;AAAAgC,iBAAAA,IAAAA,gBAAGC,MAAM,QAAA,EAAA;AAAA,QAAA;AAAA,QAAA,IAAAlC,WAAA;AAAAiC,iBAAAA,IAAAA,gBAC1BE,aAAOC,eAAA;AAAA,YAACC,WAAW7B;AAAAA,UAAI,GAAMX,KAAK,CAAA;AAAA,QAAA;AAAA,MAAA,CAAA;AAAA,IAAA;AAIzCoC,WAAAA,IAAAA,gBAAQE,aAAOC,eAAA;AAAA,MAACC,WAAW7B;AAAAA,IAAI,GAAMX,KAAK,CAAA;AAAA,EAC5C;AAEEqB,WAAiBoB,UAAU7B;AAEtBS,SAAAA;AACT;;;;"}
1
+ {"version":3,"file":"lazyRouteComponent.cjs","sources":["../../src/lazyRouteComponent.tsx"],"sourcesContent":["import { Dynamic } from 'solid-js/web'\nimport { createResource } from 'solid-js'\nimport { Outlet } from './Match'\nimport { ClientOnly } from './ClientOnly'\nimport type { AsyncRouteComponent } from './route'\n\n// If the load fails due to module not found, it may mean a new version of\n// the build was deployed and the user's browser is still using an old version.\n// If this happens, the old version in the user's browser would have an outdated\n// URL to the lazy module.\n// In that case, we want to attempt one window refresh to get the latest.\nfunction isModuleNotFoundError(error: any): boolean {\n return (\n typeof error?.message === 'string' &&\n /Failed to fetch dynamically imported module/.test(error.message)\n )\n}\n\nexport function lazyRouteComponent<\n T extends Record<string, any>,\n TKey extends keyof T = 'default',\n>(\n importer: () => Promise<T>,\n exportName?: TKey,\n ssr?: () => boolean,\n): T[TKey] extends (props: infer TProps) => any\n ? AsyncRouteComponent<TProps>\n : never {\n let loadPromise: Promise<any> | undefined\n let comp: T[TKey] | T['default']\n let error: any\n\n const load = () => {\n if (typeof document === 'undefined' && ssr?.() === false) {\n comp = (() => null) as any\n return Promise.resolve(comp)\n }\n if (!loadPromise) {\n loadPromise = importer()\n .then((res) => {\n loadPromise = undefined\n comp = res[exportName ?? 'default']\n return comp\n })\n .catch((err) => {\n error = err\n })\n }\n\n return loadPromise\n }\n\n const lazyComp = function Lazy(props: any) {\n // Now that we're out of preload and into actual render path,\n // throw the error if it was a module not found error during preload\n if (error) {\n if (isModuleNotFoundError(error)) {\n // We don't want an error thrown from preload in this case, because\n // there's nothing we want to do about module not found during preload.\n // Record the error, recover the promise with a null return,\n // and we will attempt module not found resolution during the render path.\n\n if (\n error instanceof Error &&\n typeof window !== 'undefined' &&\n typeof sessionStorage !== 'undefined'\n ) {\n // Again, we want to reload one time on module not found error and not enter\n // a reload loop if there is some other issue besides an old deploy.\n // That's why we store our reload attempt in sessionStorage.\n // Use error.message as key because it contains the module path that failed.\n const storageKey = `tanstack_router_reload:${error.message}`\n if (!sessionStorage.getItem(storageKey)) {\n sessionStorage.setItem(storageKey, '1')\n window.location.reload()\n\n // Return empty component while we wait for window to reload\n return {\n default: () => null,\n }\n }\n }\n }\n\n // Otherwise, just throw the error\n throw error\n }\n\n if (!comp) {\n const [compResource] = createResource(load, {\n initialValue: comp,\n ssrLoadFrom: 'initial',\n })\n return <>{compResource()}</>\n }\n\n if (ssr?.() === false) {\n return (\n <ClientOnly fallback={<Outlet />}>\n <Dynamic component={comp} {...props} />\n </ClientOnly>\n )\n }\n return <Dynamic component={comp} {...props} />\n }\n\n ;(lazyComp as any).preload = load\n\n return lazyComp as any\n}\n"],"names":["isModuleNotFoundError","error","message","test","lazyRouteComponent","importer","exportName","ssr","loadPromise","comp","load","document","Promise","resolve","then","res","undefined","catch","err","lazyComp","Lazy","props","Error","window","sessionStorage","storageKey","getItem","setItem","location","reload","default","compResource","createResource","initialValue","ssrLoadFrom","_$memo","_$createComponent","ClientOnly","fallback","Outlet","children","Dynamic","_$mergeProps","component","preload"],"mappings":";;;;;;AAWA,SAASA,sBAAsBC,OAAqB;AAClD,SACE,QAAOA,+BAAOC,aAAY,YAC1B,8CAA8CC,KAAKF,MAAMC,OAAO;AAEpE;AAEgBE,SAAAA,mBAIdC,UACAC,YACAC,KAGQ;AACJC,MAAAA;AACAC,MAAAA;AACAR,MAAAA;AAEJ,QAAMS,OAAOA,MAAM;AACjB,QAAI,OAAOC,aAAa,gBAAeJ,kCAAY,OAAO;AACxDE,aAAQ,MAAM;AACPG,aAAAA,QAAQC,QAAQJ,IAAI;AAAA,IAAA;AAE7B,QAAI,CAACD,aAAa;AACFH,oBAAAA,SAAAA,EACXS,KAAMC,CAAQ,QAAA;AACCC,sBAAAA;AACPD,eAAAA,IAAIT,cAAc,SAAS;AAC3BG,eAAAA;AAAAA,MAAAA,CACR,EACAQ,MAAOC,CAAQ,QAAA;AACNA,gBAAAA;AAAAA,MAAAA,CACT;AAAA,IAAA;AAGEV,WAAAA;AAAAA,EACT;AAEMW,QAAAA,WAAW,SAASC,KAAKC,OAAY;AAGzC,QAAIpB,OAAO;AACLD,UAAAA,sBAAsBC,KAAK,GAAG;AAMhC,YACEA,iBAAiBqB,SACjB,OAAOC,WAAW,eAClB,OAAOC,mBAAmB,aAC1B;AAKMC,gBAAAA,aAAa,0BAA0BxB,MAAMC,OAAO;AAC1D,cAAI,CAACsB,eAAeE,QAAQD,UAAU,GAAG;AACxBE,2BAAAA,QAAQF,YAAY,GAAG;AACtCF,mBAAOK,SAASC,OAAO;AAGhB,mBAAA;AAAA,cACLC,SAASA,MAAM;AAAA,YACjB;AAAA,UAAA;AAAA,QACF;AAAA,MACF;AAII7B,YAAAA;AAAAA,IAAAA;AAGR,QAAI,CAACQ,MAAM;AACT,YAAM,CAACsB,YAAY,IAAIC,MAAAA,eAAetB,MAAM;AAAA,QAC1CuB,cAAcxB;AAAAA,QACdyB,aAAa;AAAA,MAAA,CACd;AACD,aAAAC,IAAAA,KAAUJ,YAAY;AAAA,IAAA;AAGpBxB,SAAAA,kCAAY,OAAO;AACrB,aAAA6B,IAAAA,gBACGC,WAAAA,YAAU;AAAA,QAAA,IAACC,WAAQ;AAAAF,iBAAAA,IAAAA,gBAAGG,MAAM,QAAA,EAAA;AAAA,QAAA;AAAA,QAAA,IAAAC,WAAA;AAAAJ,iBAAAA,IAAAA,gBAC1BK,aAAOC,eAAA;AAAA,YAACC,WAAWlC;AAAAA,UAAI,GAAMY,KAAK,CAAA;AAAA,QAAA;AAAA,MAAA,CAAA;AAAA,IAAA;AAIzCe,WAAAA,IAAAA,gBAAQK,aAAOC,eAAA;AAAA,MAACC,WAAWlC;AAAAA,IAAI,GAAMY,KAAK,CAAA;AAAA,EAC5C;AAEEF,WAAiByB,UAAUlC;AAEtBS,SAAAA;AACT;;"}
@@ -1,7 +1,2 @@
1
1
  import { AsyncRouteComponent } from './route.cjs';
2
- import type * as Solid from 'solid-js';
3
- export declare function ClientOnly(props: Solid.ParentProps<{
4
- fallback?: Solid.JSX.Element;
5
- }>): Solid.JSX.Element;
6
- export declare function useHydrated(): boolean;
7
2
  export declare function lazyRouteComponent<T extends Record<string, any>, TKey extends keyof T = 'default'>(importer: () => Promise<T>, exportName?: TKey, ssr?: () => boolean): T[TKey] extends (props: infer TProps) => any ? AsyncRouteComponent<TProps> : never;
@@ -0,0 +1,49 @@
1
+ import * as Solid from 'solid-js';
2
+ export interface ClientOnlyProps {
3
+ /**
4
+ * The children to render if the JS is loaded.
5
+ */
6
+ children: Solid.JSX.Element;
7
+ /**
8
+ * The fallback component to render if the JS is not yet loaded.
9
+ */
10
+ fallback?: Solid.JSX.Element;
11
+ }
12
+ /**
13
+ * Render the children only after the JS has loaded client-side. Use an optional
14
+ * fallback component if the JS is not yet loaded.
15
+ *
16
+ * @example
17
+ * Render a Chart component if JS loads, renders a simple FakeChart
18
+ * component server-side or if there is no JS. The FakeChart can have only the
19
+ * UI without the behavior or be a loading spinner or skeleton.
20
+ *
21
+ * ```tsx
22
+ * return (
23
+ * <ClientOnly fallback={<FakeChart />}>
24
+ * <Chart />
25
+ * </ClientOnly>
26
+ * )
27
+ * ```
28
+ */
29
+ export declare function ClientOnly(props: ClientOnlyProps): Solid.JSX.Element;
30
+ /**
31
+ * Return a boolean indicating if the JS has been hydrated already.
32
+ * When doing Server-Side Rendering, the result will always be false.
33
+ * When doing Client-Side Rendering, the result will always be false on the
34
+ * first render and true from then on. Even if a new component renders it will
35
+ * always start with true.
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * // Disable a button that needs JS to work.
40
+ * let hydrated = useHydrated()
41
+ * return (
42
+ * <button type="button" disabled={!hydrated()} onClick={doSomethingCustom}>
43
+ * Click me
44
+ * </button>
45
+ * )
46
+ * ```
47
+ * @returns A signal accessor function that returns true if the JS has been hydrated already, false otherwise.
48
+ */
49
+ export declare function useHydrated(): Solid.Accessor<boolean>;
@@ -0,0 +1,19 @@
1
+ import { memo, isServer } from "solid-js/web";
2
+ import * as Solid from "solid-js";
3
+ function ClientOnly(props) {
4
+ return useHydrated() ? memo(() => props.children) : memo(() => props.fallback);
5
+ }
6
+ function useHydrated() {
7
+ const [hydrated, setHydrated] = Solid.createSignal(!isServer);
8
+ if (!isServer) {
9
+ Solid.createEffect(() => {
10
+ setHydrated(true);
11
+ });
12
+ }
13
+ return hydrated;
14
+ }
15
+ export {
16
+ ClientOnly,
17
+ useHydrated
18
+ };
19
+ //# sourceMappingURL=ClientOnly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClientOnly.js","sources":["../../src/ClientOnly.tsx"],"sourcesContent":["import * as Solid from 'solid-js'\nimport { isServer } from 'solid-js/web'\n\nexport interface ClientOnlyProps {\n /**\n * The children to render if the JS is loaded.\n */\n children: Solid.JSX.Element\n /**\n * The fallback component to render if the JS is not yet loaded.\n */\n fallback?: Solid.JSX.Element\n}\n\n/**\n * Render the children only after the JS has loaded client-side. Use an optional\n * fallback component if the JS is not yet loaded.\n *\n * @example\n * Render a Chart component if JS loads, renders a simple FakeChart\n * component server-side or if there is no JS. The FakeChart can have only the\n * UI without the behavior or be a loading spinner or skeleton.\n *\n * ```tsx\n * return (\n * <ClientOnly fallback={<FakeChart />}>\n * <Chart />\n * </ClientOnly>\n * )\n * ```\n */\nexport function ClientOnly(props: ClientOnlyProps) {\n return useHydrated() ? <>{props.children}</> : <>{props.fallback}</>\n}\n\n/**\n * Return a boolean indicating if the JS has been hydrated already.\n * When doing Server-Side Rendering, the result will always be false.\n * When doing Client-Side Rendering, the result will always be false on the\n * first render and true from then on. Even if a new component renders it will\n * always start with true.\n *\n * @example\n * ```tsx\n * // Disable a button that needs JS to work.\n * let hydrated = useHydrated()\n * return (\n * <button type=\"button\" disabled={!hydrated()} onClick={doSomethingCustom}>\n * Click me\n * </button>\n * )\n * ```\n * @returns A signal accessor function that returns true if the JS has been hydrated already, false otherwise.\n */\nexport function useHydrated() {\n const [hydrated, setHydrated] = Solid.createSignal(!isServer)\n\n if (!isServer) {\n Solid.createEffect(() => {\n setHydrated(true)\n })\n }\n\n return hydrated\n}\n"],"names":["ClientOnly","props","useHydrated","_$memo","children","fallback","hydrated","setHydrated","Solid","createSignal","isServer","createEffect"],"mappings":";;AA+BO,SAASA,WAAWC,OAAwB;AAC1CC,SAAAA,YAAAA,IAAaC,KAAMF,MAAAA,MAAMG,QAAQ,IAAAD,KAAA,MAAUF,MAAMI,QAAQ;AAClE;AAqBO,SAASH,cAAc;AAC5B,QAAM,CAACI,UAAUC,WAAW,IAAIC,MAAMC,aAAa,CAACC,QAAQ;AAE5D,MAAI,CAACA,UAAU;AACbF,UAAMG,aAAa,MAAM;AACvBJ,kBAAY,IAAI;AAAA,IAAA,CACjB;AAAA,EAAA;AAGID,SAAAA;AACT;"}
@@ -8,6 +8,7 @@ export type { BlockerFn, HistoryLocation, RouterHistory, ParsedPath, HistoryStat
8
8
  export { useAwaited, Await } from './awaited.js';
9
9
  export type { AwaitOptions } from './awaited.js';
10
10
  export { CatchBoundary, ErrorComponent } from './CatchBoundary.js';
11
+ export { ClientOnly } from './ClientOnly.js';
11
12
  export { FileRoute, createFileRoute, FileRouteLoader, LazyRoute, createLazyRoute, createLazyFileRoute, } from './fileRoute.js';
12
13
  export * from './history.js';
13
14
  export { lazyRouteComponent } from './lazyRouteComponent.js';
package/dist/esm/index.js CHANGED
@@ -4,6 +4,7 @@ import { PathParamError, SearchParamError, TSR_DEFERRED_PROMISE, cleanPath, comp
4
4
  import { createBrowserHistory, createHashHistory, createHistory, createMemoryHistory } from "@tanstack/history";
5
5
  import { Await, useAwaited } from "./awaited.js";
6
6
  import { CatchBoundary, ErrorComponent } from "./CatchBoundary.js";
7
+ import { ClientOnly } from "./ClientOnly.js";
7
8
  import { FileRoute, FileRouteLoader, LazyRoute, createFileRoute, createLazyFileRoute, createLazyRoute } from "./fileRoute.js";
8
9
  import { lazyRouteComponent } from "./lazyRouteComponent.js";
9
10
  import { Link, createLink, linkOptions, useLinkProps } from "./link.js";
@@ -39,6 +40,7 @@ export {
39
40
  Block,
40
41
  CatchBoundary,
41
42
  CatchNotFound,
43
+ ClientOnly,
42
44
  DefaultGlobalNotFound,
43
45
  ErrorComponent,
44
46
  FileRoute,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,7 +1,2 @@
1
1
  import { AsyncRouteComponent } from './route.js';
2
- import type * as Solid from 'solid-js';
3
- export declare function ClientOnly(props: Solid.ParentProps<{
4
- fallback?: Solid.JSX.Element;
5
- }>): Solid.JSX.Element;
6
- export declare function useHydrated(): boolean;
7
2
  export declare function lazyRouteComponent<T extends Record<string, any>, TKey extends keyof T = 'default'>(importer: () => Promise<T>, exportName?: TKey, ssr?: () => boolean): T[TKey] extends (props: infer TProps) => any ? AsyncRouteComponent<TProps> : never;
@@ -1,15 +1,10 @@
1
- import { memo, createComponent, Dynamic, mergeProps, isServer } from "solid-js/web";
1
+ import { memo, createComponent, Dynamic, mergeProps } from "solid-js/web";
2
2
  import { createResource } from "solid-js";
3
3
  import { Outlet } from "./Match.js";
4
+ import { ClientOnly } from "./ClientOnly.js";
4
5
  function isModuleNotFoundError(error) {
5
6
  return typeof (error == null ? void 0 : error.message) === "string" && /Failed to fetch dynamically imported module/.test(error.message);
6
7
  }
7
- function ClientOnly(props) {
8
- return useHydrated() ? memo(() => props.children) : memo(() => props.fallback);
9
- }
10
- function useHydrated() {
11
- return isServer;
12
- }
13
8
  function lazyRouteComponent(importer, exportName, ssr) {
14
9
  let loadPromise;
15
10
  let comp;
@@ -73,8 +68,6 @@ function lazyRouteComponent(importer, exportName, ssr) {
73
68
  return lazyComp;
74
69
  }
75
70
  export {
76
- ClientOnly,
77
- lazyRouteComponent,
78
- useHydrated
71
+ lazyRouteComponent
79
72
  };
80
73
  //# sourceMappingURL=lazyRouteComponent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lazyRouteComponent.js","sources":["../../src/lazyRouteComponent.tsx"],"sourcesContent":["import { Dynamic, isServer } from 'solid-js/web'\nimport { createResource } from 'solid-js'\nimport { Outlet } from './Match'\nimport type * as Solid from 'solid-js'\nimport type { AsyncRouteComponent } from './route'\n\n// If the load fails due to module not found, it may mean a new version of\n// the build was deployed and the user's browser is still using an old version.\n// If this happens, the old version in the user's browser would have an outdated\n// URL to the lazy module.\n// In that case, we want to attempt one window refresh to get the latest.\nfunction isModuleNotFoundError(error: any): boolean {\n return (\n typeof error?.message === 'string' &&\n /Failed to fetch dynamically imported module/.test(error.message)\n )\n}\n\nexport function ClientOnly(\n props: Solid.ParentProps<{ fallback?: Solid.JSX.Element }>,\n) {\n return useHydrated() ? <>{props.children}</> : <>{props.fallback}</>\n}\n\nexport function useHydrated() {\n return isServer\n}\n\nexport function lazyRouteComponent<\n T extends Record<string, any>,\n TKey extends keyof T = 'default',\n>(\n importer: () => Promise<T>,\n exportName?: TKey,\n ssr?: () => boolean,\n): T[TKey] extends (props: infer TProps) => any\n ? AsyncRouteComponent<TProps>\n : never {\n let loadPromise: Promise<any> | undefined\n let comp: T[TKey] | T['default']\n let error: any\n\n const load = () => {\n if (typeof document === 'undefined' && ssr?.() === false) {\n comp = (() => null) as any\n return Promise.resolve(comp)\n }\n if (!loadPromise) {\n loadPromise = importer()\n .then((res) => {\n loadPromise = undefined\n comp = res[exportName ?? 'default']\n return comp\n })\n .catch((err) => {\n error = err\n })\n }\n\n return loadPromise\n }\n\n const lazyComp = function Lazy(props: any) {\n // Now that we're out of preload and into actual render path,\n // throw the error if it was a module not found error during preload\n if (error) {\n if (isModuleNotFoundError(error)) {\n // We don't want an error thrown from preload in this case, because\n // there's nothing we want to do about module not found during preload.\n // Record the error, recover the promise with a null return,\n // and we will attempt module not found resolution during the render path.\n\n if (\n error instanceof Error &&\n typeof window !== 'undefined' &&\n typeof sessionStorage !== 'undefined'\n ) {\n // Again, we want to reload one time on module not found error and not enter\n // a reload loop if there is some other issue besides an old deploy.\n // That's why we store our reload attempt in sessionStorage.\n // Use error.message as key because it contains the module path that failed.\n const storageKey = `tanstack_router_reload:${error.message}`\n if (!sessionStorage.getItem(storageKey)) {\n sessionStorage.setItem(storageKey, '1')\n window.location.reload()\n\n // Return empty component while we wait for window to reload\n return {\n default: () => null,\n }\n }\n }\n }\n\n // Otherwise, just throw the error\n throw error\n }\n\n if (!comp) {\n const [compResource] = createResource(load, {\n initialValue: comp,\n ssrLoadFrom: 'initial',\n })\n return <>{compResource()}</>\n }\n\n if (ssr?.() === false) {\n return (\n <ClientOnly fallback={<Outlet />}>\n <Dynamic component={comp} {...props} />\n </ClientOnly>\n )\n }\n return <Dynamic component={comp} {...props} />\n }\n\n ;(lazyComp as any).preload = load\n\n return lazyComp as any\n}\n"],"names":["isModuleNotFoundError","error","message","test","ClientOnly","props","useHydrated","_$memo","children","fallback","isServer","lazyRouteComponent","importer","exportName","ssr","loadPromise","comp","load","document","Promise","resolve","then","res","undefined","catch","err","lazyComp","Lazy","Error","window","sessionStorage","storageKey","getItem","setItem","location","reload","default","compResource","createResource","initialValue","ssrLoadFrom","_$createComponent","Outlet","Dynamic","_$mergeProps","component","preload"],"mappings":";;;AAWA,SAASA,sBAAsBC,OAAqB;AAClD,SACE,QAAOA,+BAAOC,aAAY,YAC1B,8CAA8CC,KAAKF,MAAMC,OAAO;AAEpE;AAEO,SAASE,WACdC,OACA;AACOC,SAAAA,YAAAA,IAAaC,KAAMF,MAAAA,MAAMG,QAAQ,IAAAD,KAAA,MAAUF,MAAMI,QAAQ;AAClE;AAEO,SAASH,cAAc;AACrBI,SAAAA;AACT;AAEgBC,SAAAA,mBAIdC,UACAC,YACAC,KAGQ;AACJC,MAAAA;AACAC,MAAAA;AACAf,MAAAA;AAEJ,QAAMgB,OAAOA,MAAM;AACjB,QAAI,OAAOC,aAAa,gBAAeJ,kCAAY,OAAO;AACxDE,aAAQ,MAAM;AACPG,aAAAA,QAAQC,QAAQJ,IAAI;AAAA,IAAA;AAE7B,QAAI,CAACD,aAAa;AACFH,oBAAAA,SAAAA,EACXS,KAAMC,CAAQ,QAAA;AACCC,sBAAAA;AACPD,eAAAA,IAAIT,cAAc,SAAS;AAC3BG,eAAAA;AAAAA,MAAAA,CACR,EACAQ,MAAOC,CAAQ,QAAA;AACNA,gBAAAA;AAAAA,MAAAA,CACT;AAAA,IAAA;AAGEV,WAAAA;AAAAA,EACT;AAEMW,QAAAA,WAAW,SAASC,KAAKtB,OAAY;AAGzC,QAAIJ,OAAO;AACLD,UAAAA,sBAAsBC,KAAK,GAAG;AAMhC,YACEA,iBAAiB2B,SACjB,OAAOC,WAAW,eAClB,OAAOC,mBAAmB,aAC1B;AAKMC,gBAAAA,aAAa,0BAA0B9B,MAAMC,OAAO;AAC1D,cAAI,CAAC4B,eAAeE,QAAQD,UAAU,GAAG;AACxBE,2BAAAA,QAAQF,YAAY,GAAG;AACtCF,mBAAOK,SAASC,OAAO;AAGhB,mBAAA;AAAA,cACLC,SAASA,MAAM;AAAA,YACjB;AAAA,UAAA;AAAA,QACF;AAAA,MACF;AAIInC,YAAAA;AAAAA,IAAAA;AAGR,QAAI,CAACe,MAAM;AACT,YAAM,CAACqB,YAAY,IAAIC,eAAerB,MAAM;AAAA,QAC1CsB,cAAcvB;AAAAA,QACdwB,aAAa;AAAA,MAAA,CACd;AACD,aAAAjC,KAAU8B,YAAY;AAAA,IAAA;AAGpBvB,SAAAA,kCAAY,OAAO;AACrB,aAAA2B,gBACGrC,YAAU;AAAA,QAAA,IAACK,WAAQ;AAAAgC,iBAAAA,gBAAGC,QAAM,EAAA;AAAA,QAAA;AAAA,QAAA,IAAAlC,WAAA;AAAAiC,iBAAAA,gBAC1BE,SAAOC,WAAA;AAAA,YAACC,WAAW7B;AAAAA,UAAI,GAAMX,KAAK,CAAA;AAAA,QAAA;AAAA,MAAA,CAAA;AAAA,IAAA;AAIzCoC,WAAAA,gBAAQE,SAAOC,WAAA;AAAA,MAACC,WAAW7B;AAAAA,IAAI,GAAMX,KAAK,CAAA;AAAA,EAC5C;AAEEqB,WAAiBoB,UAAU7B;AAEtBS,SAAAA;AACT;"}
1
+ {"version":3,"file":"lazyRouteComponent.js","sources":["../../src/lazyRouteComponent.tsx"],"sourcesContent":["import { Dynamic } from 'solid-js/web'\nimport { createResource } from 'solid-js'\nimport { Outlet } from './Match'\nimport { ClientOnly } from './ClientOnly'\nimport type { AsyncRouteComponent } from './route'\n\n// If the load fails due to module not found, it may mean a new version of\n// the build was deployed and the user's browser is still using an old version.\n// If this happens, the old version in the user's browser would have an outdated\n// URL to the lazy module.\n// In that case, we want to attempt one window refresh to get the latest.\nfunction isModuleNotFoundError(error: any): boolean {\n return (\n typeof error?.message === 'string' &&\n /Failed to fetch dynamically imported module/.test(error.message)\n )\n}\n\nexport function lazyRouteComponent<\n T extends Record<string, any>,\n TKey extends keyof T = 'default',\n>(\n importer: () => Promise<T>,\n exportName?: TKey,\n ssr?: () => boolean,\n): T[TKey] extends (props: infer TProps) => any\n ? AsyncRouteComponent<TProps>\n : never {\n let loadPromise: Promise<any> | undefined\n let comp: T[TKey] | T['default']\n let error: any\n\n const load = () => {\n if (typeof document === 'undefined' && ssr?.() === false) {\n comp = (() => null) as any\n return Promise.resolve(comp)\n }\n if (!loadPromise) {\n loadPromise = importer()\n .then((res) => {\n loadPromise = undefined\n comp = res[exportName ?? 'default']\n return comp\n })\n .catch((err) => {\n error = err\n })\n }\n\n return loadPromise\n }\n\n const lazyComp = function Lazy(props: any) {\n // Now that we're out of preload and into actual render path,\n // throw the error if it was a module not found error during preload\n if (error) {\n if (isModuleNotFoundError(error)) {\n // We don't want an error thrown from preload in this case, because\n // there's nothing we want to do about module not found during preload.\n // Record the error, recover the promise with a null return,\n // and we will attempt module not found resolution during the render path.\n\n if (\n error instanceof Error &&\n typeof window !== 'undefined' &&\n typeof sessionStorage !== 'undefined'\n ) {\n // Again, we want to reload one time on module not found error and not enter\n // a reload loop if there is some other issue besides an old deploy.\n // That's why we store our reload attempt in sessionStorage.\n // Use error.message as key because it contains the module path that failed.\n const storageKey = `tanstack_router_reload:${error.message}`\n if (!sessionStorage.getItem(storageKey)) {\n sessionStorage.setItem(storageKey, '1')\n window.location.reload()\n\n // Return empty component while we wait for window to reload\n return {\n default: () => null,\n }\n }\n }\n }\n\n // Otherwise, just throw the error\n throw error\n }\n\n if (!comp) {\n const [compResource] = createResource(load, {\n initialValue: comp,\n ssrLoadFrom: 'initial',\n })\n return <>{compResource()}</>\n }\n\n if (ssr?.() === false) {\n return (\n <ClientOnly fallback={<Outlet />}>\n <Dynamic component={comp} {...props} />\n </ClientOnly>\n )\n }\n return <Dynamic component={comp} {...props} />\n }\n\n ;(lazyComp as any).preload = load\n\n return lazyComp as any\n}\n"],"names":["isModuleNotFoundError","error","message","test","lazyRouteComponent","importer","exportName","ssr","loadPromise","comp","load","document","Promise","resolve","then","res","undefined","catch","err","lazyComp","Lazy","props","Error","window","sessionStorage","storageKey","getItem","setItem","location","reload","default","compResource","createResource","initialValue","ssrLoadFrom","_$memo","_$createComponent","ClientOnly","fallback","Outlet","children","Dynamic","_$mergeProps","component","preload"],"mappings":";;;;AAWA,SAASA,sBAAsBC,OAAqB;AAClD,SACE,QAAOA,+BAAOC,aAAY,YAC1B,8CAA8CC,KAAKF,MAAMC,OAAO;AAEpE;AAEgBE,SAAAA,mBAIdC,UACAC,YACAC,KAGQ;AACJC,MAAAA;AACAC,MAAAA;AACAR,MAAAA;AAEJ,QAAMS,OAAOA,MAAM;AACjB,QAAI,OAAOC,aAAa,gBAAeJ,kCAAY,OAAO;AACxDE,aAAQ,MAAM;AACPG,aAAAA,QAAQC,QAAQJ,IAAI;AAAA,IAAA;AAE7B,QAAI,CAACD,aAAa;AACFH,oBAAAA,SAAAA,EACXS,KAAMC,CAAQ,QAAA;AACCC,sBAAAA;AACPD,eAAAA,IAAIT,cAAc,SAAS;AAC3BG,eAAAA;AAAAA,MAAAA,CACR,EACAQ,MAAOC,CAAQ,QAAA;AACNA,gBAAAA;AAAAA,MAAAA,CACT;AAAA,IAAA;AAGEV,WAAAA;AAAAA,EACT;AAEMW,QAAAA,WAAW,SAASC,KAAKC,OAAY;AAGzC,QAAIpB,OAAO;AACLD,UAAAA,sBAAsBC,KAAK,GAAG;AAMhC,YACEA,iBAAiBqB,SACjB,OAAOC,WAAW,eAClB,OAAOC,mBAAmB,aAC1B;AAKMC,gBAAAA,aAAa,0BAA0BxB,MAAMC,OAAO;AAC1D,cAAI,CAACsB,eAAeE,QAAQD,UAAU,GAAG;AACxBE,2BAAAA,QAAQF,YAAY,GAAG;AACtCF,mBAAOK,SAASC,OAAO;AAGhB,mBAAA;AAAA,cACLC,SAASA,MAAM;AAAA,YACjB;AAAA,UAAA;AAAA,QACF;AAAA,MACF;AAII7B,YAAAA;AAAAA,IAAAA;AAGR,QAAI,CAACQ,MAAM;AACT,YAAM,CAACsB,YAAY,IAAIC,eAAetB,MAAM;AAAA,QAC1CuB,cAAcxB;AAAAA,QACdyB,aAAa;AAAA,MAAA,CACd;AACD,aAAAC,KAAUJ,YAAY;AAAA,IAAA;AAGpBxB,SAAAA,kCAAY,OAAO;AACrB,aAAA6B,gBACGC,YAAU;AAAA,QAAA,IAACC,WAAQ;AAAAF,iBAAAA,gBAAGG,QAAM,EAAA;AAAA,QAAA;AAAA,QAAA,IAAAC,WAAA;AAAAJ,iBAAAA,gBAC1BK,SAAOC,WAAA;AAAA,YAACC,WAAWlC;AAAAA,UAAI,GAAMY,KAAK,CAAA;AAAA,QAAA;AAAA,MAAA,CAAA;AAAA,IAAA;AAIzCe,WAAAA,gBAAQK,SAAOC,WAAA;AAAA,MAACC,WAAWlC;AAAAA,IAAI,GAAMY,KAAK,CAAA;AAAA,EAC5C;AAEEF,WAAiByB,UAAUlC;AAEtBS,SAAAA;AACT;"}
@@ -0,0 +1,49 @@
1
+ import * as Solid from 'solid-js';
2
+ export interface ClientOnlyProps {
3
+ /**
4
+ * The children to render if the JS is loaded.
5
+ */
6
+ children: Solid.JSX.Element;
7
+ /**
8
+ * The fallback component to render if the JS is not yet loaded.
9
+ */
10
+ fallback?: Solid.JSX.Element;
11
+ }
12
+ /**
13
+ * Render the children only after the JS has loaded client-side. Use an optional
14
+ * fallback component if the JS is not yet loaded.
15
+ *
16
+ * @example
17
+ * Render a Chart component if JS loads, renders a simple FakeChart
18
+ * component server-side or if there is no JS. The FakeChart can have only the
19
+ * UI without the behavior or be a loading spinner or skeleton.
20
+ *
21
+ * ```tsx
22
+ * return (
23
+ * <ClientOnly fallback={<FakeChart />}>
24
+ * <Chart />
25
+ * </ClientOnly>
26
+ * )
27
+ * ```
28
+ */
29
+ export declare function ClientOnly(props: ClientOnlyProps): Solid.JSX.Element;
30
+ /**
31
+ * Return a boolean indicating if the JS has been hydrated already.
32
+ * When doing Server-Side Rendering, the result will always be false.
33
+ * When doing Client-Side Rendering, the result will always be false on the
34
+ * first render and true from then on. Even if a new component renders it will
35
+ * always start with true.
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * // Disable a button that needs JS to work.
40
+ * let hydrated = useHydrated()
41
+ * return (
42
+ * <button type="button" disabled={!hydrated()} onClick={doSomethingCustom}>
43
+ * Click me
44
+ * </button>
45
+ * )
46
+ * ```
47
+ * @returns A signal accessor function that returns true if the JS has been hydrated already, false otherwise.
48
+ */
49
+ export declare function useHydrated(): Solid.Accessor<boolean>;
@@ -0,0 +1,51 @@
1
+ import * as Solid from 'solid-js';
2
+ import { isServer } from 'solid-js/web';
3
+ /**
4
+ * Render the children only after the JS has loaded client-side. Use an optional
5
+ * fallback component if the JS is not yet loaded.
6
+ *
7
+ * @example
8
+ * Render a Chart component if JS loads, renders a simple FakeChart
9
+ * component server-side or if there is no JS. The FakeChart can have only the
10
+ * UI without the behavior or be a loading spinner or skeleton.
11
+ *
12
+ * ```tsx
13
+ * return (
14
+ * <ClientOnly fallback={<FakeChart />}>
15
+ * <Chart />
16
+ * </ClientOnly>
17
+ * )
18
+ * ```
19
+ */
20
+ export function ClientOnly(props) {
21
+ return useHydrated() ? <>{props.children}</> : <>{props.fallback}</>;
22
+ }
23
+ /**
24
+ * Return a boolean indicating if the JS has been hydrated already.
25
+ * When doing Server-Side Rendering, the result will always be false.
26
+ * When doing Client-Side Rendering, the result will always be false on the
27
+ * first render and true from then on. Even if a new component renders it will
28
+ * always start with true.
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * // Disable a button that needs JS to work.
33
+ * let hydrated = useHydrated()
34
+ * return (
35
+ * <button type="button" disabled={!hydrated()} onClick={doSomethingCustom}>
36
+ * Click me
37
+ * </button>
38
+ * )
39
+ * ```
40
+ * @returns A signal accessor function that returns true if the JS has been hydrated already, false otherwise.
41
+ */
42
+ export function useHydrated() {
43
+ const [hydrated, setHydrated] = Solid.createSignal(!isServer);
44
+ if (!isServer) {
45
+ Solid.createEffect(() => {
46
+ setHydrated(true);
47
+ });
48
+ }
49
+ return hydrated;
50
+ }
51
+ //# sourceMappingURL=ClientOnly.jsx.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClientOnly.jsx","sourceRoot":"","sources":["../../src/ClientOnly.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAavC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,OAAO,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAA;AACtE,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAA;IAE7D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE;YACtB,WAAW,CAAC,IAAI,CAAC,CAAA;QACnB,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC"}
@@ -8,6 +8,7 @@ export type { BlockerFn, HistoryLocation, RouterHistory, ParsedPath, HistoryStat
8
8
  export { useAwaited, Await } from './awaited';
9
9
  export type { AwaitOptions } from './awaited';
10
10
  export { CatchBoundary, ErrorComponent } from './CatchBoundary';
11
+ export { ClientOnly } from './ClientOnly';
11
12
  export { FileRoute, createFileRoute, FileRouteLoader, LazyRoute, createLazyRoute, createLazyFileRoute, } from './fileRoute';
12
13
  export * from './history';
13
14
  export { lazyRouteComponent } from './lazyRouteComponent';
@@ -5,6 +5,7 @@ pick, functionalUpdate, replaceEqualDeep, isPlainObject, isPlainArray, deepEqual
5
5
  export { createHistory, createBrowserHistory, createHashHistory, createMemoryHistory, } from '@tanstack/history';
6
6
  export { useAwaited, Await } from './awaited';
7
7
  export { CatchBoundary, ErrorComponent } from './CatchBoundary';
8
+ export { ClientOnly } from './ClientOnly';
8
9
  export { FileRoute, createFileRoute, FileRouteLoader, LazyRoute, createLazyRoute, createLazyFileRoute, } from './fileRoute';
9
10
  export * from './history';
10
11
  export { lazyRouteComponent } from './lazyRouteComponent';
@@ -1 +1 @@
1
- {"version":3,"file":"index.jsx","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAA;AACrD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,cAAc,CAAA;AAEjD,OAAO,EACL,KAAK,EACL,oBAAoB,EACpB,OAAO,EACP,SAAS,EACT,SAAS,EACT,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,WAAW,EACX,aAAa,EACb,eAAe,EACf,aAAa,EACb,cAAc,EACd,WAAW,EACX,MAAM,EACN,MAAM,EACN,WAAW,EACX,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,UAAU,EAAE,MAAM;AAClB,IAAI,EACJ,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,SAAS,EACT,OAAO,EACP,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AA8K9B,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAU1B,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAG7C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAE/D,OAAO,EACL,SAAS,EACT,eAAe,EACf,eAAe,EACf,SAAS,EACT,eAAe,EACf,mBAAmB,GACpB,MAAM,aAAa,CAAA;AAEpB,cAAc,WAAW,CAAA;AAEzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAEzD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAUpE,OAAO,EACL,OAAO,EACP,aAAa,EACb,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,eAAe,GAChB,MAAM,WAAW,CAAA;AAIlB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE/C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAE5D,OAAO,EACL,QAAQ,EACR,WAAW,EACX,KAAK,EACL,WAAW,EACX,SAAS,EACT,oBAAoB,EACpB,eAAe,EACf,0BAA0B,EAC1B,eAAe,EACf,aAAa,GACd,MAAM,SAAS,CAAA;AAWhB,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAE/C,OAAO,EACL,cAAc,EACd,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,qBAAqB,GACtB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAGxE,OAAO,EACL,2BAA2B,EAC3B,iBAAiB,GAClB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAEhD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAErD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,OAAO,EACL,gBAAgB,EAAE,MAAM;EACzB,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAClE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AA+B5D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.jsx","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"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"}
@@ -1,7 +1,2 @@
1
- import type * as Solid from 'solid-js';
2
1
  import type { AsyncRouteComponent } from './route';
3
- export declare function ClientOnly(props: Solid.ParentProps<{
4
- fallback?: Solid.JSX.Element;
5
- }>): Solid.JSX.Element;
6
- export declare function useHydrated(): boolean;
7
2
  export declare function lazyRouteComponent<T extends Record<string, any>, TKey extends keyof T = 'default'>(importer: () => Promise<T>, exportName?: TKey, ssr?: () => boolean): T[TKey] extends (props: infer TProps) => any ? AsyncRouteComponent<TProps> : never;
@@ -1,6 +1,7 @@
1
- import { Dynamic, isServer } from 'solid-js/web';
1
+ import { Dynamic } from 'solid-js/web';
2
2
  import { createResource } from 'solid-js';
3
3
  import { Outlet } from './Match';
4
+ import { ClientOnly } from './ClientOnly';
4
5
  // If the load fails due to module not found, it may mean a new version of
5
6
  // the build was deployed and the user's browser is still using an old version.
6
7
  // If this happens, the old version in the user's browser would have an outdated
@@ -10,12 +11,6 @@ function isModuleNotFoundError(error) {
10
11
  return (typeof error?.message === 'string' &&
11
12
  /Failed to fetch dynamically imported module/.test(error.message));
12
13
  }
13
- export function ClientOnly(props) {
14
- return useHydrated() ? <>{props.children}</> : <>{props.fallback}</>;
15
- }
16
- export function useHydrated() {
17
- return isServer;
18
- }
19
14
  export function lazyRouteComponent(importer, exportName, ssr) {
20
15
  let loadPromise;
21
16
  let comp;
@@ -1 +1 @@
1
- {"version":3,"file":"lazyRouteComponent.jsx","sourceRoot":"","sources":["../../src/lazyRouteComponent.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lazyRouteComponent.jsx","sourceRoot":"","sources":["../../src/lazyRouteComponent.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/solid-router",
3
- "version": "1.115.3",
3
+ "version": "1.117.0",
4
4
  "description": "Modern and scalable routing for Solid applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -61,7 +61,7 @@
61
61
  "tiny-invariant": "^1.3.3",
62
62
  "tiny-warning": "^1.0.3",
63
63
  "@tanstack/history": "1.115.0",
64
- "@tanstack/router-core": "1.115.3"
64
+ "@tanstack/router-core": "1.117.0"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@solidjs/testing-library": "^0.8.10",
@@ -0,0 +1,65 @@
1
+ import * as Solid from 'solid-js'
2
+ import { isServer } from 'solid-js/web'
3
+
4
+ export interface ClientOnlyProps {
5
+ /**
6
+ * The children to render if the JS is loaded.
7
+ */
8
+ children: Solid.JSX.Element
9
+ /**
10
+ * The fallback component to render if the JS is not yet loaded.
11
+ */
12
+ fallback?: Solid.JSX.Element
13
+ }
14
+
15
+ /**
16
+ * Render the children only after the JS has loaded client-side. Use an optional
17
+ * fallback component if the JS is not yet loaded.
18
+ *
19
+ * @example
20
+ * Render a Chart component if JS loads, renders a simple FakeChart
21
+ * component server-side or if there is no JS. The FakeChart can have only the
22
+ * UI without the behavior or be a loading spinner or skeleton.
23
+ *
24
+ * ```tsx
25
+ * return (
26
+ * <ClientOnly fallback={<FakeChart />}>
27
+ * <Chart />
28
+ * </ClientOnly>
29
+ * )
30
+ * ```
31
+ */
32
+ export function ClientOnly(props: ClientOnlyProps) {
33
+ return useHydrated() ? <>{props.children}</> : <>{props.fallback}</>
34
+ }
35
+
36
+ /**
37
+ * Return a boolean indicating if the JS has been hydrated already.
38
+ * When doing Server-Side Rendering, the result will always be false.
39
+ * When doing Client-Side Rendering, the result will always be false on the
40
+ * first render and true from then on. Even if a new component renders it will
41
+ * always start with true.
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * // Disable a button that needs JS to work.
46
+ * let hydrated = useHydrated()
47
+ * return (
48
+ * <button type="button" disabled={!hydrated()} onClick={doSomethingCustom}>
49
+ * Click me
50
+ * </button>
51
+ * )
52
+ * ```
53
+ * @returns A signal accessor function that returns true if the JS has been hydrated already, false otherwise.
54
+ */
55
+ export function useHydrated() {
56
+ const [hydrated, setHydrated] = Solid.createSignal(!isServer)
57
+
58
+ if (!isServer) {
59
+ Solid.createEffect(() => {
60
+ setHydrated(true)
61
+ })
62
+ }
63
+
64
+ return hydrated
65
+ }
package/src/index.tsx CHANGED
@@ -228,6 +228,7 @@ export { useAwaited, Await } from './awaited'
228
228
  export type { AwaitOptions } from './awaited'
229
229
 
230
230
  export { CatchBoundary, ErrorComponent } from './CatchBoundary'
231
+ export { ClientOnly } from './ClientOnly'
231
232
 
232
233
  export {
233
234
  FileRoute,
@@ -1,7 +1,7 @@
1
- import { Dynamic, isServer } from 'solid-js/web'
1
+ import { Dynamic } from 'solid-js/web'
2
2
  import { createResource } from 'solid-js'
3
3
  import { Outlet } from './Match'
4
- import type * as Solid from 'solid-js'
4
+ import { ClientOnly } from './ClientOnly'
5
5
  import type { AsyncRouteComponent } from './route'
6
6
 
7
7
  // If the load fails due to module not found, it may mean a new version of
@@ -16,16 +16,6 @@ function isModuleNotFoundError(error: any): boolean {
16
16
  )
17
17
  }
18
18
 
19
- export function ClientOnly(
20
- props: Solid.ParentProps<{ fallback?: Solid.JSX.Element }>,
21
- ) {
22
- return useHydrated() ? <>{props.children}</> : <>{props.fallback}</>
23
- }
24
-
25
- export function useHydrated() {
26
- return isServer
27
- }
28
-
29
19
  export function lazyRouteComponent<
30
20
  T extends Record<string, any>,
31
21
  TKey extends keyof T = 'default',