@voltro/web 0.51.0 → 0.53.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.
- package/CHANGELOG.md +356 -0
- package/THIRD-PARTY-NOTICES.md +281 -1
- package/dist/{defaultFallbacks-B4Ak-R6R.js → defaultFallbacks-SQ45vAhz.js} +1 -1
- package/dist/{frameworkBoot-CV_o2tIk.js → frameworkBoot-CnE9vzLQ.js} +2 -2
- package/dist/frameworkBoot.js +1 -1
- package/dist/globalContext-AuflFFmy.js +2 -0
- package/dist/hooks.js +1 -1
- package/dist/index.d.ts +247 -36
- package/dist/index.js +183 -72
- package/dist/islands.d.ts +66 -0
- package/dist/islands.js +60 -0
- package/dist/mount.js +37 -2
- package/dist/{routerState-DAT472IC.js → routerState-Cr6fTbka.js} +4 -2
- package/dist/serverContext-BwzZ6Q7d.js +1148 -0
- package/dist/ssr.d.ts +35 -10
- package/dist/ssr.js +47 -46
- package/package.json +9 -4
- package/dist/globalContext-d4A-ugDg.js +0 -10
- package/dist/mount-nudb4UCl.js +0 -81
- package/dist/serverContext-38JTbYPa.js +0 -840
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { Ref } from 'react';
|
|
|
11
11
|
import { ResolvableHeaders } from '@voltro/client';
|
|
12
12
|
import { Rpc } from '@effect/rpc';
|
|
13
13
|
import { RpcGroup } from '@effect/rpc';
|
|
14
|
+
import { Schema } from 'effect';
|
|
14
15
|
|
|
15
16
|
/** Decision outcome for a document-level anchor click. */
|
|
16
17
|
export declare type AnchorNavigationDecision = {
|
|
@@ -167,6 +168,13 @@ declare interface CompiledRoute extends PageDescriptor {
|
|
|
167
168
|
|
|
168
169
|
export declare const compileRoute: (route: PageDescriptor) => CompiledRoute;
|
|
169
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Decode a query string against a page's `searchParams` schema. Total: an
|
|
173
|
+
* invalid query yields the schema's defaults; only a schema that cannot even
|
|
174
|
+
* decode `{}` (a required field with no default) throws, naming the fix.
|
|
175
|
+
*/
|
|
176
|
+
export declare const decodeSearchParams: <A>(schema: SearchParamsSchema<A>, usp: URLSearchParams) => A;
|
|
177
|
+
|
|
170
178
|
/** The English defaults. A deployment overrides any subtree via
|
|
171
179
|
* {@link FallbackStringsProvider} or a per-component `strings` prop;
|
|
172
180
|
* unspecified keys fall through to these. */
|
|
@@ -221,6 +229,18 @@ export declare interface DevStatus {
|
|
|
221
229
|
|
|
222
230
|
export declare type DevStatusKind = 'compiling' | 'loading' | 'reconnecting' | 'error';
|
|
223
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Canonical link-side encode — the schema-free half. `routes.generated.ts`
|
|
234
|
+
* types a link's params through a TYPE-ONLY import; at runtime the values are
|
|
235
|
+
* serialised canonically: strings pass through, numbers/booleans via
|
|
236
|
+
* `String()`, arrays as repeated keys, `undefined` omitted. `Date` (or any
|
|
237
|
+
* object) is refused loudly: a link must encode to the exact string form the
|
|
238
|
+
* schema's decode side accepts, and there is no canonical Date string the type
|
|
239
|
+
* layer could guarantee — declare the field as a string/number transform
|
|
240
|
+
* instead.
|
|
241
|
+
*/
|
|
242
|
+
export declare const encodeSearchParams: (params: Readonly<Record<string, unknown>>) => URLSearchParams;
|
|
243
|
+
|
|
224
244
|
export declare interface ErrorBoundaryProps {
|
|
225
245
|
readonly error: unknown;
|
|
226
246
|
readonly reset: () => void;
|
|
@@ -322,12 +342,20 @@ export declare const getStatuses: () => ReadonlyArray<DevStatus>;
|
|
|
322
342
|
|
|
323
343
|
/**
|
|
324
344
|
* Client-side runtime: scan the document for `[data-voltro-island]`
|
|
325
|
-
* markers and schedule each for hydration per its strategy. Called
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
* mark elements as visited).
|
|
345
|
+
* markers and schedule each for hydration per its strategy. Called by the
|
|
346
|
+
* per-page islands entry, and by `@voltro/web/mount` when an islands page
|
|
347
|
+
* is reached through the full app bundle (SPA navigation). Idempotent —
|
|
348
|
+
* running twice is a no-op (we mark elements as visited).
|
|
329
349
|
*/
|
|
330
|
-
export declare const hydrateIslandsOnPage: () => void;
|
|
350
|
+
export declare const hydrateIslandsOnPage: (options?: HydrateIslandsOptions) => void;
|
|
351
|
+
|
|
352
|
+
export declare interface HydrateIslandsOptions {
|
|
353
|
+
/** Wrap every island root — the per-page islands entry of a page whose
|
|
354
|
+
* islands use framework hooks passes a `<VoltroRuntimeProvider>` here so
|
|
355
|
+
* a `useSubscription` island gets a live runtime. Purely presentational
|
|
356
|
+
* entries pass nothing and never load the client core. */
|
|
357
|
+
readonly wrap?: (children: ReactNode) => ReactNode;
|
|
358
|
+
}
|
|
331
359
|
|
|
332
360
|
export declare type HydrateStrategy =
|
|
333
361
|
/** Hydrate as soon as the client runtime mounts (after main script load). */
|
|
@@ -341,9 +369,14 @@ export declare type HydrateStrategy =
|
|
|
341
369
|
| 'interaction'
|
|
342
370
|
/** Never hydrate. Useful for fully-static islands (e.g. SSR-only data
|
|
343
371
|
* display that never changes). */
|
|
344
|
-
| 'never'
|
|
345
|
-
|
|
346
|
-
|
|
372
|
+
| 'never'
|
|
373
|
+
/** CLIENT-ONLY: the server renders an empty placeholder (never the
|
|
374
|
+
* component — a browser-only lib touching `window` in render would
|
|
375
|
+
* crash the SSR pass), and the client mounts fresh with `createRoot`
|
|
376
|
+
* instead of hydrating. Astro's `client:only`. */
|
|
377
|
+
| 'only';
|
|
378
|
+
|
|
379
|
+
declare const Image_2: ({ src, alt, width, height, fill, sizes, priority, loader, quality, placeholder, blurDataURL, style, ...rest }: ImageProps) => ReactElement;
|
|
347
380
|
export { Image_2 as Image }
|
|
348
381
|
|
|
349
382
|
/** App-level default loader for every `<Image>` below it. A per-image
|
|
@@ -355,14 +388,16 @@ export declare const ImageConfigProvider: ({ loader, children, }: {
|
|
|
355
388
|
|
|
356
389
|
/** Maps a logical src + a target pixel width to a concrete URL. The hook
|
|
357
390
|
* for on-the-fly resizing — e.g. `({src,width}) => \`${src}?w=${width}\``
|
|
358
|
-
* against an image CDN or the storage serve endpoint.
|
|
391
|
+
* against an image CDN or the storage serve endpoint. `quality` is set when
|
|
392
|
+
* the `<Image quality>` prop is — forward it if your CDN supports it. */
|
|
359
393
|
export declare type ImageLoader = (params: {
|
|
360
394
|
readonly src: string;
|
|
361
395
|
readonly width: number;
|
|
396
|
+
readonly quality?: number;
|
|
362
397
|
}) => string;
|
|
363
398
|
|
|
364
399
|
export declare interface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'width' | 'height' | 'loading' | 'srcSet'> {
|
|
365
|
-
readonly src: string;
|
|
400
|
+
readonly src: string | OptimizedImageAsset;
|
|
366
401
|
/** Required — accessibility. Use `alt=""` for purely decorative images. */
|
|
367
402
|
readonly alt: string;
|
|
368
403
|
/** Intrinsic width in px. Required unless `fill`. */
|
|
@@ -379,7 +414,14 @@ export declare interface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElem
|
|
|
379
414
|
readonly priority?: boolean;
|
|
380
415
|
/** Per-image URL loader (overrides the ImageConfigProvider default). */
|
|
381
416
|
readonly loader?: ImageLoader;
|
|
382
|
-
/**
|
|
417
|
+
/** Encode quality hint 1–100 forwarded to the URL loader (a hero wants 90,
|
|
418
|
+
* a thumbnail 50). For a build-optimized `?image` asset the quality was
|
|
419
|
+
* baked at build time (`images.quality` in app.config.ts) — this prop
|
|
420
|
+
* applies to loader/CDN-resolved URLs. */
|
|
421
|
+
readonly quality?: number;
|
|
422
|
+
/** `'blur'` paints `blurDataURL` behind the image until it loads. A
|
|
423
|
+
* build-optimized asset carries its own blur and defaults to `'blur'`;
|
|
424
|
+
* pass `'empty'` to opt out. */
|
|
383
425
|
readonly placeholder?: 'blur' | 'empty';
|
|
384
426
|
readonly blurDataURL?: string;
|
|
385
427
|
}
|
|
@@ -446,7 +488,7 @@ export declare const lazyPageRoute: (pattern: string, load: () => Promise<Record
|
|
|
446
488
|
readonly chain?: ReadonlyArray<RouteSegment>;
|
|
447
489
|
}) => PageDescriptor;
|
|
448
490
|
|
|
449
|
-
export declare const Link: ({ to, children, onClick, prefetch: prefetchProp, replace, onMouseEnter, onFocus, ref, ...anchorProps }: LinkProps) => ReactNode;
|
|
491
|
+
export declare const Link: ({ to, children, onClick, prefetch: prefetchProp, replace, transition, onMouseEnter, onFocus, ref, ...anchorProps }: LinkProps) => ReactNode;
|
|
450
492
|
|
|
451
493
|
export declare interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'onClick'> {
|
|
452
494
|
readonly to: VoltroUrl;
|
|
@@ -457,6 +499,11 @@ export declare interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLA
|
|
|
457
499
|
/** Swap the current history entry instead of pushing a new one —
|
|
458
500
|
* mirror of `NavigateOptions.replace`. */
|
|
459
501
|
readonly replace?: boolean;
|
|
502
|
+
/** Run this link's route swap through `document.startViewTransition`
|
|
503
|
+
* (`true`) or force it off (`false`), overriding the app-wide
|
|
504
|
+
* `router.viewTransitions` default — mirror of
|
|
505
|
+
* `NavigateOptions.transition`. */
|
|
506
|
+
readonly transition?: boolean;
|
|
460
507
|
/**
|
|
461
508
|
* Forwarded to the underlying `<a>`.
|
|
462
509
|
*
|
|
@@ -638,6 +685,21 @@ export declare type LoaderFn<T = unknown, Procedures = unknown> = (ctx: LoaderCo
|
|
|
638
685
|
*/
|
|
639
686
|
export declare type LoaderQuery<Procedures = unknown> = Procedures extends ProcedureTypeMap ? <Tag extends keyof Procedures & string>(tag: Tag, ...input: Record<string, never> extends ProcedureInput<Procedures[Tag]> ? [input?: ProcedureInput<Procedures[Tag]>] : [input: ProcedureInput<Procedures[Tag]>]) => Promise<ProcedureOutput<Procedures[Tag]>> : <T = unknown>(tag: string, input?: Record<string, unknown>) => Promise<T>;
|
|
640
687
|
|
|
688
|
+
/**
|
|
689
|
+
* Reference a family declared in `app.config.ts` `fonts:`.
|
|
690
|
+
*
|
|
691
|
+
* const inter = localFont('Inter')
|
|
692
|
+
* <main style={{ fontFamily: inter.fontFamily }}>…</main>
|
|
693
|
+
*/
|
|
694
|
+
export declare const localFont: (family: string) => LocalFontHandle;
|
|
695
|
+
|
|
696
|
+
export declare interface LocalFontHandle {
|
|
697
|
+
/** The CSS custom property the shell defines: `--font-<slug>`. */
|
|
698
|
+
readonly variable: string;
|
|
699
|
+
/** Ready-to-use `font-family` value: `var(--font-<slug>)`. */
|
|
700
|
+
readonly fontFamily: string;
|
|
701
|
+
}
|
|
702
|
+
|
|
641
703
|
/** The URL path a logical page takes for a given locale under URL-prefix
|
|
642
704
|
* routing: the default locale keeps the bare path, every other locale gets a
|
|
643
705
|
* `/<locale>` prefix. `/about` @ `de` → `/de/about`; @ the default → `/about`. */
|
|
@@ -707,6 +769,14 @@ export declare interface NavigateOptions {
|
|
|
707
769
|
readonly replace?: boolean;
|
|
708
770
|
/** Set to `false` to preserve the current scroll position. Defaults to true. */
|
|
709
771
|
readonly scroll?: boolean;
|
|
772
|
+
/**
|
|
773
|
+
* Run this navigation's visual route swap through
|
|
774
|
+
* `document.startViewTransition` (`true`) or force it off (`false`),
|
|
775
|
+
* overriding the app-wide `router.viewTransitions` default for this one
|
|
776
|
+
* navigation. Browsers without the API and users with
|
|
777
|
+
* `prefers-reduced-motion: reduce` always get the plain swap regardless.
|
|
778
|
+
*/
|
|
779
|
+
readonly transition?: boolean;
|
|
710
780
|
}
|
|
711
781
|
|
|
712
782
|
export declare const NavigationIndicator: () => ReactNode;
|
|
@@ -742,6 +812,31 @@ export declare class NotFoundError extends Error {
|
|
|
742
812
|
|
|
743
813
|
export declare const noticeIslandsShipTheFullBundle: (isDev: boolean) => void;
|
|
744
814
|
|
|
815
|
+
/**
|
|
816
|
+
* A build-optimized static asset — what a `?image` import resolves to:
|
|
817
|
+
*
|
|
818
|
+
* import hero from './hero.jpg?image'
|
|
819
|
+
* <Image src={hero} alt="…" />
|
|
820
|
+
*
|
|
821
|
+
* The CLI's sharp pipeline produced the variants at build time (on demand in
|
|
822
|
+
* dev); `<Image>` renders them as a `<picture>` with one `<source>` per
|
|
823
|
+
* modern format and infers width/height/blur — the CLS-required intrinsic
|
|
824
|
+
* size stops being a hand-written prop for imported assets.
|
|
825
|
+
*/
|
|
826
|
+
export declare interface OptimizedImageAsset {
|
|
827
|
+
readonly src: string;
|
|
828
|
+
readonly width: number;
|
|
829
|
+
readonly height: number;
|
|
830
|
+
readonly blurDataURL: string;
|
|
831
|
+
/** Fallback-format srcSet (jpeg/png). */
|
|
832
|
+
readonly srcSet: string;
|
|
833
|
+
/** Modern-format sources, in preference order (avif before webp). */
|
|
834
|
+
readonly sources: ReadonlyArray<{
|
|
835
|
+
readonly type: string;
|
|
836
|
+
readonly srcSet: string;
|
|
837
|
+
}>;
|
|
838
|
+
}
|
|
839
|
+
|
|
745
840
|
export declare const PAGE_SLOT_ATTR = "data-voltro-page-slot";
|
|
746
841
|
|
|
747
842
|
export declare interface PageDescriptor<TLoaderData = unknown> {
|
|
@@ -794,6 +889,19 @@ export declare interface PageDescriptor<TLoaderData = unknown> {
|
|
|
794
889
|
* set this to `'islands'` so only marked interactive zones
|
|
795
890
|
* hydrate; the rest stays pure static HTML. */
|
|
796
891
|
readonly interactive?: InteractiveMode | undefined;
|
|
892
|
+
/**
|
|
893
|
+
* Intercepting route (modal-with-URL): when a SOFT navigation reaches this
|
|
894
|
+
* page FROM one of the `from` route patterns, the page renders as an
|
|
895
|
+
* OVERLAY above the still-mounted origin page instead of replacing it —
|
|
896
|
+
* URL changes, Back closes the overlay, a hard load of the same URL
|
|
897
|
+
* renders the page standalone. `from` is one or more route PATTERNS
|
|
898
|
+
* (`'/photos'`, `'/albums/[id]'`); a soft navigation from any other route
|
|
899
|
+
* renders standalone. Full-hydration pages only (`interactive: 'full'`) —
|
|
900
|
+
* islands/none pages have no client router to intercept with.
|
|
901
|
+
*/
|
|
902
|
+
readonly intercept?: {
|
|
903
|
+
readonly from: string | ReadonlyArray<string>;
|
|
904
|
+
} | undefined;
|
|
797
905
|
}
|
|
798
906
|
|
|
799
907
|
export declare interface PageMeta {
|
|
@@ -964,6 +1072,9 @@ export declare type RenderMode = (typeof RENDER_MODES)[number];
|
|
|
964
1072
|
|
|
965
1073
|
/* Excluded from this release type: renderRouterProviderTree */
|
|
966
1074
|
|
|
1075
|
+
/** Test seam. */
|
|
1076
|
+
export declare const resetScriptRegistryForTest: () => void;
|
|
1077
|
+
|
|
967
1078
|
/**
|
|
968
1079
|
* Decide whether a click on (or inside) an anchor should be handled by the
|
|
969
1080
|
* SPA router or left to the browser. Pure — no side effects, no
|
|
@@ -1005,7 +1116,7 @@ export declare interface RouteMatch {
|
|
|
1005
1116
|
readonly params: Readonly<Record<string, string>>;
|
|
1006
1117
|
}
|
|
1007
1118
|
|
|
1008
|
-
export declare const Router: ({ routes, notFounds, notFound: NotFound, errorFallback: ErrorFallback, }: RouterProps) => ReactNode;
|
|
1119
|
+
export declare const Router: ({ routes, notFounds, notFound: NotFound, errorFallback: ErrorFallback, viewTransitions, }: RouterProps) => ReactNode;
|
|
1009
1120
|
|
|
1010
1121
|
/* Excluded from this release type: RouterContext */
|
|
1011
1122
|
|
|
@@ -1040,6 +1151,15 @@ export declare interface RouterProps {
|
|
|
1040
1151
|
readonly notFound?: ComponentType;
|
|
1041
1152
|
/** Fallback ErrorBoundary used when neither the leaf nor its chain supplies one. */
|
|
1042
1153
|
readonly errorFallback?: ComponentType<ErrorBoundaryProps>;
|
|
1154
|
+
/**
|
|
1155
|
+
* Run SPA route swaps through `document.startViewTransition` — the browser
|
|
1156
|
+
* cross-fades old and new page (customizable via `::view-transition-*` CSS).
|
|
1157
|
+
* Set from `app.config.ts` `router.viewTransitions`; individual navigations
|
|
1158
|
+
* override it via `navigate(to, { transition })` / `<Link transition>`.
|
|
1159
|
+
* Browsers without the API and `prefers-reduced-motion: reduce` fall back to
|
|
1160
|
+
* the exact untransitioned behavior.
|
|
1161
|
+
*/
|
|
1162
|
+
readonly viewTransitions?: boolean;
|
|
1043
1163
|
}
|
|
1044
1164
|
|
|
1045
1165
|
/**
|
|
@@ -1081,10 +1201,55 @@ declare interface RouteSnapshot {
|
|
|
1081
1201
|
readonly loaderData: unknown;
|
|
1082
1202
|
}
|
|
1083
1203
|
|
|
1204
|
+
/**
|
|
1205
|
+
* Declarative third-party script. Renders NOTHING into the HTML — the tag is
|
|
1206
|
+
* injected client-side per `strategy`, deduplicated process-wide by `src`
|
|
1207
|
+
* (external) or `id` (inline). Behavior per `interactive` mode is decided,
|
|
1208
|
+
* not accidental: on an `interactive: 'none'` page the app bundle never runs,
|
|
1209
|
+
* so a `<Script>` never fires (the build warns by name); on an islands page
|
|
1210
|
+
* only `<Script>` INSIDE an island ever mounts — a `visible` island's script
|
|
1211
|
+
* loads when the island hydrates (the build warns about `<Script>` in the
|
|
1212
|
+
* static part).
|
|
1213
|
+
*/
|
|
1214
|
+
export declare const Script: ({ src, children, id, strategy, onLoad, onError, nonce, attributes, }: ScriptProps) => ReactElement | null;
|
|
1215
|
+
|
|
1216
|
+
export declare interface ScriptProps {
|
|
1217
|
+
/** External script URL. Exactly one of `src` / `children` is required. */
|
|
1218
|
+
readonly src?: string;
|
|
1219
|
+
/** Inline script body. Requires `id` (the dedupe key — inline code has no
|
|
1220
|
+
* src to key on). */
|
|
1221
|
+
readonly children?: string;
|
|
1222
|
+
/** Dedupe key for inline scripts; optional label for external ones. */
|
|
1223
|
+
readonly id?: string;
|
|
1224
|
+
/** `afterInteractive` (default): inject once this component mounts —
|
|
1225
|
+
* i.e. after hydration. `lazyOnload`: wait for browser idle. */
|
|
1226
|
+
readonly strategy?: 'afterInteractive' | 'lazyOnload';
|
|
1227
|
+
/** Fires when the script has executed — ALSO on a re-mount of the same
|
|
1228
|
+
* script, answered from the registry (the script itself is never
|
|
1229
|
+
* re-fetched or re-run). */
|
|
1230
|
+
readonly onLoad?: () => void;
|
|
1231
|
+
readonly onError?: (error: unknown) => void;
|
|
1232
|
+
/** CSP nonce. Absent → the document's nonce is propagated when one exists. */
|
|
1233
|
+
readonly nonce?: string;
|
|
1234
|
+
/** Extra attributes for the tag (`data-*`, `crossorigin`, …). */
|
|
1235
|
+
readonly attributes?: Readonly<Record<string, string>>;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
declare const SEARCH_PARAMS_BRAND: unique symbol;
|
|
1239
|
+
|
|
1084
1240
|
/** The next search-params value: either the params object directly, or an
|
|
1085
1241
|
* updater that receives the CURRENT `URLSearchParams` and returns the next. */
|
|
1086
1242
|
export declare type SearchParamsInit = URLSearchParams | Readonly<Record<string, string>> | ((current: URLSearchParams) => URLSearchParams | Record<string, string>);
|
|
1087
1243
|
|
|
1244
|
+
/** A search-params schema: decodes a plain `Record<string, string | string[]>`
|
|
1245
|
+
* (the canonical URLSearchParams view) into the page's typed shape. */
|
|
1246
|
+
export declare type SearchParamsSchema<A> = Schema.Schema<A, any, never>;
|
|
1247
|
+
|
|
1248
|
+
/** The canonical object view of a query string: repeated keys become arrays. */
|
|
1249
|
+
export declare const searchParamsToObject: (usp: URLSearchParams, opts?: {
|
|
1250
|
+
readonly arrayKeys?: ReadonlySet<string>;
|
|
1251
|
+
}) => Record<string, string | ReadonlyArray<string>>;
|
|
1252
|
+
|
|
1088
1253
|
/**
|
|
1089
1254
|
* Cache key for a layout (chain segment) loader. Distinct from the page's
|
|
1090
1255
|
* key for the same (pattern, params) so a layout's data and the page's
|
|
@@ -1155,23 +1320,6 @@ export declare interface ServerLogRelayOptions {
|
|
|
1155
1320
|
readonly originLabel: string;
|
|
1156
1321
|
}
|
|
1157
1322
|
|
|
1158
|
-
export declare const ServerRequestContext: Context<ServerRequestContextValue | null>;
|
|
1159
|
-
|
|
1160
|
-
export declare interface ServerRequestContextValue {
|
|
1161
|
-
readonly cookies: Readonly<Record<string, string>>;
|
|
1162
|
-
readonly headers: Readonly<Record<string, string>>;
|
|
1163
|
-
/** Raw request URL as it came off the wire (path + query). Useful
|
|
1164
|
-
* for SSR pages that need to read `?q=…` style search params
|
|
1165
|
-
* without touching anything client-only. Empty string for build-
|
|
1166
|
-
* time SSG renders where there is no incoming request. */
|
|
1167
|
-
readonly url: string;
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
export declare const ServerRequestProvider: ({ value, children, }: {
|
|
1171
|
-
readonly value: ServerRequestContextValue;
|
|
1172
|
-
readonly children: ReactNode;
|
|
1173
|
-
}) => ReactNode;
|
|
1174
|
-
|
|
1175
1323
|
/** Push a new route snapshot. Router calls this from its render
|
|
1176
1324
|
* effect; observers re-render on the next microtask. */
|
|
1177
1325
|
export declare const setRouteSnapshot: (next: RouteSnapshot) => void;
|
|
@@ -1337,10 +1485,27 @@ export declare const useReconnect: () => (() => void);
|
|
|
1337
1485
|
* to router-pushed query changes without a reload should re-render via
|
|
1338
1486
|
* the router (e.g. `useNavigate`/`useLocation`) — this hook then
|
|
1339
1487
|
* re-resolves on that render.
|
|
1488
|
+
*
|
|
1489
|
+
* Pass the page's own `searchParams` schema export to get the DECODED, typed
|
|
1490
|
+
* shape instead (defaults applied; an invalid query falls back to the
|
|
1491
|
+
* defaults — see `decodeSearchParams`). The schema value is module-local by
|
|
1492
|
+
* design: the page imports its own export, so no generated module ever holds
|
|
1493
|
+
* schema VALUES and links stay typed through type-only imports.
|
|
1494
|
+
*
|
|
1495
|
+
* ```tsx
|
|
1496
|
+
* export const searchParams = Schema.Struct({
|
|
1497
|
+
* page: Schema.optionalWith(Schema.NumberFromString, { default: () => 1 }),
|
|
1498
|
+
* })
|
|
1499
|
+
* const { page } = useSearchParams(searchParams) // number, SSR-aware
|
|
1500
|
+
* ```
|
|
1501
|
+
*
|
|
1502
|
+
* Overload ORDER is load-bearing (the same rule `@voltro/client` pins): the
|
|
1503
|
+
* schema overload must come after the zero-arg one, or every existing
|
|
1504
|
+
* zero-arg call site would re-infer against the generic signature.
|
|
1340
1505
|
*/
|
|
1341
|
-
export declare
|
|
1506
|
+
export declare function useSearchParams(): URLSearchParams;
|
|
1342
1507
|
|
|
1343
|
-
export declare
|
|
1508
|
+
export declare function useSearchParams<A>(schema: SearchParamsSchema<A>): A;
|
|
1344
1509
|
|
|
1345
1510
|
/**
|
|
1346
1511
|
* The WRITE half of `useSearchParams` — returns a setter that updates the
|
|
@@ -1359,8 +1524,25 @@ export declare const useServerRequest: () => ServerRequestContextValue | null;
|
|
|
1359
1524
|
* pass `{ push: true }` for a distinct history entry. Client-only — during SSR
|
|
1360
1525
|
* there is no history to write, so read `useSearchParams()` off the request URL
|
|
1361
1526
|
* instead and mutate on the client after hydration.
|
|
1527
|
+
*
|
|
1528
|
+
* Pass the page's `searchParams` schema to get the TYPED setter. Its object
|
|
1529
|
+
* form REPLACES the query — same semantics as the untyped form, an absent
|
|
1530
|
+
* field decodes to its default on the next read — and its updater form
|
|
1531
|
+
* receives the CURRENT decoded params, so a merge is an explicit spread:
|
|
1532
|
+
*
|
|
1533
|
+
* ```tsx
|
|
1534
|
+
* const setParams = useSetSearchParams(searchParams)
|
|
1535
|
+
* setParams({ page: 2 }) // → ?page=2 (filter dropped)
|
|
1536
|
+
* setParams((p) => ({ ...p, page: p.page + 1 })) // keeps ?filter — typed merge
|
|
1537
|
+
* ```
|
|
1538
|
+
*
|
|
1539
|
+
* Overload ORDER is load-bearing (same rule as `useSearchParams`): the schema
|
|
1540
|
+
* overload comes after the zero-arg one, or every existing zero-arg call site
|
|
1541
|
+
* would re-infer against the generic signature.
|
|
1362
1542
|
*/
|
|
1363
|
-
export declare
|
|
1543
|
+
export declare function useSetSearchParams(): (next: SearchParamsInit, opts?: SetSearchParamsOptions) => void;
|
|
1544
|
+
|
|
1545
|
+
export declare function useSetSearchParams<A extends Readonly<Record<string, unknown>>>(schema: SearchParamsSchema<A>): (next: Partial<A> | ((current: A) => Partial<A>), opts?: SetSearchParamsOptions) => void;
|
|
1364
1546
|
|
|
1365
1547
|
/**
|
|
1366
1548
|
* Read + set the app theme, backed by the SAME `voltro:theme` cookie and `.dark`
|
|
@@ -1382,9 +1564,22 @@ export declare type VoltroExternalUrl = string & {
|
|
|
1382
1564
|
readonly [EXTERNAL_URL_BRAND]: 'external';
|
|
1383
1565
|
};
|
|
1384
1566
|
|
|
1385
|
-
/**
|
|
1386
|
-
|
|
1567
|
+
/**
|
|
1568
|
+
* A URL minted by the app's generated `routes` builder.
|
|
1569
|
+
*
|
|
1570
|
+
* `TSearch` is a compile-time-only phantom: for a route whose page exports a
|
|
1571
|
+
* `searchParams` schema, the codegen brands the builder's return as
|
|
1572
|
+
* `VoltroRouteUrl<Schema.Schema.Type<typeof searchParams>>` through a
|
|
1573
|
+
* TYPE-ONLY import — no schema value ever enters `routes.generated.ts`, so
|
|
1574
|
+
* code-splitting stays intact — and `withQuery` then type-checks the params
|
|
1575
|
+
* against the page's contract. The default is `unknown`, which every branded
|
|
1576
|
+
* URL is assignable to, so a route without a schema (and every existing call
|
|
1577
|
+
* site) is untouched.
|
|
1578
|
+
*/
|
|
1579
|
+
export declare type VoltroRouteUrl<TSearch = unknown> = string & {
|
|
1387
1580
|
readonly [ROUTE_URL_BRAND]: 'route';
|
|
1581
|
+
} & {
|
|
1582
|
+
readonly [SEARCH_PARAMS_BRAND]?: TSearch;
|
|
1388
1583
|
};
|
|
1389
1584
|
|
|
1390
1585
|
export declare type VoltroUrl = VoltroRouteUrl | VoltroExternalUrl;
|
|
@@ -1401,8 +1596,24 @@ export declare const withHash: (url: VoltroRouteUrl, hash: string) => VoltroRout
|
|
|
1401
1596
|
*
|
|
1402
1597
|
* withQuery(routes['/_/p/[orgSlug]/[projectSlug]']({…}), { env: 'prod' })
|
|
1403
1598
|
* //→ '/_/p/acme/web?env=prod' (typed as VoltroRouteUrl)
|
|
1599
|
+
*
|
|
1600
|
+
* For a route whose page exports a `searchParams` schema, the URL carries the
|
|
1601
|
+
* decoded shape as a phantom (see {@link VoltroRouteUrl}) and the params here
|
|
1602
|
+
* type-check against it — a misspelt key or a wrong value type is a compile
|
|
1603
|
+
* error. The ENCODE stays canonical and schema-free (strings pass through,
|
|
1604
|
+
* number/boolean via String(), arrays as repeated keys) so the generated
|
|
1605
|
+
* builder never needs the schema VALUE; the searchParams roundtrip test pins
|
|
1606
|
+
* that this canonical form is exactly what the schema's decode accepts.
|
|
1607
|
+
*
|
|
1608
|
+
* ONE generic signature with a CONDITIONAL params type — deliberately not two
|
|
1609
|
+
* overloads. With overloads, a wrong key on a typed URL fails the strict
|
|
1610
|
+
* overload and silently falls through to the permissive one, so the compile
|
|
1611
|
+
* error the phantom exists for never fires (the `.test-d.ts` pins exactly
|
|
1612
|
+
* that). The conditional keeps one resolution path: a schema phantom infers
|
|
1613
|
+
* `Partial<TSearch>`, the bare brand (phantom `unknown`) infers the free
|
|
1614
|
+
* record.
|
|
1404
1615
|
*/
|
|
1405
|
-
export declare
|
|
1616
|
+
export declare function withQuery<TSearch = unknown>(url: VoltroRouteUrl<TSearch>, params: [TSearch] extends [Readonly<Record<string, unknown>>] ? Partial<TSearch> : Readonly<Record<string, string | number | boolean | ReadonlyArray<string | number | boolean> | undefined>>): VoltroRouteUrl<TSearch>;
|
|
1406
1617
|
|
|
1407
1618
|
|
|
1408
1619
|
export * from "@voltro/client";
|