@buoy-gg/location 7.0.44

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 (68) hide show
  1. package/LICENSE +58 -0
  2. package/README.md +29 -0
  3. package/lib/commonjs/components/LocationBody.js +1 -0
  4. package/lib/commonjs/components/LocationChip.js +1 -0
  5. package/lib/commonjs/components/LocationToolView.js +1 -0
  6. package/lib/commonjs/components/SchematicMap.js +1 -0
  7. package/lib/commonjs/components/format.js +1 -0
  8. package/lib/commonjs/engine/adapters/community.js +1 -0
  9. package/lib/commonjs/engine/adapters/expo.js +3 -0
  10. package/lib/commonjs/engine/adapters/expoModulesCore.js +1 -0
  11. package/lib/commonjs/engine/adapters/expoModulesCore.web.js +1 -0
  12. package/lib/commonjs/engine/adapters/index.js +1 -0
  13. package/lib/commonjs/engine/adapters/wrap.js +1 -0
  14. package/lib/commonjs/engine/fixtures.js +1 -0
  15. package/lib/commonjs/engine/geo.js +1 -0
  16. package/lib/commonjs/engine/model.js +1 -0
  17. package/lib/commonjs/engine/persistence.js +1 -0
  18. package/lib/commonjs/engine/readSavedSync.js +1 -0
  19. package/lib/commonjs/engine/readSavedSync.web.js +1 -0
  20. package/lib/commonjs/engine/store.js +1 -0
  21. package/lib/commonjs/index.js +1 -0
  22. package/lib/commonjs/package.json +1 -0
  23. package/lib/commonjs/preset.js +1 -0
  24. package/lib/commonjs/sync/locationSyncAdapter.js +1 -0
  25. package/lib/module/components/LocationBody.js +1 -0
  26. package/lib/module/components/LocationChip.js +1 -0
  27. package/lib/module/components/LocationToolView.js +1 -0
  28. package/lib/module/components/SchematicMap.js +1 -0
  29. package/lib/module/components/format.js +1 -0
  30. package/lib/module/engine/adapters/community.js +1 -0
  31. package/lib/module/engine/adapters/expo.js +3 -0
  32. package/lib/module/engine/adapters/expoModulesCore.js +1 -0
  33. package/lib/module/engine/adapters/expoModulesCore.web.js +1 -0
  34. package/lib/module/engine/adapters/index.js +1 -0
  35. package/lib/module/engine/adapters/wrap.js +1 -0
  36. package/lib/module/engine/fixtures.js +1 -0
  37. package/lib/module/engine/geo.js +1 -0
  38. package/lib/module/engine/model.js +1 -0
  39. package/lib/module/engine/persistence.js +1 -0
  40. package/lib/module/engine/readSavedSync.js +1 -0
  41. package/lib/module/engine/readSavedSync.web.js +1 -0
  42. package/lib/module/engine/store.js +1 -0
  43. package/lib/module/index.js +1 -0
  44. package/lib/module/preset.js +1 -0
  45. package/lib/module/sync/locationSyncAdapter.js +1 -0
  46. package/lib/typescript/components/LocationBody.d.ts +2 -0
  47. package/lib/typescript/components/LocationChip.d.ts +8 -0
  48. package/lib/typescript/components/LocationToolView.d.ts +8 -0
  49. package/lib/typescript/components/SchematicMap.d.ts +10 -0
  50. package/lib/typescript/components/format.d.ts +24 -0
  51. package/lib/typescript/engine/adapters/community.d.ts +11 -0
  52. package/lib/typescript/engine/adapters/expo.d.ts +9 -0
  53. package/lib/typescript/engine/adapters/expoModulesCore.d.ts +8 -0
  54. package/lib/typescript/engine/adapters/expoModulesCore.web.d.ts +4 -0
  55. package/lib/typescript/engine/adapters/index.d.ts +6 -0
  56. package/lib/typescript/engine/adapters/wrap.d.ts +25 -0
  57. package/lib/typescript/engine/fixtures.d.ts +24 -0
  58. package/lib/typescript/engine/geo.d.ts +116 -0
  59. package/lib/typescript/engine/model.d.ts +70 -0
  60. package/lib/typescript/engine/persistence.d.ts +22 -0
  61. package/lib/typescript/engine/readSavedSync.d.ts +9 -0
  62. package/lib/typescript/engine/readSavedSync.web.d.ts +4 -0
  63. package/lib/typescript/engine/store.d.ts +187 -0
  64. package/lib/typescript/index.d.ts +15 -0
  65. package/lib/typescript/preset.d.ts +45 -0
  66. package/lib/typescript/sync/locationSyncAdapter.d.ts +29 -0
  67. package/lib/web/index.mjs +3 -0
  68. package/package.json +110 -0
