@levo-so/site-runtime 0.3.23 → 0.3.25

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 (4) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/index.d.ts +53 -7
  3. package/index.js +453 -450
  4. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @levo-so/site-runtime
2
2
 
3
+ ## 0.3.25
4
+
5
+ ### Patch Changes
6
+
7
+ - 12bdba7: Adds `LevoLink`, the router's `<Link>` with a `to` that accepts any site path. On a multi-variant site, shared chrome (navbar, footer, CTAs) must link to the language-neutral path (`/about-us`) so the doorway sends each visitor to their own variant, but `<Link to="/about-us">` fails the publish type check because the neutral path is not a registered route. `LevoLink` is that link with the typing escape in one place and the reason attached, instead of a cast in every site; navigation is unchanged and still goes through the root route's locale redirect.
8
+ - 07c0850: Dynamic pages type-check with the loader attached. The loader from `createLevoLoader` no longer declares `params` on its context type: TanStack inferred a route's params from that annotation instead of from the file path, so `Route.useParams()` on a `$slug` route was typed `{ [x: string]: string } | undefined` and `const { slug } = Route.useParams()` failed the publish type check (#4696). A plain `$slug` route now gets `slug: string`, a route under a `$locale` layout keeps `locale`, a `levoParams` route keeps its split variables, and a static route has no params. The loader still reads the route params at runtime and prefetches the same sources; sites can drop the `Route.useParams() ?? {}` workaround.
9
+ - @levo-so/core@0.3.25
10
+ - @levo-so/insights@0.3.25
11
+
12
+ ## 0.3.24
13
+
14
+ ### Patch Changes
15
+
16
+ - Event registration form: the name and email fields hint the expected format ("John Doe", "name@company.com") instead of showing a demo person.
17
+ - @levo-so/core@0.3.24
18
+ - @levo-so/insights@0.3.24
19
+
3
20
  ## 0.3.23
4
21
 
5
22
  ### Patch Changes
package/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { AnyRouter } from '@tanstack/react-router';
1
2
  import { ILemaCollection } from '@levo-so/core';
2
3
  import { ILevoClient } from '@levo-so/core';
3
4
  import { ILevoInsights } from '@levo-so/insights';
@@ -5,6 +6,7 @@ import { ILevoMembership } from '@levo-so/core';
5
6
  import { IMediaObject } from '@levo-so/core';
6
7
  import { JSX } from 'react/jsx-runtime';
7
8
  import { LevoQuery } from '@levo-so/core';
9
+ import { LinkComponentProps } from '@tanstack/react-router';
8
10
 
9
11
  /**
10
12
  * Build the canonical + hreflang link set for one page.
@@ -55,7 +57,8 @@ export declare const createLevoHead: (site: ISiteJson) => (meta?: IPlatformMetaF
55
57
  * return them keyed by source key — that map is the route's `loaderData`, which
56
58
  * `levoHead`'s dynamic config reads for per-record heads. An empty `dataSources` ({})
57
59
  * resolves to an empty map. Context is typed structurally (just `queryClient`) so the
58
- * scaffold's router types never enter the package.
60
+ * scaffold's router types never enter the package — and WITHOUT `params`, see
61
+ * `ILevoLoaderContext`.
59
62
  *
60
63
  * Takes the raw `site.json` — same single input as `createLevoHead` and
61
64
  * `LevoSiteProvider` — and derives the client config itself.
@@ -72,12 +75,7 @@ export declare const createLevoHead: (site: ISiteJson) => (meta?: IPlatformMetaF
72
75
  * `meta` is optional so sites generated before this shipped keep working unchanged — they
73
76
  * simply prefetch as they always did (and have no gates to protect).
74
77
  */
75
- export declare const createLevoLoader: (site: ISiteJson) => (sources: ILevoDataSources, meta?: IPlatformMetaFile) => ({ context, params, }: {
76
- context: {
77
- queryClient: IQueryClientLike;
78
- };
79
- params?: Record<string, string>;
80
- }) => Promise<Record<string, unknown>>;
78
+ export declare const createLevoLoader: (site: ISiteJson) => (sources: ILevoDataSources, meta?: IPlatformMetaFile) => (ctx: ILevoLoaderContext) => Promise<Record<string, unknown>>;
81
79
 
