tempest-react-sdk 0.14.0 → 0.16.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.
@@ -569,6 +569,17 @@ export declare interface BannerProps extends Omit<HTMLAttributes<HTMLDivElement>
569
569
 
570
570
  export declare type BannerVariant = "info" | "success" | "warning" | "danger";
571
571
 
572
+ /**
573
+ * Initial bearing (forward azimuth) from `origin` to `destination`, in degrees
574
+ * clockwise from true north, normalized to `[0, 360)`. Useful for orienting a
575
+ * heading arrow on a trajectory.
576
+ *
577
+ * @param origin - Start coordinate.
578
+ * @param destination - End coordinate.
579
+ * @returns Bearing in degrees, `[0, 360)`.
580
+ */
581
+ export declare function bearingDeg(origin: Coordinate, destination: Coordinate): number;
582
+
572
583
  /**
573
584
  * Fixed-bottom mobile tab bar. 3–5 items recommended. Pair with
574
585
  * `<Show below="md">` to render only on mobile.
@@ -638,6 +649,18 @@ export declare interface BottomSheetProps extends Omit<HTMLAttributes<HTMLDivEle
638
649
  children?: ReactNode;
639
650
  }
640
651
 
652
+ /**
653
+ * Compute the axis-aligned bounding box that contains every point. Returns
654
+ * `null` for an empty list (there is nothing to bound).
655
+ *
656
+ * @param points - Coordinates to enclose.
657
+ * @returns The bounds, or `null` when `points` is empty.
658
+ */
659
+ export declare function boundingBox(points: readonly Coordinate[]): GeoBounds | null;
660
+
661
+ /** Geometric center of a bounding box. */
662
+ export declare function boundsCenter(bounds: GeoBounds): Coordinate;
663
+
641
664
  export declare interface BreadcrumbItem {
642
665
  label: ReactNode;
643
666
  href?: string;
@@ -978,6 +1001,9 @@ export declare function chunk<T>(items: T[], size: number): T[][];
978
1001
  */
979
1002
  export declare function clamp(value: number, min: number, max: number): number;
980
1003
 
1004
+ /** Clamp a latitude into the valid `[-90, 90]` range. */
1005
+ export declare function clampLatitude(latitude: number): number;
1006
+
981
1007
  declare type ClassValue = string | number | bigint | boolean | null | undefined | ClassValue[];
982
1008
 
983
1009
  /**
@@ -1218,6 +1244,18 @@ export { Control }
1218
1244
 
1219
1245
  export { Controller }
1220
1246
 
1247
+ /**
1248
+ * WGS84 geographic coordinate. Mirrors the `Coordinate` schema from
1249
+ * `tempest-fastapi-sdk` (`geo/schemas.py`) — `latitude` in `[-90, 90]`,
1250
+ * `longitude` in `[-180, 180]`, serialized snake_case on the wire.
1251
+ */
1252
+ export declare interface Coordinate {
1253
+ /** WGS84 latitude in degrees, `[-90, 90]`. E.g. `-23.5505`. */
1254
+ latitude: number;
1255
+ /** WGS84 longitude in degrees, `[-180, 180]`. E.g. `-46.6333`. */
1256
+ longitude: number;
1257
+ }
1258
+
1221
1259
  /**
1222
1260
  * Button that copies a string to the clipboard and shows a transient "copied"
1223
1261
  * state for `timeout` milliseconds.
@@ -1493,6 +1531,26 @@ export declare interface CreateLoggerOptions {
1493
1531
  */
1494
1532
  export declare function createOfflineStore<TItem, TKey extends string | number = string>(config: OfflineStoreConfig<TItem>): OfflineStore<TItem, TKey>;
1495
1533
 
1534
+ /**
1535
+ * Build a {@link RoutingBackend} backed by an OSRM server **you host**. OSRM
1536
+ * only serves a driving profile, so motorcycle/bus durations are derived by
1537
+ * scaling the car duration through {@link durationFactor} — same approach as
1538
+ * the FastAPI SDK's `OSRMBackend`.
1539
+ *
1540
+ * !!! warning
1541
+ * This makes a network request to `baseUrl`. It is opt-in: nothing in the
1542
+ * SDK calls it unless you construct it and pass your own server URL. For a
1543
+ * zero-network estimate, use {@link estimateTravel} instead.
1544
+ *
1545
+ * @param options - Server URL, optional `fetch`, per-mode factors.
1546
+ * @returns A backend whose `route()` queries OSRM.
1547
+ *
1548
+ * @example
1549
+ * const backend = createOSRMBackend({ baseUrl: "https://osrm.internal" });
1550
+ * const estimate = await backend.route(origin, destination, { mode: "car" });
1551
+ */
1552
+ export declare function createOSRMBackend(options: OSRMBackendOptions): RoutingBackend;
1553
+
1496
1554
  /**
1497
1555
  * Build a `206 Partial Content` response from a full one for an HTTP `Range`
1498
1556
  * request. Supports `bytes=start-end`, open-ended `bytes=start-` and suffix
@@ -1504,6 +1562,52 @@ export declare function createOfflineStore<TItem, TKey extends string | number =
1504
1562
  */
1505
1563
  export declare function createPartialResponse(request: Request, response: Response): Promise<Response>;
1506
1564
 
1565
+ /**
1566
+ * Record a live GPS trajectory from `navigator.geolocation.watchPosition`.
1567
+ * Framework-free — the {@link usePositionTracker} hook wraps this for React.
1568
+ *
1569
+ * Jitter while stationary is filtered by `minDistanceKm`; distance is
1570
+ * accumulated across the *full* run even when `maxPoints` trims the retained
1571
+ * array. 100% browser-side: no network, no external service.
1572
+ *
1573
+ * @param options - Filtering, retention and callbacks.
1574
+ * @returns A controller with `start`/`stop`/`clear` and live getters.
1575
+ *
1576
+ * @example
1577
+ * const tracker = createPositionTracker({
1578
+ * minDistanceKm: 0.01,
1579
+ * onUpdate: (pts) => console.log(pts.length, "points"),
1580
+ * });
1581
+ * tracker.start();
1582
+ * // …later
1583
+ * tracker.stop();
1584
+ * console.log(tracker.distanceKm);
1585
+ */
1586
+ export declare function createPositionTracker(options?: CreatePositionTrackerOptions): PositionTracker;
1587
+
1588
+ /** Options for {@link createPositionTracker}. */
1589
+ export declare interface CreatePositionTrackerOptions {
1590
+ /**
1591
+ * Discard a new sample when it is closer than this (in km) to the last
1592
+ * kept point — filters GPS jitter while standing still. Default: `0.005`
1593
+ * (5 meters). Pass `0` to keep every sample.
1594
+ */
1595
+ minDistanceKm?: number;
1596
+ /**
1597
+ * Cap the retained trajectory to the most recent N points (older points are
1598
+ * dropped, but their distance stays counted). Default: `Infinity`.
1599
+ */
1600
+ maxPoints?: number;
1601
+ /** Forwarded to `navigator.geolocation.watchPosition`. */
1602
+ positionOptions?: PositionOptions;
1603
+ /** Called with the full trajectory each time a point is added. */
1604
+ onUpdate?: (points: readonly TrackPoint[]) => void;
1605
+ /** Called on a `GeolocationPositionError`. */
1606
+ onError?: (error: GeolocationPositionError) => void;
1607
+ /** Called whenever the status changes. */
1608
+ onStatusChange?: (status: TrackerStatus) => void;
1609
+ }
1610
+
1507
1611
  /**
1508
1612
  * Build a [[TelemetryAdapter]] backed by [`posthog-js`](https://posthog.com/docs/libraries/js).
1509
1613
  * The PostHog client is supplied by the caller (not bundled).
@@ -2096,6 +2200,25 @@ export declare function decodeJWT(token: string): DecodedJWT;
2096
2200
  */
2097
2201
  export declare function deepMerge<T>(target: T, source: Partial<T>): T;
2098
2202
 
2203
+ /**
2204
+ * Default average car speed in km/h used to derive duration from distance.
2205
+ * Mirrors `DEFAULT_CAR_SPEED_KMH` from `tempest-fastapi-sdk`.
2206
+ */
2207
+ export declare const DEFAULT_CAR_SPEED_KMH = 50;
2208
+
2209
+ /**
2210
+ * Multiplier applied to the great-circle distance to approximate real road
2211
+ * distance. Mirrors `DEFAULT_CIRCUITY_FACTOR` from `tempest-fastapi-sdk`.
2212
+ */
2213
+ export declare const DEFAULT_CIRCUITY_FACTOR = 1.3;
2214
+
2215
+ /**
2216
+ * Per-mode multipliers applied to the car duration. Mirrors
2217
+ * `DEFAULT_MODE_DURATION_FACTORS` from `tempest-fastapi-sdk` — motorcycles are
2218
+ * a touch faster, buses considerably slower (stops + dedicated lanes).
2219
+ */
2220
+ export declare const DEFAULT_MODE_DURATION_FACTORS: Record<TravelMode, number>;
2221
+
2099
2222
  /**
2100
2223
  * Identity helper that types a declarative route tree. Use it so editors give
2101
2224
  * autocomplete and type-checking on every node; the array is returned as-is.
@@ -2261,6 +2384,22 @@ export declare interface DropzoneProps {
2261
2384
  className?: string;
2262
2385
  }
2263
2386
 
2387
+ /**
2388
+ * Look up the duration multiplier for a travel mode, falling back to `1.0`
2389
+ * for unknown modes. Mirrors `duration_factor` from `tempest-fastapi-sdk`.
2390
+ *
2391
+ * @param mode - Travel mode.
2392
+ * @param factors - Optional override map (partial merges over the defaults).
2393
+ * @returns The multiplier for `mode`.
2394
+ */
2395
+ export declare function durationFactor(mode: TravelMode, factors?: Partial<Record<TravelMode, number>>): number;
2396
+
2397
+ /**
2398
+ * Mean Earth radius in kilometers. Same value used by `tempest-fastapi-sdk`
2399
+ * (`geo/distance.py`) so client and server distances agree.
2400
+ */
2401
+ export declare const EARTH_RADIUS_KM = 6371.0088;
2402
+
2264
2403
  export declare interface ElementSize {
2265
2404
  width: number;
2266
2405
  height: number;
@@ -2365,6 +2504,37 @@ export declare interface ErrorTextProps extends HTMLAttributes<HTMLParagraphElem
2365
2504
 
2366
2505
  export declare function estimatePasswordStrength(value: string): PasswordStrength;
2367
2506
 
2507
+ /**
2508
+ * Offline travel estimate between two coordinates. No network — distance comes
2509
+ * from {@link haversineKm} scaled by circuity, duration from a mode-adjusted
2510
+ * average speed. Mirrors `estimate_travel` from `tempest-fastapi-sdk`.
2511
+ *
2512
+ * @param origin - Start coordinate.
2513
+ * @param destination - End coordinate.
2514
+ * @param mode - Travel mode. Default: `"car"`.
2515
+ * @param options - Tuning knobs (circuity, speed, per-mode factors).
2516
+ * @returns A `"heuristic"` {@link TravelEstimate}.
2517
+ * @throws {RangeError} If `carSpeedKmh <= 0` or `circuityFactor <= 0`.
2518
+ *
2519
+ * @example
2520
+ * estimateTravel(
2521
+ * { latitude: -23.5505, longitude: -46.6333 },
2522
+ * { latitude: -23.5629, longitude: -46.6544 },
2523
+ * "car",
2524
+ * ); // { mode: "car", distance_km: …, duration_minutes: …, source: "heuristic" }
2525
+ */
2526
+ export declare function estimateTravel(origin: Coordinate, destination: Coordinate, mode?: TravelMode, options?: EstimateTravelOptions): TravelEstimate;
2527
+
2528
+ /** Options for {@link estimateTravel}. */
2529
+ export declare interface EstimateTravelOptions {
2530
+ /** Distance multiplier over the great-circle line. Default: `1.3`. */
2531
+ circuityFactor?: number;
2532
+ /** Average car speed in km/h. Default: `50`. */
2533
+ carSpeedKmh?: number;
2534
+ /** Per-mode duration multipliers (merged over the defaults). */
2535
+ modeDurationFactors?: Partial<Record<TravelMode, number>>;
2536
+ }
2537
+
2368
2538
  export declare interface EventStreamController {
2369
2539
  close: () => void;
2370
2540
  /** Force an immediate reconnect, resetting the retry counter. */
@@ -2386,6 +2556,18 @@ export declare interface EventStreamMessage<T> {
2386
2556
 
2387
2557
  export declare type EventStreamStatus = "idle" | "connecting" | "open" | "closed" | "error";
2388
2558
 
2559
+ /**
2560
+ * Grow a bounding box outward by `ratio` of its own span on every side, with a
2561
+ * small absolute floor so a single-point (zero-span) box still gets padding.
2562
+ * A `ratio` of `0.1` adds 10% margin — handy so a plotted trajectory does not
2563
+ * hug the edge of the viewport.
2564
+ *
2565
+ * @param bounds - The box to expand.
2566
+ * @param ratio - Fraction of the span to add per side. Default: `0.1`.
2567
+ * @returns A new, larger {@link GeoBounds}.
2568
+ */
2569
+ export declare function expandBounds(bounds: GeoBounds, ratio?: number): GeoBounds;
2570
+
2389
2571
  export declare interface FeatureFlagsAdapter {
2390
2572
  /** Synchronous lookup of a flag with a default. */
2391
2573
  isEnabled: (key: string, defaultValue?: boolean) => boolean;
@@ -2446,6 +2628,38 @@ export declare interface FileUploadProps {
2446
2628
 
2447
2629
  export declare type FilterPredicate<T> = (item: T, search: string) => boolean;
2448
2630
 
2631
+ /**
2632
+ * Build a projection that fits `bounds` into a `width × height` viewport while
2633
+ * preserving aspect ratio (uniform scale, centered). This is what powers the
2634
+ * tile-free trajectory plot: project the bounds, scale to the SVG box, keep
2635
+ * shapes undistorted.
2636
+ *
2637
+ * @param bounds - Geographic extent to fit.
2638
+ * @param width - Viewport width in pixels.
2639
+ * @param height - Viewport height in pixels.
2640
+ * @param options - Padding tuning.
2641
+ * @returns A {@link FittedProjection} with a `project(coord)` mapper.
2642
+ */
2643
+ export declare function fitProjection(bounds: GeoBounds, width: number, height: number, options?: FitProjectionOptions): FittedProjection;
2644
+
2645
+ /** Options for {@link fitProjection}. */
2646
+ export declare interface FitProjectionOptions {
2647
+ /** Inner padding in pixels kept clear on every edge. Default: `16`. */
2648
+ padding?: number;
2649
+ }
2650
+
2651
+ /** A ready-to-use mapping from coordinates to viewport pixels. */
2652
+ export declare interface FittedProjection {
2653
+ /** Project a coordinate to a pixel inside the viewport. */
2654
+ project: (coord: Coordinate) => PixelPoint;
2655
+ /** Uniform scale (unit-plane → pixels) actually used, after aspect fit. */
2656
+ scale: number;
2657
+ /** Viewport width in pixels. */
2658
+ width: number;
2659
+ /** Viewport height in pixels. */
2660
+ height: number;
2661
+ }
2662
+
2449
2663
  export declare type FlagValue = boolean | string | number | null;
2450
2664
 
2451
2665
  /**
@@ -2739,6 +2953,17 @@ export declare interface ForProps<T> {
2739
2953
  */
2740
2954
  export declare function generateIdempotencyKey(): string;
2741
2955
 
2956
+ /**
2957
+ * Axis-aligned geographic bounding box. `min`/`max` follow the same degree
2958
+ * ranges as {@link Coordinate}.
2959
+ */
2960
+ export declare interface GeoBounds {
2961
+ minLatitude: number;
2962
+ maxLatitude: number;
2963
+ minLongitude: number;
2964
+ maxLongitude: number;
2965
+ }
2966
+
2742
2967
  export declare interface GeolocationState {
2743
2968
  loading: boolean;
2744
2969
  error: GeolocationPositionError | null;
@@ -2880,6 +3105,22 @@ export declare interface GrowthBookLike {
2880
3105
 
2881
3106
  export { HashRouter }
2882
3107
 
3108
+ /**
3109
+ * Great-circle distance between two coordinates using the haversine formula
3110
+ * (spherical Earth). Mirrors `haversine_km` from `tempest-fastapi-sdk`.
3111
+ *
3112
+ * @param origin - Start coordinate.
3113
+ * @param destination - End coordinate.
3114
+ * @returns Distance in kilometers (`>= 0`).
3115
+ *
3116
+ * @example
3117
+ * haversineKm(
3118
+ * { latitude: -23.5505, longitude: -46.6333 }, // São Paulo
3119
+ * { latitude: -22.9068, longitude: -43.1729 }, // Rio de Janeiro
3120
+ * ); // ≈ 360.9
3121
+ */
3122
+ export declare function haversineKm(origin: Coordinate, destination: Coordinate): number;
3123
+
2883
3124
  /** Inverse of `<Show>` — hides children when the condition matches. */
2884
3125
  export declare function Hide({ above, below, only, children }: HideProps): ReactNode;
2885
3126
 
@@ -3199,6 +3440,12 @@ export declare type InterpolationValues = Record<string, string | number>;
3199
3440
  */
3200
3441
  export declare function isApiError(error: unknown): error is ApiError;
3201
3442
 
3443
+ /**
3444
+ * Type guard for {@link Coordinate}: an object with finite, in-range
3445
+ * `latitude` and `longitude`.
3446
+ */
3447
+ export declare function isCoordinate(value: unknown): value is Coordinate;
3448
+
3202
3449
  /**
3203
3450
  * Type guard for a {@link CursorPage} envelope.
3204
3451
  *
@@ -3296,6 +3543,12 @@ export declare function isShareSupported(): boolean;
3296
3543
  */
3297
3544
  export declare function isString(value: unknown): value is string;
3298
3545
 
3546
+ /** True when `value` is a finite latitude in `[-90, 90]`. */
3547
+ export declare function isValidLatitude(value: number): boolean;
3548
+
3549
+ /** True when `value` is a finite longitude in `[-180, 180]`. */
3550
+ export declare function isValidLongitude(value: number): boolean;
3551
+
3299
3552
  /**
3300
3553
  * Renders a `<kbd>` styled like a keyboard key — useful for shortcut hints.
3301
3554
  * Compose multiple keys by rendering siblings: `<Kbd>Ctrl</Kbd> + <Kbd>K</Kbd>`.
@@ -3558,6 +3811,21 @@ export declare interface MenubarProps extends HTMLAttributes<HTMLDivElement> {
3558
3811
  menus: MenubarMenu[];
3559
3812
  }
3560
3813
 
3814
+ /**
3815
+ * Web Mercator (EPSG:3857) latitude clamp. Latitudes beyond this diverge to
3816
+ * infinity in the projection, so tile maps cap here.
3817
+ */
3818
+ export declare const MERCATOR_MAX_LATITUDE = 85.05112878;
3819
+
3820
+ /**
3821
+ * A point projected onto the unit Web Mercator plane. Both axes are in `[0, 1]`
3822
+ * — `x` grows east, `y` grows south (screen convention).
3823
+ */
3824
+ export declare interface MercatorPoint {
3825
+ x: number;
3826
+ y: number;
3827
+ }
3828
+
3561
3829
  export declare type Messages = Record<string, string>;
3562
3830
 
3563
3831
  /**
@@ -3812,6 +4080,12 @@ export declare interface NavigationRailProps extends Omit<HTMLAttributes<HTMLEle
3812
4080
 
3813
4081
  export { NavLink }
3814
4082
 
4083
+ /**
4084
+ * Normalize a longitude into the `[-180, 180]` range, wrapping values that
4085
+ * cross the antimeridian (e.g. `190` → `-170`).
4086
+ */
4087
+ export declare function normalizeLongitude(longitude: number): number;
4088
+
3815
4089
  /**
3816
4090
  * Module-level singleton progress controller. Drive it imperatively from
3817
4091
  * anywhere (router transitions, fetch interceptors) and render the visual bar
@@ -4011,6 +4285,19 @@ export declare interface OpenModalOptions {
4011
4285
  onClose?: () => void;
4012
4286
  }
4013
4287
 
4288
+ /** Options for {@link createOSRMBackend}. */
4289
+ export declare interface OSRMBackendOptions {
4290
+ /**
4291
+ * Base URL of an **OSRM** HTTP server. There is no default on purpose — this
4292
+ * SDK ships no external endpoint. Point it at a routing engine **you host**.
4293
+ */
4294
+ baseUrl: string;
4295
+ /** `fetch` implementation. Default: the global `fetch`. */
4296
+ fetch?: typeof globalThis.fetch;
4297
+ /** Per-mode duration multipliers applied over the car profile. */
4298
+ modeDurationFactors?: Partial<Record<TravelMode, number>>;
4299
+ }
4300
+
4014
4301
  export { Outlet }
4015
4302
 
4016
4303
  /**
@@ -4113,6 +4400,15 @@ export declare type PasswordStrength = 0 | 1 | 2 | 3 | 4;
4113
4400
 
4114
4401
  export { Path }
4115
4402
 
4403
+ /**
4404
+ * Total length of a trajectory: the sum of haversine distances between each
4405
+ * consecutive pair of points. Returns `0` for an empty or single-point path.
4406
+ *
4407
+ * @param points - Ordered coordinates along the path.
4408
+ * @returns Cumulative distance in kilometers.
4409
+ */
4410
+ export declare function pathLengthKm(points: readonly Coordinate[]): number;
4411
+
4116
4412
  /**
4117
4413
  * Extract a permission list from a JWT.
4118
4414
  *
@@ -4193,6 +4489,12 @@ export declare type PinInputSize = "sm" | "md" | "lg";
4193
4489
 
4194
4490
  export declare type PinInputType = "numeric" | "alphanumeric";
4195
4491
 
4492
+ /** A pixel coordinate inside the plotting viewport. */
4493
+ export declare interface PixelPoint {
4494
+ x: number;
4495
+ y: number;
4496
+ }
4497
+
4196
4498
  /**
4197
4499
  * Convenience wrapper around a shared {@link AudioPlayer}. Use this for
4198
4500
  * one-off notification sounds. For more complex flows (e.g. several
@@ -4281,6 +4583,22 @@ export declare interface PortalProps {
4281
4583
  container?: Element | null;
4282
4584
  }
4283
4585
 
4586
+ /** Imperative controller returned by {@link createPositionTracker}. */
4587
+ export declare interface PositionTracker {
4588
+ /** Begin watching position. No-op if already tracking. */
4589
+ start: () => void;
4590
+ /** Stop watching. Retains the recorded trajectory. */
4591
+ stop: () => void;
4592
+ /** Stop and discard the recorded trajectory. */
4593
+ clear: () => void;
4594
+ /** Snapshot of the recorded trajectory (newest last). */
4595
+ readonly points: readonly TrackPoint[];
4596
+ /** Total distance of the recorded trajectory in kilometers. */
4597
+ readonly distanceKm: number;
4598
+ /** Current tracker status. */
4599
+ readonly status: TrackerStatus;
4600
+ }
4601
+
4284
4602
  /**
4285
4603
  * Minimal subset of `posthog-js` used by the adapter. Pass either the real
4286
4604
  * default export (`import posthog from "posthog-js"`) or a stubbed object
@@ -4313,6 +4631,16 @@ export declare interface ProgressProps {
4313
4631
 
4314
4632
  export declare type ProgressVariant = "primary" | "success" | "warning" | "danger";
4315
4633
 
4634
+ /**
4635
+ * Project a geographic coordinate onto the unit Web Mercator plane. This is the
4636
+ * same projection tile servers use, so a self-hosted tile layer and the
4637
+ * tile-free SVG plot line up pixel-for-pixel.
4638
+ *
4639
+ * @param coord - Coordinate to project.
4640
+ * @returns `{ x, y }` in `[0, 1]`.
4641
+ */
4642
+ export declare function projectMercator(coord: Coordinate): MercatorPoint;
4643
+
4316
4644
  /**
4317
4645
  * Service-worker context helpers for handling `push` and `notificationclick`
4318
4646
  * events. Import these inside your own `sw.ts` — they expect to run in the
@@ -4700,6 +5028,21 @@ export declare type RouterKind = "browser" | "hash" | "memory";
4700
5028
 
4701
5029
  export { Routes }
4702
5030
 
5031
+ /**
5032
+ * Pluggable routing backend. A backend turns two coordinates into a
5033
+ * {@link TravelEstimate}. Mirrors the `RoutingBackend` protocol from
5034
+ * `tempest-fastapi-sdk` so client and server share the same contract.
5035
+ *
5036
+ * Implement this to route against your own self-hosted engine (OSRM, Valhalla,
5037
+ * GraphHopper). The offline {@link estimateTravel} heuristic satisfies the same
5038
+ * shape without any network.
5039
+ */
5040
+ export declare interface RoutingBackend {
5041
+ route: (origin: Coordinate, destination: Coordinate, options?: {
5042
+ mode?: TravelMode;
5043
+ }) => Promise<TravelEstimate>;
5044
+ }
5045
+
4703
5046
  /** A single runtime-caching rule, matched against each `GET` request. */
4704
5047
  export declare interface RuntimeRoute {
4705
5048
  /** A `RegExp` tested against the full URL, or a predicate over the parsed URL. */
@@ -5741,6 +6084,89 @@ export declare interface TooltipProps {
5741
6084
  openDelay?: number;
5742
6085
  }
5743
6086
 
6087
+ /** Convert degrees to radians. */
6088
+ export declare function toRadians(degrees: number): number;
6089
+
6090
+ /** Lifecycle status of a {@link PositionTracker}. */
6091
+ export declare type TrackerStatus = "idle" | "tracking" | "error";
6092
+
6093
+ /**
6094
+ * A single sample in a recorded trajectory: a {@link Coordinate} stamped with
6095
+ * the epoch millisecond it was captured, plus the optional accuracy radius
6096
+ * reported by the Geolocation API.
6097
+ */
6098
+ export declare interface TrackPoint extends Coordinate {
6099
+ /** Capture time in epoch milliseconds (`GeolocationPosition.timestamp`). */
6100
+ timestamp: number;
6101
+ /** Horizontal accuracy radius in meters, if the device reported one. */
6102
+ accuracy?: number;
6103
+ }
6104
+
6105
+ /**
6106
+ * Plot a GPS trajectory. By default it renders a **tile-free SVG** map (Web
6107
+ * Mercator projection, auto-fit to the points, optional grid + scale bar) —
6108
+ * 100% self-contained, no external tiles or paid API. Pass `tileUrl` pointing
6109
+ * at a map server **you host** to upgrade to a real Leaflet tile layer.
6110
+ *
6111
+ * @example
6112
+ * // Zero-dependency SVG plot
6113
+ * <TrajectoryMap points={points} current={lastPoint} height={360} />
6114
+ *
6115
+ * @example
6116
+ * // Real tiles from your own server (requires `leaflet` installed)
6117
+ * <TrajectoryMap points={points} tileUrl="https://tiles.internal/{z}/{x}/{y}.png" />
6118
+ */
6119
+ export declare function TrajectoryMap({ points, current, height, padding, showGrid, showScale, strokeColor, tileUrl, tileAttribution, label, className, style, ...rest }: TrajectoryMapProps): JSX.Element;
6120
+
6121
+ export declare interface TrajectoryMapProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
6122
+ /** Ordered coordinates forming the trajectory. */
6123
+ points: readonly Coordinate[];
6124
+ /** Optional "current position" marker, drawn on top of the path. */
6125
+ current?: Coordinate | null;
6126
+ /** Viewport height in pixels. Default: `320`. */
6127
+ height?: number;
6128
+ /** Inner padding in pixels kept clear on every edge. Default: `24`. */
6129
+ padding?: number;
6130
+ /** Draw a light reference grid behind the path (SVG mode). Default: `true`. */
6131
+ showGrid?: boolean;
6132
+ /** Draw a distance scale bar (SVG mode). Default: `true`. */
6133
+ showScale?: boolean;
6134
+ /** Path stroke color. Default: the primary token. */
6135
+ strokeColor?: string;
6136
+ /**
6137
+ * Tile URL template (`{z}/{x}/{y}`) of a map server **you host**. When set,
6138
+ * the map upgrades to a real Leaflet tile layer (requires `leaflet` to be
6139
+ * installed). Omit for the zero-dependency, zero-network SVG plot.
6140
+ */
6141
+ tileUrl?: string;
6142
+ /** Attribution text shown over the tile layer. */
6143
+ tileAttribution?: string;
6144
+ /** Accessible label for the map region. Default: `"Trajetória"`. */
6145
+ label?: string;
6146
+ }
6147
+
6148
+ /**
6149
+ * Estimated travel between two coordinates. Mirrors the `TravelEstimate`
6150
+ * schema from `tempest-fastapi-sdk` (`geo/schemas.py`), snake_case preserved so
6151
+ * a response deserializes straight into this type.
6152
+ */
6153
+ export declare interface TravelEstimate {
6154
+ /** Travel mode the estimate was computed for. */
6155
+ mode: TravelMode;
6156
+ /** Great-circle distance scaled by circuity, in kilometers (`>= 0`). */
6157
+ distance_km: number;
6158
+ /** Estimated duration in minutes (`>= 0`). */
6159
+ duration_minutes: number;
6160
+ /** How the estimate was produced. `"heuristic"` (offline) or `"osrm"`. */
6161
+ source: "heuristic" | "osrm";
6162
+ }
6163
+
6164
+ /**
6165
+ * Travel mode. Mirrors the `TravelMode` string enum from `tempest-fastapi-sdk`
6166
+ * (`geo/enums.py`) — the on-the-wire value is the raw string.
6167
+ */
6168
+ export declare type TravelMode = "car" | "motorcycle" | "bus";
6169
+
5744
6170
  /**
5745
6171
  * Truncate a string to `max` characters, appending `suffix` when cut.
5746
6172
  * Returns the original when shorter than (or equal to) `max`.
@@ -5788,6 +6214,15 @@ export declare function uniqueBy<T>(items: T[], key: (item: T) => unknown): T[];
5788
6214
  /** Strip any masking and return only digits. */
5789
6215
  export declare function unmask(value: string): string;
5790
6216
 
6217
+ /**
6218
+ * Inverse of {@link projectMercator}: recover a coordinate from a unit-plane
6219
+ * point.
6220
+ *
6221
+ * @param point - `{ x, y }` in `[0, 1]`.
6222
+ * @returns The geographic coordinate.
6223
+ */
6224
+ export declare function unprojectMercator(point: MercatorPoint): Coordinate;
6225
+
5791
6226
  /**
5792
6227
  * Unregister all registered service workers for this origin.
5793
6228
  *
@@ -6597,6 +7032,49 @@ export declare interface UsePollResult<T> {
6597
7032
  start: () => void;
6598
7033
  }
6599
7034
 
7035
+ /**
7036
+ * React hook wrapping {@link createPositionTracker}. Records a live GPS
7037
+ * trajectory tied to the component lifecycle — the watch is torn down on
7038
+ * unmount. Fully browser-side; no external service.
7039
+ *
7040
+ * @example
7041
+ * const { points, distanceKm, isTracking, start, stop } = usePositionTracker({
7042
+ * minDistanceKm: 0.01,
7043
+ * });
7044
+ * return (
7045
+ * <>
7046
+ * <button onClick={isTracking ? stop : start}>{isTracking ? "Parar" : "Rastrear"}</button>
7047
+ * <TrajectoryMap points={points} />
7048
+ * <span>{distanceKm.toFixed(2)} km</span>
7049
+ * </>
7050
+ * );
7051
+ */
7052
+ export declare function usePositionTracker(options?: UsePositionTrackerOptions): UsePositionTrackerResult;
7053
+
7054
+ export declare interface UsePositionTrackerOptions extends Omit<CreatePositionTrackerOptions, "onUpdate" | "onStatusChange"> {
7055
+ /** Start tracking automatically on mount. Default: `false`. */
7056
+ autoStart?: boolean;
7057
+ }
7058
+
7059
+ export declare interface UsePositionTrackerResult {
7060
+ /** Recorded trajectory (newest last). */
7061
+ points: readonly TrackPoint[];
7062
+ /** Most recent point, or `null` before the first fix. */
7063
+ lastPoint: TrackPoint | null;
7064
+ /** Total distance of the trajectory in kilometers. */
7065
+ distanceKm: number;
7066
+ /** Current tracker status. */
7067
+ status: TrackerStatus;
7068
+ /** True while `status === "tracking"`. */
7069
+ isTracking: boolean;
7070
+ /** Begin watching position. */
7071
+ start: () => void;
7072
+ /** Stop watching, keeping the trajectory. */
7073
+ stop: () => void;
7074
+ /** Stop and discard the trajectory. */
7075
+ clear: () => void;
7076
+ }
7077
+
6600
7078
  /**
6601
7079
  * Return the value from the previous render. `undefined` on the first render.
6602
7080
  *