@@ -0,0 +1,187 @@
1
+ import { type Coordinate, type Fix, type Region, type RegionState } from "./geo";
2
+ import { type LocationConditions, type LocationOverride, type LocationSettings, type NamedRoute, type Place } from "./model";
3
+ import { type SavedTask, type TaskKind } from "./persistence";
4
+ export declare function realSetTimeout(fn: () => void, ms: number): unknown;
5
+ export { CONDITIONS, currentConditions, type LocationConditions } from "./model";
6
+ export type Precision = "full" | "reduced";
7
+ /** What the app's permission getter reports (the device, or the Permissions tool's override). */
8
+ export interface PermissionInfo {
9
+ status: "granted" | "denied" | "undetermined";
10
+ /** Background ("Always") permission, or null when the library can't say. */
11
+ background: boolean | null;
12
+ precision: Precision;
13
+ }
14
+ export interface WatchRegistration {
15
+ library: string;
16
+ id: number | string;
17
+ kind: "position" | "heading";
18
+ /** Options the app passed (accuracy, distanceInterval, timeInterval…). */
19
+ options: Record<string, unknown>;
20
+ /** Called with each new fix (position watches) or heading (heading watches). */
21
+ deliver: (fix: Fix) => void;
22
+ /** Called when the watch should see an error (services switched off). */
23
+ fail?: (reason: string) => void;
24
+ }
25
+ export interface WatchInfo {
26
+ key: string;
27
+ library: string;
28
+ id: number | string;
29
+ kind: "position" | "heading";
30
+ options: Record<string, unknown>;
31
+ since: number;
32
+ updates: number;
33
+ }
34
+ export interface Adapter {
35
+ library: string;
36
+ /** Run a task the app defined with TaskManager.defineTask. Resolves with what it returned. */
37
+ fireTask?: (task: SavedTask, data: unknown) => Promise<unknown>;
38
+ /** The override turned on (true) or off (false): move native watches and tasks. */
39
+ onActiveChange?: (active: boolean) => void;
40
+ /** The app's current permission, as its own permission getter reports it. */
41
+ readPermission?: () => Promise<PermissionInfo | null>;
42
+ }
43
+ export interface RegionInfo extends Region {
44
+ /** A registered place at the region's center ("BK Riverton"), else null. */
45
+ label: string | null;
46
+ state: RegionState;
47
+ /** Meters from the current simulated position, or null with no fix. */
48
+ distance: number | null;
49
+ }
50
+ export interface TaskInfo {
51
+ name: string;
52
+ kind: TaskKind;
53
+ library: string;
54
+ intercepted: boolean;
55
+ since: number;
56
+ runs: number;
57
+ regions: RegionInfo[];
58
+ options: Record<string, unknown>;
59
+ }
60
+ export type LogKind = "request" | "watch" | "enter" | "exit" | "batch" | "error" | "task";
61
+ export interface LogEntry {
62
+ id: number;
63
+ at: number;
64
+ kind: LogKind;
65
+ library: string;
66
+ /** What happened, in the app's terms ("Entered BK Riverton"). */
67
+ text: string;
68
+ /** Technical detail: task names, watch ids, return values. */
69
+ detail?: string;
70
+ }
71
+ export interface LocationSnapshot {
72
+ /** Anything differs from the real device (position, signal or services). */
73
+ active: boolean;
74
+ /** Positions come from the override. */
75
+ simulating: boolean;
76
+ override: LocationOverride;
77
+ /** What the app would get right now, or why it gets nothing. */
78
+ current: {
79
+ fix: Fix | null;
80
+ reason: "real" | "signal" | "gap" | "services" | null;
81
+ precision: Precision;
82
+ };
83
+ /** The app's location permission, or null when no library reports it. */
84
+ permission: PermissionInfo | null;
85
+ /** Where the simulation is right now, even in a dead zone; null on the real location. */
86
+ position: Coordinate | null;
87
+ /** Present in route mode. */
88
+ progress: {
89
+ along: number;
90
+ length: number;
91
+ finished: boolean;
92
+ leg: number;
93
+ etaMs: number | null;
94
+ } | null;
95
+ watches: WatchInfo[];
96
+ tasks: TaskInfo[];
97
+ log: LogEntry[];
98
+ /** Location libraries found in the app's binary and patched. */
99
+ libraries: string[];
100
+ places: Place[];
101
+ routes: NamedRoute[];
102
+ settings: LocationSettings;
103
+ lastDeliveryAt: number | null;
104
+ }
105
+ export declare function subscribeLocation(listener: () => void): () => void;
106
+ export declare function addLog(kind: LogKind, library: string, text: string, detail?: string): void;
107
+ export declare function isLocationActive(): boolean;
108
+ export declare function isSimulating(): boolean;
109
+ export declare function servicesEnabled(): boolean;
110
+ export declare function getPrecision(): Precision;
111
+ /** Adapters report the permission accuracy they read (Permissions tool overrides included). */
112
+ export declare function notePrecision(next: Precision | null): void;
113
+ /** Adapters report the whole permission state they read. */
114
+ export declare function notePermission(next: PermissionInfo | null): void;
115
+ /** The fix the app should see at `now`, or why there is none. */
116
+ export declare function currentFix(now?: number): {
117
+ fix: Fix | null;
118
+ reason: LocationSnapshot["current"]["reason"];
119
+ };
120
+ /** Ask each adapter for the app's current permission. The tool calls this while it is open. */
121
+ export declare function refreshLocationPermission(): void;
122
+ export declare function registerAdapter(adapter: Adapter): void;
123
+ export declare function getAdapters(): string[];
124
+ export declare function trackWatch(reg: WatchRegistration): void;
125
+ export declare function untrackWatch(library: string, kind: "position" | "heading", id: number | string): boolean;
126
+ export declare function hasWatch(library: string, kind: "position" | "heading", id: number | string): boolean;
127
+ /** Record a geofence or background task. Intercepted = the native side never saw it. */
128
+ export declare function trackTask(saved: SavedTask, intercepted: boolean): void;
129
+ export declare function untrackTask(name: string): SavedTask | null;
130
+ export declare function getTask(name: string): (SavedTask & {
131
+ intercepted: boolean;
132
+ }) | null;
133
+ export declare function getTasks(kind?: TaskKind): Array<SavedTask & {
134
+ intercepted: boolean;
135
+ }>;
136
+ /** Mark whether the native side is running a task (after moving it on or off the override). */
137
+ export declare function setTaskIntercepted(name: string, intercepted: boolean): void;
138
+ /** Add named places to the tool's list (for example your app's stores). */
139
+ export declare function registerLocationPlaces(places: Place[]): void;
140
+ /** Add named routes to the tool's list. Each needs two or more points. */
141
+ export declare function registerLocationRoutes(routes: NamedRoute[]): void;
142
+ /** Pin the app to one place. */
143
+ export declare function setPlace(place: Place): LocationSnapshot;
144
+ /** Where the route or pin currently is, for starting the next thing from here. */
145
+ export declare function currentPoint(): Coordinate;
146
+ /** Play a route from its first point. */
147
+ export declare function startRoute(route: NamedRoute): LocationSnapshot;
148
+ export declare function pauseRoute(): LocationSnapshot;
149
+ export declare function resumeRoute(): LocationSnapshot;
150
+ /** Jump to a point along the route, in meters from its start. */
151
+ export declare function seekRoute(meters: number): LocationSnapshot;
152
+ export declare function setRouteSpeed(speed: number): LocationSnapshot;
153
+ export interface OverrideTuning {
154
+ accuracy?: number;
155
+ jitter?: number;
156
+ altitude?: number | null;
157
+ heading?: number | null;
158
+ interval?: number;
159
+ }
160
+ export declare function tuneOverride(t: OverrideTuning): LocationSnapshot;
161
+ export declare function setSignal(on: boolean): LocationSnapshot;
162
+ export declare function setServices(on: boolean): LocationSnapshot;
163
+ /** Set signal, services, accuracy and drift in one step. */
164
+ export declare function setConditions(name: LocationConditions): LocationSnapshot;
165
+ /** Stop a route and stay where it got to. */
166
+ export declare function stopRoute(): LocationSnapshot;
167
+ /** Stop simulating the position; signal and services settings stay. */
168
+ export declare function useRealLocation(): LocationSnapshot;
169
+ /** Move just inside or just outside a geofence region. */
170
+ export declare function moveToRegion(identifier: string, side: "inside" | "outside", taskName?: string): LocationSnapshot;
171
+ /** Everything back to the real device. */
172
+ export declare function resetLocation(): LocationSnapshot;
173
+ export declare function updateLocationSettings(patch: Partial<LocationSettings>): LocationSnapshot;
174
+ export declare function getLocationSettings(): LocationSettings;
175
+ export declare function clearLog(): LocationSnapshot;
176
+ export declare function getLocationSnapshot(): LocationSnapshot;
177
+ /**
178
+ * Restore a saved override. Synchronous when expo-file-system can read the
179
+ * file directly, so the override is in place before app code asks. Safe to
180
+ * call more than once.
181
+ */
182
+ export declare function bootLocation(): void;
183
+ /** Test hook: forget everything. */
184
+ export declare function __resetForTests(): void;
185
+ /** Test hook: run one loop step now. */
186
+ export declare function __tickForTests(): void;
187
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1,15 @@
1
+ export { locationToolPreset, createLocationTool } from "./preset";
2
+ export { LocationBody } from "./components/LocationBody";
3
+ export { LocationToolView } from "./components/LocationToolView";
4
+ export type { LocationToolViewProps, LocationActionHandler } from "./components/LocationToolView";
5
+ export { LocationChip, LOCATION_CHIP_ID } from "./components/LocationChip";
6
+ export { LocationToolIcon, LOCATION_TOOL_ICON_COLOR } from "@buoy-gg/shared-ui";
7
+ export { locationSyncAdapter } from "./sync/locationSyncAdapter";
8
+ export type { LocationSyncSnapshot, LocationAction } from "./sync/locationSyncAdapter";
9
+ export { bootLocation, setPlace, startRoute, pauseRoute, resumeRoute, seekRoute, setRouteSpeed, tuneOverride, setSignal, setServices, setConditions, stopRoute, moveToRegion, useRealLocation, resetLocation, registerLocationPlaces, registerLocationRoutes, getLocationSnapshot, subscribeLocation, isLocationActive, refreshLocationPermission, } from "./engine/store";
10
+ export type { LocationSnapshot, LocationConditions, PermissionInfo, TaskInfo, RegionInfo, WatchInfo, LogEntry, } from "./engine/store";
11
+ export { installLocationAdapters } from "./engine/adapters";
12
+ export type { LocationOverride, LocationMode, LocationSettings, NamedRoute, Place } from "./engine/model";
13
+ export { BUILT_IN_PLACES, ROUTE_PRESETS, buildPresetRoute } from "./engine/fixtures";
14
+ export { distanceMeters, bearingDegrees, destination, parseCoordinate, type Coordinate, type Fix, type Route, } from "./engine/geo";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Pre-configured Location tool for FloatingDevTools.
3
+ *
4
+ * @example
5
+ * ```tsx
6
+ * import { locationToolPreset } from '@buoy-gg/location';
7
+ *
8
+ * <FloatingDevTools apps={[locationToolPreset]} />
9
+ * ```
10
+ */
11
+ import { LocationBody } from "./components/LocationBody";
12
+ export declare const locationToolPreset: {
13
+ id: string;
14
+ name: string;
15
+ description: string;
16
+ slot: "both";
17
+ color: string;
18
+ icon: ({ size, color }: {
19
+ size: number;
20
+ color?: string;
21
+ slot?: string;
22
+ }) => import("react").JSX.Element;
23
+ component: typeof LocationBody;
24
+ modal: {
25
+ subtitle: string;
26
+ };
27
+ };
28
+ /** Create a custom Location tool configuration. */
29
+ export declare const createLocationTool: (options?: (Record<never, never> & import("@buoy-gg/shared-ui").ToolPresetOverrides) | undefined) => {
30
+ id: string;
31
+ name: string;
32
+ description: string;
33
+ slot: "both";
34
+ color: string;
35
+ icon: ({ size, color }: {
36
+ size: number;
37
+ color?: string;
38
+ slot?: string;
39
+ }) => import("react").JSX.Element;
40
+ component: typeof LocationBody;
41
+ modal: {
42
+ subtitle: string;
43
+ };
44
+ };
45
+ //# sourceMappingURL=preset.d.ts.map
@@ -0,0 +1,29 @@
1
+ import { type LocationSnapshot } from "../engine/store";
2
+ import type { Place } from "../engine/model";
3
+ import { ROUTE_PRESETS } from "../engine/fixtures";
4
+ export interface LocationSyncSnapshot extends LocationSnapshot {
5
+ builtInPlaces: Place[];
6
+ presets: typeof ROUTE_PRESETS;
7
+ }
8
+ export declare const locationSyncAdapter: import("@buoy-gg/shared-ui").SyncAdapter<LocationSyncSnapshot, {
9
+ getState(): LocationSyncSnapshot;
10
+ setLocation(params: unknown): LocationSyncSnapshot;
11
+ startRoute(params: unknown): LocationSyncSnapshot;
12
+ stopRoute(): LocationSyncSnapshot;
13
+ setConditions(params: unknown): LocationSyncSnapshot;
14
+ pauseRoute(): LocationSyncSnapshot;
15
+ resumeRoute(): LocationSyncSnapshot;
16
+ seekRoute(params: unknown): LocationSyncSnapshot;
17
+ setSpeed(params: unknown): LocationSyncSnapshot;
18
+ tune(params: unknown): LocationSyncSnapshot;
19
+ setSignal(params: unknown): LocationSyncSnapshot;
20
+ setServices(params: unknown): LocationSyncSnapshot;
21
+ enterRegion(params: unknown): LocationSyncSnapshot;
22
+ exitRegion(params: unknown): LocationSyncSnapshot;
23
+ useRealLocation(): LocationSyncSnapshot;
24
+ reset(): LocationSyncSnapshot;
25
+ updateSettings(params: unknown): LocationSyncSnapshot;
26
+ clearLog(): LocationSyncSnapshot;
27
+ }>;
28
+ export type LocationAction = keyof NonNullable<typeof locationSyncAdapter.actions>;
29
+ //# sourceMappingURL=locationSyncAdapter.d.ts.map
@@ -0,0 +1,3 @@
1
+ "use client";var Bt=Object.defineProperty;var si=Object.getOwnPropertyDescriptor;var ci=Object.getOwnPropertyNames;var ui=Object.prototype.hasOwnProperty;var di=(e,t)=>{for(var n in t)Bt(e,n,{get:t[n],enumerable:true})},jt=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ci(t))!ui.call(e,o)&&o!==n&&Bt(e,o,{get:()=>t[o],enumerable:!(i=si(t,o))||i.enumerable});return e},pi=(e,t,n)=>(jt(e,t,"default"),n&&jt(n,t,"default"));var Ft=process.env.NODE_ENV!=="production";typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);import{realNow as D}from"@buoy-gg/shared-ui/web";var _t=63710088e-1,Z=e=>e*Math.PI/180,ct=e=>e*180/Math.PI;function be(e){if(!e||typeof e!="object")return false;let{latitude:t,longitude:n}=e;return typeof t=="number"&&typeof n=="number"&&Number.isFinite(t)&&Number.isFinite(n)&&Math.abs(t)<=90&&Math.abs(n)<=180}function zt(e){let t=((e+180)%360+360)%360-180;return t===-180&&e>0?180:t}function U(e,t){let n=Z(t.latitude-e.latitude),i=Z(t.longitude-e.longitude),o=Math.sin(n/2)**2+Math.cos(Z(e.latitude))*Math.cos(Z(t.latitude))*Math.sin(i/2)**2;return 2*_t*Math.asin(Math.min(1,Math.sqrt(o)))}function qe(e,t){let n=Z(e.latitude),i=Z(t.latitude),o=Z(t.longitude-e.longitude),r=Math.sin(o)*Math.cos(i),l=Math.cos(n)*Math.sin(i)-Math.sin(n)*Math.cos(i)*Math.cos(o);return(ct(Math.atan2(r,l))+360)%360}function Re(e,t,n){let i=n/_t,o=Z(t),r=Z(e.latitude),l=Z(e.longitude),p=Math.asin(Math.sin(r)*Math.cos(i)+Math.cos(r)*Math.sin(i)*Math.cos(o)),f=l+Math.atan2(Math.sin(o)*Math.sin(i)*Math.cos(r),Math.cos(i)-Math.sin(r)*Math.sin(p));return{latitude:ct(p),longitude:zt(ct(f))}}function fi(e,t,n){if(n<=0)return{latitude:e.latitude,longitude:e.longitude};if(n>=1)return{latitude:t.latitude,longitude:t.longitude};let i=U(e,t);return i<1e-6?{latitude:e.latitude,longitude:e.longitude}:Re(e,qe(e,t),i*n)}function Wt(e){let t=[];for(let n=1;n<e.length;n++)t.push(U(e[n-1],e[n]));return t}function ut(e){return Wt(e).reduce((t,n)=>t+n,0)}function Ke(e,t){let{points:n}=e;if(n.length===0)throw new Error("A route needs at least one point.");let i=n[0];if(n.length===1)return{...i,along:0,heading:0,leg:0,finished:true,inGap:false};let o=Wt(n),r=o.reduce((y,T)=>y+T,0),l=Math.max(0,t),p=false;r<=0?(l=0,p=!e.loop):e.loop?l=l%r:l>=r&&(l=r,p=true);let f=(e.gaps??[]).some(([y,T])=>l>=y&&l<T),g=l;for(let y=0;y<o.length;y++){let T=o[y],S=n[y],C=n[y+1],F=y===o.length-1;if(g<T||F){let _=T>0?Math.min(1,g/T):1;return{...fi(S,C,_),along:l,heading:qe(S,C),leg:y,finished:p,inGap:f}}g-=T}return{...n[n.length-1],along:l,heading:0,leg:o.length-1,finished:p,inGap:f}}function gi(e,t,n){if(t<=0)return{latitude:e.latitude,longitude:e.longitude};let i=Ht(Math.sin(n*12.9898)*43758.5453),o=Ht(Math.sin(n*78.233)*12543.1234);return Re(e,i*360,Math.sqrt(o)*t)}function Ht(e){return e-Math.floor(e)}var hi=3e3;function mi(e){let t=Math.round(e.latitude/.03)*.03,n=.03/Math.max(.2,Math.cos(Z(t))),i=Math.round(e.longitude/n)*n;return{...e,latitude:Ut(t),longitude:Ut(zt(i)),accuracy:Math.max(e.accuracy,hi),heading:null,speed:null}}function Ut(e){return Math.round(e*1e6)/1e6}function yi(e,t){return U(e,t)<=e.radius}function bi(e,t,n){let i={},o=[];for(let r of e){let l=t[r.identifier]??"unknown",p=yi(r,n)?"inside":"outside";if(i[r.identifier]=p,l===p)continue;let f=p==="inside"?"enter":"exit",g=l==="unknown";(g||(f==="enter"?r.notifyOnEnter:r.notifyOnExit))&&o.push({identifier:r.identifier,kind:f,initial:g})}return{states:i,transitions:o}}function vi(e,t,n){if(t==="inside")return{latitude:e.latitude,longitude:e.longitude};let i=n&&U(e,n)>1?qe(e,n):0;return Re(e,i,e.radius+Math.max(50,e.radius*.25))}function Vt(e,t){if(!be(e))return null;let n=e,i=Number(n.radius);return!Number.isFinite(i)||i<=0?null:{identifier:typeof n.identifier=="string"&&n.identifier?n.identifier:`region-${t+1}`,latitude:n.latitude,longitude:n.longitude,radius:i,notifyOnEnter:n.notifyOnEnter!==false,notifyOnExit:n.notifyOnExit!==false}}function dt(e){let t=e.trim(),n=[/@(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)/,/[?&](?:q|ll|query|center)=(-?\d+(?:\.\d+)?)(?:,|%2C)\s*(-?\d+(?:\.\d+)?)/i,/^(-?\d+(?:\.\d+)?)\s*[,\s]\s*(-?\d+(?:\.\d+)?)$/];for(let i of n){let o=t.match(i);if(o){let r={latitude:Number(o[1]),longitude:Number(o[2])};if(be(r))return r}}return null}function Ne(e,t=5){return`${e.latitude.toFixed(t)}, ${e.longitude.toFixed(t)}`}var pt={persist:true,showChip:true},wi={latitude:37.3349,longitude:-122.009,label:"Apple Park"};function ft(){return{mode:"real",place:{...wi},altitude:30,accuracy:5,jitter:0,heading:null,route:null,playing:false,anchorReal:0,anchorMeters:0,signal:true,services:true,interval:1e3}}function Ee(e){return!!e&&(e.mode!=="real"||!e.signal||!e.services)}function ve(e){return!!e&&e.mode!=="real"}function ge(e,t,n=-1/0,i=1/0){let o=typeof e=="number"?e:Number(e);return Number.isFinite(o)?Math.min(i,Math.max(n,o)):t}function ki(e,t){if(e===null)return null;let n=typeof e=="number"?e:Number(e);return e!==void 0&&Number.isFinite(n)?n:t}function gt(e){if(!e||typeof e!="object")return null;let t=e,n=Array.isArray(t.points)?t.points.filter(be):[];if(n.length<2)return null;let i=Array.isArray(t.gaps)?t.gaps.filter(o=>Array.isArray(o)&&o.length===2&&o.every(r=>typeof r=="number"&&Number.isFinite(r))):void 0;return{id:typeof t.id=="string"?t.id:void 0,name:typeof t.name=="string"?t.name:void 0,points:n.map(o=>({latitude:o.latitude,longitude:o.longitude})),speed:ge(t.speed,1.4,.1,400),loop:t.loop===true,gaps:i&&i.length?i:void 0}}function Gt(e){if(!e||typeof e!="object")return null;let t=e,n=ft(),i=t.mode==="fixed"||t.mode==="route"?t.mode:"real",o=t.place,r=be(o)?{latitude:o.latitude,longitude:o.longitude,label:typeof o.label=="string"?o.label:void 0}:n.place,l=gt(t.route);return{mode:i==="route"&&!l?"fixed":i,place:r,altitude:ki(t.altitude,n.altitude),accuracy:ge(t.accuracy,n.accuracy,0,1e5),jitter:ge(t.jitter,0,0,1e4),heading:t.heading===null||t.heading===void 0?null:ge(t.heading,0,0,360)%360,route:l,playing:t.playing===true&&!!l,anchorReal:ge(t.anchorReal,0),anchorMeters:ge(t.anchorMeters,0,0),signal:t.signal!==false,services:t.services!==false,interval:ge(t.interval,n.interval,100,6e4)}}var qt={good:{accuracy:5,jitter:0,signal:true,services:true},weak:{accuracy:65,jitter:50,signal:true,services:true},"no-signal":{accuracy:5,jitter:0,signal:false,services:true},off:{accuracy:5,jitter:0,signal:true,services:false}};function xi(e){if(!e.services)return"off";if(!e.signal)return"no-signal";for(let t of["good","weak"]){let n=qt[t];if(e.accuracy===n.accuracy&&e.jitter===n.jitter)return t}return null}import{devToolsStorageKeys as Ti,persistentStorage as Kt}from"@buoy-gg/shared-ui/web";var Xt=Ti.location.state();function Si(e){if(!e||typeof e!="object")return null;let t=e;return typeof t.name!="string"||!t.name||t.kind!=="geofencing"&&t.kind!=="locationUpdates"?null:{name:t.name,kind:t.kind,library:typeof t.library=="string"?t.library:"expo-location",options:t.options&&typeof t.options=="object"?t.options:{}}}function Ai(e){if(!e)return null;try{let t=JSON.parse(e);if(!t||t.v!==1)return null;let n=t.settings??{};return{v:1,override:Gt(t.override),settings:{persist:typeof n.persist=="boolean"?n.persist:pt.persist,showChip:typeof n.showChip=="boolean"?n.showChip:pt.showChip},tasks:Array.isArray(t.tasks)?t.tasks.map(Si).filter(i=>i!==null):[]}}catch{return null}}async function Ci(){try{return Ai(await Kt.getItem(Xt))}catch{return null}}var ht=Promise.resolve();function Ii(e){let t=JSON.stringify(e);return ht=ht.then(()=>Kt.setItem(Xt,t)).catch(()=>{}),ht.then(()=>{})}function Yt(){return globalThis.__buoyRealTimers??globalThis}function ie(e,t){return Yt().setTimeout(e,t)}function Li(e){Yt().clearTimeout(e)}var d=ft(),ce={...pt},we="full",ke=null,mt=false,Xe=false,xe=new Map,oe=new Map,O=new Map,Te=[],$i=0,Zt=null,Jt=1,De=[],Ye=[],Ze=new Set,Oe=null;function z(){Oe=null;for(let e of Array.from(Ze))try{e()}catch{}}function Be(e){return Ze.add(e),()=>{Ze.delete(e)}}var Qt=100;function I(e,t,n,i){Te.push({id:++$i,at:D(),kind:e,library:t,text:n,...i?{detail:i}:{}}),Te.length>Qt&&Te.splice(0,Te.length-Qt),z()}function N(){return Ee(d)}function je(){return d.services}function Mi(e){!e||e===we||(we=e,z())}function Pi(e){if(!e)return;let t=ke&&ke.status===e.status&&ke.background===e.background&&ke.precision===e.precision;e.precision!==we&&(we=e.precision),!t&&(ke=e,z())}function Se(e){return d.route?d.playing?d.anchorMeters+Math.max(0,e-d.anchorReal)/1e3*d.route.speed:d.anchorMeters:0}function he(e=D()){if(!d.services)return{fix:null,reason:"services"};if(!d.signal)return{fix:null,reason:"signal"};if(d.mode==="real")return{fix:null,reason:"real"};let t,n=d.heading,i=0;if(d.mode==="route"&&d.route){let r=Ke(d.route,Se(e));if(r.inGap)return{fix:null,reason:"gap"};t=r;let l=d.playing&&!r.finished;n=r.heading,i=l?d.route.speed:0}else t=d.place;d.jitter>0&&(t=gi(t,d.jitter,Math.floor(e/d.interval)+Jt));let o={latitude:t.latitude,longitude:t.longitude,altitude:d.altitude,accuracy:Math.max(d.accuracy,d.jitter),altitudeAccuracy:d.altitude===null?null:3,heading:n,speed:i};return we==="reduced"&&(o=mi(o)),{fix:o,reason:null}}var Ae=null,en=0;function Ri(){return ve(d)?oe.size>0||O.size>0?true:d.mode==="route"&&d.playing&&Ze.size>0:false}function Je(){Ae===null&&Ri()&&(Ae=ie(()=>{Ae=null,rn(),Je()},d.interval))}function tn(){Ae!==null&&Li(Ae),Ae=null}function nn(){tn(),rn(),Je()}function on(e,t){let n=Number(e.options[t]);return Number.isFinite(n)&&n>0?n:0}function rn(){let e=D(),{fix:t}=he(e);if(d.mode==="route"&&d.route&&d.playing){let n=Ke(d.route,Se(e));n.finished&&(d={...d,playing:false,anchorMeters:n.along,anchorReal:e},Ie())}t&&(an(t,false),ln(t)),e-en>5e3&&(en=e,Di()),z()}function an(e,t){for(let n of Array.from(oe.values())){if(n.kind==="heading"){let i=e.heading??0;if(!t&&n.lastHeading===i&&n.updates>0)continue;n.lastHeading=i}else{let i=on(n,"distanceInterval");if(!t&&n.last&&U(n.last,e)<Math.max(i,.01))continue;n.last={latitude:e.latitude,longitude:e.longitude}}n.updates+=1,Zt=D();try{n.deliver(e)}catch(i){I("error",n.library,`Watch ${n.id} callback threw: ${String(i?.message??i)}`)}}}function ln(e){for(let t of Array.from(O.values()))if(t.kind==="geofencing"){let{states:n,transitions:i}=bi(t.regions,t.states,e);t.states=n;for(let o of i)Ni(t,o)}else{let n=on(t,"distanceInterval");if(t.lastBatchAt&&U(t.lastBatchAt,e)<Math.max(n,.01))continue;t.lastBatchAt={latitude:e.latitude,longitude:e.longitude},sn(t,{locations:[e]},"a location update")}}function Ni(e,t){let n=e.regions.find(o=>o.identifier===t.identifier);if(!n)return;I(t.kind,e.library,`${t.kind==="enter"?"Entered":"Left"} ${et(n)??n.identifier}`,`${e.name} \xB7 region ${n.identifier}${t.initial?" \xB7 first check after monitoring started":""}`);let i=et(n)??n.identifier;sn(e,{eventType:t.kind==="enter"?1:2,region:n},`${t.kind==="enter"?"entering":"leaving"} ${i}`)}function sn(e,t,n){let i=xe.get(e.library);if(!i?.fireTask)return;e.runs+=1,e.kind==="locationUpdates"&&I("batch",e.library,"Sent a background location update",e.name),i.fireTask(e,t).then(o=>{I("task",e.library,`Task ran for ${n}`,o!=null?`${e.name} \xB7 returned ${Ei(o)}`:e.name)},o=>{I("error",e.library,`Task failed for ${n}`,`${e.name} \xB7 ${String(o?.message??o)}`)})}function Ei(e){try{let t=typeof e=="string"?e:JSON.stringify(e);return t.length>80?`${t.slice(0,77)}\u2026`:t}catch{return String(e)}}function Di(){Qe()}function Qe(){for(let e of xe.values())e.readPermission?.().then(Pi,()=>{})}function cn(e){xe.set(e.library,e),z()}function un(e){let t=`${e.library}:${e.kind}:${e.id}`;oe.set(t,{...e,key:t,since:D(),updates:0,last:null,lastHeading:null}),I("watch",e.library,e.kind==="heading"?"The app started watching the compass heading":"The app started watching location",`watch ${e.id} \xB7 ${e.library}`),ie(()=>{let n=oe.get(t);if(!n)return;let{fix:i,reason:o}=he();i?(an(i,false),z()):o==="services"&&n.fail?.("Location services are disabled")},0),Je()}function Fe(e,t,n){let i=`${e}:${t}:${n}`,o=oe.delete(i);return o&&I("watch",e,t==="heading"?"The app stopped watching the heading":"The app stopped watching location",`watch ${n} \xB7 ${e}`),o}function Oi(e,t,n){return oe.has(`${e}:${t}:${n}`)}function yt(e,t){let n=e.kind==="geofencing"?(e.options.regions??[]).map((i,o)=>Vt(i,o)).filter(i=>i!==null):[];O.set(e.name,{...e,regions:n,states:{},since:D(),runs:0,intercepted:t,lastBatchAt:null}),I("task",e.library,e.kind==="geofencing"?`The app started monitoring ${n.length} geofence${n.length===1?"":"s"}`:"The app started background location updates",e.name),Ie(),ve(d)&&ie(()=>{let{fix:i}=he(),o=O.get(e.name);i&&o&&(ln(i),z())},0),Je()}function bt(e){let t=O.get(e);return t?(O.delete(e),I("task",t.library,t.kind==="geofencing"?"The app stopped monitoring geofences":"The app stopped background updates",t.name),Ie(),t):null}function Ce(e){return O.get(e)??null}function vt(e){return Array.from(O.values()).filter(t=>!e||t.kind===e)}function dn(e,t){let n=O.get(e);n&&(n.intercepted=t,t||(n.states={}),Ie())}function Bi(e){for(let t of e){let n=De.findIndex(i=>i.label&&i.label===t.label);n>=0?De[n]={...t}:De.push({...t})}z()}function et(e){let t=null,n=1/0;for(let i of De){if(!i.label)continue;let o=U(i,e);o<=Math.max(50,e.radius)&&o<n&&(t=i,n=o)}return t?.label??null}function ji(e){for(let t of e){let n=gt(t);if(!n)continue;let i=Ye.findIndex(o=>(o.id??o.name)===(n.id??n.name));i>=0?Ye[i]=n:Ye.push(n)}z()}function V(e){d=e;let t=Ee(d);if(t!==Xe){Xe=t;for(let n of xe.values())try{n.onActiveChange?.(t)}catch(i){I("error",n.library,`Switching failed: ${String(i?.message??i)}`)}}return Ie(),ve(d)?nn():(tn(),z()),P()}function tt(e){return V({...d,mode:"fixed",place:{latitude:e.latitude,longitude:e.longitude,label:e.label},playing:false})}function _e(){return d.mode==="route"&&d.route?Ke(d.route,Se(D())):d.place}function pn(e){let t=gt(e);if(!t)throw new Error("A route needs two or more valid points.");return V({...d,mode:"route",route:t,playing:true,anchorReal:D(),anchorMeters:0})}function wt(){if(d.mode!=="route"||!d.playing)return P();let e=D();return V({...d,playing:false,anchorMeters:Se(e),anchorReal:e})}function kt(){if(d.mode!=="route"||!d.route)return P();let e=ut(d.route.points),t=!d.route.loop&&d.anchorMeters>=e?0:d.anchorMeters;return V({...d,playing:true,anchorReal:D(),anchorMeters:t})}function fn(e){if(d.mode!=="route"||!d.route)throw new Error("No route is playing.");return V({...d,anchorMeters:Math.max(0,e),anchorReal:D()})}function gn(e){if(!d.route)throw new Error("No route is loaded.");if(!Number.isFinite(e)||e<=0)throw new Error("Speed must be a positive number of m/s.");let t=D();return V({...d,route:{...d.route,speed:e},anchorMeters:Se(t),anchorReal:t})}function hn(e){let t=Gt({...d,...Fi(e)});return t?V({...t,anchorMeters:d.anchorMeters,anchorReal:d.anchorReal}):P()}function Fi(e){let t={};for(let[n,i]of Object.entries(e))i!==void 0&&(t[n]=i);return t}function mn(e){return V({...d,signal:e})}function yn(e){let t=V({...d,services:e});if(!e){for(let n of Array.from(oe.values()))n.kind==="position"&&n.fail?.("Location services are disabled");I("error","device","Location services switched off","open watches got an error")}return t}function bn(e){let t=qt[e];if(!t)throw new Error(`Unknown conditions "${String(e)}". Use good, weak, no-signal or off.`);let n=d.services,i=e==="good"||e==="weak"?t:{signal:t.signal,services:t.services},o=V({...d,...i});if(n&&!t.services){for(let r of Array.from(oe.values()))r.kind==="position"&&r.fail?.("Location services are disabled");I("error","device","Location services switched off","open watches got an error")}return o}function vn(){if(d.mode!=="route"||!d.route)return P();let e=_e();return tt({latitude:e.latitude,longitude:e.longitude})}function wn(){return V({...d,mode:"real",playing:false})}function xt(e,t,n){for(let i of O.values()){if(n&&i.name!==n)continue;let o=i.regions.find(p=>p.identifier===e);if(!o)continue;let r=vi(o,t,_e()),l=et(o)??o.identifier;return tt({...r,label:t==="inside"?`At ${l}`:`Outside ${l}`})}throw new Error(`No geofence region "${e}" is being monitored.`)}function Tt(){let e=ft();return V({...e,place:d.place})}function _i(e){return ce={persist:typeof e.persist=="boolean"?e.persist:ce.persist,showChip:typeof e.showChip=="boolean"?e.showChip:ce.showChip},Ie(),z(),P()}function zi(){return ce}function Wi(){return Te.length=0,z(),P()}function P(){if(Oe)return Oe;let e=D(),{fix:t,reason:n}=he(e),i=null;if(d.mode==="route"&&d.route){let l=Ke(d.route,Se(e)),p=ut(d.route.points);i={along:l.along,length:p,finished:l.finished,leg:l.leg,etaMs:d.playing&&!d.route.loop&&!l.finished?(p-l.along)/d.route.speed*1e3:null}}let o=ve(d)?_e():null,r=t??o;return Oe={active:Ee(d),simulating:ve(d),override:d,current:{fix:t,reason:n,precision:we},permission:ke,position:o?{latitude:o.latitude,longitude:o.longitude}:null,progress:i,watches:Array.from(oe.values()).map(l=>({key:l.key,library:l.library,id:l.id,kind:l.kind,options:l.options,since:l.since,updates:l.updates})),tasks:Array.from(O.values()).map(l=>({name:l.name,kind:l.kind,library:l.library,intercepted:l.intercepted,since:l.since,runs:l.runs,options:l.options,regions:l.regions.map(p=>({...p,label:et(p),state:l.states[p.identifier]??"unknown",distance:r?U(p,r):null}))})),log:Te.slice(-50),libraries:Array.from(xe.keys()),places:De.slice(),routes:Ye.slice(),settings:ce,lastDeliveryAt:Zt},Oe}function Ie(){if(!mt)return;let e={v:1,override:ce.persist&&Ee(d)?d:null,settings:ce,tasks:Array.from(O.values()).filter(t=>t.intercepted).map(({name:t,kind:n,library:i,options:o})=>({name:t,kind:n,library:i,options:o}))};Ii(e)}function kn(e){if(e){ce=e.settings;for(let t of e.tasks)O.has(t.name)||Hi(t);e.override&&Ee(e.override)&&(d=e.override,Xe=true)}}function Hi(e){let t=e.kind==="geofencing"?(e.options.regions??[]).map((n,i)=>Vt(n,i)).filter(n=>!!n):[];O.set(e.name,{...e,regions:t,states:{},since:D(),runs:0,intercepted:true,lastBatchAt:null})}function St(){if(mt)return;mt=true,Jt=Math.floor(Math.random()*1e3)+1;let e=void 0;if(e!==void 0){kn(e),xn();return}Ci().then(t=>{kn(t),xn()})}function xn(){for(let e of xe.values())e.onActiveChange?.(Xe);ve(d)?ie(nn,0):z()}var Tn="__buoyLocationNext";function L(e,t,n){let i=e[t];if(typeof i!="function")return null;let o=i[Tn]??i,r=(...p)=>o.apply(e,p),l=n(r);l[Tn]=o;try{e[t]=l}catch{return null}return e[t]===l?r:null}function Ui(e,t){let n=new Error(t);return n.code=e,n}var At={};di(At,{AccessibilityInfo:()=>Ki,ActivityIndicator:()=>zo,Alert:()=>Uo,Animated:()=>Xi,AppRegistry:()=>Zi,AppState:()=>Ji,Appearance:()=>Yi,BackHandler:()=>Qi,Button:()=>Wo,CheckBox:()=>ho,Clipboard:()=>eo,DeviceEventEmitter:()=>An,Dimensions:()=>to,Easing:()=>no,FlatList:()=>mo,I18nManager:()=>io,Image:()=>yo,ImageBackground:()=>bo,InteractionManager:()=>ro,Keyboard:()=>oo,KeyboardAvoidingView:()=>vo,LayoutAnimation:()=>ao,Linking:()=>lo,LogBox:()=>Mo,Modal:()=>Fo,NativeEventEmitter:()=>so,NativeModules:()=>qi,PanResponder:()=>co,Picker:()=>wo,PixelRatio:()=>uo,Platform:()=>Sn,Pressable:()=>jo,ProgressBar:()=>ko,RefreshControl:()=>xo,SafeAreaView:()=>To,ScrollView:()=>In,SectionList:()=>So,Share:()=>po,StatusBar:()=>Ao,StyleSheet:()=>re,Switch:()=>_o,Text:()=>A,TextInput:()=>Cn,Touchable:()=>Co,TouchableHighlight:()=>Oo,TouchableNativeFeedback:()=>Io,TouchableOpacity:()=>ae,TouchableWithoutFeedback:()=>Bo,UIManager:()=>fo,Vibration:()=>go,View:()=>v,VirtualizedList:()=>Lo,YellowBox:()=>$o,findNodeHandle:()=>Ho,unstable_createElement:()=>Gi,useColorScheme:()=>Po,useLocaleContext:()=>Ro,useWindowDimensions:()=>No});pi(At,Vi);import*as Vi from"react-native-web";import{unstable_createElement as Gi,NativeModules as qi,AccessibilityInfo as Ki,Animated as Xi,Appearance as Yi,AppRegistry as Zi,AppState as Ji,BackHandler as Qi,Clipboard as eo,Dimensions as to,Easing as no,I18nManager as io,Keyboard as oo,InteractionManager as ro,LayoutAnimation as ao,Linking as lo,NativeEventEmitter as so,PanResponder as co,PixelRatio as uo,Platform as Sn,Share as po,StyleSheet as re,UIManager as fo,Vibration as go,CheckBox as ho,FlatList as mo,Image as yo,ImageBackground as bo,KeyboardAvoidingView as vo,Picker as wo,ProgressBar as ko,RefreshControl as xo,SafeAreaView as To,SectionList as So,StatusBar as Ao,Touchable as Co,TouchableNativeFeedback as Io,VirtualizedList as Lo,YellowBox as $o,LogBox as Mo,DeviceEventEmitter as An,useColorScheme as Po,useLocaleContext as Ro,useWindowDimensions as No}from"react-native-web";import*as W from"react-native-web";import{createElement as Eo,forwardRef as Do}from"react";function G(e){let t=Do((i,o)=>{let{accessibilityState:r,accessibilityValue:l,...p}=i;for(let f of["busy","checked","disabled","expanded","selected"])r?.[f]!==void 0&&p[`aria-${f}`]===void 0&&(p[`aria-${f}`]=r[f]);for(let[f,g]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))l?.[f]!==void 0&&p[`aria-${g}`]===void 0&&(p[`aria-${g}`]=l[f]);return Eo(e,{...p,ref:o})}),n=e.State;return n&&Object.assign(t,{State:n}),t.displayName=e.displayName??e.name??"NativeWebView",t}var v=G(W.View),A=G(W.Text),Cn=G(W.TextInput),ae=G(W.TouchableOpacity),Oo=G(W.TouchableHighlight),Bo=G(W.TouchableWithoutFeedback),jo=G(W.Pressable),In=G(W.ScrollView),Fo=G(W.Modal),_o=G(W.Switch),zo=G(W.ActivityIndicator),Wo=G(W.Button),Ho=W.findNodeHandle,Uo={alert(e,t,n,i){if(typeof document>"u")return;let o=document.createElement("dialog");o.dataset.buoyRoot="",o.setAttribute("aria-label",e),o.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let r=document.createElement("h2");if(r.textContent=e,r.style.cssText="font-size:18px;margin:0 0 12px",o.appendChild(r),t){let g=document.createElement("p");g.textContent=t,g.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",o.appendChild(g)}let l=document.createElement("div");l.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let p=n?.length?n:[{text:"OK"}],f=()=>{o.close?.(),o.remove()};for(let g of p){let y=document.createElement("button");y.type="button",y.textContent=g.text??"OK",y.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${g.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,y.onclick=()=>{f(),g.onPress?.()},l.appendChild(y)}o.addEventListener("cancel",g=>{g.preventDefault(),i?.cancelable!==false&&(f(),i?.onDismiss?.())}),o.appendChild(l),document.body.appendChild(o),o.showModal?o.showModal():o.setAttribute("open","")}};var Vo=[{module:"RNCGeolocation",library:"@react-native-community/geolocation"},{module:"RNFusedLocation",library:"react-native-geolocation-service"}],Go={PERMISSION_DENIED:1,POSITION_UNAVAILABLE:2,TIMEOUT:3};function Ct(e,t){return{code:e,message:t,...Go}}function Ln(){return At}function qo(e){let t=Ln();if(!t)return null;let n=null;try{(globalThis.__turboModuleProxy!=null||typeof t.TurboModuleRegistry?.get=="function")&&(n=t.TurboModuleRegistry?.get?.(e))}catch{n=null}if(!n)try{n=t.NativeModules?.[e]}catch{n=null}return n&&typeof n=="object"?n:null}function $n(e,t,n){let i={coords:{latitude:e.latitude,longitude:e.longitude,altitude:e.altitude,accuracy:e.accuracy,altitudeAccuracy:e.altitudeAccuracy,heading:e.heading??(t==="ios"?-1:0),speed:e.speed??(t==="ios"?-1:0)},timestamp:n};return t==="android"&&(i.mocked=false),i}var Ko=[];function Xo(e){let t=qo(e.module);if(!t||typeof t.getCurrentPosition!="function")return false;Ko.push(t);let n=Ln(),i=n?.Platform?.OS??"ios",o=(g,y)=>n?.DeviceEventEmitter?.emit(g,y),r={options:null,native:false,on:false},l=()=>un({library:e.library,id:"observer",kind:"position",options:r.options??{},deliver:g=>o("geolocationDidChange",$n(g,i,Date.now())),fail:g=>o("geolocationError",Ct(2,g))});L(t,"getCurrentPosition",g=>(...y)=>{if(!N())return g(...y);let T=y[1],S=y[2];if(!je()){I("request",e.library,"getCurrentPosition \u2192 services off"),S?.(Ct(2,"No location provider available."));return}let{fix:C}=he();if(!C){I("request",e.library,"getCurrentPosition \u2192 no signal"),ie(()=>S?.(Ct(3,"Unable to fetch location within 1.0s.")),1e3);return}I("request",e.library,`getCurrentPosition \u2192 ${C.latitude.toFixed(5)}, ${C.longitude.toFixed(5)}`),ie(()=>T?.($n(C,i,Date.now())),0)});let p=L(t,"startObserving",g=>(...y)=>{if(r.options=y[0]&&typeof y[0]=="object"?y[0]:{},r.on=true,!N())return r.native=true,g(...y);r.native=false,l()}),f=L(t,"stopObserving",g=>(...y)=>{if(r.on=false,Fe(e.library,"position","observer"),r.native)return r.native=false,g(...y)});return cn({library:e.library,onActiveChange(g){r.on&&(g&&r.native?(r.native=false,f?.(),l()):!g&&!r.native&&(Fe(e.library,"position","observer"),r.native=true,p?.(r.options??{})))}}),true}function Yo(){return Vo.filter(Xo).map(e=>e.library)}function Zo(e){return null}function Jo(e){return null}var E="expo-location";function Qo(){return Sn?.OS??"ios"}function Mn(e){try{let n=globalThis.expo?.modules?.[e];if(n&&typeof n=="object")return n}catch{}let t=Zo(e);return t&&typeof t=="object"?t:null}function It(e,t,n){let i=t==="ios",o={coords:{latitude:e.latitude,longitude:e.longitude,altitude:e.altitude??(i?0:null),accuracy:e.accuracy,altitudeAccuracy:e.altitudeAccuracy??(i?-1:null),heading:e.heading??(i?-1:null),speed:e.speed??(i?-1:null)},timestamp:n};return t==="android"&&(o.mocked=false),o}function er(e,t,n){return n==="ios"?`Calling the '${e}' function has failed
2
+ \u2192 Caused by: ${t}`:`Call to function 'ExpoLocation.${e}' has been rejected.
3
+ \u2192 Caused by: ${t}`}var Pn={denied:{ios:{code:"ERR_DENIED_FOREGROUND_LOCATION_PERMISSION",reason:"Location permission is required to do this operation"},android:{code:"ERR_LOCATION_UNAUTHORIZED",reason:"Not authorized to use location services"}},deniedBackground:{ios:{code:"ERR_DENIED_BACKGROUND_LOCATION_PERMISSION",reason:"Background location permission is required to do this operation"},android:{code:"ERR_LOCATION_BACKGROUND_UNAUTHORIZED",reason:"Not authorized to use background location services"}},services:{ios:{code:"ERR_LOCATION_SERVICES_DISABLED",reason:"Location services are disabled"},android:{code:"ERR_LOCATION_SETTINGS_UNSATISFIED",reason:"Location request failed due to unsatisfied device settings"}},unavailable:{ios:{code:"ERR_LOCATION_UNAVAILABLE",reason:"Cannot obtain current location"},android:{code:"ERR_CURRENT_LOCATION_IS_UNAVAILABLE",reason:"Current location is unavailable. Make sure that location services are enabled"}}};function le(e,t,n){let i=n==="android"?Pn[e].android:Pn[e].ios;return Promise.reject(Ui(i.code,er(t,i.reason,n)))}var Rn=false;function tr(){let e=Mn("ExpoLocation");if(!e||typeof e.getCurrentPositionAsync!="function")return false;let t=e,n=Mn("ExpoTaskManager"),i=Qo(),o=new Map,r={},l=()=>Date.now(),p=c=>s=>t.emit?.("Expo.locationChanged",{watchId:c,location:It(s,i,l())}),f=c=>s=>{let u=s.heading??0;t.emit?.("Expo.headingChanged",{watchId:c,heading:{trueHeading:u,magHeading:u,accuracy:3}})},g=c=>s=>t.emit?.("Expo.locationError",{watchId:c,reason:s});async function y(){let c=t.getForegroundPermissionsAsync,s={granted:true,status:"granted",precision:"full",reported:false};if(typeof c!="function")return s;try{let u=await c.call(t),w=u?.ios?.accuracy==="reduced"||u?.android?.accuracy==="coarse"?"reduced":"full";Mi(w);let x=u?.granted===true,ne=x?"granted":u?.status==="undetermined"?"undetermined":"denied";return{granted:x,status:ne,precision:w,reported:true}}catch{return s}}async function T(){let c=t.getBackgroundPermissionsAsync;if(typeof c!="function")return null;try{return(await c.call(t))?.granted===true}catch{return null}}async function S(){let c=t.getBackgroundPermissionsAsync;if(typeof c!="function")return true;try{return(await c.call(t))?.granted===true}catch{return true}}function C(c,s){un({library:E,id:c,kind:s.kind,options:s.options,deliver:s.kind==="position"?p(c):f(c),fail:g(c)})}r.getCurrentPositionAsync=L(t,"getCurrentPositionAsync",c=>async(...s)=>{if(!N())return c(...s);let u="getCurrentPositionAsync";if(!je())return I("request",E,"getCurrentPositionAsync \u2192 services off"),le("services",u,i);if(!(await y()).granted)return I("request",E,"getCurrentPositionAsync \u2192 permission denied"),le("denied",u,i);let{fix:w}=he();return w?(I("request",E,`getCurrentPositionAsync \u2192 ${w.latitude.toFixed(5)}, ${w.longitude.toFixed(5)}`),It(w,i,l())):(I("request",E,"getCurrentPositionAsync \u2192 no signal"),await new Promise(x=>ie(()=>x(null),1e3)),le("unavailable",u,i))}),r.getLastKnownPositionAsync=L(t,"getLastKnownPositionAsync",c=>async(...s)=>{if(!N())return c(...s);if(!(await y()).granted)return le("denied","getLastKnownPositionAsync",i);let{fix:u}=he();return I("request",E,`getLastKnownPositionAsync \u2192 ${u?"simulated":"null"}`),u?It(u,i,l()):null}),r.watchPositionImplAsync=L(t,"watchPositionImplAsync",c=>async(...s)=>{let u=Number(s[0]),w=s[1]&&typeof s[1]=="object"?s[1]:{};if(!N()){let ne=await c(...s),se={kind:"position",options:w,native:true};return o.set(u,se),N()&&ye(u,se),ne}if(!(await y()).granted)return le("denied","watchPositionImplAsync",i);if(!N())return o.set(u,{kind:"position",options:w,native:true}),c(...s);let x={kind:"position",options:w,native:false};o.set(u,x),C(u,x)}),r.watchDeviceHeading=L(t,"watchDeviceHeading",c=>async(...s)=>{let u=Number(s[0]);if(!N()){let x=await c(...s),ne={kind:"heading",options:{},native:true};return o.set(u,ne),N()&&ye(u,ne),x}if(!(await y()).granted)return le("denied","watchDeviceHeading",i);if(!N())return o.set(u,{kind:"heading",options:{},native:true}),c(...s);let w={kind:"heading",options:{},native:false};o.set(u,w),C(u,w)}),r.removeWatchAsync=L(t,"removeWatchAsync",c=>async(...s)=>{let u=Number(s[0]),w=o.get(u);if(o.delete(u),Fe(E,"position",u),Fe(E,"heading",u),!w||w.native)return c(...s)}),L(t,"hasServicesEnabledAsync",c=>async(...s)=>N()&&!je()?false:c(...s)),L(t,"getProviderStatusAsync",c=>async(...s)=>{let u=await c(...s);if(!N()||je())return u;let w={...u,locationServicesEnabled:false};for(let x of["gpsAvailable","networkAvailable","passiveAvailable"])x in w&&(w[x]=false);return w});let F=(c,s)=>L(t,s,u=>async(...w)=>{let x=String(w[0]),ne=w[1]&&typeof w[1]=="object"?w[1]:{},se={name:x,kind:c,library:E,options:ne};if(!N()){let st=await u(...w);return yt(se,false),N()&&b(true),st}if(c==="locationUpdates"&&!je())return le("services",s,i);if(!(await y()).granted)return le("denied",s,i);if(c==="geofencing"&&!await S())return le("deniedBackground",s,i);yt(se,true)});r.startLocationUpdatesAsync=F("locationUpdates","startLocationUpdatesAsync"),r.startGeofencingAsync=F("geofencing","startGeofencingAsync");let _=(c,s)=>L(t,s,u=>async(...w)=>{let x=Ce(String(w[0]));if(!(x&&x.kind===c&&(bt(x.name),x.intercepted)))return u(...w)});r.stopLocationUpdatesAsync=_("locationUpdates","stopLocationUpdatesAsync"),r.stopGeofencingAsync=_("geofencing","stopGeofencingAsync");let de=(c,s)=>L(t,s,u=>async(...w)=>{let x=Ce(String(w[0]));return x&&x.kind===c?true:u(...w)});de("locationUpdates","hasStartedLocationUpdatesAsync"),de("geofencing","hasStartedGeofencingAsync");let pe=new Map,lt=0,Ve={geofencing:"geofencing",locationUpdates:"location"};n&&(L(n,"notifyTaskFinishedAsync",c=>async(...s)=>{let u=s[1]??{},w=u.eventId?pe.get(u.eventId):void 0;if(w&&u.eventId){pe.delete(u.eventId),w(u.result);return}return c(...s)}),L(n,"isTaskRegisteredAsync",c=>async(...s)=>Ce(String(s[0]))?.intercepted?true:c(...s)),L(n,"getTaskOptionsAsync",c=>async(...s)=>{let u=Ce(String(s[0]));return u?.intercepted?u.options:c(...s)}),L(n,"getRegisteredTasksAsync",c=>async(...s)=>{let u=await c(...s)??[],w=vt().filter(x=>x.intercepted).map(x=>({taskName:x.name,taskType:Ve[x.kind],options:x.options}));return[...u,...w]}),L(n,"unregisterTaskAsync",c=>async(...s)=>{let u=Ce(String(s[0]));if(!(u&&(bt(u.name),u.intercepted)))return c(...s)}),L(n,"unregisterAllTasksAsync",c=>async(...s)=>{for(let u of vt())bt(u.name);return c(...s)}));function Pe(){if(!n)return null;if(n.__expo_module_name__&&typeof n.emit=="function")return(s,u)=>n.emit(s,u);let c=An;return c?(s,u)=>c.emit(s,u):null}async function fe(c){for(let s=0;s<5e3&&Jo(c)===false;s+=100)await new Promise(u=>ie(()=>u(null),100))}async function Ge(c,s){await fe(c.name);let u=Pe();if(!u)return Promise.reject(new Error("expo-task-manager is not installed"));let w=`buoy-location-${++lt}`,x=typeof n?.EVENT_NAME=="string"?n.EVENT_NAME:"TaskManager.executeTask";return new Promise((ne,se)=>{pe.set(w,ne),ie(()=>{pe.delete(w)&&se(new Error("did not finish within 30 s"))},3e4);try{u(x,{data:s,error:null,executionInfo:{eventId:w,taskName:c.name,appState:"active"}})}catch(st){pe.delete(w),se(st)}})}function ye(c,s){s.native&&(s.native=false,Promise.resolve(r.removeWatchAsync?.(c)).catch(()=>{}),C(c,s))}function b(c){for(let[s,u]of Array.from(o.entries()))if(c&&u.native)ye(s,u);else if(!c&&!u.native){Fe(E,u.kind,s);let w=u.kind==="position"?r.watchPositionImplAsync:r.watchDeviceHeading;u.native=true,Promise.resolve(u.kind==="position"?w?.(s,u.options):w?.(s)).catch(x=>{u.native=false,g(s)(String(x?.message??x))})}else c&&!u.native&&!Oi(E,u.kind,s)&&C(s,u);for(let s of vt()){if(s.library!==E)continue;let u=s.kind==="geofencing";if(c&&!s.intercepted){let w=u?r.stopGeofencingAsync:r.stopLocationUpdatesAsync;Promise.resolve(w?.(s.name)).catch(()=>{}),dn(s.name,true)}else if(!c&&s.intercepted){let w=u?r.startGeofencingAsync:r.startLocationUpdatesAsync;dn(s.name,false),Promise.resolve(w?.(s.name,s.options)).catch(x=>{I("error",E,`Could not restart ${s.name} natively: ${String(x?.message??x)}`)})}}}return cn({library:E,fireTask:Ge,onActiveChange:b,readPermission:async()=>{let c=await y();if(!c.reported)return null;let s=c.status==="granted"?await T():false;return{status:c.status,background:s,precision:c.precision}}}),Rn||(Rn=true,n&&typeof n.getRegisteredTasksAsync=="function"&&Promise.resolve(n.getRegisteredTasksAsync.call(n)).then(c=>{for(let s of c??[]){if(!s?.taskName||Ce(s.taskName))continue;let u=s.taskType==="geofencing"?"geofencing":s.taskType==="location"?"locationUpdates":null;u&&(yt({name:s.taskName,kind:u,library:E,options:s.options??{}},false),N()&&b(true))}}).catch(()=>{})),true}var ze=null;function Lt(){return ze||(ze=[],tr()&&ze.push("expo-location"),ze.push(...Yo()),ze)}import{useSyncExternalStore as nr}from"react";import{FloatingTool as ir,LocationToolIcon as Nn,Pause as or,Play as rr,RefreshCw as ar,X as lr,dismissFloatingTool as sr,getFloatingTools as cr,night as ue,openFloatingTool as ur}from"@buoy-gg/shared-ui/web";var dr=new Set(["US","GB","LR","MM"]),En=null;function pr(){try{let e=Intl.DateTimeFormat().resolvedOptions().locale,t=/[-_]([A-Z]{2})\b/.exec(e);return t?t[1]:null}catch{return null}}var $t=null;function Le(){return En!==null?En:($t===null&&($t=dr.has(pr()??"")),$t)}var Dn=3.28084,On=1609.344;function q(e){if(!Number.isFinite(e))return"\u2013";let t=Math.abs(e);if(Le()){let n=t/On;return n<.1?`${Math.round(t*Dn/10)*10} ft`:`${Bn(n)} mi`}return t<1e3?`${Math.round(t)} m`:`${Bn(t/1e3)} km`}function Bn(e){let t=Math.round(e*10)/10;return t<10?t.toFixed(1):Math.round(e).toLocaleString("en-US")}function jn(e){return Number.isFinite(e)?e>=1e3?`\xB1${q(e)}`:Le()?`\xB1${Math.round(e*Dn)} ft`:`\xB1${Math.round(e)} m`:"\u2013"}function Mt(e){if(e==null||e<0)return"\u2013";let t=Le()?e*3600/On:e*3.6,n=Le()?"mph":"km/h";return`${t<10?t.toFixed(1):Math.round(t)} ${n}`}function fr(e){if(!Number.isFinite(e)||e<0)return"\u2013";let t=Math.round(e/6e4);if(t<1)return`${Math.max(1,Math.round(e/1e3))} sec`;if(t<60)return`${t} min`;let n=Math.floor(t/60),i=t%60;return i?`${n} hr ${i} min`:`${n} hr`}function gr(e,t){let n=Math.max(0,Math.round((t-e)/1e3));if(n<5)return"now";if(n<60)return`${n}s ago`;try{return new Date(e).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})}catch{let i=new Date(e);return`${i.getHours()}:${String(i.getMinutes()).padStart(2,"0")}`}}function Fn(e){return e.override.services?e.override.signal?e.override.mode==="real"?"Real Location":e.override.mode==="route"?e.override.route?.name??"Route":e.override.place.label||"Dropped Pin":"No GPS Signal":"Location Services Off"}function hr(e){return!e.override.services||!e.override.signal?"broken":e.override.mode==="real"?"real":"simulated"}function mr(e){if(!e.override.services)return"The app is told location services are off";if(!e.override.signal)return"Updates stop and location requests fail";if(e.override.mode==="real")return"The app gets the device's location";let t=[];if(e.override.mode==="route"&&e.progress){let i=e.progress;i.finished?t.push("Arrived"):e.override.playing||t.push("Paused"),e.current.reason==="gap"&&t.push("no signal here"),i.finished||(t.push(`${q(i.along)} of ${q(i.length)}`),i.etaMs!=null?t.push(`${fr(i.etaMs)} left`):e.override.route?.loop&&t.push("on repeat"))}else t.push("Pinned");let n=e.current.fix;return n&&e.override.mode==="fixed"&&t.push(jn(n.accuracy)),e.current.precision==="reduced"&&t.push("approximate"),t.join(" \xB7 ")}function yr(e){return e.status==="denied"?"Not Allowed":e.status==="undetermined"?"Not Asked Yet":`${e.background?"Always":"While Using"} \xB7 ${e.precision==="reduced"?"Approximate":"Precise"}`}function br(e){if(!e.override.services)return"The app is told location is off";if(!e.override.signal)return"Updates stop, requests fail";if(e.override.mode==="route"&&e.progress){if(e.progress.finished)return"Arrived";let n=`${q(e.progress.along)} of ${q(e.progress.length)}`;return e.override.playing?n:`Paused \xB7 ${n}`}let t=e.current.fix;return t?`Pinned \xB7 ${Ne(t,3)}`:"Pinned"}import{jsx as H,jsxs as _n}from"react/jsx-runtime";var nt="location-chip",vr={id:nt,render:e=>H(Un,{...e})},wr=()=>cr().some(e=>e.id===nt),zn=false,Pt=false,Wn=null;function Hn(e){Pt!==e&&(Pt=e,Wn?.())}function kr(){if(zn)return;zn=true;let e=false,t=()=>{let n=P().active&&zi().showChip&&!Pt;n&&!e?ur(vr):!n&&wr()&&sr(nt),e=n};Wn=t,Be(t),t()}function Un({id:e,revealToken:t}){let n=nr(Be,P,P),i=Fn(n),o=n.override.mode==="route"&&n.progress,r=n.override.playing,l=!!o&&o.finished;return H(ir,{id:e,revealToken:t,variant:"strip",dragFromSurface:true,defaultPlacement:"top",accessibilityLabel:`Move or hide the location chip. ${i}`,handleAdornment:H(Nn,{size:12}),children:_n(v,{style:me.row,children:[H(Nn,{size:18}),_n(v,{style:me.text,children:[H(A,{style:me.title,numberOfLines:1,testID:"location-chip-title",children:i}),H(A,{style:me.detail,numberOfLines:1,testID:"location-chip-detail",children:br(n)})]}),o?H(ae,{testID:"location-chip-playpause",accessibilityRole:"button",accessibilityLabel:r?"Pause the route":l?"Play the route again":"Resume the route",onPress:()=>r?wt():kt(),style:me.pill,hitSlop:{top:8,bottom:8,left:4,right:4},children:r?H(or,{size:14,color:ue.color.accent}):l?H(ar,{size:14,color:ue.color.accent}):H(rr,{size:14,color:ue.color.accent})}):null,H(v,{style:me.separator}),H(ae,{testID:"location-chip-reset",accessibilityRole:"button",accessibilityLabel:"Back to the real location",onPress:()=>Tt(),style:me.button,hitSlop:{top:8,bottom:8,left:4,right:8},children:H(lr,{size:16,color:ue.color.textSecondary})})]})})}var me=re.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingLeft:10,paddingRight:4,paddingVertical:6,minWidth:230,maxWidth:340},text:{flexShrink:1,minWidth:120},title:{color:ue.color.text,fontSize:14,fontWeight:"600"},detail:{color:ue.color.textSecondary,fontSize:11,fontVariant:["tabular-nums"]},pill:{width:30,height:30,borderRadius:15,alignItems:"center",justifyContent:"center",backgroundColor:ue.color.accentFill},button:{width:32,height:32,alignItems:"center",justifyContent:"center",borderRadius:16},separator:{width:re.hairlineWidth,height:20,backgroundColor:ue.color.separator}});import{LocationToolIcon as xr,LOCATION_TOOL_ICON_COLOR as Tr,createToolFactory as Sr,defineToolPreset as Ar}from"@buoy-gg/shared-ui/web";import{useEffect as Cr,useState as Ir}from"react";import{FeatureGate as Lr}from"@buoy-gg/shared-ui/web";import{createSyncAdapter as $r}from"@buoy-gg/shared-ui/web";var it=[{latitude:37.3349,longitude:-122.009,label:"Apple Park"},{latitude:37.422,longitude:-122.0841,label:"Googleplex"},{latitude:40.758,longitude:-73.9855,label:"Times Square"},{latitude:51.508,longitude:-.1281,label:"Trafalgar Square"},{latitude:48.8584,longitude:2.2945,label:"Eiffel Tower"},{latitude:35.6595,longitude:139.7005,label:"Shibuya Crossing"},{latitude:-33.8568,longitude:151.2153,label:"Sydney Opera House"},{latitude:-23.5614,longitude:-46.6559,label:"S\xE3o Paulo"},{latitude:0,longitude:0,label:"Null Island"}],$e=[{id:"walk",name:"Walk",description:"1 km north from here at walking pace",speed:1.4},{id:"run",name:"Run",description:"3 km north, then east, at running pace",speed:3.3},{id:"drive",name:"City Drive",description:"4 km of city streets with turns",speed:13.4},{id:"highway",name:"Highway",description:"30 km north at highway speed",speed:30},{id:"tunnel",name:"Tunnel",description:"3 km drive with no signal for 600 m in the middle",speed:13.4},{id:"loop",name:"Block Loop",description:"A 400 m block, walked on repeat",speed:1.4}];function Vn(e,t,n=0){let i=$e.find(g=>g.id===e);if(!i)throw new Error(`Unknown route preset "${e}". Use one of: ${$e.map(g=>g.id).join(", ")}.`);let o={latitude:t.latitude,longitude:t.longitude},r=(g,y,T)=>Re(g,n+y,T),l,p,f=false;switch(e){case"walk":l=[o,r(o,0,1e3)];break;case"run":l=[o,r(o,0,1500),r(r(o,0,1500),90,1500)];break;case"drive":{let g=r(o,0,1200),y=r(g,90,800),T=r(y,0,1e3),S=r(T,-90,1e3);l=[o,g,y,T,S];break}case"highway":l=[o,r(o,0,3e4)];break;case"tunnel":l=[o,r(o,0,3e3)],p=[[1200,1800]];break;case"loop":{let g=r(o,0,100),y=r(g,90,100),T=r(y,180,100);l=[o,g,y,T,o],f=true;break}}return{id:`preset:${e}`,name:i.name,points:l,speed:i.speed,loop:f,gaps:p}}function Mr(e,t,n){return{id:"line",name:t.label?`To ${t.label}`:"Straight line",points:[{latitude:e.latitude,longitude:e.longitude},{latitude:t.latitude,longitude:t.longitude}],speed:n}}function J(e){return e&&typeof e=="object"?e:{}}function We(e,...t){for(let n of t){let i=e[n];if(typeof i=="boolean")return i;if(i==="true"||i==="on")return true;if(i==="false"||i==="off")return false}}function K(e,...t){for(let n of t){let i=e[n];if(i==null||i==="")continue;let o=Number(i);if(Number.isFinite(o))return o}}function $(){return{...P(),builtInPlaces:it,presets:$e}}function Pr(e){let t=e.trim().toLowerCase(),n=[...P().places,...it];return n.find(i=>i.label?.toLowerCase()===t)??n.find(i=>i.label?.toLowerCase().includes(t))??null}function Gn(e){let t=typeof e.label=="string"?e.label:void 0,n=K(e,"latitude","lat"),i=K(e,"longitude","lon","lng");if(n!==void 0&&i!==void 0){let o={latitude:n,longitude:i};if(!be(o))throw new Error("latitude must be within \xB190 and longitude within \xB1180.");return{...o,label:t}}for(let o of["place","to","query","coordinate","at"]){let r=e[o];if(be(r))return{...r,label:r.label??t};if(typeof r=="string"&&r.trim()){let l=dt(r);if(l)return{...l,label:t};let p=Pr(r);if(p)return p;throw new Error(`No place called "${r}". Give latitude and longitude, or one of: ${Rr()}.`)}}return null}function Rr(){return[...P().places,...it].map(e=>e.label).filter(Boolean).join(", ")}function Nr(e){let t=K(e,"speed","metersPerSecond"),n=K(e,"heading","bearing")??0;if(Array.isArray(e.points))return{points:e.points,speed:t??1.4,loop:We(e,"loop")??false,name:typeof e.name=="string"?e.name:"Custom route",gaps:Array.isArray(e.gaps)?e.gaps:void 0};let i=typeof e.route=="string"?e.route:typeof e.routeId=="string"?e.routeId:typeof e.preset=="string"?e.preset:void 0;if(i){let r=P().routes.find(f=>f.id===i||f.name?.toLowerCase()===i.toLowerCase());if(r)return t?{...r,speed:t}:r;let l=$e.find(f=>f.id===i||f.name.toLowerCase()===i.toLowerCase());if(l){let f=Vn(l.id,_e(),n);return t?{...f,speed:t}:f}let p=[...P().routes.map(f=>f.id??f.name),...$e.map(f=>f.id)];throw new Error(`No route "${i}". Use one of: ${p.join(", ")}; or pass points.`)}let o=Gn(e);if(o)return Mr(_e(),o,t??1.4);throw new Error("startRoute needs `points` (two or more {latitude, longitude}), `route` (a preset or app route id), or `to` (a place).")}var Rt=$r({version:1,getSnapshot(){return $()},subscribe(e){return Be(e)},actions:{getState(){return $()},setLocation(e){let t=Gn(J(e));if(!t)throw new Error('setLocation needs `latitude` and `longitude`, `query` ("lat, lon" or a map link), or `place` (a place name).');return tt(t),$()},startRoute(e){return pn(Nr(J(e))),$()},stopRoute(){return vn(),$()},setConditions(e){let t=J(e),n=(typeof t.conditions=="string"?t.conditions:typeof t.preset=="string"?t.preset:"").trim().toLowerCase().replace(/[\s_]+/g,"-"),i={good:"good",weak:"weak","no-signal":"no-signal",nosignal:"no-signal",off:"off","services-off":"off","location-off":"off"}[n];if(!i)throw new Error("setConditions needs `conditions`: good, weak, no-signal or off.");return bn(i),$()},pauseRoute(){return wt(),$()},resumeRoute(){return kt(),$()},seekRoute(e){let t=J(e),n=K(t,"meters","along"),i=K(t,"fraction","progress"),o=P().progress?.length??0;if(n===void 0&&i===void 0)throw new Error("seekRoute needs `meters` or `fraction` (0 to 1).");return fn(n??(i??0)*o),$()},setSpeed(e){let t=K(J(e),"speed","metersPerSecond");if(t===void 0)throw new Error("setSpeed needs `speed` in meters per second.");return gn(t),$()},tune(e){let t=J(e);return hn({accuracy:K(t,"accuracy"),jitter:K(t,"jitter","drift"),altitude:t.altitude===null?null:K(t,"altitude"),heading:t.heading===null?null:K(t,"heading"),interval:K(t,"interval","intervalMs")}),$()},setSignal(e){let t=We(J(e),"on","signal","enabled");if(t===void 0)throw new Error("setSignal needs `on`: true or false.");return mn(t),$()},setServices(e){let t=We(J(e),"on","services","enabled");if(t===void 0)throw new Error("setServices needs `on`: true or false.");return yn(t),$()},enterRegion(e){let t=J(e),n=typeof t.identifier=="string"?t.identifier:typeof t.region=="string"?t.region:void 0;if(!n)throw new Error("enterRegion needs `identifier` (a monitored geofence region).");return xt(n,"inside",typeof t.task=="string"?t.task:void 0),$()},exitRegion(e){let t=J(e),n=typeof t.identifier=="string"?t.identifier:typeof t.region=="string"?t.region:void 0;if(!n)throw new Error("exitRegion needs `identifier` (a monitored geofence region).");return xt(n,"outside",typeof t.task=="string"?t.task:void 0),$()},useRealLocation(){return wn(),$()},reset(){return Tt(),$()},updateSettings(e){let t=J(e);return _i({persist:We(t,"persist"),showChip:We(t,"showChip")}),$()},clearLog(){return Wi(),$()}}});import{useEffect as Er,useState as Me}from"react";import{Check as Dr,ChevronLeft as Or,ChevronRight as Br,NightButton as qn,NightCard as R,NightFootnote as Q,NightRows as ee,NightSectionLabel as X,NightSegmented as Nt,NightSwitch as jr,Pause as Fr,Play as _r,RefreshCw as zr,copyToClipboard as Wr,monoFont as Hr,night as h,realNow as Et,useSafeAreaInsets as Ur,useToolScreenHeader as Vr}from"@buoy-gg/shared-ui/web";import{night as te}from"@buoy-gg/shared-ui/web";import{jsx as Y,jsxs as ot}from"react/jsx-runtime";var Kn="#F87171",He=1.8,Gr=6e4,qr=400;function Kr({snapshot:e,onPinPlace:t,onCrossRegion:n}){let i=e.position,o=e.override.mode==="route"?e.override.route:null,r=i??e.places[0]??Xr(e.tasks)??null;if(!r)return null;let l=b=>!i||U(i,b)<=Gr,p=e.places.filter(l),f=e.tasks.filter(b=>b.kind==="geofencing").flatMap(b=>b.regions.filter(l).map(c=>({task:b,region:c}))),g=e.places.length-p.length,y=Math.cos(r.latitude*Math.PI/180),T=b=>({x:(b.longitude-r.longitude)*111320*y,y:(b.latitude-r.latitude)*110540}),S=[];i&&S.push({...T(i),r:60});for(let b of o?.points??[])S.push({...T(b),r:0});for(let b of p)S.push({...T(b),r:60});for(let b of f)S.push({...T(b.region),r:b.region.radius});let C=1/0,F=-1/0,_=1/0,de=-1/0;for(let b of S)C=Math.min(C,b.x-b.r),F=Math.max(F,b.x+b.r),_=Math.min(_,b.y-b.r),de=Math.max(de,b.y+b.r);let pe=(C+F)/2,lt=(_+de)/2,Ve=Math.max(qr,(de-_)*1.35,(F-C)*1.2/He),Pe=Ve*He,fe=b=>{let c=T(b);return{x:.5+(c.x-pe)/Pe,y:.5-(c.y-lt)/Ve}},Ge=Zr(Pe),ye=e.override.mode==="fixed"?e.override.place.label:void 0;return Y(v,{children:ot(v,{style:M.map,testID:"location-map",accessibilityLabel:"Map of places, geofences and the simulated position",children:[Xn.map(b=>Y(v,{style:[M.gridV,{left:B(b)}]},`v${b}`)),Xn.map(b=>Y(v,{style:[M.gridH,{top:B(b)}]},`h${b}`)),f.map(({task:b,region:c})=>{let s=fe(c),u=2*c.radius/Pe,w=u*He,x=c.state==="inside";return Y(ae,{testID:`location-map-region-${Yn(c.identifier)}`,accessibilityRole:"button",accessibilityLabel:`${x?"Leave":"Enter"} ${c.label??c.identifier}`,activeOpacity:.6,onPress:()=>n(b,c),style:[M.fence,x?M.fenceInside:null,{left:B(s.x-u/2),top:B(s.y-w/2),width:B(u),height:B(w)}]},`${b.name}:${c.identifier}`)}),o?Yr(o.points.map(fe)).map((b,c)=>Y(v,{pointerEvents:"none",style:[M.segment,{left:B(b.midX-b.length/2),top:B(b.midY),width:B(b.length),transform:[{rotate:`${b.angle}rad`}]}]},`seg${c}`)):null,p.map((b,c)=>{let s=fe(b),u=!!ye&&ye===b.label;return ot(ae,{testID:`location-map-place-${Yn(b.label??String(c))}`,accessibilityRole:"button",accessibilityLabel:`Pin ${b.label??"this place"}`,activeOpacity:.6,onPress:()=>t(b),style:[M.placeHit,{left:B(s.x),top:B(s.y)}],children:[Y(v,{style:[M.placeDot,u?M.placeDotSelected:null]}),b.label?Y(A,{style:M.placeLabel,numberOfLines:1,children:b.label}):null]},`${b.label??c}`)}),i?ot(v,{pointerEvents:"none",style:[M.pinWrap,{left:B(fe(i).x),top:B(fe(i).y)}],children:[Y(v,{style:M.pinHalo}),Y(v,{style:[M.pin,e.current.reason==="gap"?M.pinHollow:null]})]}):null,ot(v,{style:M.scale,pointerEvents:"none",children:[Y(v,{style:[M.scaleBar,{width:B(Ge.fraction)}]}),Y(A,{style:M.scaleLabel,children:Ge.label})]}),g>0?Y(A,{style:M.offMap,pointerEvents:"none",children:`${g} more ${g===1?"place":"places"} off the map`}):null]})})}var Xn=[.2,.4,.6,.8];function B(e){return`${e*100}%`}function Xr(e){for(let t of e)if(t.regions[0])return t.regions[0];return null}function Yr(e){let t=[];for(let n=1;n<e.length;n++){let i=e[n-1],o=e[n],r=o.x-i.x,l=(o.y-i.y)/He;t.push({midX:(i.x+o.x)/2,midY:(i.y+o.y)/2,length:Math.sqrt(r*r+l*l),angle:Math.atan2(l,r)})}return t}function Zr(e){let t=e/4,n=Le()?1609.344:1e3,i=Le()?[.01,.02,.05,.1,.2,.5,1,2,5,10,20,50,100].map(r=>r*n):[10,20,50,100,200,500,1e3,2e3,5e3,1e4,2e4,5e4,1e5],o=i[0];for(let r of i)r<=t&&(o=r);return{fraction:o/e,label:q(o)}}function Yn(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}var M=re.create({map:{width:"100%",aspectRatio:He,borderRadius:te.radius.card,borderWidth:1,borderColor:te.color.border,backgroundColor:te.color.surface,overflow:"hidden"},gridV:{position:"absolute",top:0,bottom:0,width:re.hairlineWidth,backgroundColor:"rgba(255, 255, 255, 0.04)"},gridH:{position:"absolute",left:0,right:0,height:re.hairlineWidth,backgroundColor:"rgba(255, 255, 255, 0.04)"},fence:{position:"absolute",borderRadius:9999,borderWidth:1,borderColor:"rgba(255, 255, 255, 0.22)",backgroundColor:"rgba(255, 255, 255, 0.04)",minWidth:10,minHeight:10},fenceInside:{borderColor:te.color.accentBorderStrong,backgroundColor:te.color.accentSoft},segment:{position:"absolute",height:3,marginTop:-1.5,borderRadius:1.5,backgroundColor:"rgba(248, 113, 113, 0.45)"},placeHit:{position:"absolute",flexDirection:"row",alignItems:"center",gap:4,height:24,marginTop:-12,marginLeft:-12,paddingLeft:8,paddingRight:4},placeDot:{width:8,height:8,borderRadius:4,backgroundColor:te.color.textSecondary},placeDotSelected:{backgroundColor:te.color.text},placeLabel:{color:te.color.textSecondary,fontSize:10,fontWeight:"500",maxWidth:110},pinWrap:{position:"absolute",width:28,height:28,marginLeft:-14,marginTop:-14,alignItems:"center",justifyContent:"center"},pinHalo:{position:"absolute",width:28,height:28,borderRadius:14,backgroundColor:"rgba(248, 113, 113, 0.22)"},pin:{width:14,height:14,borderRadius:7,backgroundColor:Kn,borderWidth:2,borderColor:"#FFFFFF"},pinHollow:{backgroundColor:"transparent",borderColor:Kn},scale:{position:"absolute",left:10,right:10,bottom:8,gap:3},scaleBar:{height:2,borderRadius:1,backgroundColor:te.color.textTertiary},scaleLabel:{color:te.color.textTertiary,fontSize:10,fontVariant:["tabular-nums"]},offMap:{position:"absolute",right:10,bottom:8,color:te.color.textTertiary,fontSize:10}});import{Fragment as Ue,jsx as a,jsxs as k}from"react/jsx-runtime";var Zn={places:"Other Location",routes:"Route",speed:"Speed",accuracy:"Accuracy & Drift",activity:"Activity",options:"Options"},Jr="#F87171",Jn=[{key:"1.4",label:"Walking"},{key:"3.3",label:"Running"},{key:"5.5",label:"Cycling"},{key:"13.4",label:"City Traffic"},{key:"30",label:"Highway"},{key:"250",label:"Airplane"}],Qn=[{key:"good",label:"Good"},{key:"weak",label:"Weak"},{key:"no-signal",label:"No Signal"},{key:"off",label:"Off"}],Qr={good:"Precise fixes, like outdoors with a clear sky.",weak:"Fixes are \xB165 m and wander by up to 50 m, like indoors or between tall buildings.","no-signal":"Watches get no updates and location requests fail.",off:"The app is told location services are turned off.",custom:"Custom accuracy and drift."},ei=[{key:"5",label:"5 m"},{key:"20",label:"20 m"},{key:"65",label:"65 m"},{key:"1000",label:"1 km"}],ti=[{key:"0",label:"Off"},{key:"10",label:"10 m"},{key:"50",label:"50 m"},{key:"200",label:"200 m"}],ea=4;function Dt(e){let[t,n]=Me(()=>Et());return Er(()=>{if(!e)return;let i=setInterval(()=>n(Et()),1e3);return()=>clearInterval(i)},[e]),t}function ni({snapshot:e,onAction:t}){let n=Ur({minBottom:16}),[i,o]=Me(null),[r,l]=Me("main"),p=()=>l("main"),f=Vr(r==="main"?null:{title:Zn[r],subtitle:"",onBack:p,searchable:false},[r]),g=(C,F)=>{o(null),t(C,F).catch(_=>{o(_ instanceof Error?_.message:String(_))})};if(!e)return a(v,{style:m.waiting,testID:"location-waiting",children:a(Q,{centered:true,children:"Waiting for the app\u2026"})});let y=i?a(Q,{tone:"danger",centered:true,children:a(A,{testID:"location-error",children:i})}):null,T=(C,F)=>{g(C,F),p()},S;switch(r){case"places":S=a(aa,{snapshot:e,pick:T});break;case"routes":S=a(ua,{snapshot:e,pick:T});break;case"speed":S=a(pa,{snapshot:e,pick:T});break;case"accuracy":S=a(ba,{snapshot:e,run:g});break;case"activity":S=a(wa,{snapshot:e,run:g});break;case"options":S=a(xa,{snapshot:e,run:g});break;default:S=k(Ue,{children:[a(ta,{snapshot:e,run:g}),y,a(ia,{snapshot:e,run:g}),a(oa,{snapshot:e,run:g,open:l}),a(sa,{snapshot:e,open:l}),a(ga,{snapshot:e,run:g}),a(ya,{snapshot:e,run:g,open:l}),a(va,{snapshot:e,open:l})]})}return k(In,{style:m.fill,contentContainerStyle:[m.content,{paddingBottom:n.bottom}],testID:"location-scroll",keyboardShouldPersistTaps:"handled",children:[r!=="main"&&!f?a(Ta,{title:Zn[r],onBack:p}):null,r!=="main"?y:null,S]},r)}function ta({snapshot:e,run:t}){let n=e.override,i=n.mode==="route"?n.route:null,o=e.progress;Dt(!!i&&n.playing);let r=hr(e),l=e.current.fix,p=o&&o.length>0?Math.min(1,o.along/o.length):0,[f,g]=Me(false);return k(R,{children:[k(v,{style:m.status,children:[a(A,{style:[m.statusTitle,r==="simulated"?m.titleSimulated:r==="broken"?m.titleBroken:null],testID:"location-hero-title",numberOfLines:1,adjustsFontSizeToFit:true,children:Fn(e)}),a(A,{style:m.statusLine,testID:"location-hero-status",children:mr(e)}),l&&e.simulating?a(ae,{testID:"location-copy-coordinates",accessibilityRole:"button",accessibilityLabel:"Copy coordinates",activeOpacity:.6,onPress:()=>{Wr(`${l.latitude}, ${l.longitude}`).then(y=>{y&&(g(true),setTimeout(()=>g(false),1500))})},children:a(A,{style:m.coordinates,children:f?"Copied":Ne(l,5)})}):null,i&&o?k(v,{style:m.progressTrack,testID:"location-route-progress",children:[a(v,{style:[m.progressFill,{width:`${p*100}%`}]}),(i.gaps??[]).map(([y,T],S)=>a(v,{style:[m.progressGap,{left:`${y/o.length*100}%`,width:`${(T-y)/o.length*100}%`}]},S))]}):null,e.active?k(v,{style:m.statusButtons,children:[i&&o?a(na,{testID:n.playing?"location-route-pause":"location-route-resume",label:n.playing?"Pause":o.finished?"Play again":"Resume",onPress:()=>t(n.playing?"pauseRoute":"resumeRoute"),children:n.playing?a(Fr,{size:18,color:h.color.onAccent}):o.finished?a(zr,{size:18,color:h.color.onAccent}):a(_r,{size:18,color:h.color.onAccent})}):null,a(v,{style:m.flex,children:a(qn,{label:"Use Real Location",size:"md",testID:"location-reset",onPress:()=>t("reset")})})]}):null]}),e.permission?k(v,{style:m.permission,testID:"location-permission",children:[k(v,{style:m.rowBetween,children:[a(A,{style:m.rowTitle,children:"Permission"}),a(A,{style:[m.rowValue,e.permission.status!=="granted"?m.valueWarning:null],testID:"location-permission-value",children:yr(e.permission)})]}),e.permission.status!=="granted"?a(A,{style:m.detail,children:"The app's location requests fail until it's allowed. Change it in Settings or the Permissions tool."}):null]}):null]})}function na({children:e,label:t,onPress:n,testID:i}){return a(ae,{testID:i,accessibilityRole:"button",accessibilityLabel:t,activeOpacity:.7,onPress:n,style:m.round,children:e})}function ia({snapshot:e,run:t}){return!!e.position||e.places.length>0||e.tasks.some(n=>n.regions.length>0)?k(v,{children:[a(Kr,{snapshot:e,onPinPlace:n=>t("setLocation",{latitude:n.latitude,longitude:n.longitude,label:n.label}),onCrossRegion:(n,i)=>t(i.state==="inside"?"exitRegion":"enterRegion",{identifier:i.identifier,task:n.name})}),a(Q,{children:"Map views in the app still show the device's own blue dot. Move the simulator's location for those."})]}):null}function oa({snapshot:e,run:t,open:n}){let i=e.places.length>0?e.places:e.builtInPlaces.slice(0,ea),o=e.override.mode==="fixed"?e.override.place:null,r=e.position,l=!!o&&!i.some(p=>rt(p,o));return k(v,{children:[a(X,{children:"Location"}),a(R,{children:k(ee,{children:[i.map((p,f)=>a(j,{title:p.label??Ne(p,4),value:r&&!(o&&rt(p,o))?ra(r,p):void 0,checked:!!o&&rt(p,o),testID:`location-place-${at(p.label??String(f))}`,onPress:()=>t("setLocation",{latitude:p.latitude,longitude:p.longitude,label:p.label})},`${p.label??f}`)),a(j,{title:"Other Location\u2026",value:l?o.label||Ne(o,3):void 0,chevron:true,testID:"location-other",onPress:()=>n("places")},"other")]})})]})}function ra(e,t){let n=U(e,t);return n<30?"Here":q(n)}function rt(e,t){return e.label&&t.label?e.label===t.label:U(e,t)<1}function aa({snapshot:e,pick:t}){let[n,i]=Me(""),o=dt(n),r=e.override.mode==="fixed"?e.override.place:null,l=()=>{o&&(t("setLocation",{query:n}),i(""))};return k(Ue,{children:[k(v,{children:[a(X,{children:"Coordinates"}),a(R,{children:k(v,{style:m.editor,children:[k(v,{style:m.inputRow,children:[a(Cn,{value:n,onChangeText:i,placeholder:"Coordinates or a Maps link",placeholderTextColor:h.color.placeholder,autoCapitalize:"none",autoCorrect:false,style:m.input,testID:"location-coordinate-input",accessibilityLabel:"Coordinates or a Maps link",returnKeyType:"done",onSubmitEditing:l}),a(qn,{label:"Pin",size:"md",variant:"primary",disabled:!o,testID:"location-coordinate-set",onPress:l})]}),n.length>0?a(A,{style:o?m.detail:m.warning,testID:"location-coordinate-preview",children:o?la(o):"Type a latitude and longitude, like 40.7580, -73.9855, or paste a Google or Apple Maps link."}):null]})})]}),k(v,{children:[a(X,{children:"Places"}),a(R,{children:a(ee,{children:e.builtInPlaces.map((p,f)=>a(j,{title:p.label??Ne(p,4),detail:p.label==="Null Island"?"0, 0: catches code that treats 0 as no location":void 0,checked:!!r&&rt(p,r),testID:`location-place-${at(p.label??String(f))}`,onPress:()=>t("setLocation",{latitude:p.latitude,longitude:p.longitude,label:p.label})},`${p.label??f}`))})}),e.places.length===0?a(Q,{children:"Add your own places, such as your stores, with registerLocationPlaces()."}):null]})]})}function la(e){let t=`${Math.abs(e.latitude).toFixed(4)}\xB0 ${e.latitude>=0?"N":"S"}`,n=`${Math.abs(e.longitude).toFixed(4)}\xB0 ${e.longitude>=0?"E":"W"}`;return`${t}, ${n}`}function sa({snapshot:e,open:t}){let n=e.override.mode==="route"?e.override.route:null;return k(v,{children:[a(X,{children:"Movement"}),a(R,{children:k(ee,{children:[a(j,{title:"Route",value:n?.name??"None",chevron:true,testID:"location-route",onPress:()=>t("routes")},"route"),n?a(j,{title:"Speed",value:ca(n.speed),chevron:true,testID:"location-speed",onPress:()=>t("speed")},"speed"):null]})})]})}function ca(e){let t=Jn.find(n=>Math.abs(Number(n.key)-e)<.05);return t?t.label:Mt(e)}function ua({snapshot:e,pick:t}){let n=e.override.mode==="route"?e.override.route:null,i=n?.id;return k(Ue,{children:[n?a(v,{children:a(R,{children:a(ee,{children:a(j,{title:"Stop Here",detail:"End the route and stay where it got to",testID:"location-route-stop",onPress:()=>t("stopRoute")},"stop")})})}):null,e.routes.length>0?k(v,{children:[a(X,{children:"This App"}),a(R,{children:a(ee,{children:e.routes.map((o,r)=>a(j,{title:o.name??o.id??`Route ${r+1}`,detail:`${q(ut(o.points))} at ${Mt(o.speed)}${o.loop?", on repeat":""}`,checked:!!i&&i===o.id,testID:`location-route-${at(o.id??o.name??String(r))}`,onPress:()=>t("startRoute",{route:o.id??o.name})},o.id??`${o.name}-${r}`))})})]}):null,k(v,{children:[a(X,{children:"From Here"}),a(R,{children:a(ee,{children:e.presets.map(o=>a(j,{title:o.name,detail:da(o.id)??o.description,checked:i===`preset:${o.id}`,testID:`location-preset-${o.id}`,onPress:()=>t("startRoute",{route:o.id})},o.id))})}),a(Q,{children:"These start where the app is now."})]})]})}function da(e){let t=q;switch(e){case"walk":return`${t(1e3)} north at walking pace`;case"run":return`${t(3e3)} north, then east, at running pace`;case"drive":return`${t(4e3)} of city streets with turns`;case"highway":return`${t(3e4)} north at highway speed`;case"tunnel":return`${t(3e3)} drive with no signal for ${t(600)} in the middle`;case"loop":return`A ${t(400)} block, walked on repeat`;default:return null}}function pa({snapshot:e,pick:t}){let n=e.override.route?.speed??0;return k(v,{children:[a(R,{children:a(ee,{children:Jn.map(i=>a(j,{title:i.label,value:Mt(Number(i.key)),checked:Math.abs(Number(i.key)-n)<.05,testID:`location-speed-${i.key}`,onPress:()=>t("setSpeed",{speed:Number(i.key)})},i.key))})}),a(Q,{children:"Heading and speed follow the route."})]})}var fa=1e4;function ga({snapshot:e,run:t}){let n=e.tasks.filter(f=>f.kind==="geofencing"&&f.regions.length>0),[i,o]=Me(null),r=Dt(!!i);if(n.length===0)return null;let l=n.length>1,p=n.map(f=>f.name).join(", ");return k(v,{children:[a(X,{children:"Geofences"}),a(R,{children:a(ee,{children:n.flatMap(f=>f.regions.map(g=>{let y=`${f.name}:${g.identifier}`,T=g.state==="inside",S=i?.key===y&&r-i.at<fa?i:null,C=[ha(g)];return l&&C.push(f.name),a(j,{title:g.label??g.identifier,detail:C.join(" \xB7 "),note:S?ma(e,f,S.at):void 0,action:T?"Leave":"Enter",testID:`location-region-${at(g.identifier)}`,onPress:()=>{o({key:y,at:Et()}),t(T?"exitRegion":"enterRegion",{identifier:g.identifier,task:f.name})}},y)}))})}),k(Q,{children:["Tap a region to cross its edge. ",l?"The app's tasks":`The app's ${p} task`," runs as it would from the OS."]})]})}function ha(e){return e.state==="inside"?"Inside":e.distance==null?`${q(e.radius)} radius`:`${q(Math.max(0,e.distance-e.radius))} away`}function ma(e,t,n){let i=e.log.filter(r=>r.at>=n-50&&(r.detail??"").startsWith(t.name)),o=i.find(r=>r.kind==="error");return o?{text:`Task failed: ${o.detail?.slice(t.name.length+3)??""}`,tone:"bad"}:i.find(r=>r.kind==="task")?{text:"Task ran",tone:"ok"}:i.find(r=>r.kind==="enter"||r.kind==="exit")?{text:"Running the app's task\u2026",tone:"wait"}:{text:"Already on this side",tone:"wait"}}function ya({snapshot:e,run:t,open:n}){let i=e.override,o=xi(i),r=e.simulating?Qn:Qn.filter(l=>l.key!=="weak");return k(v,{children:[a(X,{children:"Conditions"}),k(R,{children:[a(v,{style:m.segmentWrap,children:a(Nt,{tabs:r,activeKey:o??"",size:"sm",testIDPrefix:"location-conditions",onChange:l=>t("setConditions",{conditions:l})})}),e.simulating&&i.services&&i.signal?a(v,{style:m.separatorTop,children:a(j,{title:"Accuracy & Drift",value:`${jn(i.accuracy)}${i.jitter>0?` \xB7 drifts ${q(i.jitter)}`:""}`,chevron:true,testID:"location-accuracy",onPress:()=>n("accuracy")})}):null]}),a(Q,{children:Qr[o??"custom"]})]})}function ba({snapshot:e,run:t}){let n=e.override;return k(Ue,{children:[k(v,{children:[a(X,{children:"Accuracy"}),a(R,{children:a(v,{style:m.segmentWrap,children:a(Nt,{tabs:ei,activeKey:oi(ei,n.accuracy)??"",size:"sm",testIDPrefix:"location-accuracy",onChange:i=>t("tune",{accuracy:Number(i)})})})}),a(Q,{children:"The accuracy radius the app is given with each fix."})]}),k(v,{children:[a(X,{children:"Drift"}),a(R,{children:a(v,{style:m.segmentWrap,children:a(Nt,{tabs:ti,activeKey:oi(ti,n.jitter)??"0",size:"sm",testIDPrefix:"location-drift",onChange:i=>t("tune",{jitter:Number(i)})})})}),a(Q,{children:"Moves each fix by up to this much at random, the way a real fix wanders."})]})]})}function va({snapshot:e,open:t}){let n=e.log.length;return a(v,{children:a(R,{children:k(ee,{children:[a(j,{title:"Activity",value:n===0?"None":`${n} ${n===1?"event":"events"}`,chevron:true,testID:"location-activity",onPress:()=>t("activity")},"activity"),a(j,{title:"Options",chevron:true,testID:"location-options",onPress:()=>t("options")},"options")]})})})}function wa({snapshot:e,run:t}){let n=Dt(true),i=e.log.slice().reverse(),o=e.watches.filter(f=>f.kind==="position").length,r=e.tasks.filter(f=>f.kind==="locationUpdates").length,l=e.tasks.filter(f=>f.kind==="geofencing").reduce((f,g)=>f+g.regions.length,0),p=[o?`${o} location ${o===1?"watch":"watches"}`:null,l?`${l} ${l===1?"geofence":"geofences"}`:null,r?"background updates":null].filter(Boolean);return k(Ue,{children:[k(v,{children:[a(X,{children:"The App Is Using"}),a(R,{children:k(v,{style:m.editor,children:[a(A,{style:m.rowTitle,testID:"location-activity-summary",children:p.length?p.join(", "):"Nothing right now"}),a(A,{style:m.detail,children:e.libraries.length?`Through ${e.libraries.join(" and ")}.`:"No supported location library was found in this app."})]})})]}),k(v,{children:[a(X,{children:"Recent"}),a(R,{children:k(ee,{children:[i.length===0?a(v,{style:m.editor,children:a(A,{style:m.detail,children:"Location requests, watches and geofence crossings show up here."})},"empty"):i.map(f=>k(v,{style:m.logRow,testID:"location-log-entry",children:[a(v,{style:[m.logDot,ka(f.kind)]}),k(v,{style:m.flex,children:[a(A,{style:m.logText,children:f.text}),f.detail?a(A,{style:m.logDetail,numberOfLines:2,children:f.detail}):null]}),a(A,{style:m.logWhen,children:gr(f.at,n)})]},f.id)),i.length>0?a(j,{title:"Clear",tint:true,testID:"location-clear-log",onPress:()=>t("clearLog")},"clear"):null]})})]})]})}function ka(e){return e==="enter"?m.dotEnter:e==="exit"?m.dotExit:e==="error"?m.dotError:e==="task"?m.dotTask:null}function xa({snapshot:e,run:t}){return k(v,{children:[a(R,{children:k(ee,{children:[a(ii,{title:"Keep Across Reloads",value:e.settings.persist,testID:"location-setting-persist",onValueChange:n=>t("updateSettings",{persist:n})},"persist"),a(ii,{title:"Show Floating Status",value:e.settings.showChip,testID:"location-setting-showChip",onValueChange:n=>t("updateSettings",{showChip:n})},"chip")]})}),a(Q,{children:"The floating status stays on screen while the app is somewhere else, so a simulated location is never left on by accident."})]})}function Ta({title:e,onBack:t}){return k(ae,{testID:"location-back",accessibilityRole:"button",accessibilityLabel:"Back",activeOpacity:.6,onPress:t,style:m.backRow,children:[a(Or,{size:18,color:h.color.accent}),a(A,{style:m.backLabel,children:"Location"}),a(A,{style:m.backTitle,numberOfLines:1,children:e})]})}function j({title:e,detail:t,note:n,value:i,action:o,checked:r,chevron:l,tint:p,onPress:f,testID:g}){return k(ae,{testID:g,accessibilityRole:"button",accessibilityLabel:o?`${o} ${e}`:e,accessibilityState:r?{selected:true}:void 0,activeOpacity:.6,onPress:f,style:m.row,children:[k(v,{style:m.rowText,children:[a(A,{style:[m.rowTitle,p?m.titleTint:null],numberOfLines:1,children:e}),t?a(A,{style:m.detail,children:t}):null,n?a(A,{style:[m.note,n.tone==="ok"?m.noteOk:n.tone==="bad"?m.noteBad:null],testID:`${g}-result`,children:n.text}):null]}),i?a(A,{style:m.rowValue,numberOfLines:1,children:i}):null,o?a(A,{style:m.rowAction,children:o}):null,r?a(Dr,{size:18,color:h.color.accent}):null,l?a(Br,{size:16,color:h.color.textTertiary}):null]})}function ii({title:e,value:t,onValueChange:n,testID:i}){return k(v,{style:m.row,children:[a(v,{style:m.rowText,children:a(A,{style:m.rowTitle,children:e})}),a(jr,{value:t,testID:i,accessibilityLabel:e,onValueChange:n})]})}function oi(e,t){let n=null,i=1/0;for(let o of e){let r=Math.abs(Number(o.key)-t);r<i&&(n=o.key,i=r)}return n!==null&&i<=Math.max(.05,Number(n)*.05)?n:null}function at(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}var m=re.create({fill:{flex:1},flex:{flex:1},content:{paddingHorizontal:h.gutter,paddingTop:8,gap:h.groupGap},waiting:{flex:1,alignItems:"center",justifyContent:"center",padding:24},status:{padding:h.cardPad+2,gap:6},statusTitle:{color:h.color.text,fontSize:28,fontWeight:"600"},titleSimulated:{color:h.color.accent},titleBroken:{color:Jr},statusLine:{color:h.color.textSecondary,fontSize:h.font.row,fontVariant:["tabular-nums"]},coordinates:{color:h.color.textTertiary,fontSize:h.font.caption,fontFamily:Hr},statusButtons:{flexDirection:"row",alignItems:"center",gap:10,marginTop:10},round:{width:44,height:44,borderRadius:22,alignItems:"center",justifyContent:"center",backgroundColor:h.color.accent},progressTrack:{height:6,borderRadius:3,marginTop:8,backgroundColor:h.color.fillSecondary,overflow:"hidden"},progressFill:{position:"absolute",left:0,top:0,bottom:0,backgroundColor:h.color.accent},progressGap:{position:"absolute",top:0,bottom:0,backgroundColor:"rgba(255, 255, 255, 0.28)"},permission:{borderTopWidth:re.hairlineWidth,borderTopColor:h.color.separator,paddingHorizontal:h.rowPadH,paddingVertical:12,gap:4},rowBetween:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12},valueWarning:{color:h.color.warning},row:{flexDirection:"row",alignItems:"center",gap:10,minHeight:48,paddingHorizontal:h.rowPadH,paddingVertical:10},rowText:{flex:1,gap:2},rowTitle:{color:h.color.text,fontSize:h.font.row},titleTint:{color:h.color.accent},rowValue:{color:h.color.textSecondary,fontSize:h.font.row,maxWidth:"50%"},rowAction:{color:h.color.accent,fontSize:h.font.row,fontWeight:"500"},detail:{color:h.color.textTertiary,fontSize:h.font.caption},note:{color:h.color.textSecondary,fontSize:h.font.caption,marginTop:2},noteOk:{color:h.color.accent},noteBad:{color:h.color.danger},warning:{color:h.color.warning,fontSize:h.font.caption},separatorTop:{borderTopWidth:re.hairlineWidth,borderTopColor:h.color.separator},segmentWrap:{flexDirection:"row",padding:10},editor:{paddingHorizontal:h.rowPadH,paddingVertical:14,gap:8},inputRow:{flexDirection:"row",alignItems:"center",gap:8},input:{flex:1,color:h.color.text,fontSize:h.font.body,backgroundColor:h.color.bg,borderRadius:h.radius.input,borderWidth:1,borderColor:h.color.border,paddingHorizontal:12,paddingVertical:9},backRow:{flexDirection:"row",alignItems:"center",gap:4,paddingVertical:4},backLabel:{color:h.color.accent,fontSize:h.font.row},backTitle:{flex:1,color:h.color.text,fontSize:h.font.row,fontWeight:"600",textAlign:"center",marginRight:70},logRow:{flexDirection:"row",alignItems:"flex-start",gap:10,paddingHorizontal:h.rowPadH,paddingVertical:10},logDot:{width:8,height:8,borderRadius:4,marginTop:6,backgroundColor:h.color.textTertiary},dotEnter:{backgroundColor:h.color.accent},dotExit:{backgroundColor:h.color.warning},dotError:{backgroundColor:h.color.danger},dotTask:{backgroundColor:h.color.info},logText:{color:h.color.text,fontSize:h.font.body},logDetail:{color:h.color.textTertiary,fontSize:h.font.caption,marginTop:2},logWhen:{color:h.color.textTertiary,fontSize:h.font.caption,fontVariant:["tabular-nums"],marginTop:1}});import{jsx as ri}from"react/jsx-runtime";var Sa=Rt.actions;async function Aa(e,t){let n=Sa[e];if(!n)throw new Error(`Unknown location action: ${e}`);return n(t)}var Ot=()=>Rt.getSnapshot(),Ca=2e3;function ai(){let[e,t]=Ir(Ot);return Cr(()=>{Lt(),St(),t(Ot()),Hn(true),Qe();let n=setInterval(Qe,Ca),i=Be(()=>t(Ot()));return()=>{clearInterval(n),i(),Hn(false)}},[]),ri(Lr,{featureName:"Location",children:ri(ni,{snapshot:e,onAction:Aa})})}import{jsx as Ia}from"react/jsx-runtime";var li=Ar({id:"location",name:"LOCATION",description:"Pin the app anywhere, play routes, trigger geofences",slot:"both",color:Tr,icon:({size:e,color:t})=>Ia(xr,{size:e,color:t}),component:ai,modal:{subtitle:"simulate where the app is"}}),La=Sr(li);import{LocationToolIcon as $a,LOCATION_TOOL_ICON_COLOR as Ma}from"@buoy-gg/shared-ui/web";var Pa=typeof navigator<"u"&&navigator.product==="ReactNative";Pa&&(kr(),typeof Ft<"u"&&Ft&&(Lt(),St()));export{it as BUILT_IN_PLACES,nt as LOCATION_CHIP_ID,Ma as LOCATION_TOOL_ICON_COLOR,ai as LocationBody,Un as LocationChip,$a as LocationToolIcon,ni as LocationToolView,$e as ROUTE_PRESETS,qe as bearingDegrees,St as bootLocation,Vn as buildPresetRoute,La as createLocationTool,Re as destination,U as distanceMeters,P as getLocationSnapshot,Lt as installLocationAdapters,N as isLocationActive,Rt as locationSyncAdapter,li as locationToolPreset,xt as moveToRegion,dt as parseCoordinate,wt as pauseRoute,Qe as refreshLocationPermission,Bi as registerLocationPlaces,ji as registerLocationRoutes,Tt as resetLocation,kt as resumeRoute,fn as seekRoute,bn as setConditions,tt as setPlace,gn as setRouteSpeed,yn as setServices,mn as setSignal,pn as startRoute,vn as stopRoute,Be as subscribeLocation,hn as tuneOverride,wn as useRealLocation};
package/package.json ADDED
@@ -0,0 +1,110 @@
1
+ {
2
+ "name": "@buoy-gg/location",
3
+ "version": "7.0.44",
4
+ "description": "Location override for React Native: pin the app to any place, play routes with speed and heading, trigger geofences and test signal loss. Works with expo-location, @react-native-community/geolocation and react-native-geolocation-service.",
5
+ "main": "lib/commonjs/index.js",
6
+ "module": "lib/module/index.js",
7
+ "types": "lib/typescript/index.d.ts",
8
+ "react-native": "lib/module/index.js",
9
+ "source": "src/index.tsx",
10
+ "files": [
11
+ "lib"
12
+ ],
13
+ "sideEffects": [
14
+ "./src/index.tsx",
15
+ "./lib/commonjs/index.js",
16
+ "./lib/module/index.js",
17
+ "./lib/web/**/*.mjs"
18
+ ],
19
+ "dependencies": {
20
+ "@buoy-gg/shared-ui": "^7.0.44"
21
+ },
22
+ "peerDependencies": {
23
+ "react": "*"
24
+ },
25
+ "devDependencies": {
26
+ "@types/react": "^19.1.0",
27
+ "@types/react-native": "^0.73.0",
28
+ "typescript": "~5.8.3"
29
+ },
30
+ "react-native-builder-bob": {
31
+ "source": "src",
32
+ "output": "lib",
33
+ "targets": [
34
+ "commonjs",
35
+ "module",
36
+ [
37
+ "typescript",
38
+ {
39
+ "project": "tsconfig.build.json"
40
+ }
41
+ ]
42
+ ]
43
+ },
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/Buoy-gg/buoy.git",
47
+ "directory": "packages/location"
48
+ },
49
+ "bugs": {
50
+ "url": "https://github.com/LovesWorking/react-native-buoy/issues"
51
+ },
52
+ "homepage": "https://buoy.gg/buoy/latest/docs/tools/location",
53
+ "publishConfig": {
54
+ "access": "public",
55
+ "tag": "latest"
56
+ },
57
+ "keywords": [
58
+ "react-native",
59
+ "expo",
60
+ "devtools",
61
+ "debugging",
62
+ "react-native-devtools",
63
+ "location",
64
+ "geolocation",
65
+ "mock-location",
66
+ "gps",
67
+ "geofence",
68
+ "expo-location"
69
+ ],
70
+ "exports": {
71
+ ".": {
72
+ "react-native": "./lib/module/index.js",
73
+ "browser": {
74
+ "types": "./lib/typescript/index.d.ts",
75
+ "default": "./lib/web/index.mjs"
76
+ },
77
+ "import": {
78
+ "types": "./lib/typescript/index.d.ts",
79
+ "default": "./lib/module/index.js"
80
+ },
81
+ "require": {
82
+ "types": "./lib/typescript/index.d.ts",
83
+ "default": "./lib/commonjs/index.js"
84
+ }
85
+ },
86
+ "./web": {
87
+ "types": "./lib/typescript/index.d.ts",
88
+ "default": "./lib/web/index.mjs"
89
+ }
90
+ },
91
+ "peerDependenciesMeta": {
92
+ "react-native": {
93
+ "optional": true
94
+ },
95
+ "react-native-web": {
96
+ "optional": true
97
+ },
98
+ "react-dom": {
99
+ "optional": true
100
+ }
101
+ },
102
+ "scripts": {
103
+ "build": "bob build && pnpm run build:web",
104
+ "typecheck": "tsc --noEmit",
105
+ "clean": "rimraf lib",
106
+ "test": "pnpm run typecheck",
107
+ "postinstall": "echo \"Run pnpm build to compile this package\"",
108
+ "build:web": "node ../../scripts/build-web.mjs location"
109
+ }
110
+ }