82
80
  /**
83
81
  * Build a route-existence matcher from a generated `routeTree`.
@@ -769,6 +767,41 @@ export declare interface ILevoFormTheme {
769
767
  /** How the form lays its fields out. */
770
768
  export declare type ILevoFormVariant = "default" | "single-field" | "steps" | "steps-2";
771
769
 
770
+ /**
771
+ * `Link`'s props with `to` widened to any site path.
772
+ *
773
+ * `params` is dropped: a neutral path carries none, and a shared component that links to a
774
+ * dynamic page composes the string (`` `/accelerators/${slug}` ``).
775
+ */
776
+ export declare interface ILevoLinkProps extends Omit<LinkComponentProps<"a", AnyRouter, string, string, string, string>, "to" | "params"> {
777
+ /** A site path — the neutral `/about-us` in shared chrome. Not checked against the routes. */
778
+ to: string;
779
+ }
780
+
781
+ /**
782
+ * The slice of the router's loader context the loader reads. Structural on purpose (like
783
+ * `IHeadCtx`) so the scaffold's router types never enter the package.
784
+ *
785
+ * `params` is deliberately NOT declared here, and must not be re-added in any form. TanStack
786
+ * infers a route's param type from the loader it is handed: `createFileRoute(path)({ loader })`
787
+ * carries a `TParams` type parameter whose DEFAULT is the params parsed from the path, and the
788
+ * loader argument's `params` property is an inference site for it. Any annotation on that
789
+ * property — `params?: Record<string, string>`, `params?: unknown`, a generic bound — becomes
790
+ * the inferred `TParams` and beats the default, so `Route.useParams()` on `$slug.tsx` read
791
+ * `{ [x: string]: string } | undefined` and `slug` failed the publish type check (#4696).
792
+ * Left undeclared, the loader contributes no candidate and the route keeps the params its
793
+ * path (or its `params.parse`) gives it. `loaderParams` reads them at runtime.
794
+ *
795
+ * Exported (and re-exported from the package root) because a route file's `Route` type
796
+ * carries its loader's type: a site that emits declarations (`Register { router }` makes the
797
+ * router an exported type) would otherwise fail with TS4023 "cannot be named".
798
+ */
799
+ export declare interface ILevoLoaderContext {
800
+ context: {
801
+ queryClient: IQueryClientLike;
802
+ };
803
+ }
804
+
772
805
  export declare interface ILevoLoginActions {
773
806
  /**
774
807
  * Send a verification code. `identifier` is the email address (medium `"email"`) or the
@@ -1802,6 +1835,19 @@ export declare const LevoEventRegister: ({ eventID, title, external, buttonText,
1802
1835
  */
1803
1836
  export declare const LevoForm: React.FC<ILevoFormProps>;
1804
1837
 
1838
+ /**
1839
+ * `<Link>` whose `to` accepts any site path.
1840
+ *
1841
+ * Use it in shared chrome for the language-neutral path: `<LevoLink to="/about-us">`. Inside a
1842
+ * variant folder (`src/routes/fr-FR/pricing.tsx`) keep `<Link to="/fr-FR/about">`: the variant
1843
+ * is fixed there, and `Link` keeps that path checked against the routes, which this cannot.
1844
+ * Everything else — `className`, `activeProps`, `preload`, `ref`, the render-function
1845
+ * `children` — is `Link`'s own.
1846
+ *
1847
+ * @since 0.3.25
1848
+ */
1849
+ export declare const LevoLink: React.FC<ILevoLinkProps>;
1850
+
1805
1851
  export declare const levoParams: <TSegment extends string, TPattern extends string, TSiblings extends string = never>(key: TSegment, pattern: TPattern, _siblings?: readonly TSiblings[]) => ILevoParams<TSegment, TPattern, TSiblings>;
1806
1852
 
1807
1853
  /**