@stacksjs/mobile 0.75.153 → 0.75.155
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -0
- package/dist/index.d.ts +151 -1
- package/dist/index.js +2 -2
- package/dist/route.d.ts +13 -1
- package/dist/types.d.ts +116 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -116,6 +116,70 @@ if (health.supports('getHeartRateSamples')) {
|
|
|
116
116
|
}
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
## Heart-rate strap
|
|
120
|
+
|
|
121
|
+
`heartRate` reads a Bluetooth heart-rate strap (Polar, Garmin, Wahoo), or a
|
|
122
|
+
watch broadcasting its heart rate, through the standard Heart Rate Service.
|
|
123
|
+
`scan` finds straps nearby (`onDevice` hears each), `connect(id)` subscribes
|
|
124
|
+
to its readings (`onReading`: bpm and RR intervals, about once a second) and
|
|
125
|
+
remembers it, so `reconnect()` finds it next time without a scan; a strap that
|
|
126
|
+
drops out is asked for again until `disconnect()`. `startRecording()` keeps
|
|
127
|
+
every reading natively, screen locked or app closed, until `stopRecording()`
|
|
128
|
+
hands them back. iOS only, behind `capabilities.heartRate` (which adds the
|
|
129
|
+
`bluetooth-central` background mode); Bluetooth needs no network.
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { createRouteRecorder, heartRate, location } from '@stacksjs/mobile'
|
|
133
|
+
|
|
134
|
+
const stop = heartRate.onDevice(device => list.push(device)) // { id, name, rssi }
|
|
135
|
+
await heartRate.scan({ timeout: 15 }) // can show iOS's Bluetooth prompt
|
|
136
|
+
await heartRate.connect(list[0].id) // rejects TIMEOUT while still asking
|
|
137
|
+
heartRate.onReading(reading => show(reading.bpm))
|
|
138
|
+
|
|
139
|
+
// With a route: the strap records with it, and each fix gets its heart rate.
|
|
140
|
+
const recorder = createRouteRecorder({ location, heartRate })
|
|
141
|
+
await recorder.start()
|
|
142
|
+
const fixes = await recorder.stop() // fixes[i].heartRate
|
|
143
|
+
const samples = recorder.heartRate // every reading: { timestamp, bpm, rr? }
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Without a route, record it on its own (`heartRate.startRecording()` /
|
|
147
|
+
`stopRecording()`), and `attachHeartRate(fixes, samples)` pairs readings
|
|
148
|
+
with fixes recorded separately. In a browser and on Android `isAvailable()` is
|
|
149
|
+
false, the state says `available: false` and nothing fires. Word iOS's prompt
|
|
150
|
+
with `ios.usageDescriptions.NSBluetoothAlwaysUsageDescription`.
|
|
151
|
+
|
|
152
|
+
## Apple Music
|
|
153
|
+
|
|
154
|
+
`music` shows what the Music app is playing (title, artist, album, a small
|
|
155
|
+
artwork data URL, duration, position, playback state) and steers it: `play`,
|
|
156
|
+
`pause`, `togglePlayPause`, `skipToNext` and `skipToPrevious`, which restarts
|
|
157
|
+
the song a few seconds in, like the Music app's own button. Changes arrive
|
|
158
|
+
from native as they happen, so a page never polls. iOS only, behind
|
|
159
|
+
`capabilities.appleMusic`; music control is local to the phone, so it works
|
|
160
|
+
offline.
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import { music } from '@stacksjs/mobile'
|
|
164
|
+
|
|
165
|
+
// From the person's tap, never on load: iOS shows its prompt the first time.
|
|
166
|
+
if (await music.requestAuthorization() === 'authorized') {
|
|
167
|
+
render(await music.getNowPlaying())
|
|
168
|
+
const stop = music.onChange(render) // observes while anyone listens
|
|
169
|
+
await music.togglePlayPause()
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Only Apple Music: iOS gives no app the controls of another player, Spotify
|
|
174
|
+
included, so while one plays the song fields are null and `otherAudioPlaying`
|
|
175
|
+
is true; say so rather than show controls that do nothing. Nothing is read
|
|
176
|
+
before access is allowed (`authorization` is `notDetermined`, `denied` or
|
|
177
|
+
`restricted` until then). In a browser and on Android `isAvailable()` is false,
|
|
178
|
+
every call answers `{ available: false }` and `onChange` never fires. Word the
|
|
179
|
+
prompt with `ios.usageDescriptions.NSAppleMusicUsageDescription`. The
|
|
180
|
+
simulator's Music app has nothing to play; launch a simulator build with
|
|
181
|
+
`-CraftFakeMusicPlayer YES` for three made-up songs that play and skip.
|
|
182
|
+
|
|
119
183
|
## Recording a route
|
|
120
184
|
|
|
121
185
|
Craft records the route natively: fixes go to disk, keep coming with the screen
|
package/dist/index.d.ts
CHANGED
|
@@ -73,6 +73,28 @@ declare const keepAwake: KeepAwakeApi;
|
|
|
73
73
|
* backlight to set: `isAvailable()` is false and the calls resolve `null`.
|
|
74
74
|
*/
|
|
75
75
|
declare const brightness: BrightnessApi;
|
|
76
|
+
/**
|
|
77
|
+
* What the Music app is playing, and its play/pause/skip, for a screen the
|
|
78
|
+
* person trains with. iOS only, and only Apple Music: iOS gives no app another
|
|
79
|
+
* player's controls (Spotify included), so then the song fields are null and
|
|
80
|
+
* `otherAudioPlaying` is true. Nothing is read until `requestAuthorization()`,
|
|
81
|
+
* which shows iOS's prompt once; call it from the person's tap. In a browser
|
|
82
|
+
* and on Android every call answers `{ available: false }` and changes never
|
|
83
|
+
* fire. Music control is local to the phone, so it works offline.
|
|
84
|
+
*/
|
|
85
|
+
declare const music: MusicApi;
|
|
86
|
+
/**
|
|
87
|
+
* A Bluetooth heart-rate strap (Polar, Garmin, Wahoo...), or a watch
|
|
88
|
+
* broadcasting its heart rate, through the standard Heart Rate Service. iOS
|
|
89
|
+
* only, in an app built with `capabilities.heartRate`: scan, connect (the
|
|
90
|
+
* strap is remembered; `reconnect()` finds it next time without a scan), a
|
|
91
|
+
* reading about once a second with its RR intervals, and a recording kept
|
|
92
|
+
* natively, so a workout's heart rate survives the screen being locked and the
|
|
93
|
+
* app being closed. Pass it to `createRouteRecorder({ heartRate })` to record
|
|
94
|
+
* it with a route. In a browser and on Android it is unavailable: the state
|
|
95
|
+
* says `available: false` and nothing fires. Bluetooth works offline.
|
|
96
|
+
*/
|
|
97
|
+
declare const heartRate: HeartRateApi;
|
|
76
98
|
/**
|
|
77
99
|
* Short spoken cues ("Rest, 15 seconds"). In the app the voice ducks the
|
|
78
100
|
* user's music and plays with the silent switch on; in a browser it falls back
|
|
@@ -427,6 +449,13 @@ declare interface TabRootHost {
|
|
|
427
449
|
}
|
|
428
450
|
|
|
429
451
|
// From: src/route.ts
|
|
452
|
+
/**
|
|
453
|
+
* The fixes with the heart rate of the reading nearest each one, when there
|
|
454
|
+
* is one within `maxGapMs`: a strap reads about once a second, a phone fixes
|
|
455
|
+
* about once a second, and neither waits for the other. A fix with no reading
|
|
456
|
+
* near it (the strap off, or not worn yet) keeps none.
|
|
457
|
+
*/
|
|
458
|
+
declare function attachHeartRate<T extends RouteFix>(fixes: readonly T[], samples: readonly HeartRateSample[], maxGapMs?: unknown): T[];
|
|
430
459
|
/** Great-circle distance between two fixes, metres. */
|
|
431
460
|
declare function fixDistance(a: { latitude: number, longitude: number }, b: { latitude: number, longitude: number }): number;
|
|
432
461
|
/** The fixes worth counting, oldest first: a known position, accurate enough. */
|
|
@@ -452,11 +481,14 @@ declare function speedLabel(metresPerSecond: number | null | undefined): string;
|
|
|
452
481
|
* in front. Reading pauses with the page hidden; the recording does not.
|
|
453
482
|
*/
|
|
454
483
|
declare function createRouteRecorder(options: RouteRecorderOptions): RouteRecorder;
|
|
484
|
+
/** A fix and a strap's reading further apart than this, ms, do not belong together. */
|
|
485
|
+
declare const HEART_RATE_MATCH_MS: 5000;
|
|
455
486
|
/** Fixes further apart than this, seconds, are a break in the route (a pause). */
|
|
456
487
|
declare const ROUTE_GAP_S: 30;
|
|
457
488
|
/** A fix as Craft records it. */
|
|
458
489
|
declare interface RouteFix extends Location {
|
|
459
490
|
altitudeAccuracy?: number
|
|
491
|
+
heartRate?: number
|
|
460
492
|
}
|
|
461
493
|
declare interface RouteStats {
|
|
462
494
|
distanceM: number
|
|
@@ -476,6 +508,7 @@ declare interface RouteRecorderOptions extends RouteStatsOptions {
|
|
|
476
508
|
onUpdate?: (stats: RouteStats) => void
|
|
477
509
|
location: LocationApi
|
|
478
510
|
locationOptions?: LocationOptions
|
|
511
|
+
heartRate?: HeartRateRecordingApi
|
|
479
512
|
}
|
|
480
513
|
declare interface RouteRecorder {
|
|
481
514
|
start: () => Promise<RouteStats>
|
|
@@ -486,6 +519,7 @@ declare interface RouteRecorder {
|
|
|
486
519
|
refresh: () => Promise<RouteStats>
|
|
487
520
|
dispose: () => void
|
|
488
521
|
readonly stats: RouteStats
|
|
522
|
+
readonly heartRate: HeartRateSample[]
|
|
489
523
|
}
|
|
490
524
|
|
|
491
525
|
// From: src/session-clock.ts
|
|
@@ -1216,6 +1250,7 @@ declare interface CraftMobileCapabilities {
|
|
|
1216
1250
|
orientationLock?: boolean
|
|
1217
1251
|
deepLinks?: boolean
|
|
1218
1252
|
flashlight?: boolean
|
|
1253
|
+
music?: boolean
|
|
1219
1254
|
network?: boolean
|
|
1220
1255
|
deviceInfo?: boolean
|
|
1221
1256
|
badge?: boolean
|
|
@@ -1262,6 +1297,8 @@ declare interface MobileApi {
|
|
|
1262
1297
|
deepLinks: DeepLinksApi
|
|
1263
1298
|
keepAwake: KeepAwakeApi
|
|
1264
1299
|
brightness: BrightnessApi
|
|
1300
|
+
music: MusicApi
|
|
1301
|
+
heartRate: HeartRateApi
|
|
1265
1302
|
speech: SpeechApi
|
|
1266
1303
|
network: NetworkApi
|
|
1267
1304
|
pushNotifications: PushNotificationsApi
|
|
@@ -1451,6 +1488,107 @@ declare interface SpeechApi {
|
|
|
1451
1488
|
speak: (text: string, options?: SpeechOptions) => Promise<boolean>
|
|
1452
1489
|
stop: () => Promise<void>
|
|
1453
1490
|
}
|
|
1491
|
+
/**
|
|
1492
|
+
* What the Music app is playing. The song fields are null without access,
|
|
1493
|
+
* with nothing queued, and while another app (Spotify, a podcast) plays; then
|
|
1494
|
+
* `otherAudioPlaying` is true.
|
|
1495
|
+
*/
|
|
1496
|
+
declare interface NowPlaying {
|
|
1497
|
+
available: boolean
|
|
1498
|
+
authorization: MusicAuthorization
|
|
1499
|
+
source: 'appleMusic' | 'simulated' | null
|
|
1500
|
+
playbackState: MusicPlaybackState
|
|
1501
|
+
isPlaying: boolean
|
|
1502
|
+
itemId: string | null
|
|
1503
|
+
title: string | null
|
|
1504
|
+
artist: string | null
|
|
1505
|
+
album: string | null
|
|
1506
|
+
duration: number | null
|
|
1507
|
+
position: number | null
|
|
1508
|
+
artworkDataURL: string | null
|
|
1509
|
+
otherAudioPlaying: boolean
|
|
1510
|
+
timestamp: number
|
|
1511
|
+
}
|
|
1512
|
+
declare interface MusicSkipOptions {
|
|
1513
|
+
restartAfter?: number
|
|
1514
|
+
}
|
|
1515
|
+
/** A heart-rate strap, or a watch broadcasting its heart rate. */
|
|
1516
|
+
declare interface HeartRateDevice {
|
|
1517
|
+
id: string
|
|
1518
|
+
name: string
|
|
1519
|
+
rssi: number | null
|
|
1520
|
+
}
|
|
1521
|
+
declare interface HeartRateRecordingState {
|
|
1522
|
+
id: string | null
|
|
1523
|
+
active: boolean
|
|
1524
|
+
paused: boolean
|
|
1525
|
+
startedAt: number | null
|
|
1526
|
+
sampleCount: number | null
|
|
1527
|
+
}
|
|
1528
|
+
declare interface HeartRateState {
|
|
1529
|
+
available: boolean
|
|
1530
|
+
bluetooth: BluetoothState
|
|
1531
|
+
authorization: HeartRateAuthorization
|
|
1532
|
+
scanning: boolean
|
|
1533
|
+
connection: HeartRateConnection
|
|
1534
|
+
device: HeartRateDevice | null
|
|
1535
|
+
lastDevice: HeartRateDevice | null
|
|
1536
|
+
bpm: number | null
|
|
1537
|
+
lastReadingAt: number | null
|
|
1538
|
+
recording: HeartRateRecordingState
|
|
1539
|
+
}
|
|
1540
|
+
declare interface HeartRateReading {
|
|
1541
|
+
bpm: number
|
|
1542
|
+
rrIntervals: number[]
|
|
1543
|
+
contact: boolean | null
|
|
1544
|
+
energyExpended: number | null
|
|
1545
|
+
timestamp: number
|
|
1546
|
+
deviceId: string | null
|
|
1547
|
+
}
|
|
1548
|
+
/** A reading as a recording keeps it. */
|
|
1549
|
+
declare interface HeartRateSample {
|
|
1550
|
+
timestamp: number
|
|
1551
|
+
bpm: number
|
|
1552
|
+
rr?: number[]
|
|
1553
|
+
}
|
|
1554
|
+
/** The recording half of HeartRateApi: what a route recorder drives. */
|
|
1555
|
+
declare interface HeartRateRecordingApi {
|
|
1556
|
+
isAvailable: () => boolean
|
|
1557
|
+
startRecording: () => Promise<HeartRateRecordingState>
|
|
1558
|
+
pauseRecording: () => Promise<HeartRateRecordingState>
|
|
1559
|
+
resumeRecording: () => Promise<HeartRateRecordingState>
|
|
1560
|
+
stopRecording: () => Promise<HeartRateRecordingState & { samples: HeartRateSample[] }>
|
|
1561
|
+
getRecordingState: () => Promise<HeartRateRecordingState>
|
|
1562
|
+
readRecording: (options?: { since?: number }) => Promise<HeartRateSample[]>
|
|
1563
|
+
}
|
|
1564
|
+
declare interface HeartRateApi extends HeartRateRecordingApi {
|
|
1565
|
+
isAvailable: () => boolean
|
|
1566
|
+
supports: (method: HeartRateMethod) => boolean
|
|
1567
|
+
getState: () => Promise<HeartRateState>
|
|
1568
|
+
requestAuthorization: () => Promise<HeartRateAuthorization>
|
|
1569
|
+
scan: (options?: { timeout?: number }) => Promise<HeartRateState>
|
|
1570
|
+
stopScan: () => Promise<HeartRateState>
|
|
1571
|
+
getDevices: () => Promise<HeartRateDevice[]>
|
|
1572
|
+
connect: (id: string) => Promise<HeartRateState>
|
|
1573
|
+
reconnect: () => Promise<HeartRateState>
|
|
1574
|
+
disconnect: (options?: { forget?: boolean }) => Promise<HeartRateState>
|
|
1575
|
+
onReading: (callback: (reading: HeartRateReading) => void) => () => void
|
|
1576
|
+
onDevice: (callback: (device: HeartRateDevice) => void) => () => void
|
|
1577
|
+
onState: (callback: (state: HeartRateState) => void) => () => void
|
|
1578
|
+
}
|
|
1579
|
+
declare interface MusicApi {
|
|
1580
|
+
isAvailable: () => boolean
|
|
1581
|
+
supports: (method: MusicMethod) => boolean
|
|
1582
|
+
getAuthorizationStatus: () => Promise<MusicAuthorization>
|
|
1583
|
+
requestAuthorization: () => Promise<MusicAuthorization>
|
|
1584
|
+
getNowPlaying: () => Promise<NowPlaying>
|
|
1585
|
+
play: () => Promise<NowPlaying>
|
|
1586
|
+
pause: () => Promise<NowPlaying>
|
|
1587
|
+
togglePlayPause: () => Promise<NowPlaying>
|
|
1588
|
+
skipToNext: () => Promise<NowPlaying>
|
|
1589
|
+
skipToPrevious: (options?: MusicSkipOptions) => Promise<NowPlaying>
|
|
1590
|
+
onChange: (callback: (nowPlaying: NowPlaying) => void) => () => void
|
|
1591
|
+
}
|
|
1454
1592
|
declare interface DeepLinksApi {
|
|
1455
1593
|
getInitialURL: () => Promise<string | null>
|
|
1456
1594
|
onLink: (callback: (url: string, link?: { initial: boolean }) => void) => () => void
|
|
@@ -1621,6 +1759,18 @@ type PermissionStatus = 'granted' | 'denied' | 'undetermined' | 'restricted';
|
|
|
1621
1759
|
type BiometricType = 'faceId' | 'touchId' | 'fingerprint' | 'face' | 'iris' | 'none';
|
|
1622
1760
|
type AppState = 'active' | 'inactive' | 'background';
|
|
1623
1761
|
type HapticKind = 'impact' | 'notification' | 'selection';
|
|
1762
|
+
/** Whether the person has let the app see their music. `unavailable` off a phone. */
|
|
1763
|
+
type MusicAuthorization = 'authorized' | 'denied' | 'restricted' | 'notDetermined' | 'unavailable';
|
|
1764
|
+
type MusicPlaybackState = 'stopped' | 'playing' | 'paused' | 'interrupted' | 'seekingForward' | 'seekingBackward' | 'unknown';
|
|
1765
|
+
type MusicMethod = 'getAuthorizationStatus' | 'requestAuthorization' | 'getNowPlaying' | 'play' | 'pause' | 'togglePlayPause' | 'skipToNext' | 'skipToPrevious' | 'observe';
|
|
1766
|
+
/** Whether the person has let the app use Bluetooth. `unavailable` off a phone. */
|
|
1767
|
+
type HeartRateAuthorization = 'authorized' | 'denied' | 'restricted' | 'notDetermined' | 'unavailable';
|
|
1768
|
+
/** The phone's Bluetooth radio; `unknown` until something has asked for it. */
|
|
1769
|
+
type BluetoothState = 'poweredOn' | 'poweredOff' | 'unauthorized' | 'unsupported' | 'resetting' | 'unknown';
|
|
1770
|
+
/** A strap that drops out is asked for again (`reconnecting`) until `disconnect()`. */
|
|
1771
|
+
type HeartRateConnection = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
|
|
1772
|
+
type HeartRateMethod = 'getState' | 'requestAuthorization' | 'scan' | 'stopScan' | 'getDevices' | 'connect' | 'reconnect' | 'disconnect'
|
|
1773
|
+
| 'startRecording' | 'pauseRecording' | 'resumeRecording' | 'stopRecording' | 'getRecordingState' | 'readRecording';
|
|
1624
1774
|
type HealthDataType = | 'steps'
|
|
1625
1775
|
| 'heartRate'
|
|
1626
1776
|
| 'activeEnergy'
|
|
@@ -1642,6 +1792,6 @@ type HealthSleepStage = 'inBed' | 'awake' | 'asleep' | 'core' | 'deep' | 'rem';
|
|
|
1642
1792
|
/** The health reads an installed app build may or may not answer. */
|
|
1643
1793
|
type HealthReadMethod = 'getWorkouts' | 'getDailyStatistics' | 'getHeartRateSamples' | 'getSleepIntervals';
|
|
1644
1794
|
|
|
1645
|
-
export { normalizeDeepLinkURL, getNativeMobileBridge, isNativeMobile, whenNativeMobile, onMobileReady, withNativeFeedback, biometrics, camera, device, lifecycle, location, notifications, permissions, secureStorage, share, appReview, haptics, deepLinks, snapshots, keepAwake, brightness, speech, network, pushNotifications, health, liveActivities, watchConnectivity, splash, mobile, craftHost, craftRoot, hasNativeMobileHost, bridgePending, whenBridgeReady, nativeFunctionNow, nativeFunction, callNative, afterBridge, subscribeWhenReady, onCraftEvent, BRIDGE_WAIT_MS, CraftHost, CallNativeOptions, observeLongPress, segmentAt, observeSegmentScrub, segmentForKey, focusSegment, installPressables, LongPressOptions, SegmentScrubOptions, currentAppearance, normalizeAppearance, onAppearance, onResume, onMemoryWarning, onSilentPush, onBackgroundRefresh, NativeAppearance, pageScrollTop, observePageScroll, pullDistance, observePullToRefresh, largeTitleMetrics, observeLargeTitle, resolveScrollHost, ScrollHost, PullToRefreshOptions, LargeTitleMetrics, LargeTitleOptions, canGoBack, goBack, enterNavTrail, backLabelFor, navTrail, previousScreenPath, goBackToTabRoot, trailEntryFor, deepLinkPath, followDeepLinks, HistoryHost, NavTrailEntry, TabRootHost, fixDistance, usableFixes, routeStats, paceLabel, speedLabel, createRouteRecorder, ROUTE_GAP_S, RouteFix, RouteStats, RouteStatsOptions, RouteRecorderOptions, RouteRecorder, startSessionClock, pauseSessionClock, resumeSessionClock, sessionClockElapsed, SessionClock, indoorVerdict, typedDistanceKm, INDOOR_CHECK_AFTER_S, IndoorFix, IndoorVerdict, toNativeRect, useActionSheet, confirmAction, showContextMenuFor, dialog, contextMenu, browser, symbols, statusBar, chrome, refresh, background, clipboard, db, files, shortcuts, widgets, orientation, auth, storeKit, DialogApi, ConfirmActionOptions, ContextMenuApi, BrowserOpenOptions, BrowserResult, BrowserApi, SymbolOptions, SymbolsApi, StatusBarApi, ChromeApi, RefreshApi, BackgroundApi, ClipboardApi, DatabaseExecuteResult, DatabaseApi, PickedFile, ScannedCode, FilesApi, HomeScreenShortcut, ShortcutsApi, WidgetsApi, OrientationApi, AppleSignInResult, AppleSignInOptions, AuthApi, StoreProduct, StoreTransaction, StoreKitApi, StatusBarStyle, OrientationLock, ActionSheetOptions, AlertOptions, ChoiceOptions, ConfirmOptions, ContextMenuItem, ContextMenuOptions, DialogAction, DialogActionStyle, NativeRect, isShown, observeNativeRefresh, NativeRefreshOptions, sheetStops, settleSheet, rubberBand, observeSheetDrag, lockBackground, liftToBody, presentPageAsCard, SHEET_FLICK_VELOCITY, SheetStop, SheetDragOptions, SheetDetent, SheetSettle, trapFocus, presentChoice, presentAlert, presentConfirm, presentActionSheet, placeMenu, presentContextMenu, applyAppearance, pageBackground, pageIsDark, installNativeChrome, NativeChromeOptions, readSpotlightKinds, spotlightKind, spotlightAction, spotlightSlot, spotlightActions, spotlightActivityTypes, spotlightTitle, placeSpotlightItem, removeSpotlightItem, spotlightRoute, readSpotlightEntries, spotlightBridge, createSpotlightIndex, onSpotlightTap, MAX_SPOTLIGHT_SLOTS_PER_KIND, SpotlightKind, SpotlightKindInput, SpotlightItem, SpotlightEntry, SpotlightKindsResult, SpotlightPlacement, SpotlightBridge, SpotlightIndexOptions, SpotlightIndex, readTabLinks, nativeTabs, routerHandlesTabs, handleTabReselect, coverTabBar, mirrorTabBar, tabBar, TAB_BAR_COVER_EVENT, TabBarApi, TabLink, TabReselectOptions, MirrorTabBarOptions, CraftMobileCapabilities, CraftMobileBridge, CraftReadyEvent, MobileApi, DeviceInfo, DeviceCapabilities, CameraOptions, PhotoResult, Location, LocationOptions, LocationRecordingState, LocationRecordingResult, ShareOptions, NotificationOptions, DeviceApi, HapticsApi, PermissionsApi, CameraApi, BiometricsApi, SecureStorageApi, LocationApi, ShareApi, LifecycleApi, NotificationsApi, KeepAwakeApi, BrightnessApi, SpeechOptions, SpeechApi, DeepLinksApi, SnapshotsApi, NetworkStatus, NetworkApi, AppReviewApi, PushNotificationsApi, HealthDataOptions, HealthDataResult, HealthWorkoutLocation, HealthWorkout, HealthWorkoutResult, HealthWorkoutQuery, HealthWorkoutSample, HealthDailyValue, HealthSampleQuery, HealthHeartRateQuery, HealthHeartRateSample, HealthSleepInterval, HealthAuthorizationOptions, HealthApi, LiveActivityState, LiveActivityOptions, LiveActivitiesApi, WatchConnectivityApi, HapticStyle, HapticNotificationType, PermissionType, PermissionStatus, BiometricType, AppState, HapticKind, HealthDataType, HealthDailyType, HealthWorkoutType, HealthWorkoutActivity, HealthSleepStage, HealthReadMethod };
|
|
1795
|
+
export { normalizeDeepLinkURL, getNativeMobileBridge, isNativeMobile, whenNativeMobile, onMobileReady, withNativeFeedback, biometrics, camera, device, lifecycle, location, notifications, permissions, secureStorage, share, appReview, haptics, deepLinks, snapshots, keepAwake, brightness, music, heartRate, speech, network, pushNotifications, health, liveActivities, watchConnectivity, splash, mobile, craftHost, craftRoot, hasNativeMobileHost, bridgePending, whenBridgeReady, nativeFunctionNow, nativeFunction, callNative, afterBridge, subscribeWhenReady, onCraftEvent, BRIDGE_WAIT_MS, CraftHost, CallNativeOptions, observeLongPress, segmentAt, observeSegmentScrub, segmentForKey, focusSegment, installPressables, LongPressOptions, SegmentScrubOptions, currentAppearance, normalizeAppearance, onAppearance, onResume, onMemoryWarning, onSilentPush, onBackgroundRefresh, NativeAppearance, pageScrollTop, observePageScroll, pullDistance, observePullToRefresh, largeTitleMetrics, observeLargeTitle, resolveScrollHost, ScrollHost, PullToRefreshOptions, LargeTitleMetrics, LargeTitleOptions, canGoBack, goBack, enterNavTrail, backLabelFor, navTrail, previousScreenPath, goBackToTabRoot, trailEntryFor, deepLinkPath, followDeepLinks, HistoryHost, NavTrailEntry, TabRootHost, attachHeartRate, fixDistance, usableFixes, routeStats, paceLabel, speedLabel, createRouteRecorder, HEART_RATE_MATCH_MS, ROUTE_GAP_S, RouteFix, RouteStats, RouteStatsOptions, RouteRecorderOptions, RouteRecorder, startSessionClock, pauseSessionClock, resumeSessionClock, sessionClockElapsed, SessionClock, indoorVerdict, typedDistanceKm, INDOOR_CHECK_AFTER_S, IndoorFix, IndoorVerdict, toNativeRect, useActionSheet, confirmAction, showContextMenuFor, dialog, contextMenu, browser, symbols, statusBar, chrome, refresh, background, clipboard, db, files, shortcuts, widgets, orientation, auth, storeKit, DialogApi, ConfirmActionOptions, ContextMenuApi, BrowserOpenOptions, BrowserResult, BrowserApi, SymbolOptions, SymbolsApi, StatusBarApi, ChromeApi, RefreshApi, BackgroundApi, ClipboardApi, DatabaseExecuteResult, DatabaseApi, PickedFile, ScannedCode, FilesApi, HomeScreenShortcut, ShortcutsApi, WidgetsApi, OrientationApi, AppleSignInResult, AppleSignInOptions, AuthApi, StoreProduct, StoreTransaction, StoreKitApi, StatusBarStyle, OrientationLock, ActionSheetOptions, AlertOptions, ChoiceOptions, ConfirmOptions, ContextMenuItem, ContextMenuOptions, DialogAction, DialogActionStyle, NativeRect, isShown, observeNativeRefresh, NativeRefreshOptions, sheetStops, settleSheet, rubberBand, observeSheetDrag, lockBackground, liftToBody, presentPageAsCard, SHEET_FLICK_VELOCITY, SheetStop, SheetDragOptions, SheetDetent, SheetSettle, trapFocus, presentChoice, presentAlert, presentConfirm, presentActionSheet, placeMenu, presentContextMenu, applyAppearance, pageBackground, pageIsDark, installNativeChrome, NativeChromeOptions, readSpotlightKinds, spotlightKind, spotlightAction, spotlightSlot, spotlightActions, spotlightActivityTypes, spotlightTitle, placeSpotlightItem, removeSpotlightItem, spotlightRoute, readSpotlightEntries, spotlightBridge, createSpotlightIndex, onSpotlightTap, MAX_SPOTLIGHT_SLOTS_PER_KIND, SpotlightKind, SpotlightKindInput, SpotlightItem, SpotlightEntry, SpotlightKindsResult, SpotlightPlacement, SpotlightBridge, SpotlightIndexOptions, SpotlightIndex, readTabLinks, nativeTabs, routerHandlesTabs, handleTabReselect, coverTabBar, mirrorTabBar, tabBar, TAB_BAR_COVER_EVENT, TabBarApi, TabLink, TabReselectOptions, MirrorTabBarOptions, CraftMobileCapabilities, CraftMobileBridge, CraftReadyEvent, MobileApi, DeviceInfo, DeviceCapabilities, CameraOptions, PhotoResult, Location, LocationOptions, LocationRecordingState, LocationRecordingResult, ShareOptions, NotificationOptions, DeviceApi, HapticsApi, PermissionsApi, CameraApi, BiometricsApi, SecureStorageApi, LocationApi, ShareApi, LifecycleApi, NotificationsApi, KeepAwakeApi, BrightnessApi, SpeechOptions, SpeechApi, NowPlaying, MusicSkipOptions, HeartRateDevice, HeartRateRecordingState, HeartRateState, HeartRateReading, HeartRateSample, HeartRateRecordingApi, HeartRateApi, MusicApi, DeepLinksApi, SnapshotsApi, NetworkStatus, NetworkApi, AppReviewApi, PushNotificationsApi, HealthDataOptions, HealthDataResult, HealthWorkoutLocation, HealthWorkout, HealthWorkoutResult, HealthWorkoutQuery, HealthWorkoutSample, HealthDailyValue, HealthSampleQuery, HealthHeartRateQuery, HealthHeartRateSample, HealthSleepInterval, HealthAuthorizationOptions, HealthApi, LiveActivityState, LiveActivityOptions, LiveActivitiesApi, WatchConnectivityApi, HapticStyle, HapticNotificationType, PermissionType, PermissionStatus, BiometricType, AppState, HapticKind, MusicAuthorization, MusicPlaybackState, MusicMethod, HeartRateAuthorization, BluetoothState, HeartRateConnection, HeartRateMethod, HealthDataType, HealthDailyType, HealthWorkoutType, HealthWorkoutActivity, HealthSleepStage, HealthReadMethod };
|
|
1646
1796
|
export { NativeTab } from 'craft-native/mobile';
|
|
1647
1797
|
export { NativeTabBarOptions } from 'craft-native/mobile';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{appReview as
|
|
1
|
+
import{appReview as kn,biometrics as Ae,brightness as re,camera as oe,deepLinks as gt,device as D,haptics as ie,health as V,heartRate as A,keepAwake as ht,lifecycle as En,liveActivities as ke,location as N,music as P,network as bt,notifications as ae,permissions as G,pushNotifications as Ee,secureStorage as se,share as vt,speech as Te,snapshots as le,splash as Tn,watchConnectivity as X}from"craft-native/mobile";var Jn=2500;function S(){if(typeof window>"u")return;return window}function xt(){let e=S()?.craft;return e&&typeof e==="object"?e:void 0}function wt(){return typeof navigator>"u"?"":navigator.userAgent||""}function pe(){let e=S();if(!e)return!1;if(e.CraftAndroid)return!0;return Boolean(e.webkit?.messageHandlers?.craft)&&/iPhone|iPad|iPod/.test(wt())}function J(){let e=S();if(!e||e.craft)return!1;return pe()||Boolean(e.webkit?.messageHandlers?.craft)}function B(e=15000){let t=S();if(t?.craft)return Promise.resolve(!0);if(!t||!J())return Promise.resolve(!1);return new Promise((n)=>{let r=()=>{clearTimeout(o),t.removeEventListener("craftReady",r),n(Boolean(t.craft))},o=setTimeout(r,e);t.addEventListener("craftReady",r)})}function At(e,t){if(!e)return null;let n=t.split("."),r=e;for(let i of n.slice(0,-1))if(r=r?.[i],!r||typeof r!=="object"&&typeof r!=="function")return null;let o=r?.[n[n.length-1]];return typeof o==="function"?o.bind(r):null}function L(e){return At(xt(),e)}async function kt(e,t=2500){let n=L(e);if(n||!J())return n;return await B(t),L(e)}async function v(e,t,n,r={}){let o=await kt(e,r.timeoutMs);if(!o)return n();try{return await o(...t)}catch(i){if(r.fallbackOnError)return n();throw i}}async function c(e,t=2500){if(J())await B(t);return e()}function _(e,t=2500){let n,r=!1;if(!J())n=e();else B(t).then(()=>{if(!r)n=e()});return()=>{if(r=!0,typeof n==="function")n()}}function O(e,t){let n=S();if(!n)return()=>{};let r=(o)=>t(o.detail??{});return n.addEventListener(e,r),()=>n.removeEventListener(e,r)}var Le="native-dialog-styles",Et=`
|
|
2
2
|
.native-dialog { position: fixed; inset: 0; z-index: 2147483000; font-size: var(--native-font-size, 17px); font-family: var(--native-font-family, -apple-system, system-ui, sans-serif); -webkit-tap-highlight-color: transparent; }
|
|
3
3
|
.native-dialog-backdrop { position: absolute; inset: 0; background: rgb(0 0 0 / 0.3); opacity: 0; transition: opacity 220ms ease; }
|
|
4
4
|
.native-dialog--menu .native-dialog-backdrop { background: rgb(0 0 0 / 0.12); -webkit-backdrop-filter: blur(14px) saturate(140%); backdrop-filter: blur(14px) saturate(140%); }
|
|
@@ -52,4 +52,4 @@ import{appReview as vn,biometrics as ye,brightness as Q,camera as Z,deepLinks as
|
|
|
52
52
|
.native-dialog-group, .native-menu { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--native-dialog-solid, rgb(242 242 247)); }
|
|
53
53
|
.dark .native-dialog-group, .dark .native-menu { background: var(--native-dialog-solid-dark, rgb(44 44 46)); }
|
|
54
54
|
}
|
|
55
|
-
`;function Ee(){return S()?.document}function kt(e){if(e.getElementById(ke))return;let t=e.createElement("style");t.id=ke,t.textContent=At,(e.head??e.documentElement).appendChild(t)}var Et=0;function A(e,t,n,r){let o=e.createElement(t);if(o.className=n,r!==void 0)o.textContent=r;return o}var Te='button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function Tt(e,t){if(t.key!=="Tab")return;let n=Array.from(e.querySelectorAll(Te));if(n.length===0){t.preventDefault();return}let r=n[0],o=n[n.length-1],i=e.ownerDocument.activeElement;if(t.shiftKey&&(i===r||!e.contains(i)))t.preventDefault(),o.focus();else if(!t.shiftKey&&(i===o||!e.contains(i)))t.preventDefault(),r.focus()}function Le(e,t,n,r){kt(e);let o=S(),i=e.activeElement,a=A(e,"div",`native-dialog native-dialog--${t}`);return a.setAttribute("data-native-dialog",t),a.appendChild(A(e,"div","native-dialog-backdrop")),new Promise((s)=>{let l=!1,m=(g)=>{if(l)return;l=!0,a.classList.remove("is-open"),e.removeEventListener("keydown",p,!0),setTimeout(()=>{if(a.remove(),i&&typeof i.focus==="function")i.focus()},260),s(g)},p=(g)=>{if(g.key==="Escape"){g.preventDefault(),m(r());return}Tt(c,g)},c=n({root:a,settle:m});a.appendChild(c),e.body.appendChild(a),e.addEventListener("keydown",p,!0);let f=o;(typeof f?.requestAnimationFrame==="function"?(g)=>f.requestAnimationFrame(()=>f.requestAnimationFrame(g)):(g)=>setTimeout(g,16))(()=>{if(!l)a.classList.add("is-open")}),(c.querySelector("[data-native-autofocus]")??c.querySelector(Te))?.focus()})}function ce(e){let t=Ee();if(!t?.body)return Promise.resolve(null);let n=`native-dialog-${++Et}`,r=e.actions.find((a)=>a.style==="cancel"),o=e.variant==="sheet"?e.actions.filter((a)=>a.style!=="cancel"):e.actions,i=e.variant==="sheet"?r??{id:"__cancel",title:e.cancelLabel||"Cancel",style:"cancel"}:void 0;return Le(t,e.variant,({root:a,settle:s})=>{let l=(u)=>u.style==="cancel"?null:u.id,m=A(t,"div","native-dialog-panel");m.setAttribute("role","alertdialog"),m.setAttribute("aria-modal","true"),m.tabIndex=-1;let p=A(t,"div","native-dialog-group");if(e.title||e.message){let u=A(t,"div","native-dialog-header");if(e.title){let d=A(t,"p","native-dialog-title",e.title);d.id=`${n}-title`,u.appendChild(d),m.setAttribute("aria-labelledby",d.id)}if(e.message){let d=A(t,"p","native-dialog-message",e.message);d.id=`${n}-message`,u.appendChild(d),m.setAttribute("aria-describedby",d.id)}p.appendChild(u)}let c=A(t,"div","native-dialog-actions");if(e.variant==="alert"&&o.length===2)c.classList.add("is-row");for(let u of o){let d=A(t,"button",`native-dialog-action${u.style==="destructive"?" is-destructive":""}${u.style==="cancel"?" is-cancel":""}`,u.title);d.type="button",d.setAttribute("data-action-id",u.id),d.addEventListener("click",()=>s(l(u))),c.appendChild(d)}if(p.appendChild(c),m.appendChild(p),i){let u=A(t,"div","native-dialog-group"),d=A(t,"button","native-dialog-action is-cancel",i.title);d.type="button",d.setAttribute("data-action-id",i.id),d.addEventListener("click",()=>s(null)),u.appendChild(d),m.appendChild(u)}let f=a.querySelector(".native-dialog-backdrop");if(e.variant==="sheet")f?.addEventListener("click",()=>s(null));return m},()=>{if(e.variant==="sheet")return null;if(r)return null;return o.length===1?o[0].id:null})}async function Re(e){await ce({variant:"alert",title:e.title,message:e.message,actions:[{id:"ok",title:e.okLabel||"OK"}]})}async function Me(e){return await ce({variant:"alert",title:e.title,message:e.message,actions:[{id:"cancel",title:e.cancelLabel||"Cancel",style:"cancel"},{id:"confirm",title:e.confirmLabel||"OK",style:e.destructive?"destructive":"default"}]})==="confirm"}function Pe(e){return ce({variant:"sheet",title:e.title,message:e.message,actions:e.actions,cancelLabel:e.cancelLabel})}function Lt(e,t,n){let i=Math.max(12,Math.min(e.x,n.width-t.width-12)),a=e.y+e.height+8,s=a+t.height<=n.height-12,l=e.y-8-t.height,m=s||l<12?Math.max(12,Math.min(a,n.height-t.height-12)):l,p=e.x+e.width/2>n.width/2?"right":"left";return{top:m,left:i,origin:`${s||l<12?"top":"bottom"} ${p}`}}function Ce(e){let t=Ee();if(!t?.body)return Promise.resolve(null);let n=S();return Le(t,"menu",({root:r,settle:o})=>{let i=A(t,"div","native-menu native-dialog-panel");if(i.setAttribute("role","menu"),e.title)i.appendChild(A(t,"p","native-menu-title",e.title)),i.setAttribute("aria-label",e.title);for(let a of e.items){let s=A(t,"button",`native-menu-item${a.destructive?" is-destructive":""}`);if(s.type="button",s.setAttribute("role","menuitem"),s.setAttribute("data-action-id",a.id),a.disabled)s.disabled=!0;if(s.appendChild(A(t,"span","native-menu-label",a.title)),a.icon){let l=A(t,"i",`native-menu-icon ${a.icon}`);l.setAttribute("aria-hidden","true"),s.appendChild(l)}s.addEventListener("click",()=>o(a.id)),i.appendChild(s)}return r.querySelector(".native-dialog-backdrop")?.addEventListener("click",()=>o(null)),queueMicrotask(()=>{let a=i.getBoundingClientRect?.(),s=Lt(e.anchor,{width:a?.width||248,height:a?.height||e.items.length*44},{width:n?.innerWidth||390,height:n?.innerHeight||844});i.style.top=`${s.top}px`,i.style.left=`${s.left}px`,i.style.setProperty("--native-menu-origin",s.origin)}),i},()=>null)}var He=()=>!0,E=()=>!1,L=()=>null;function Oe(){return S()?.navigator??(typeof navigator>"u"?void 0:navigator)}function fe(e){return{x:Math.round(e.x??e.left??0),y:Math.round(e.y??e.top??0),width:Math.round(e.width),height:Math.round(e.height)}}var _={alert:(e)=>b("dialog.alert",[e],()=>Re(e),{fallbackOnError:!0}).then(()=>{}),confirm:(e)=>b("dialog.confirm",[e],()=>Me(e),{fallbackOnError:!0}).then(Boolean),actionSheet:async(e)=>{let t={...e,anchor:e.anchor?fe(e.anchor):void 0},n=await b("dialog.actionSheet",[t],()=>Pe(e),{fallbackOnError:!0});if(typeof n!=="string")return null;return e.actions.find((r)=>r.id===n)?.style==="cancel"?null:n}};function Vn(){return(e)=>_.actionSheet(e)}async function Xn(e){if((e.style??(e.destructive?"sheet":"alert"))==="alert")return _.confirm(e);return await _.actionSheet({title:e.title,message:e.message,anchor:e.anchor,actions:[{id:"confirm",title:e.confirmLabel||"OK",style:e.destructive?"destructive":"default"},{id:"cancel",title:e.cancelLabel||"Cancel",style:"cancel"}]})==="confirm"}var me={show:async(e)=>{let t={title:e.title,anchor:fe(e.anchor),items:e.items.map(({id:r,title:o,symbol:i,destructive:a,disabled:s})=>({id:r,title:o,symbol:i,destructive:a,disabled:s}))},n=await b("contextMenu.show",[t],()=>Ce(e),{fallbackOnError:!0});return typeof n==="string"?n:null}};function Jn(e,t){return me.show({...t,anchor:fe(e.getBoundingClientRect())})}function Rt(e,t){let n=S();if(!n)return{cancelled:!0};if(typeof n.craft?.openURL==="function")return Promise.resolve(n.craft.openURL(e)).catch(()=>{}),{cancelled:!1};if(t.mode==="auth")return n.location?.assign(e),{cancelled:!1};if(!(typeof n.open==="function"?n.open(e,"_blank","noopener"):null))n.location?.assign(e);return{cancelled:!1}}var _e={open:async(e,t={})=>{let n=await b("browser.open",[e,t],()=>Rt(e,t),{fallbackOnError:!0});if(!n||typeof n!=="object")return{cancelled:!1};let{url:r,cancelled:o}=n;return typeof r==="string"?{url:r,cancelled:Boolean(o)}:{cancelled:Boolean(o)}}},ue=new Map,de=new Map;function Ie(e,t){return`${e}|${t.pointSize??""}|${t.weight??""}|${t.color??""}|${t.scale??""}`}var De={isAvailable:()=>T("symbols.image")!==null,image:(e,t={})=>{let n=Ie(e,t),r=ue.get(n);if(r)return r;let o=b("symbols.image",[e,t],L).then((i)=>typeof i==="string"&&i.startsWith("data:")?i:null,L).then((i)=>(de.set(n,i),i));return ue.set(n,o),o},cached:(e,t={})=>de.get(Ie(e,t)),clearCache:()=>{ue.clear(),de.clear()}},j={setStyle:(e)=>b("statusBar.setStyle",[e],E,{fallbackOnError:!0}).then((t)=>t!==!1)},D={setUnderPageColor:(e)=>b("chrome.setUnderPageColor",[e],E,{fallbackOnError:!0}).then((t)=>t!==!1),setKeyboardAccessory:(e)=>b("chrome.setKeyboardAccessory",[e],E,{fallbackOnError:!0}).then((t)=>t!==!1)},P={isAvailable:()=>T("refresh.enable")!==null,enable:(e)=>b("refresh.enable",[e??{}],E,{fallbackOnError:!0}).then((t)=>t!==!1),disable:()=>b("refresh.disable",[],E,{fallbackOnError:!0}).then((e)=>e!==!1),end:()=>b("refresh.end",[],E,{fallbackOnError:!0}).then((e)=>e!==!1),onRefresh:(e)=>R("craftRefresh",()=>e())},B={complete:(e)=>b("background.complete",[e],E,{fallbackOnError:!0}).then((t)=>t!==!1)},Be={write:(e)=>b("clipboard.write",[e],async()=>{let t=Oe()?.clipboard;if(!t?.writeText)return!1;return t.writeText(e).then(He,E)},{fallbackOnError:!0}).then((t)=>t!==!1),read:()=>b("clipboard.read",[],async()=>{let e=Oe()?.clipboard;if(!e?.readText)return null;return e.readText().catch(L)},{fallbackOnError:!0}).then((e)=>typeof e==="string"?e:null)},Fe={isAvailable:()=>T("db.query")!==null,query:(e,t=[])=>b("db.query",[e,t],L).then((n)=>Array.isArray(n)?n:null),execute:(e,t=[])=>b("db.execute",[e,t],L).then((n)=>{if(!n||typeof n!=="object")return null;let{rowsAffected:r,lastInsertId:o}=n;return{rowsAffected:Number(r)||0,lastInsertId:Number(o)||0}})};function pe(e,t){let n=S()?.document;if(!n?.body)return null;let r=n.createElement("a");return r.href=e,r.download=t,r.rel="noopener",r.style.display="none",n.body.appendChild(r),r.click(),r.remove(),t}function Mt(e){let t=S()?.document;if(!t?.body)return Promise.resolve(null);return new Promise((n)=>{let r=t.createElement("input");if(r.type="file",r.style.display="none",e.length)r.accept=e.map((i)=>i.includes("/")||i.startsWith(".")?i:`.${i}`).join(",");let o=(i)=>{r.remove(),n(i)};r.addEventListener("cancel",()=>o(null)),r.addEventListener("change",()=>{let i=r.files?.[0];if(!i)return o(null);let a=new FileReader;a.onload=()=>o({name:i.name,mimeType:i.type||void 0,data:typeof a.result==="string"?a.result:void 0}),a.onerror=()=>o({name:i.name,mimeType:i.type||void 0}),a.readAsDataURL(i)}),t.body.appendChild(r),r.click()})}var Ke={openPDF:(e,t=0)=>b("openPDF",[e,t],()=>{let n=S();return Boolean(n?.open?.(e,"_blank","noopener"))}).then((n)=>n!==!1),takeScreenshot:()=>b("takeScreenshot",[],L,{fallbackOnError:!0}).then((e)=>typeof e==="string"?e:null),scanQRCode:()=>b("scanQRCode",[],L).then((e)=>{if(!e||typeof e!=="object")return null;let{type:t,data:n}=e;return typeof n==="string"?{type:String(t??""),data:n}:null},L),pickFile:(e=[])=>b("pickFile",[e],()=>Mt(e)).then((t)=>{if(!t||typeof t!=="object")return null;let n=t;if(typeof n.name!=="string")return null;return{name:n.name,path:typeof n.path==="string"?n.path:void 0,data:typeof n.data==="string"?n.data:void 0,mimeType:typeof n.mimeType==="string"?n.mimeType:void 0}},L),saveFile:(e,t,n)=>b("saveFile",[e,t,n],()=>{if(e.startsWith("data:"))return pe(e,t);let r=new Blob([e],{type:n||"text/plain"}),o=URL.createObjectURL(r),i=pe(o,t);return setTimeout(()=>URL.revokeObjectURL(o),1000),i}).then((r)=>typeof r==="string"?r:null),downloadFile:(e,t)=>b("downloadFile",[e,t],()=>pe(e,t)).then((n)=>typeof n==="string"?n:null)},$e={set:(e)=>b("shortcuts.set",[e.map(({symbol:t,...n})=>t?{...n,iconName:t}:n)],E).then((t)=>t!==!1),clear:()=>b("shortcuts.clear",[],E).then((e)=>e!==!1),onShortcut:(e)=>R("craftShortcut",(t)=>{if(typeof t.type==="string")e(t.type)})},qe={update:(e)=>b("widget.update",[e],E).then((t)=>t!==!1),reload:()=>b("widget.reload",[],E).then((e)=>e!==!1)},Pt={portrait:"portrait-primary",portraitUpsideDown:"portrait-secondary",landscape:"landscape",landscapeLeft:"landscape-primary",landscapeRight:"landscape-secondary"};function Ne(){return S()?.screen?.orientation}var Ue={lock:(e)=>b("lockOrientation",[e],()=>{let t=Ne();return t?.lock?t.lock(Pt[e]).then(He,E):!1}).then((t)=>t!==!1),unlock:()=>b("unlockOrientation",[],()=>(Ne()?.unlock?.(),!0)).then((e)=>e!==!1)},We={signInWithApple:(e={})=>b("signInWithApple",e.nonce?[{nonce:e.nonce}]:[],L).then((t)=>{if(!t||typeof t!=="object"||typeof t.userId!=="string")return null;return t})},ze={isAvailable:()=>T("iap.purchase")!==null,products:(e)=>b("iap.getProducts",[e],()=>[]).then((t)=>Array.isArray(t)?t:[]),purchase:(e)=>b("iap.purchase",[e],L).then((t)=>t&&typeof t==="object"?t:null,(t)=>{if(/cancel/i.test(String(t?.message??t)))return null;throw t}),restore:()=>b("iap.restore",[],()=>[]).then((e)=>Array.isArray(e)?e:[])};function er(e,t){let n=t.delay??500,r=t.tolerance??10,o=null,i=null,a=!1,s=()=>{if(o)clearTimeout(o);if(o=null,i&&!a)t.onPressEnd?.();i=null},l=(f)=>{let u=f;if(u.button!==void 0&&u.button!==0)return;a=!1,i={x:u.clientX,y:u.clientY},t.onPressStart?.(),o=setTimeout(()=>{if(o=null,!i)return;a=!0,t.onLongPress({...i}),i=null},n)},m=(f)=>{if(!i)return;let u=f;if(Math.hypot(u.clientX-i.x,u.clientY-i.y)>r)s()},p=(f)=>{if(!a)return;a=!1,f.preventDefault(),f.stopPropagation()},c=(f)=>f.preventDefault();return e.addEventListener("pointerdown",l),e.addEventListener("pointermove",m),e.addEventListener("pointerup",s),e.addEventListener("pointercancel",s),e.addEventListener("pointerleave",s),e.addEventListener("click",p,!0),e.addEventListener("contextmenu",c),()=>{s(),e.removeEventListener("pointerdown",l),e.removeEventListener("pointermove",m),e.removeEventListener("pointerup",s),e.removeEventListener("pointercancel",s),e.removeEventListener("pointerleave",s),e.removeEventListener("click",p,!0),e.removeEventListener("contextmenu",c)}}function Ct(e,t,n){if(n<=1||t.width<=0)return 0;let r=Math.floor((e-t.left)/t.width*n);return Math.max(0,Math.min(n-1,r))}function tr(e,t){let n=null,r=null,o=!1,i=0,a=(u)=>{let d=e.getBoundingClientRect();return Ct(u,{left:d.left+2,width:d.width-4},t.count())},s=(u)=>{let d=u;if(d.button!==void 0&&d.button!==0)return;let g=a(d.clientX);if(g!==t.selected())return;n=g,i=g,o=!1,r=d.pointerId;try{e.setPointerCapture?.(d.pointerId)}catch{}t.onPress?.(!0)},l=(u)=>{if(n===null)return;let d=a(u.clientX);if(d===i)return;o=!0,i=d,t.onScrub(d)},m=(u)=>{if(n===null)return;if(r!==null)try{e.releasePointerCapture?.(r)}catch{}if(t.onPress?.(!1),u&&o)t.onCommit(i);else if(o)t.onScrub(n);n=null,r=null},p=(u)=>{if(!o)return;o=!1,u.preventDefault(),u.stopPropagation()},c=()=>m(!0),f=()=>m(!1);return e.addEventListener("pointerdown",s),e.addEventListener("pointermove",l),e.addEventListener("pointerup",c),e.addEventListener("pointercancel",f),e.addEventListener("click",p,!0),()=>{e.removeEventListener("pointerdown",s),e.removeEventListener("pointermove",l),e.removeEventListener("pointerup",c),e.removeEventListener("pointercancel",f),e.removeEventListener("click",p,!0)}}function nr(e,t,n){if(n<=0)return null;switch(e){case"ArrowRight":case"ArrowDown":return(t+1)%n;case"ArrowLeft":case"ArrowUp":return(t-1+n)%n;case"Home":return 0;case"End":return n-1;default:return null}}function rr(e,t){e.querySelectorAll('[role="tab"]')[t]?.focus()}function or(e){let t=(n)=>{if(!n.target?.closest?.("[data-native-pressable]"))return;let o=T("haptics.prepare");if(o)Promise.resolve().then(()=>o("impact")).catch(()=>{})};return e.addEventListener("touchstart",t,{passive:!0,capture:!0}),()=>e.removeEventListener("touchstart",t,{capture:!0})}function ge(e){let t=S();try{return Boolean(t?.matchMedia?.(e).matches)}catch{return!1}}function Ye(e){return e!==null&&e!==void 0&&e!=="false"&&e!=="0"}function je(){let e=S()?.document?.documentElement,t=Number.parseFloat(e?.style?.getPropertyValue("--craft-font-scale")||"");return{fontScale:Number.isFinite(t)&&t>0?t:1,reduceMotion:Ye(e?.getAttribute("data-craft-reduce-motion"))||ge("(prefers-reduced-motion: reduce)"),reduceTransparency:Ye(e?.getAttribute("data-craft-reduce-transparency"))||ge("(prefers-reduced-transparency: reduce)"),colorScheme:e?.classList?.contains("dark")||ge("(prefers-color-scheme: dark)")?"dark":"light"}}function Ot(e){let t=je(),n=Number(e?.fontScale);return{contentSizeCategory:typeof e?.contentSizeCategory==="string"?e.contentSizeCategory:void 0,fontScale:Number.isFinite(n)&&n>0?n:t.fontScale,reduceMotion:typeof e?.reduceMotion==="boolean"?e.reduceMotion:t.reduceMotion,reduceTransparency:typeof e?.reduceTransparency==="boolean"?e.reduceTransparency:t.reduceTransparency,colorScheme:e?.colorScheme==="dark"||e?.colorScheme==="light"?e.colorScheme:t.colorScheme}}function Ge(e,t={}){if(t.immediate!==!1)e(je());return R("craftAppearance",(n)=>e(Ot(n)))}function lr(e){return R("craftResume",(t)=>e({backgroundedMs:Number(t.backgroundedMs)||0}))}function cr(e){return R("craftMemoryWarning",()=>e())}function Ve(e){return(t)=>{Promise.resolve().then(()=>e(t)).then(()=>B.complete(!0),()=>B.complete(!1))}}function ur(e){let t=Ve(e);return R("craftSilentPush",(n)=>t(n.payload??{}))}function dr(e){let t=Ve(()=>e());return R("craftBackgroundRefresh",()=>t(void 0))}import{haptics as It}from"craft-native/mobile";function he(){if(typeof window>"u")return;return window}function F(e=he()){if(!e)return 0;if(typeof e.scrollY==="number")return e.scrollY;if(typeof e.scrollTop==="number")return e.scrollTop;return e.document?.scrollingElement?.scrollTop??0}function Nt(e,t=he()){if(!t)return()=>{};let n=!1,r=typeof requestAnimationFrame==="function"?requestAnimationFrame:(i)=>setTimeout(i,16),o=()=>{if(n)return;n=!0,r(()=>{n=!1,e(F(t))})};return e(F(t)),t.addEventListener("scroll",o,{passive:!0}),()=>t.removeEventListener("scroll",o)}function Ht(e,t){let n=Math.max(0,-e),r=e<=0?Math.max(0,t)*0.5:0;return Math.round(Math.max(n,r))}function mr(e){let t=e.host??he();if(!t)return()=>{};let n=e.threshold??72,r=null,o=!1,i=!1,a=typeof requestAnimationFrame==="function"?requestAnimationFrame:(g)=>setTimeout(g,16),s=null,l=(g)=>{s=null,e.onPull?.(g,o,{bounce:Math.min(g,Math.max(0,-F(t)))})},m=(g)=>{let x=s!==null;if(s=g,x)return;a(()=>{if(s!==null)l(s)})},p=(g)=>{let x=g.touches?.[0];return x?x.clientY:null},c=(g)=>{if(i||F(t)>0)return;r=p(g),o=!1},f=(g)=>{if(r===null)return;let x=p(g);if(x===null)return;let N=Ht(F(t),x-r);if(!o&&N>=n)o=!0,Promise.resolve(It.impact("medium")).catch(()=>{});else if(o&&N<n*0.8)o=!1;m(N)},u=async()=>{if(r===null)return;if(r=null,!o){l(0);return}o=!1,i=!0,l(n);try{await e.onRefresh()}finally{i=!1,l(0)}},d=()=>{if(r===null)return;r=null,o=!1,l(0)};return t.addEventListener("touchstart",c,{passive:!0}),t.addEventListener("touchmove",f,{passive:!0}),t.addEventListener("touchend",u),t.addEventListener("touchcancel",d),()=>{s=null,t.removeEventListener("touchstart",c),t.removeEventListener("touchmove",f),t.removeEventListener("touchend",u),t.removeEventListener("touchcancel",d)}}function _t(e,t=52){let n=Math.max(1,t),r=Math.min(1,Math.max(0,e/n)),o=e<0?1+Math.min(0.1,-e/600):1;return{progress:Math.round(r*1000)/1000,stretch:Math.round(o*1000)/1000}}function gr(e,t={}){let n="",r=()=>t.title?.offsetHeight||t.height||52;return Nt((o)=>{let i=_t(o,r()),a=`${i.progress}|${i.stretch}`;if(a===n)return;n=a,e.style.setProperty("--native-nav-progress",String(i.progress)),e.style.setProperty("--native-nav-stretch",String(i.stretch)),t.onChange?.(i)},t.host)}function hr(e){if(!e||typeof window>"u")return;let t=window.document?.querySelector(e);return t?t:void 0}function Qe(){if(typeof window>"u")return;return window}var Xe="__stxPushed",Dt="__stxScroll";function Bt(e=Qe()){let t=e?.history?.state;if(t===null||t===void 0)return!1;if(typeof t!=="object")return!0;let n=t;if(Xe in n)return n[Xe]===!0;return!(Dt in n)}function vr(e=Qe()){if(!Bt(e))return!1;return e.history.back(),!0}function yr(e,t,n=50){let r=e[e.length-1];if(e.length>=2&&e[e.length-2].path===t)e.pop();else if(!r||r.path!==t)e.push({path:t,title:""});if(e.length>n)e.splice(0,e.length-n);return{current:e[e.length-1],previous:e[e.length-2]??null}}function xr(e,t,n=12){let r=e?.title.trim()??"";return r&&r.length<=n?r:t}function Sr(){if(typeof window>"u")return[];let e=window;return e.__stacksNavTrail??=[]}function Ft(e){try{let t=new URL(e,"http://local");return`${t.pathname}${t.search}`}catch{return e}}function wr(){if(typeof window>"u")return;let e=window.stxRouter;if(typeof e?.screens!=="function")return;let t=e.screens(),n=t.find((o)=>o.active);if(!n)return;let r=t.filter((o)=>o.tab===n.tab&&o.depth<n.depth);if(!r.length)return null;return Ft(r.reduce((o,i)=>i.depth>o.depth?i:o).url)}function Ar(e=typeof window>"u"?void 0:window){let t=e?.stxRouter;if(typeof t?.screens!=="function"||typeof e?.history?.go!=="function")return!1;let n=t.screens(),r=n.find((a)=>a.active);if(!r)return!1;let o=n.filter((a)=>a.tab===r.tab&&a.depth<r.depth);if(!o.length)return!1;let i=o.reduce((a,s)=>s.depth<a.depth?s:a);return e.history.go(i.depth-r.depth),!0}function kr(e,t){for(let n=e.length-1;n>=0;n--)if(e[n].path===t)return e[n];return null}function Kt(e,t=$t()){let n;try{n=new URL(e)}catch{return null}let r=`${n.search}${n.hash}`;if(n.protocol==="http:"||n.protocol==="https:"){if(!t||n.origin!==t)return null;return`${n.pathname||"/"}${r}`}return`${`/${[n.host,n.pathname.replace(/^\/+/,"")].filter(Boolean).join("/")}`}${r}`}function $t(){if(typeof window>"u")return;return window.location?.origin}var Je="stacks-mobile-deep-link";function Er(e,t){let n=(r)=>{let o=Kt(r);if(o)e(o)};return t.getInitialURL().then((r)=>{if(!r)return;try{if(sessionStorage.getItem(Je)===r)return;sessionStorage.setItem(Je,r)}catch{}n(r)}).catch(()=>{}),t.onLink((r,o)=>{if(o?.initial)return;n(r)})}var Lr=30;function qt(e,t){let n=Math.PI/180,r=(t.latitude-e.latitude)*n,o=(t.longitude-e.longitude)*n,i=Math.sin(r/2)**2+Math.cos(e.latitude*n)*Math.cos(t.latitude*n)*Math.sin(o/2)**2;return 12742017.6*Math.asin(Math.min(1,Math.sqrt(i)))}function Ut(e,t=25){let n=new Set;return e.filter((r)=>Number.isFinite(r.latitude)&&Number.isFinite(r.longitude)&&Number.isFinite(r.timestamp)&&Math.abs(r.latitude)<=90&&Math.abs(r.longitude)<=180&&Number.isFinite(r.accuracy)&&r.accuracy>=0&&r.accuracy<=t).sort((r,o)=>r.timestamp-o.timestamp).filter((r)=>{if(n.has(r.timestamp))return!1;return n.add(r.timestamp),!0})}function Ze(e,t={}){let n=Ut(e,t.maxAccuracyM??25),r=t.paceWindowS??30,o=[],i=0,a=0,s=null;for(let c of n){let f=o[o.length-1],u=s?(c.timestamp-s.timestamp)/1000:0;if(s=c,!f){o.push({fix:c,cumM:0});continue}if(u>30){o.push({fix:c,cumM:i});continue}let d=(c.timestamp-f.fix.timestamp)/1000,g=qt(f.fix,c),x=Math.min(10,Math.max(3,f.fix.accuracy,c.accuracy));if(g<x)continue;if(i+=g,d>0&&g/d>=0.5)a+=d;o.push({fix:c,cumM:i})}let l=o[o.length-1],m=null,p=null;if(l&&n.at(-1).timestamp-l.fix.timestamp<=r*1000){let c=l.fix.timestamp-r*1000,f=o.find((g)=>g.fix.timestamp>=c)??l,u=l.cumM-f.cumM,d=(l.fix.timestamp-f.fix.timestamp)/1000;if(u>=20&&d>0)p=u/d,m=d/(u/1000)}return{distanceM:i,movingS:a,paceSPerKm:m,averagePaceSPerKm:i>=50&&a>0?a/(i/1000):null,speedMps:p,accuracyM:n.length?n[n.length-1].accuracy:e.length?e[e.length-1].accuracy??null:null,fixes:n.length}}function Rr(e){if(e==null||e<=0||!Number.isFinite(e)||e>3600)return"–";let t=Math.round(e);return`${Math.floor(t/60)}:${String(t%60).padStart(2,"0")}`}function Mr(e){return e!=null&&e>0&&Number.isFinite(e)?(e*3.6).toFixed(1):"–"}var et={distanceM:0,movingS:0,paceSPerKm:null,averagePaceSPerKm:null,speedMps:null,accuracyM:null,fixes:0};function Pr(e){let t=e.location,n=e.intervalMs??3000,r=et,o=null,i=()=>typeof document<"u"&&document.visibilityState==="hidden",a=0,s=null,l=Promise.resolve(),m=null,p=!1;function c(g){let x=l.then(g);return l=x.then(()=>{},()=>{}),x}function f(){if(s)return s;let g=a;return s=(async()=>{let x=await t.readRecording();if(g===a&&!p)r=Ze(x,e),e.onUpdate?.(r);return r})().finally(()=>{s=null}),s}function u(){if(d(),p)return;o=setInterval(()=>{if(!i())f().catch(()=>{})},n)}function d(){if(o)clearInterval(o);o=null}return{get stats(){return r},start(){return m=null,c(async()=>{if(await t.startRecording({enableHighAccuracy:!0,...e.locationOptions}),a++,r={...et},!p)e.onUpdate?.(r);return u(),r})},attach(){return c(async()=>{let g=await t.getRecordingState();if(!g?.active)return null;if(await f().catch(()=>{}),!g.paused)u();return g})},pause(){return c(async()=>{await t.pauseRecording(),d(),await f().catch(()=>{})})},resume(){return c(async()=>{await t.resumeRecording(),u()})},stop(){if(m)return m;return m=c(async()=>{d(),a++;let x=(await t.stopRecording())?.locations??[];if(r=Ze(x,e),!p)e.onUpdate?.(r);return x}).catch((g)=>{throw m=null,g}),m},dispose(){p=!0,a++,d()},refresh:f}}function Or(e){return{startedAt:Number.isFinite(e)?e:null,pausedAt:null,pausedMs:0}}function Ir(e,t){return e.startedAt===null||e.pausedAt!==null||!Number.isFinite(t)?e:{...e,pausedAt:Math.max(e.startedAt,t)}}function Nr(e,t){return e.pausedAt===null||!Number.isFinite(t)?e:{...e,pausedAt:null,pausedMs:e.pausedMs+Math.max(0,t-e.pausedAt)}}function Hr(e,t){if(e.startedAt===null)return 0;let n=((e.pausedAt??t)-e.startedAt-e.pausedMs)/1000;return Number.isFinite(n)?Math.max(0,n):0}var Dr=150;function Wt(e,t){let n=Math.PI/180,r=(t.latitude-e.latitude)*n,o=(t.longitude-e.longitude)*n,i=Math.sin(r/2)**2+Math.cos(e.latitude*n)*Math.cos(t.latitude*n)*Math.sin(o/2)**2;return 12742017.6*Math.asin(Math.min(1,Math.sqrt(i)))}function G(e,t){let n=[...e].sort((r,o)=>r-o);return n[Math.min(n.length-1,Math.floor(t*n.length))]}function Br(e,t){let n=(e||[]).filter((a)=>Number.isFinite(a?.latitude)&&Number.isFinite(a?.longitude)&&Math.abs(a.latitude)<=90&&Math.abs(a.longitude)<=180),r=n.filter((a)=>a.accuracy!=null).map((a)=>Number(a.accuracy)).filter((a)=>Number.isFinite(a)&&a>=0),o=r.length?G(r,0.5):Number.POSITIVE_INFINITY,i=0;if(n.length){let a={latitude:G(n.map((s)=>s.latitude),0.5),longitude:G(n.map((s)=>s.longitude),0.5)};i=G(n.map((s)=>Wt(a,s)),0.8)}if(n.length>=10&&i>150&&o<=15)return"outside";if(t<150)return"unsure";if(n.length<3||o>30||i<25)return"indoors";if(i<50&&o>10)return"indoors";return"unsure"}function Fr(e,t={}){let r=String(e||"").trim().toLowerCase().replace(",",".").match(/^(\d+(?:\.\d*)?|\.\d+)\s*(km|k|m|mi)?$/);if(!r)return null;let o=Number(r[1]),i=r[2]||t.defaultUnit||(o>100?"m":"km"),a=i==="m"?o/1000:i==="mi"?o*1.609344:o;return Number.isFinite(a)&&a>=0&&a<=2000?Math.round(a*1000)/1000:null}var J=new Set,tt=!1,V=null;function zt(e){return e.isConnected&&e.getClientRects().length>0}function nt(){return[...J].find((e)=>zt(e.element))}function X(){let e=nt(),t=Boolean(e);if(t===tt)return;if(tt=t,t)P.enable(e?.tintColor?{tintColor:e.tintColor}:{});else P.disable()}function Yt(){let e=nt();if(!e){P.end();return}Promise.resolve().then(()=>e.run()).catch(()=>{}).finally(()=>P.end())}function qr(e,t){let n={element:e,tintColor:t.tintColor,run:t.onRefresh};J.add(n);let r=e.ownerDocument?.defaultView;if(!V){let o=P.onRefresh(Yt),i=()=>X();r?.addEventListener("stx:load",i),V=()=>{o(),r?.removeEventListener("stx:load",i)}}return X(),r?.requestAnimationFrame?.(()=>X()),()=>{if(J.delete(n),J.size===0)V?.(),V=null;X()}}var Wr=0.5;function jt(e,t,n){let r=[];if(n.includes("large")||n.length===0)r.push({name:"large",y:0});if(n.includes("medium"))r.push({name:"medium",y:Math.max(0,Math.round(e-t*0.5))});return r.push({name:"dismiss",y:Math.max(1,e)}),r.sort((o,i)=>o.y-i.y)}function Gt(e){let{y:t,velocity:n,stops:r}=e,o=r.filter((s)=>s.name!=="dismiss"),i=r.find((s)=>s.name==="dismiss");if(o.length===0)return"dismiss";if(n>0.5)return(r.filter((l)=>l.y>t+1)[0]??i).name;if(n<-0.5){let s=o.filter((l)=>l.y<t-1);return(s[s.length-1]??o[0]).name}let a=o[o.length-1];if(t>a.y+(i.y-a.y)*0.5)return"dismiss";return o.reduce((s,l)=>Math.abs(l.y-t)<Math.abs(s.y-t)?l:s).name}function Vt(e,t=400){if(e<=0)return 0;return e*t*0.55/(t+e*0.55)}function zr(e){let{panel:t}=e,n=null,r=[],o=0,i=()=>e.viewport?.()??t.ownerDocument?.defaultView?.innerHeight??800,a=()=>jt(t.offsetHeight||t.getBoundingClientRect().height,i(),e.detents()),s=(p)=>{let c=p;if(c.button!==void 0&&c.button!==0)return;if(c.target?.closest?.("button, a, input, select, textarea, [role=button]"))return;let f=a().find((u)=>u.name===e.detent())?.y??0;n={y:c.clientY,base:f,pointerId:c.pointerId},o=f,r=[{y:f,t:c.timeStamp}],t.classList.add("is-dragging");try{p.currentTarget?.setPointerCapture?.(c.pointerId)}catch{}},l=(p)=>{if(!n)return;let c=p,f=n.base+c.clientY-n.y;o=f<0?-Vt(-f):f,r.push({y:o,t:c.timeStamp});while(r.length>2&&c.timeStamp-r[0].t>100)r.shift();t.style.transform=`translateY(${o}px)`;let u=t.offsetHeight||1;t.parentElement?.style.setProperty("--native-sheet-presence",String(Math.max(0,Math.min(1,1-o/u))))},m=(p)=>{if(!n)return;let c=p;n=null;let f=r[0],u=Math.max(1,c.timeStamp-f.t),d=(o-f.y)/u;t.classList.remove("is-dragging"),t.style.transform="",t.parentElement?.style.removeProperty("--native-sheet-presence"),e.onSettle(Gt({y:o,velocity:d,stops:a()}))};for(let p of e.handles)p.addEventListener("pointerdown",s),p.addEventListener("pointermove",l),p.addEventListener("pointerup",m),p.addEventListener("pointercancel",m);return()=>{for(let p of e.handles)p.removeEventListener("pointerdown",s),p.removeEventListener("pointermove",l),p.removeEventListener("pointerup",m),p.removeEventListener("pointercancel",m)}}var rt=0,be="";function Yr(e){let t=e.ownerDocument,n=[],r=e;while(r.parentElement&&r!==t.body){for(let a of Array.from(r.parentElement.children)){if(a===r||a.hasAttribute("inert")||a.hasAttribute("data-native-dialog"))continue;if(["SCRIPT","STYLE","TEMPLATE","LINK"].includes(a.tagName))continue;if(a.hasAttribute("data-native-sheet")&&a.getAttribute("aria-hidden")==="true")continue;a.setAttribute("inert",""),n.push(a)}r=r.parentElement}let o=t.documentElement;if(rt++===0)be=o.style.overflow||"",o.style.overflow="hidden";let i=!1;return()=>{if(i)return;i=!0;for(let a of n)a.removeAttribute("inert");if(--rt===0)if(be)o.style.overflow=be;else o.style.removeProperty("overflow")}}function jr(e){let t=e.ownerDocument;if(e.parentElement===t.body)return()=>{};let n=t.createComment("native-sheet");return e.parentNode?.insertBefore(n,e),t.body.appendChild(e),()=>{if(n.parentNode)n.parentNode.insertBefore(e,n);else e.remove();n.remove()}}function Gr(e,t){let n=e.documentElement;if(!t){n.removeAttribute("data-native-sheet-card");return}let r=e.defaultView,o=(r?.scrollY??0)+(r?.innerHeight??800)/2;n.style.setProperty("--native-sheet-card-origin",`${Math.round(o)}px`),n.setAttribute("data-native-sheet-card","")}function Xt(e,t){e.style.setProperty("--native-font-scale",String(t.fontScale)),e.toggleAttribute("data-native-reduce-motion",t.reduceMotion),e.toggleAttribute("data-native-reduce-transparency",t.reduceTransparency)}function Jt(e){let t=e.replace(/\s+/g,"").toLowerCase();return!t||t==="transparent"||/^rgba\(\d+,\d+,\d+,0(\.0+)?\)$/.test(t)||/\/0(\.0+)?\)$/.test(t)}function Qt(e){let t=e.defaultView;if(!t?.getComputedStyle)return null;for(let n of[e.body,e.documentElement]){if(!n)continue;let r=t.getComputedStyle(n).backgroundColor;if(r&&!Jt(r))return r}return null}function Zt(e){if(e.documentElement.classList.contains("dark"))return!0;if(e.documentElement.classList.contains("light"))return!1;return Boolean(e.defaultView?.matchMedia?.("(prefers-color-scheme: dark)").matches)}function Qr(e,t={}){let n=t.root??e.documentElement;D.setKeyboardAccessory(t.keyboardAccessory===!0);let r="",o="",i=()=>{let p=Qt(e);if(p&&p!==r)r=p,D.setUnderPageColor(p);let c=Zt(e)?"light":"dark";if(c!==o)o=c,j.setStyle(c)},a=Ge((p)=>{Xt(n,p),i()}),s=e.defaultView,l=typeof s?.MutationObserver==="function"?new s.MutationObserver(i):null;l?.observe(e.documentElement,{attributes:!0,attributeFilter:["class","style","data-theme"]});let m=s?.matchMedia?.("(prefers-color-scheme: dark)");return m?.addEventListener?.("change",i),s?.addEventListener("stx:load",i),i(),()=>{a(),l?.disconnect(),m?.removeEventListener?.("change",i),s?.removeEventListener("stx:load",i)}}var eo=64;var en=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,tn=/^(?:0|[1-9]\d*)$/;function it(e){let t=[],n=[],r=e&&typeof e==="object"&&!Array.isArray(e)?e:{};for(let[o,i]of Object.entries(r)){let a=i&&typeof i==="object"?i:null;if(!a){n.push(`spotlight kind "${o}" is not an object`);continue}let{slots:s,route:l}=a,m=typeof a.noun==="string"&&a.noun.trim()?a.noun.trim():"Item";if(!en.test(o)||o.includes("-slot-")){n.push(`spotlight kind "${o}" is not a usable name: lowercase letters, digits and single dashes, and never "-slot-"`);continue}if(typeof s!=="number"||!Number.isInteger(s)||s<=0||s>64){n.push(`spotlight kind "${o}" needs slots between 1 and 64, not ${String(s)}`);continue}if(typeof l!=="string"||!l.startsWith("/")||!l.includes(":id")){n.push(`spotlight kind "${o}" needs a route starting with "/" and carrying ":id", not ${String(l)}`);continue}t.push({name:o,slots:s,route:l,noun:m})}return{kinds:t,problems:n}}function q(e,t){return e.find((n)=>n.name===t)??null}function K(e,t,n){let r=q(e,t);if(!r||!Number.isInteger(n)||n<0||n>=r.slots)return null;return`${t}-slot-${n}`}function nn(e,t){if(typeof t!=="string")return null;let n=t.lastIndexOf("-slot-");if(n<=0)return null;let r=t.slice(0,n),o=t.slice(n+6);if(!tn.test(o))return null;let i=Number(o);return K(e,r,i)===t?{kind:r,slot:i}:null}function at(e){return e.flatMap((t)=>Array.from({length:t.slots},(n,r)=>`${t.name}-slot-${r}`))}function to(e,t){let n=e&&typeof e==="object"?e:{};if(n.enabled===!1)return[];let o=[...(Array.isArray(n.activityTypes)?n.activityTypes.filter((i)=>typeof i==="string"&&i.trim().length>0):[]).map((i)=>i.trim()),...at(it(n.kinds).kinds)];return[...new Set(o)].map((i)=>`${t}.${i}`)}function st(e,t,n){let r=typeof n.name==="string"?n.name.replace(/\s+/g," ").trim():"";if(!r)return`${q(e,t)?.noun??"Item"} #${n.id}`;return r.length>120?`${r.slice(0,119).trimEnd()}…`:r}function rn(e,t,n,r,o=Date.now()){let i=q(e,n);if(!i||!Number.isInteger(r.id)||r.id<=0)return null;let a=t.filter((d)=>d.kind===n),s=st(e,n,r),l=a.find((d)=>d.itemId===r.id)??null,m=l?null:ln(a,i.slots),p=l||m!==null?null:cn(a),c=l?.slot??m??p?.slot;if(c===void 0||c===null)return null;let f={kind:n,slot:c,itemId:r.id,title:s,donatedAt:o},u=t.filter((d)=>d.kind!==n||d.slot!==c&&d.itemId!==r.id);return{entries:lt(e,[...u,f]),entry:f,evicted:p,changed:!l||l.title!==s}}function on(e,t,n){let r=e.find((o)=>o.kind===t&&o.itemId===n)??null;return{entries:r?e.filter((o)=>o!==r):[...e],removed:r}}function an(e,t,n){let r=nn(e,n);if(!r)return null;let o=t.find((a)=>a.kind===r.kind&&a.slot===r.slot),i=q(e,r.kind)?.route;return o&&i?i.replace(":id",String(o.itemId)):null}function sn(e,t){if(!Array.isArray(t))return[];let n=new Map,r=new Set;for(let o of t){if(!o||typeof o!=="object")continue;let i=o,{kind:a,slot:s,itemId:l,title:m,donatedAt:p}=i;if(typeof a!=="string"||typeof s!=="number"||K(e,a,s)===null)continue;if(typeof l!=="number"||!Number.isInteger(l)||l<=0)continue;let c=`${a}-slot-${s}`,f=`${a}#${l}`;if(n.has(c)||r.has(f))continue;n.set(c,{kind:a,slot:s,itemId:l,title:typeof m==="string"&&m.trim()?m:st(e,a,{id:l}),donatedAt:typeof p==="number"&&Number.isFinite(p)&&p>0?p:0}),r.add(f)}return lt(e,[...n.values()])}function lt(e,t){let n=new Map(e.map((r,o)=>[r.name,o]));return[...t].sort((r,o)=>(n.get(r.kind)??0)-(n.get(o.kind)??0)||r.slot-o.slot)}function ln(e,t){let n=new Set(e.map((r)=>r.slot));for(let r=0;r<t;r++)if(!n.has(r))return r;return null}function cn(e){return e.reduce((t,n)=>!t||n.donatedAt<t.donatedAt?n:t,null)}function un(){let e=globalThis.craft;return e&&typeof e==="object"?e.siri:void 0}var dn="stacks_spotlight_index",pn=3000;function no(e){let t=e.onProblem??((v)=>console.warn(`[spotlight] ${v}`)),n=Array.isArray(e.kinds)?{kinds:[...e.kinds],problems:[]}:it(e.kinds);for(let v of n.problems)t(v);let r=e.enabled===!1?[]:n.kinds,o=e.storageKey??dn,i=e.legacyStorageKeys??[],a=e.timeoutMs??pn,s=e.now??(()=>Date.now()),l=e.bridge??un,m=null;function p(){try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function c(){if(m)return m;m=[];let v=p();if(!v)return m;try{let y=[o,...i].map((w)=>v.getItem(w)).find((w)=>w);m=y?sn(r,JSON.parse(y)):[]}catch{m=[]}return m}function f(v){m=v;let y=p();if(!y)return;try{y.setItem(o,JSON.stringify(v));for(let w of i)y.removeItem(w)}catch{}}async function u(v){if(!v)return null;let y;try{return await Promise.race([v,new Promise((w)=>{y=setTimeout(()=>w(null),a)})])}catch{return null}finally{if(y!==void 0)clearTimeout(y)}}let d=Promise.resolve();function g(v){let y=d.then(v,v);return d=y.catch(()=>{return}),y}async function x(v,y){let w=l()?.register;if(!w||r.length===0)return!1;return g(async()=>{let k=rn(r,c(),v,y,s()),C=k&&K(r,v,k.entry.slot);if(!k||!C)return!1;if(!k.changed)return f(k.entries),!0;let H=await u(w(k.entry.title,C))!==null;if(H)f(k.entries);return H})}async function N(v,y){let w=l()?.remove;if(!w)return!1;return g(async()=>{let{entries:k,removed:C}=on(c(),v,y);if(!C)return!1;let H=K(r,v,C.slot),vt=H?await u(w(H))!==null:!1;return f(k),vt})}async function ht(v,y){let w=q(r,v)?.slots;if(!w||!l()?.register)return 0;let k=0;for(let C of[...y].slice(0,w).reverse())if(await x(v,C))k++;return k}async function bt(){let v=l()?.remove;if(!v)return f([]),0;return g(async()=>{let y=0;for(let w of c()){let k=K(r,w.kind,w.slot);if(k&&await u(v(k))!==null)y++}return f([]),y})}return{kinds:r,index:x,sync:ht,remove:N,clear:bt,routeFor:(v)=>an(r,c(),v),entries:()=>c(),activityTypes:(v)=>at(r).map((y)=>`${v}.${y}`),reset:()=>{m=null}}}var ot=["craftShortcut","craftSiriShortcut"];function ro(e,t){let n=(r)=>{let o=r.detail,i=typeof o==="string"?o:o&&typeof o==="object"?o.action??o.type:null,a=typeof i==="string"?e.routeFor(i):null;if(a)t(a)};if(typeof globalThis.addEventListener!=="function")return()=>{};for(let r of ot)globalThis.addEventListener(r,n);return()=>{for(let r of ot)globalThis.removeEventListener(r,n)}}import{tabBar as fn}from"craft-native/mobile";var mn=fn;function gn(e){return Array.from(e.querySelectorAll("a[data-native-tab]")).map((t)=>({id:t.getAttribute("href")||"",title:t.getAttribute("data-native-tab")||t.getAttribute("aria-label")||"",symbol:t.getAttribute("data-native-tab-symbol")||"circle",badge:(t.querySelector(".native-tab-badge")?.textContent||"").trim(),current:t.hasAttribute("data-stx-nav-current")||t.classList.contains("is-active")})).filter((t)=>t.id&&t.title)}function hn(e){return{tabs:e.map(({id:n,title:r,symbol:o,badge:i})=>i?{id:n,title:r,symbol:o,badge:i}:{id:n,title:r,symbol:o}),selected:e.find((n)=>n.current)?.id}}function ut(){if(typeof window>"u")return;let e=window.stxRouter;return e&&typeof e==="object"?e:void 0}function bn(){return typeof ut()?.selectTab==="function"}function ao(e,t={}){let n=(r)=>{if(bn()||r.defaultPrevented)return;let o=r.target?.closest?.("a[data-native-tab]");if(!o||!e.contains(o))return;if(!o.hasAttribute("data-stx-nav-current")&&!o.classList.contains("is-active")&&o.getAttribute("aria-current")!=="page")return;r.preventDefault();let i=e.ownerDocument.defaultView;if(t.scrollToTop)t.scrollToTop();else i?.scrollTo?.({top:0,behavior:i.matchMedia?.("(prefers-reduced-motion: reduce)").matches?"auto":"smooth"});i?.dispatchEvent(new CustomEvent("stx:tabreselect",{detail:{href:o.getAttribute("href")||""}}))};return e.addEventListener("click",n),()=>e.removeEventListener("click",n)}function ct(e){let t=e.trim();return/^#[0-9a-f]{6}$/i.test(t)?t:void 0}var ve="stacks:tab-bar-cover";function so(e,t){if(t)e.setAttribute("data-native-covers-tab-bar","");else e.removeAttribute("data-native-covers-tab-bar");e.ownerDocument?.defaultView?.dispatchEvent(new Event(ve))}function lo(e,t={}){let n=t.api??mn;if(!n.isAvailable())return null;let r=t.hidden??(()=>Boolean(e.ownerDocument?.querySelector("[data-native-hide-tab-bar], [data-native-covers-tab-bar]"))),o=typeof getComputedStyle==="function"?getComputedStyle(e):null,i=ct(o?.getPropertyValue("--native-tab-active")||""),a=ct(o?.getPropertyValue("--native-tab-active-dark")||""),s="",l=()=>{if(r()){if(s!=="hidden")n.hide();s="hidden";return}let{tabs:f,selected:u}=hn(gn(e)),d=JSON.stringify({tabs:f,selected:u});if(d===s)return;let g=s&&s!=="hidden"?JSON.parse(s):null;if(g&&u&&JSON.stringify(g.tabs)===JSON.stringify(f))n.select(u);else n.set(f,{selected:u,tint:i,tintDark:a});s=d},m=typeof MutationObserver==="function"?new MutationObserver(l):null;m?.observe(e,{attributes:!0,attributeFilter:["data-stx-nav-current","class"],childList:!0,subtree:!0,characterData:!0});let p=n.onSelect((f)=>{let u=ut();if(u?.selectTab){u.selectTab(f);return}Array.from(e.querySelectorAll("a[data-native-tab]")).find((g)=>g.getAttribute("href")===f)?.click()}),c=()=>l();if(typeof window<"u")window.addEventListener("stx:load",c),window.addEventListener("stx:screen-shown",c),window.addEventListener(ve,c);return l(),()=>{if(m?.disconnect(),p(),typeof window<"u")window.removeEventListener("stx:load",c),window.removeEventListener("stx:screen-shown",c),window.removeEventListener(ve,c);n.hide()}}var Sn={isAvailable:()=>h(()=>ye.isAvailable()),getBiometricType:()=>h(()=>ye.getBiometricType()),authenticate:(e)=>h(()=>ye.authenticate(e))},wn={takePicture:(e)=>h(()=>Z.takePicture(e)),pickImage:()=>h(()=>Z.pickImage()),pickMultiple:(e)=>h(()=>Z.pickMultiple(e)),isAvailable:()=>h(()=>Z.isAvailable())},An={getInfo:()=>h(()=>O.getInfo()),getCapabilities:()=>h(()=>O.getCapabilities()),isMobile:()=>O.isMobile(),isIOS:()=>O.isIOS(),isAndroid:()=>O.isAndroid(),getLocale:()=>O.getLocale(),getTimezone:()=>O.getTimezone()},kn=yn,En={getCurrentPosition:(e)=>h(()=>M.getCurrentPosition(e)),watchPosition:(e,t)=>M.watchPosition(e,t),clearWatch:(e)=>M.clearWatch(e),startRecording:(e)=>h(()=>M.startRecording(e)),pauseRecording:()=>h(()=>M.pauseRecording()),resumeRecording:()=>h(()=>M.resumeRecording()),stopRecording:()=>h(()=>M.stopRecording()),getRecordingState:()=>h(()=>M.getRecordingState()),readRecording:()=>h(()=>M.readRecording())},Tn={show:(e)=>h(()=>te.show(e)),schedule:(e)=>h(()=>te.schedule(e)),cancelAll:()=>h(()=>te.cancelAll()),setBadge:(e)=>h(()=>te.setBadge(e))},Ln={check:(e)=>h(()=>W.check(e)),request:(e)=>h(()=>W.request(e)),checkMultiple:(e)=>h(()=>W.checkMultiple(e)),requestMultiple:(e)=>h(()=>W.requestMultiple(e)),openSettings:()=>h(()=>W.openSettings())},Rn={set:(e,t)=>h(()=>ne.set(e,t)),get:(e)=>h(()=>ne.get(e)),delete:(e)=>h(()=>ne.delete(e)),clear:()=>h(()=>ne.clear())},Mn={share:(e)=>h(()=>mt.share(e)),isAvailable:()=>mt.isAvailable()},Pn={request:()=>h(()=>vn.request())},oe={impact:(e)=>Promise.resolve().then(()=>ee.impact(e)).catch(()=>{}),notification:(e)=>Promise.resolve().then(()=>ee.notification(e)).catch(()=>{}),selection:()=>Promise.resolve().then(()=>ee.selection()).catch(()=>{}),vibrate:(e)=>Promise.resolve().then(()=>ee.vibrate(e)).catch(()=>{}),prepare:(e)=>{let t=T("haptics.prepare");return t?Promise.resolve().then(()=>t(e)).then(()=>{},()=>{}):Promise.resolve()}};function gt(e){if(typeof e==="string")return e.trim()||null;if(!e||typeof e!=="object")return null;let t=e.url;return typeof t==="string"&&t.trim()?t:null}var Cn={async getInitialURL(){if(!await I())return null;return gt(await dt.getInitialURL?.())},onLink(e){let t=null,n=!1,r=()=>{if(n)return;t=dt.onLink?.((o,i)=>{let a=gt(o);if(a)e(a,{initial:i?.initial===!0})})??null};if(ae()?.craft)r();else I().then(r);return()=>{n=!0,t?.()}}},mo={isAvailable:()=>re.isAvailable(),set:(e,t)=>re.set(e,t),remove:(e)=>re.remove(e),clear:()=>re.clear()},On={enable:()=>h(()=>pt.enable()),disable:()=>h(()=>pt.disable())},In={isAvailable:()=>Q.isAvailable(),get:()=>h(()=>Q.get()),set:(e)=>h(()=>Q.set(e)),restore:()=>h(()=>Q.restore())},Nn={isAvailable:()=>we.isAvailable(),speak:(e,t)=>h(()=>we.speak(e,t)),stop:()=>h(()=>we.stop())},Hn={getStatus:()=>h(()=>ft.getStatus()),onChange:(e)=>le(()=>ft.onChange(e))},_n={register:()=>h(()=>Se.register()),onToken:(e)=>Se.onToken(e),onNotification:(e)=>le(()=>Se.onNotification(e))},Dn={requestAuthorization:(e,t)=>h(()=>U.requestAuthorization(e,t)),getData:(e,t)=>h(()=>U.getData(e,t)),saveWorkout:(e)=>h(()=>U.saveWorkout(e)),getWorkouts:(e)=>h(()=>U.getWorkouts(e)),getDailyStatistics:(e,t)=>h(()=>U.getDailyStatistics(e,t)),getHeartRateSamples:(e)=>b("health.getHeartRateSamples",[e??{}],()=>[]).then((t)=>Array.isArray(t)?t:[]),getSleepIntervals:(e)=>b("health.getSleepIntervals",[e??{}],()=>[]).then((t)=>Array.isArray(t)?t:[]),supports:(e)=>T(`health.${e}`)!==null},Bn={start:(e)=>h(()=>xe.start(e)),update:(e)=>h(()=>xe.update(e)),end:()=>h(()=>xe.end())},Fn={send:(e)=>h(()=>z.send(e)),updateContext:(e)=>h(()=>z.updateContext(e)),isReachable:()=>h(()=>z.isReachable()),onMessage:(e)=>z.onMessage(e),onReachabilityChange:(e)=>z.onReachabilityChange(e)},go=xn;function ae(){return S()}function ie(){let e=ae()?.craft;if(!e||typeof e!=="object")return null;if(!("platform"in e)||e.platform!=="ios"&&e.platform!=="android")return null;let t="capabilities"in e?e.capabilities:void 0,n=t&&typeof t==="object"&&!Array.isArray(t)?Object.fromEntries(Object.entries(t).filter(([,r])=>typeof r==="boolean")):{};return{platform:e.platform,capabilities:n}}function Ae(){return ie()!==null}function Kn(e=2000){if(Ae()||se())return Promise.resolve(!0);let t=ae();if(!t||!(t.craft||t.webkit?.messageHandlers?.craft))return Promise.resolve(!1);return new Promise((n)=>{let r=()=>{clearTimeout(o),t.removeEventListener("craftReady",r),n(Ae())},o=setTimeout(r,e);t.addEventListener("craftReady",r,{once:!0})})}function $n(e){let t=ae();if(!t)return()=>{};if(ie()){let r=!1;return queueMicrotask(()=>{if(!r)e(new Event("craftReady"))}),()=>{r=!0}}let n=(r)=>{if(!ie())return;t.removeEventListener("craftReady",n),e(r)};return t.addEventListener("craftReady",n),()=>t.removeEventListener("craftReady",n)}async function qn(e){await oe.impact("light");try{let t=await e();return await oe.notification("success"),t}catch(t){throw await oe.notification("error"),t}}var ho={get nativeBridge(){return ie()},biometrics:Sn,camera:wn,device:An,haptics:oe,lifecycle:kn,location:En,notifications:Tn,permissions:Ln,secureStorage:Rn,share:Mn,appReview:Pn,deepLinks:Cn,keepAwake:On,brightness:In,speech:Nn,network:Hn,pushNotifications:_n,health:Dn,liveActivities:Bn,watchConnectivity:Fn,dialog:_,contextMenu:me,browser:_e,symbols:De,statusBar:j,chrome:D,refresh:P,background:B,clipboard:Be,db:Fe,files:Ke,shortcuts:$e,widgets:qe,orientation:Ue,auth:We,storeKit:ze,isNativeMobile:Ae,whenNative:Kn,onReady:$n,withFeedback:qn};export{Un as BRIDGE_WAIT_MS,Dr as INDOOR_CHECK_AFTER_S,eo as MAX_SPOTLIGHT_SLOTS_PER_KIND,Lr as ROUTE_GAP_S,Wr as SHEET_FLICK_VELOCITY,ve as TAB_BAR_COVER_EVENT,h as afterBridge,Pn as appReview,Xt as applyAppearance,We as auth,xr as backLabelFor,B as background,Sn as biometrics,Y as bridgePending,In as brightness,_e as browser,b as callNative,wn as camera,Bt as canGoBack,D as chrome,Be as clipboard,Xn as confirmAction,me as contextMenu,so as coverTabBar,S as craftHost,yt as craftRoot,Pr as createRouteRecorder,no as createSpotlightIndex,je as currentAppearance,Fe as db,Kt as deepLinkPath,Cn as deepLinks,An as device,_ as dialog,yr as enterNavTrail,Ke as files,qt as fixDistance,rr as focusSegment,Er as followDeepLinks,ie as getNativeMobileBridge,vr as goBack,Ar as goBackToTabRoot,ao as handleTabReselect,oe as haptics,se as hasNativeMobileHost,Dn as health,Br as indoorVerdict,Qr as installNativeChrome,or as installPressables,Ae as isNativeMobile,zt as isShown,On as keepAwake,_t as largeTitleMetrics,kn as lifecycle,jr as liftToBody,Bn as liveActivities,En as location,Yr as lockBackground,lo as mirrorTabBar,ho as mobile,wt as nativeFunction,T as nativeFunctionNow,hn as nativeTabs,Sr as navTrail,Hn as network,Ot as normalizeAppearance,gt as normalizeDeepLinkURL,Tn as notifications,gr as observeLargeTitle,er as observeLongPress,qr as observeNativeRefresh,Nt as observePageScroll,mr as observePullToRefresh,tr as observeSegmentScrub,zr as observeSheetDrag,Ge as onAppearance,dr as onBackgroundRefresh,R as onCraftEvent,cr as onMemoryWarning,$n as onMobileReady,lr as onResume,ur as onSilentPush,ro as onSpotlightTap,Ue as orientation,Rr as paceLabel,Qt as pageBackground,Zt as pageIsDark,F as pageScrollTop,Ir as pauseSessionClock,Ln as permissions,Lt as placeMenu,rn as placeSpotlightItem,Pe as presentActionSheet,Re as presentAlert,ce as presentChoice,Me as presentConfirm,Ce as presentContextMenu,Gr as presentPageAsCard,wr as previousScreenPath,Ht as pullDistance,_n as pushNotifications,sn as readSpotlightEntries,it as readSpotlightKinds,gn as readTabLinks,P as refresh,on as removeSpotlightItem,hr as resolveScrollHost,Nr as resumeSessionClock,Ze as routeStats,bn as routerHandlesTabs,Vt as rubberBand,Rn as secureStorage,Ct as segmentAt,nr as segmentForKey,Hr as sessionClockElapsed,Gt as settleSheet,Mn as share,jt as sheetStops,$e as shortcuts,Jn as showContextMenuFor,mo as snapshots,Nn as speech,Mr as speedLabel,go as splash,K as spotlightAction,at as spotlightActions,to as spotlightActivityTypes,un as spotlightBridge,q as spotlightKind,an as spotlightRoute,nn as spotlightSlot,st as spotlightTitle,Or as startSessionClock,j as statusBar,ze as storeKit,le as subscribeWhenReady,De as symbols,mn as tabBar,fe as toNativeRect,kr as trailEntryFor,Tt as trapFocus,Fr as typedDistanceKm,Ut as usableFixes,Vn as useActionSheet,Fn as watchConnectivity,I as whenBridgeReady,Kn as whenNativeMobile,qe as widgets,qn as withNativeFeedback};
|
|
55
|
+
`;function Me(){return S()?.document}function Tt(e){if(e.getElementById(Le))return;let t=e.createElement("style");t.id=Le,t.textContent=Et,(e.head??e.documentElement).appendChild(t)}var Rt=0;function E(e,t,n,r){let o=e.createElement(t);if(o.className=n,r!==void 0)o.textContent=r;return o}var Pe='button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function Lt(e,t){if(t.key!=="Tab")return;let n=Array.from(e.querySelectorAll(Pe));if(n.length===0){t.preventDefault();return}let r=n[0],o=n[n.length-1],i=e.ownerDocument.activeElement;if(t.shiftKey&&(i===r||!e.contains(i)))t.preventDefault(),o.focus();else if(!t.shiftKey&&(i===o||!e.contains(i)))t.preventDefault(),r.focus()}function Ce(e,t,n,r){Tt(e);let o=S(),i=e.activeElement,a=E(e,"div",`native-dialog native-dialog--${t}`);return a.setAttribute("data-native-dialog",t),a.appendChild(E(e,"div","native-dialog-backdrop")),new Promise((s)=>{let l=!1,g=(h)=>{if(l)return;l=!0,a.classList.remove("is-open"),e.removeEventListener("keydown",p,!0),setTimeout(()=>{if(a.remove(),i&&typeof i.focus==="function")i.focus()},260),s(h)},p=(h)=>{if(h.key==="Escape"){h.preventDefault(),g(r());return}Lt(u,h)},u=n({root:a,settle:g});a.appendChild(u),e.body.appendChild(a),e.addEventListener("keydown",p,!0);let f=o;(typeof f?.requestAnimationFrame==="function"?(h)=>f.requestAnimationFrame(()=>f.requestAnimationFrame(h)):(h)=>setTimeout(h,16))(()=>{if(!l)a.classList.add("is-open")}),(u.querySelector("[data-native-autofocus]")??u.querySelector(Pe))?.focus()})}function fe(e){let t=Me();if(!t?.body)return Promise.resolve(null);let n=`native-dialog-${++Rt}`,r=e.actions.find((a)=>a.style==="cancel"),o=e.variant==="sheet"?e.actions.filter((a)=>a.style!=="cancel"):e.actions,i=e.variant==="sheet"?r??{id:"__cancel",title:e.cancelLabel||"Cancel",style:"cancel"}:void 0;return Ce(t,e.variant,({root:a,settle:s})=>{let l=(d)=>d.style==="cancel"?null:d.id,g=E(t,"div","native-dialog-panel");g.setAttribute("role","alertdialog"),g.setAttribute("aria-modal","true"),g.tabIndex=-1;let p=E(t,"div","native-dialog-group");if(e.title||e.message){let d=E(t,"div","native-dialog-header");if(e.title){let m=E(t,"p","native-dialog-title",e.title);m.id=`${n}-title`,d.appendChild(m),g.setAttribute("aria-labelledby",m.id)}if(e.message){let m=E(t,"p","native-dialog-message",e.message);m.id=`${n}-message`,d.appendChild(m),g.setAttribute("aria-describedby",m.id)}p.appendChild(d)}let u=E(t,"div","native-dialog-actions");if(e.variant==="alert"&&o.length===2)u.classList.add("is-row");for(let d of o){let m=E(t,"button",`native-dialog-action${d.style==="destructive"?" is-destructive":""}${d.style==="cancel"?" is-cancel":""}`,d.title);m.type="button",m.setAttribute("data-action-id",d.id),m.addEventListener("click",()=>s(l(d))),u.appendChild(m)}if(p.appendChild(u),g.appendChild(p),i){let d=E(t,"div","native-dialog-group"),m=E(t,"button","native-dialog-action is-cancel",i.title);m.type="button",m.setAttribute("data-action-id",i.id),m.addEventListener("click",()=>s(null)),d.appendChild(m),g.appendChild(d)}let f=a.querySelector(".native-dialog-backdrop");if(e.variant==="sheet")f?.addEventListener("click",()=>s(null));return g},()=>{if(e.variant==="sheet")return null;if(r)return null;return o.length===1?o[0].id:null})}async function Oe(e){await fe({variant:"alert",title:e.title,message:e.message,actions:[{id:"ok",title:e.okLabel||"OK"}]})}async function Ne(e){return await fe({variant:"alert",title:e.title,message:e.message,actions:[{id:"cancel",title:e.cancelLabel||"Cancel",style:"cancel"},{id:"confirm",title:e.confirmLabel||"OK",style:e.destructive?"destructive":"default"}]})==="confirm"}function Ie(e){return fe({variant:"sheet",title:e.title,message:e.message,actions:e.actions,cancelLabel:e.cancelLabel})}function Mt(e,t,n){let i=Math.max(12,Math.min(e.x,n.width-t.width-12)),a=e.y+e.height+8,s=a+t.height<=n.height-12,l=e.y-8-t.height,g=s||l<12?Math.max(12,Math.min(a,n.height-t.height-12)):l,p=e.x+e.width/2>n.width/2?"right":"left";return{top:g,left:i,origin:`${s||l<12?"top":"bottom"} ${p}`}}function He(e){let t=Me();if(!t?.body)return Promise.resolve(null);let n=S();return Ce(t,"menu",({root:r,settle:o})=>{let i=E(t,"div","native-menu native-dialog-panel");if(i.setAttribute("role","menu"),e.title)i.appendChild(E(t,"p","native-menu-title",e.title)),i.setAttribute("aria-label",e.title);for(let a of e.items){let s=E(t,"button",`native-menu-item${a.destructive?" is-destructive":""}`);if(s.type="button",s.setAttribute("role","menuitem"),s.setAttribute("data-action-id",a.id),a.disabled)s.disabled=!0;if(s.appendChild(E(t,"span","native-menu-label",a.title)),a.icon){let l=E(t,"i",`native-menu-icon ${a.icon}`);l.setAttribute("aria-hidden","true"),s.appendChild(l)}s.addEventListener("click",()=>o(a.id)),i.appendChild(s)}return r.querySelector(".native-dialog-backdrop")?.addEventListener("click",()=>o(null)),queueMicrotask(()=>{let a=i.getBoundingClientRect?.(),s=Mt(e.anchor,{width:a?.width||248,height:a?.height||e.items.length*44},{width:n?.innerWidth||390,height:n?.innerHeight||844});i.style.top=`${s.top}px`,i.style.left=`${s.left}px`,i.style.setProperty("--native-menu-origin",s.origin)}),i},()=>null)}var Fe=()=>!0,R=()=>!1,M=()=>null;function _e(){return S()?.navigator??(typeof navigator>"u"?void 0:navigator)}function be(e){return{x:Math.round(e.x??e.left??0),y:Math.round(e.y??e.top??0),width:Math.round(e.width),height:Math.round(e.height)}}var q={alert:(e)=>v("dialog.alert",[e],()=>Oe(e),{fallbackOnError:!0}).then(()=>{}),confirm:(e)=>v("dialog.confirm",[e],()=>Ne(e),{fallbackOnError:!0}).then(Boolean),actionSheet:async(e)=>{let t={...e,anchor:e.anchor?be(e.anchor):void 0},n=await v("dialog.actionSheet",[t],()=>Ie(e),{fallbackOnError:!0});if(typeof n!=="string")return null;return e.actions.find((r)=>r.id===n)?.style==="cancel"?null:n}};function rr(){return(e)=>q.actionSheet(e)}async function or(e){if((e.style??(e.destructive?"sheet":"alert"))==="alert")return q.confirm(e);return await q.actionSheet({title:e.title,message:e.message,anchor:e.anchor,actions:[{id:"confirm",title:e.confirmLabel||"OK",style:e.destructive?"destructive":"default"},{id:"cancel",title:e.cancelLabel||"Cancel",style:"cancel"}]})==="confirm"}var ve={show:async(e)=>{let t={title:e.title,anchor:be(e.anchor),items:e.items.map(({id:r,title:o,symbol:i,destructive:a,disabled:s})=>({id:r,title:o,symbol:i,destructive:a,disabled:s}))},n=await v("contextMenu.show",[t],()=>He(e),{fallbackOnError:!0});return typeof n==="string"?n:null}};function ir(e,t){return ve.show({...t,anchor:be(e.getBoundingClientRect())})}function Pt(e,t){let n=S();if(!n)return{cancelled:!0};if(typeof n.craft?.openURL==="function")return Promise.resolve(n.craft.openURL(e)).catch(()=>{}),{cancelled:!1};if(t.mode==="auth")return n.location?.assign(e),{cancelled:!1};if(!(typeof n.open==="function"?n.open(e,"_blank","noopener"):null))n.location?.assign(e);return{cancelled:!1}}var Ke={open:async(e,t={})=>{let n=await v("browser.open",[e,t],()=>Pt(e,t),{fallbackOnError:!0});if(!n||typeof n!=="object")return{cancelled:!1};let{url:r,cancelled:o}=n;return typeof r==="string"?{url:r,cancelled:Boolean(o)}:{cancelled:Boolean(o)}}},me=new Map,ge=new Map;function De(e,t){return`${e}|${t.pointSize??""}|${t.weight??""}|${t.color??""}|${t.scale??""}`}var $e={isAvailable:()=>L("symbols.image")!==null,image:(e,t={})=>{let n=De(e,t),r=me.get(n);if(r)return r;let o=v("symbols.image",[e,t],M).then((i)=>typeof i==="string"&&i.startsWith("data:")?i:null,M).then((i)=>(ge.set(n,i),i));return me.set(n,o),o},cached:(e,t={})=>ge.get(De(e,t)),clearCache:()=>{me.clear(),ge.clear()}},Q={setStyle:(e)=>v("statusBar.setStyle",[e],R,{fallbackOnError:!0}).then((t)=>t!==!1)},U={setUnderPageColor:(e)=>v("chrome.setUnderPageColor",[e],R,{fallbackOnError:!0}).then((t)=>t!==!1),setKeyboardAccessory:(e)=>v("chrome.setKeyboardAccessory",[e],R,{fallbackOnError:!0}).then((t)=>t!==!1)},I={isAvailable:()=>L("refresh.enable")!==null,enable:(e)=>v("refresh.enable",[e??{}],R,{fallbackOnError:!0}).then((t)=>t!==!1),disable:()=>v("refresh.disable",[],R,{fallbackOnError:!0}).then((e)=>e!==!1),end:()=>v("refresh.end",[],R,{fallbackOnError:!0}).then((e)=>e!==!1),onRefresh:(e)=>O("craftRefresh",()=>e())},W={complete:(e)=>v("background.complete",[e],R,{fallbackOnError:!0}).then((t)=>t!==!1)},qe={write:(e)=>v("clipboard.write",[e],async()=>{let t=_e()?.clipboard;if(!t?.writeText)return!1;return t.writeText(e).then(Fe,R)},{fallbackOnError:!0}).then((t)=>t!==!1),read:()=>v("clipboard.read",[],async()=>{let e=_e()?.clipboard;if(!e?.readText)return null;return e.readText().catch(M)},{fallbackOnError:!0}).then((e)=>typeof e==="string"?e:null)},Ue={isAvailable:()=>L("db.query")!==null,query:(e,t=[])=>v("db.query",[e,t],M).then((n)=>Array.isArray(n)?n:null),execute:(e,t=[])=>v("db.execute",[e,t],M).then((n)=>{if(!n||typeof n!=="object")return null;let{rowsAffected:r,lastInsertId:o}=n;return{rowsAffected:Number(r)||0,lastInsertId:Number(o)||0}})};function he(e,t){let n=S()?.document;if(!n?.body)return null;let r=n.createElement("a");return r.href=e,r.download=t,r.rel="noopener",r.style.display="none",n.body.appendChild(r),r.click(),r.remove(),t}function Ct(e){let t=S()?.document;if(!t?.body)return Promise.resolve(null);return new Promise((n)=>{let r=t.createElement("input");if(r.type="file",r.style.display="none",e.length)r.accept=e.map((i)=>i.includes("/")||i.startsWith(".")?i:`.${i}`).join(",");let o=(i)=>{r.remove(),n(i)};r.addEventListener("cancel",()=>o(null)),r.addEventListener("change",()=>{let i=r.files?.[0];if(!i)return o(null);let a=new FileReader;a.onload=()=>o({name:i.name,mimeType:i.type||void 0,data:typeof a.result==="string"?a.result:void 0}),a.onerror=()=>o({name:i.name,mimeType:i.type||void 0}),a.readAsDataURL(i)}),t.body.appendChild(r),r.click()})}var We={openPDF:(e,t=0)=>v("openPDF",[e,t],()=>{let n=S();return Boolean(n?.open?.(e,"_blank","noopener"))}).then((n)=>n!==!1),takeScreenshot:()=>v("takeScreenshot",[],M,{fallbackOnError:!0}).then((e)=>typeof e==="string"?e:null),scanQRCode:()=>v("scanQRCode",[],M).then((e)=>{if(!e||typeof e!=="object")return null;let{type:t,data:n}=e;return typeof n==="string"?{type:String(t??""),data:n}:null},M),pickFile:(e=[])=>v("pickFile",[e],()=>Ct(e)).then((t)=>{if(!t||typeof t!=="object")return null;let n=t;if(typeof n.name!=="string")return null;return{name:n.name,path:typeof n.path==="string"?n.path:void 0,data:typeof n.data==="string"?n.data:void 0,mimeType:typeof n.mimeType==="string"?n.mimeType:void 0}},M),saveFile:(e,t,n)=>v("saveFile",[e,t,n],()=>{if(e.startsWith("data:"))return he(e,t);let r=new Blob([e],{type:n||"text/plain"}),o=URL.createObjectURL(r),i=he(o,t);return setTimeout(()=>URL.revokeObjectURL(o),1000),i}).then((r)=>typeof r==="string"?r:null),downloadFile:(e,t)=>v("downloadFile",[e,t],()=>he(e,t)).then((n)=>typeof n==="string"?n:null)},ze={set:(e)=>v("shortcuts.set",[e.map(({symbol:t,...n})=>t?{...n,iconName:t}:n)],R).then((t)=>t!==!1),clear:()=>v("shortcuts.clear",[],R).then((e)=>e!==!1),onShortcut:(e)=>O("craftShortcut",(t)=>{if(typeof t.type==="string")e(t.type)})},Ye={update:(e)=>v("widget.update",[e],R).then((t)=>t!==!1),reload:()=>v("widget.reload",[],R).then((e)=>e!==!1)},Ot={portrait:"portrait-primary",portraitUpsideDown:"portrait-secondary",landscape:"landscape",landscapeLeft:"landscape-primary",landscapeRight:"landscape-secondary"};function Be(){return S()?.screen?.orientation}var je={lock:(e)=>v("lockOrientation",[e],()=>{let t=Be();return t?.lock?t.lock(Ot[e]).then(Fe,R):!1}).then((t)=>t!==!1),unlock:()=>v("unlockOrientation",[],()=>(Be()?.unlock?.(),!0)).then((e)=>e!==!1)},Ve={signInWithApple:(e={})=>v("signInWithApple",e.nonce?[{nonce:e.nonce}]:[],M).then((t)=>{if(!t||typeof t!=="object"||typeof t.userId!=="string")return null;return t})},Ge={isAvailable:()=>L("iap.purchase")!==null,products:(e)=>v("iap.getProducts",[e],()=>[]).then((t)=>Array.isArray(t)?t:[]),purchase:(e)=>v("iap.purchase",[e],M).then((t)=>t&&typeof t==="object"?t:null,(t)=>{if(/cancel/i.test(String(t?.message??t)))return null;throw t}),restore:()=>v("iap.restore",[],()=>[]).then((e)=>Array.isArray(e)?e:[])};function lr(e,t){let n=t.delay??500,r=t.tolerance??10,o=null,i=null,a=!1,s=()=>{if(o)clearTimeout(o);if(o=null,i&&!a)t.onPressEnd?.();i=null},l=(f)=>{let d=f;if(d.button!==void 0&&d.button!==0)return;a=!1,i={x:d.clientX,y:d.clientY},t.onPressStart?.(),o=setTimeout(()=>{if(o=null,!i)return;a=!0,t.onLongPress({...i}),i=null},n)},g=(f)=>{if(!i)return;let d=f;if(Math.hypot(d.clientX-i.x,d.clientY-i.y)>r)s()},p=(f)=>{if(!a)return;a=!1,f.preventDefault(),f.stopPropagation()},u=(f)=>f.preventDefault();return e.addEventListener("pointerdown",l),e.addEventListener("pointermove",g),e.addEventListener("pointerup",s),e.addEventListener("pointercancel",s),e.addEventListener("pointerleave",s),e.addEventListener("click",p,!0),e.addEventListener("contextmenu",u),()=>{s(),e.removeEventListener("pointerdown",l),e.removeEventListener("pointermove",g),e.removeEventListener("pointerup",s),e.removeEventListener("pointercancel",s),e.removeEventListener("pointerleave",s),e.removeEventListener("click",p,!0),e.removeEventListener("contextmenu",u)}}function Nt(e,t,n){if(n<=1||t.width<=0)return 0;let r=Math.floor((e-t.left)/t.width*n);return Math.max(0,Math.min(n-1,r))}function cr(e,t){let n=null,r=null,o=!1,i=0,a=(d)=>{let m=e.getBoundingClientRect();return Nt(d,{left:m.left+2,width:m.width-4},t.count())},s=(d)=>{let m=d;if(m.button!==void 0&&m.button!==0)return;let h=a(m.clientX);if(h!==t.selected())return;n=h,i=h,o=!1,r=m.pointerId;try{e.setPointerCapture?.(m.pointerId)}catch{}t.onPress?.(!0)},l=(d)=>{if(n===null)return;let m=a(d.clientX);if(m===i)return;o=!0,i=m,t.onScrub(m)},g=(d)=>{if(n===null)return;if(r!==null)try{e.releasePointerCapture?.(r)}catch{}if(t.onPress?.(!1),d&&o)t.onCommit(i);else if(o)t.onScrub(n);n=null,r=null},p=(d)=>{if(!o)return;o=!1,d.preventDefault(),d.stopPropagation()},u=()=>g(!0),f=()=>g(!1);return e.addEventListener("pointerdown",s),e.addEventListener("pointermove",l),e.addEventListener("pointerup",u),e.addEventListener("pointercancel",f),e.addEventListener("click",p,!0),()=>{e.removeEventListener("pointerdown",s),e.removeEventListener("pointermove",l),e.removeEventListener("pointerup",u),e.removeEventListener("pointercancel",f),e.removeEventListener("click",p,!0)}}function ur(e,t,n){if(n<=0)return null;switch(e){case"ArrowRight":case"ArrowDown":return(t+1)%n;case"ArrowLeft":case"ArrowUp":return(t-1+n)%n;case"Home":return 0;case"End":return n-1;default:return null}}function dr(e,t){e.querySelectorAll('[role="tab"]')[t]?.focus()}function pr(e){let t=(n)=>{if(!n.target?.closest?.("[data-native-pressable]"))return;let o=L("haptics.prepare");if(o)Promise.resolve().then(()=>o("impact")).catch(()=>{})};return e.addEventListener("touchstart",t,{passive:!0,capture:!0}),()=>e.removeEventListener("touchstart",t,{capture:!0})}function ye(e){let t=S();try{return Boolean(t?.matchMedia?.(e).matches)}catch{return!1}}function Xe(e){return e!==null&&e!==void 0&&e!=="false"&&e!=="0"}function Je(){let e=S()?.document?.documentElement,t=Number.parseFloat(e?.style?.getPropertyValue("--craft-font-scale")||"");return{fontScale:Number.isFinite(t)&&t>0?t:1,reduceMotion:Xe(e?.getAttribute("data-craft-reduce-motion"))||ye("(prefers-reduced-motion: reduce)"),reduceTransparency:Xe(e?.getAttribute("data-craft-reduce-transparency"))||ye("(prefers-reduced-transparency: reduce)"),colorScheme:e?.classList?.contains("dark")||ye("(prefers-color-scheme: dark)")?"dark":"light"}}function It(e){let t=Je(),n=Number(e?.fontScale);return{contentSizeCategory:typeof e?.contentSizeCategory==="string"?e.contentSizeCategory:void 0,fontScale:Number.isFinite(n)&&n>0?n:t.fontScale,reduceMotion:typeof e?.reduceMotion==="boolean"?e.reduceMotion:t.reduceMotion,reduceTransparency:typeof e?.reduceTransparency==="boolean"?e.reduceTransparency:t.reduceTransparency,colorScheme:e?.colorScheme==="dark"||e?.colorScheme==="light"?e.colorScheme:t.colorScheme}}function Qe(e,t={}){if(t.immediate!==!1)e(Je());return O("craftAppearance",(n)=>e(It(n)))}function hr(e){return O("craftResume",(t)=>e({backgroundedMs:Number(t.backgroundedMs)||0}))}function br(e){return O("craftMemoryWarning",()=>e())}function Ze(e){return(t)=>{Promise.resolve().then(()=>e(t)).then(()=>W.complete(!0),()=>W.complete(!1))}}function vr(e){let t=Ze(e);return O("craftSilentPush",(n)=>t(n.payload??{}))}function yr(e){let t=Ze(()=>e());return O("craftBackgroundRefresh",()=>t(void 0))}import{haptics as Ht}from"craft-native/mobile";function Se(){if(typeof window>"u")return;return window}function z(e=Se()){if(!e)return 0;if(typeof e.scrollY==="number")return e.scrollY;if(typeof e.scrollTop==="number")return e.scrollTop;return e.document?.scrollingElement?.scrollTop??0}function _t(e,t=Se()){if(!t)return()=>{};let n=!1,r=typeof requestAnimationFrame==="function"?requestAnimationFrame:(i)=>setTimeout(i,16),o=()=>{if(n)return;n=!0,r(()=>{n=!1,e(z(t))})};return e(z(t)),t.addEventListener("scroll",o,{passive:!0}),()=>t.removeEventListener("scroll",o)}function Dt(e,t){let n=Math.max(0,-e),r=e<=0?Math.max(0,t)*0.5:0;return Math.round(Math.max(n,r))}function wr(e){let t=e.host??Se();if(!t)return()=>{};let n=e.threshold??72,r=null,o=!1,i=!1,a=typeof requestAnimationFrame==="function"?requestAnimationFrame:(h)=>setTimeout(h,16),s=null,l=(h)=>{s=null,e.onPull?.(h,o,{bounce:Math.min(h,Math.max(0,-z(t)))})},g=(h)=>{let k=s!==null;if(s=h,k)return;a(()=>{if(s!==null)l(s)})},p=(h)=>{let k=h.touches?.[0];return k?k.clientY:null},u=(h)=>{if(i||z(t)>0)return;r=p(h),o=!1},f=(h)=>{if(r===null)return;let k=p(h);if(k===null)return;let C=Dt(z(t),k-r);if(!o&&C>=n)o=!0,Promise.resolve(Ht.impact("medium")).catch(()=>{});else if(o&&C<n*0.8)o=!1;g(C)},d=async()=>{if(r===null)return;if(r=null,!o){l(0);return}o=!1,i=!0,l(n);try{await e.onRefresh()}finally{i=!1,l(0)}},m=()=>{if(r===null)return;r=null,o=!1,l(0)};return t.addEventListener("touchstart",u,{passive:!0}),t.addEventListener("touchmove",f,{passive:!0}),t.addEventListener("touchend",d),t.addEventListener("touchcancel",m),()=>{s=null,t.removeEventListener("touchstart",u),t.removeEventListener("touchmove",f),t.removeEventListener("touchend",d),t.removeEventListener("touchcancel",m)}}function Bt(e,t=52){let n=Math.max(1,t),r=Math.min(1,Math.max(0,e/n)),o=e<0?1+Math.min(0.1,-e/600):1;return{progress:Math.round(r*1000)/1000,stretch:Math.round(o*1000)/1000}}function Ar(e,t={}){let n="",r=()=>t.title?.offsetHeight||t.height||52;return _t((o)=>{let i=Bt(o,r()),a=`${i.progress}|${i.stretch}`;if(a===n)return;n=a,e.style.setProperty("--native-nav-progress",String(i.progress)),e.style.setProperty("--native-nav-stretch",String(i.stretch)),t.onChange?.(i)},t.host)}function kr(e){if(!e||typeof window>"u")return;let t=window.document?.querySelector(e);return t?t:void 0}function nt(){if(typeof window>"u")return;return window}var et="__stxPushed",Ft="__stxScroll";function Kt(e=nt()){let t=e?.history?.state;if(t===null||t===void 0)return!1;if(typeof t!=="object")return!0;let n=t;if(et in n)return n[et]===!0;return!(Ft in n)}function Tr(e=nt()){if(!Kt(e))return!1;return e.history.back(),!0}function Rr(e,t,n=50){let r=e[e.length-1];if(e.length>=2&&e[e.length-2].path===t)e.pop();else if(!r||r.path!==t)e.push({path:t,title:""});if(e.length>n)e.splice(0,e.length-n);return{current:e[e.length-1],previous:e[e.length-2]??null}}function Lr(e,t,n=12){let r=e?.title.trim()??"";return r&&r.length<=n?r:t}function Mr(){if(typeof window>"u")return[];let e=window;return e.__stacksNavTrail??=[]}function $t(e){try{let t=new URL(e,"http://local");return`${t.pathname}${t.search}`}catch{return e}}function Pr(){if(typeof window>"u")return;let e=window.stxRouter;if(typeof e?.screens!=="function")return;let t=e.screens(),n=t.find((o)=>o.active);if(!n)return;let r=t.filter((o)=>o.tab===n.tab&&o.depth<n.depth);if(!r.length)return null;return $t(r.reduce((o,i)=>i.depth>o.depth?i:o).url)}function Cr(e=typeof window>"u"?void 0:window){let t=e?.stxRouter;if(typeof t?.screens!=="function"||typeof e?.history?.go!=="function")return!1;let n=t.screens(),r=n.find((a)=>a.active);if(!r)return!1;let o=n.filter((a)=>a.tab===r.tab&&a.depth<r.depth);if(!o.length)return!1;let i=o.reduce((a,s)=>s.depth<a.depth?s:a);return e.history.go(i.depth-r.depth),!0}function Or(e,t){for(let n=e.length-1;n>=0;n--)if(e[n].path===t)return e[n];return null}function qt(e,t=Ut()){let n;try{n=new URL(e)}catch{return null}let r=`${n.search}${n.hash}`;if(n.protocol==="http:"||n.protocol==="https:"){if(!t||n.origin!==t)return null;return`${n.pathname||"/"}${r}`}return`${`/${[n.host,n.pathname.replace(/^\/+/,"")].filter(Boolean).join("/")}`}${r}`}function Ut(){if(typeof window>"u")return;return window.location?.origin}var tt="stacks-mobile-deep-link";function Nr(e,t){let n=(r)=>{let o=qt(r);if(o)e(o)};return t.getInitialURL().then((r)=>{if(!r)return;try{if(sessionStorage.getItem(tt)===r)return;sessionStorage.setItem(tt,r)}catch{}n(r)}).catch(()=>{}),t.onLink((r,o)=>{if(o?.initial)return;n(r)})}var Hr=5000;function Wt(e,t,n=5000){let r=t.filter((o)=>Number.isFinite(o.timestamp)&&Number.isFinite(o.bpm)&&o.bpm>0).slice().sort((o,i)=>o.timestamp-i.timestamp);if(!r.length)return e.slice();return e.map((o)=>{let i=0,a=r.length;while(i<a){let p=i+a>>1;if(r[p].timestamp<o.timestamp)i=p+1;else a=p}let s=r[i],l=r[i-1],g=!s?l:!l?s:o.timestamp-l.timestamp<=s.timestamp-o.timestamp?l:s;if(!g||Math.abs(g.timestamp-o.timestamp)>n)return o;return{...o,heartRate:Math.round(g.bpm)}})}var zt=6371008.8,Yt=30,jt=Yt;function Vt(e,t){let n=Math.PI/180,r=(t.latitude-e.latitude)*n,o=(t.longitude-e.longitude)*n,i=Math.sin(r/2)**2+Math.cos(e.latitude*n)*Math.cos(t.latitude*n)*Math.sin(o/2)**2;return 2*zt*Math.asin(Math.min(1,Math.sqrt(i)))}function Gt(e,t=25){let n=new Set;return e.filter((r)=>Number.isFinite(r.latitude)&&Number.isFinite(r.longitude)&&Number.isFinite(r.timestamp)&&Math.abs(r.latitude)<=90&&Math.abs(r.longitude)<=180&&Number.isFinite(r.accuracy)&&r.accuracy>=0&&r.accuracy<=t).sort((r,o)=>r.timestamp-o.timestamp).filter((r)=>{if(n.has(r.timestamp))return!1;return n.add(r.timestamp),!0})}function rt(e,t={}){let n=Gt(e,t.maxAccuracyM??25),r=t.paceWindowS??30,o=[],i=0,a=0,s=null;for(let u of n){let f=o[o.length-1],d=s?(u.timestamp-s.timestamp)/1000:0;if(s=u,!f){o.push({fix:u,cumM:0});continue}if(d>jt){o.push({fix:u,cumM:i});continue}let m=(u.timestamp-f.fix.timestamp)/1000,h=Vt(f.fix,u),k=Math.min(10,Math.max(3,f.fix.accuracy,u.accuracy));if(h<k)continue;if(i+=h,m>0&&h/m>=0.5)a+=m;o.push({fix:u,cumM:i})}let l=o[o.length-1],g=null,p=null;if(l&&n.at(-1).timestamp-l.fix.timestamp<=r*1000){let u=l.fix.timestamp-r*1000,f=o.find((h)=>h.fix.timestamp>=u)??l,d=l.cumM-f.cumM,m=(l.fix.timestamp-f.fix.timestamp)/1000;if(d>=20&&m>0)p=d/m,g=m/(d/1000)}return{distanceM:i,movingS:a,paceSPerKm:g,averagePaceSPerKm:i>=50&&a>0?a/(i/1000):null,speedMps:p,accuracyM:n.length?n[n.length-1].accuracy:e.length?e[e.length-1].accuracy??null:null,fixes:n.length}}function _r(e){if(e==null||e<=0||!Number.isFinite(e)||e>3600)return"–";let t=Math.round(e);return`${Math.floor(t/60)}:${String(t%60).padStart(2,"0")}`}function Dr(e){return e!=null&&e>0&&Number.isFinite(e)?(e*3.6).toFixed(1):"–"}var ot={distanceM:0,movingS:0,paceSPerKm:null,averagePaceSPerKm:null,speedMps:null,accuracyM:null,fixes:0};function Br(e){let t=e.location,n=e.intervalMs??3000,r=ot,o=null,i=e.heartRate,a=!1,s=[],l=()=>typeof document<"u"&&document.visibilityState==="hidden",g=0,p=null,u=Promise.resolve(),f=null,d=!1;function m(x){let b=u.then(x);return u=b.then(()=>{},()=>{}),b}function h(){if(p)return p;let x=g;return p=(async()=>{let b=await t.readRecording();if(x===g&&!d)r=rt(b,e),e.onUpdate?.(r);return r})().finally(()=>{p=null}),p}function k(){if(C(),d)return;o=setInterval(()=>{if(!l())h().catch(()=>{})},n)}function C(){if(o)clearInterval(o);o=null}async function F(x){if(!i||!a)return;await x(i).catch(()=>{})}return{get stats(){return r},get heartRate(){return s},start(){return f=null,m(async()=>{if(await t.startRecording({enableHighAccuracy:!0,...e.locationOptions}),s=[],a=!!i?.isAvailable(),await F((x)=>x.startRecording()),g++,r={...ot},!d)e.onUpdate?.(r);return k(),r})},attach(){return m(async()=>{let x=await t.getRecordingState();if(!x?.active)return null;if(i?.isAvailable())a=!!(await i.getRecordingState().catch(()=>null))?.active;if(await h().catch(()=>{}),!x.paused)k();return x})},pause(){return m(async()=>{await t.pauseRecording(),await F((x)=>x.pauseRecording()),C(),await h().catch(()=>{})})},resume(){return m(async()=>{await t.resumeRecording(),await F((x)=>x.resumeRecording()),k()})},stop(){if(f)return f;return f=m(async()=>{C(),g++;let b=(await t.stopRecording())?.locations??[];if(i&&a){let y=await i.stopRecording().catch(()=>null);a=!1,s=y?.samples??[],b=Wt(b,s)}if(r=rt(b,e),!d)e.onUpdate?.(r);return b}).catch((x)=>{throw f=null,x}),f},dispose(){d=!0,g++,C()},refresh:h}}function Kr(e){return{startedAt:Number.isFinite(e)?e:null,pausedAt:null,pausedMs:0}}function $r(e,t){return e.startedAt===null||e.pausedAt!==null||!Number.isFinite(t)?e:{...e,pausedAt:Math.max(e.startedAt,t)}}function qr(e,t){return e.pausedAt===null||!Number.isFinite(t)?e:{...e,pausedAt:null,pausedMs:e.pausedMs+Math.max(0,t-e.pausedAt)}}function Ur(e,t){if(e.startedAt===null)return 0;let n=((e.pausedAt??t)-e.startedAt-e.pausedMs)/1000;return Number.isFinite(n)?Math.max(0,n):0}var zr=150;function Xt(e,t){let n=Math.PI/180,r=(t.latitude-e.latitude)*n,o=(t.longitude-e.longitude)*n,i=Math.sin(r/2)**2+Math.cos(e.latitude*n)*Math.cos(t.latitude*n)*Math.sin(o/2)**2;return 12742017.6*Math.asin(Math.min(1,Math.sqrt(i)))}function Z(e,t){let n=[...e].sort((r,o)=>r-o);return n[Math.min(n.length-1,Math.floor(t*n.length))]}function Yr(e,t){let n=(e||[]).filter((a)=>Number.isFinite(a?.latitude)&&Number.isFinite(a?.longitude)&&Math.abs(a.latitude)<=90&&Math.abs(a.longitude)<=180),r=n.filter((a)=>a.accuracy!=null).map((a)=>Number(a.accuracy)).filter((a)=>Number.isFinite(a)&&a>=0),o=r.length?Z(r,0.5):Number.POSITIVE_INFINITY,i=0;if(n.length){let a={latitude:Z(n.map((s)=>s.latitude),0.5),longitude:Z(n.map((s)=>s.longitude),0.5)};i=Z(n.map((s)=>Xt(a,s)),0.8)}if(n.length>=10&&i>150&&o<=15)return"outside";if(t<150)return"unsure";if(n.length<3||o>30||i<25)return"indoors";if(i<50&&o>10)return"indoors";return"unsure"}function jr(e,t={}){let r=String(e||"").trim().toLowerCase().replace(",",".").match(/^(\d+(?:\.\d*)?|\.\d+)\s*(km|k|m|mi)?$/);if(!r)return null;let o=Number(r[1]),i=r[2]||t.defaultUnit||(o>100?"m":"km"),a=i==="m"?o/1000:i==="mi"?o*1.609344:o;return Number.isFinite(a)&&a>=0&&a<=2000?Math.round(a*1000)/1000:null}var ne=new Set,it=!1,ee=null;function Jt(e){return e.isConnected&&e.getClientRects().length>0}function at(){return[...ne].find((e)=>Jt(e.element))}function te(){let e=at(),t=Boolean(e);if(t===it)return;if(it=t,t)I.enable(e?.tintColor?{tintColor:e.tintColor}:{});else I.disable()}function Qt(){let e=at();if(!e){I.end();return}Promise.resolve().then(()=>e.run()).catch(()=>{}).finally(()=>I.end())}function Xr(e,t){let n={element:e,tintColor:t.tintColor,run:t.onRefresh};ne.add(n);let r=e.ownerDocument?.defaultView;if(!ee){let o=I.onRefresh(Qt),i=()=>te();r?.addEventListener("stx:load",i),ee=()=>{o(),r?.removeEventListener("stx:load",i)}}return te(),r?.requestAnimationFrame?.(()=>te()),()=>{if(ne.delete(n),ne.size===0)ee?.(),ee=null;te()}}var Qr=0.5;function Zt(e,t,n){let r=[];if(n.includes("large")||n.length===0)r.push({name:"large",y:0});if(n.includes("medium"))r.push({name:"medium",y:Math.max(0,Math.round(e-t*0.5))});return r.push({name:"dismiss",y:Math.max(1,e)}),r.sort((o,i)=>o.y-i.y)}function en(e){let{y:t,velocity:n,stops:r}=e,o=r.filter((s)=>s.name!=="dismiss"),i=r.find((s)=>s.name==="dismiss");if(o.length===0)return"dismiss";if(n>0.5)return(r.filter((l)=>l.y>t+1)[0]??i).name;if(n<-0.5){let s=o.filter((l)=>l.y<t-1);return(s[s.length-1]??o[0]).name}let a=o[o.length-1];if(t>a.y+(i.y-a.y)*0.5)return"dismiss";return o.reduce((s,l)=>Math.abs(l.y-t)<Math.abs(s.y-t)?l:s).name}function tn(e,t=400){if(e<=0)return 0;return e*t*0.55/(t+e*0.55)}function Zr(e){let{panel:t}=e,n=null,r=[],o=0,i=()=>e.viewport?.()??t.ownerDocument?.defaultView?.innerHeight??800,a=()=>Zt(t.offsetHeight||t.getBoundingClientRect().height,i(),e.detents()),s=(p)=>{let u=p;if(u.button!==void 0&&u.button!==0)return;if(u.target?.closest?.("button, a, input, select, textarea, [role=button]"))return;let f=a().find((d)=>d.name===e.detent())?.y??0;n={y:u.clientY,base:f,pointerId:u.pointerId},o=f,r=[{y:f,t:u.timeStamp}],t.classList.add("is-dragging");try{p.currentTarget?.setPointerCapture?.(u.pointerId)}catch{}},l=(p)=>{if(!n)return;let u=p,f=n.base+u.clientY-n.y;o=f<0?-tn(-f):f,r.push({y:o,t:u.timeStamp});while(r.length>2&&u.timeStamp-r[0].t>100)r.shift();t.style.transform=`translateY(${o}px)`;let d=t.offsetHeight||1;t.parentElement?.style.setProperty("--native-sheet-presence",String(Math.max(0,Math.min(1,1-o/d))))},g=(p)=>{if(!n)return;let u=p;n=null;let f=r[0],d=Math.max(1,u.timeStamp-f.t),m=(o-f.y)/d;t.classList.remove("is-dragging"),t.style.transform="",t.parentElement?.style.removeProperty("--native-sheet-presence"),e.onSettle(en({y:o,velocity:m,stops:a()}))};for(let p of e.handles)p.addEventListener("pointerdown",s),p.addEventListener("pointermove",l),p.addEventListener("pointerup",g),p.addEventListener("pointercancel",g);return()=>{for(let p of e.handles)p.removeEventListener("pointerdown",s),p.removeEventListener("pointermove",l),p.removeEventListener("pointerup",g),p.removeEventListener("pointercancel",g)}}var st=0,xe="";function eo(e){let t=e.ownerDocument,n=[],r=e;while(r.parentElement&&r!==t.body){for(let a of Array.from(r.parentElement.children)){if(a===r||a.hasAttribute("inert")||a.hasAttribute("data-native-dialog"))continue;if(["SCRIPT","STYLE","TEMPLATE","LINK"].includes(a.tagName))continue;if(a.hasAttribute("data-native-sheet")&&a.getAttribute("aria-hidden")==="true")continue;a.setAttribute("inert",""),n.push(a)}r=r.parentElement}let o=t.documentElement;if(st++===0)xe=o.style.overflow||"",o.style.overflow="hidden";let i=!1;return()=>{if(i)return;i=!0;for(let a of n)a.removeAttribute("inert");if(--st===0)if(xe)o.style.overflow=xe;else o.style.removeProperty("overflow")}}function to(e){let t=e.ownerDocument;if(e.parentElement===t.body)return()=>{};let n=t.createComment("native-sheet");return e.parentNode?.insertBefore(n,e),t.body.appendChild(e),()=>{if(n.parentNode)n.parentNode.insertBefore(e,n);else e.remove();n.remove()}}function no(e,t){let n=e.documentElement;if(!t){n.removeAttribute("data-native-sheet-card");return}let r=e.defaultView,o=(r?.scrollY??0)+(r?.innerHeight??800)/2;n.style.setProperty("--native-sheet-card-origin",`${Math.round(o)}px`),n.setAttribute("data-native-sheet-card","")}function nn(e,t){e.style.setProperty("--native-font-scale",String(t.fontScale)),e.toggleAttribute("data-native-reduce-motion",t.reduceMotion),e.toggleAttribute("data-native-reduce-transparency",t.reduceTransparency)}function rn(e){let t=e.replace(/\s+/g,"").toLowerCase();return!t||t==="transparent"||/^rgba\(\d+,\d+,\d+,0(\.0+)?\)$/.test(t)||/\/0(\.0+)?\)$/.test(t)}function on(e){let t=e.defaultView;if(!t?.getComputedStyle)return null;for(let n of[e.body,e.documentElement]){if(!n)continue;let r=t.getComputedStyle(n).backgroundColor;if(r&&!rn(r))return r}return null}function an(e){if(e.documentElement.classList.contains("dark"))return!0;if(e.documentElement.classList.contains("light"))return!1;return Boolean(e.defaultView?.matchMedia?.("(prefers-color-scheme: dark)").matches)}function ao(e,t={}){let n=t.root??e.documentElement;U.setKeyboardAccessory(t.keyboardAccessory===!0);let r="",o="",i=()=>{let p=on(e);if(p&&p!==r)r=p,U.setUnderPageColor(p);let u=an(e)?"light":"dark";if(u!==o)o=u,Q.setStyle(u)},a=Qe((p)=>{nn(n,p),i()}),s=e.defaultView,l=typeof s?.MutationObserver==="function"?new s.MutationObserver(i):null;l?.observe(e.documentElement,{attributes:!0,attributeFilter:["class","style","data-theme"]});let g=s?.matchMedia?.("(prefers-color-scheme: dark)");return g?.addEventListener?.("change",i),s?.addEventListener("stx:load",i),i(),()=>{a(),l?.disconnect(),g?.removeEventListener?.("change",i),s?.removeEventListener("stx:load",i)}}var lo=64;var sn=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,ln=/^(?:0|[1-9]\d*)$/;function ct(e){let t=[],n=[],r=e&&typeof e==="object"&&!Array.isArray(e)?e:{};for(let[o,i]of Object.entries(r)){let a=i&&typeof i==="object"?i:null;if(!a){n.push(`spotlight kind "${o}" is not an object`);continue}let{slots:s,route:l}=a,g=typeof a.noun==="string"&&a.noun.trim()?a.noun.trim():"Item";if(!sn.test(o)||o.includes("-slot-")){n.push(`spotlight kind "${o}" is not a usable name: lowercase letters, digits and single dashes, and never "-slot-"`);continue}if(typeof s!=="number"||!Number.isInteger(s)||s<=0||s>64){n.push(`spotlight kind "${o}" needs slots between 1 and 64, not ${String(s)}`);continue}if(typeof l!=="string"||!l.startsWith("/")||!l.includes(":id")){n.push(`spotlight kind "${o}" needs a route starting with "/" and carrying ":id", not ${String(l)}`);continue}t.push({name:o,slots:s,route:l,noun:g})}return{kinds:t,problems:n}}function j(e,t){return e.find((n)=>n.name===t)??null}function Y(e,t,n){let r=j(e,t);if(!r||!Number.isInteger(n)||n<0||n>=r.slots)return null;return`${t}-slot-${n}`}function cn(e,t){if(typeof t!=="string")return null;let n=t.lastIndexOf("-slot-");if(n<=0)return null;let r=t.slice(0,n),o=t.slice(n+6);if(!ln.test(o))return null;let i=Number(o);return Y(e,r,i)===t?{kind:r,slot:i}:null}function ut(e){return e.flatMap((t)=>Array.from({length:t.slots},(n,r)=>`${t.name}-slot-${r}`))}function co(e,t){let n=e&&typeof e==="object"?e:{};if(n.enabled===!1)return[];let o=[...(Array.isArray(n.activityTypes)?n.activityTypes.filter((i)=>typeof i==="string"&&i.trim().length>0):[]).map((i)=>i.trim()),...ut(ct(n.kinds).kinds)];return[...new Set(o)].map((i)=>`${t}.${i}`)}function dt(e,t,n){let r=typeof n.name==="string"?n.name.replace(/\s+/g," ").trim():"";if(!r)return`${j(e,t)?.noun??"Item"} #${n.id}`;return r.length>120?`${r.slice(0,119).trimEnd()}…`:r}function un(e,t,n,r,o=Date.now()){let i=j(e,n);if(!i||!Number.isInteger(r.id)||r.id<=0)return null;let a=t.filter((m)=>m.kind===n),s=dt(e,n,r),l=a.find((m)=>m.itemId===r.id)??null,g=l?null:mn(a,i.slots),p=l||g!==null?null:gn(a),u=l?.slot??g??p?.slot;if(u===void 0||u===null)return null;let f={kind:n,slot:u,itemId:r.id,title:s,donatedAt:o},d=t.filter((m)=>m.kind!==n||m.slot!==u&&m.itemId!==r.id);return{entries:pt(e,[...d,f]),entry:f,evicted:p,changed:!l||l.title!==s}}function dn(e,t,n){let r=e.find((o)=>o.kind===t&&o.itemId===n)??null;return{entries:r?e.filter((o)=>o!==r):[...e],removed:r}}function pn(e,t,n){let r=cn(e,n);if(!r)return null;let o=t.find((a)=>a.kind===r.kind&&a.slot===r.slot),i=j(e,r.kind)?.route;return o&&i?i.replace(":id",String(o.itemId)):null}function fn(e,t){if(!Array.isArray(t))return[];let n=new Map,r=new Set;for(let o of t){if(!o||typeof o!=="object")continue;let i=o,{kind:a,slot:s,itemId:l,title:g,donatedAt:p}=i;if(typeof a!=="string"||typeof s!=="number"||Y(e,a,s)===null)continue;if(typeof l!=="number"||!Number.isInteger(l)||l<=0)continue;let u=`${a}-slot-${s}`,f=`${a}#${l}`;if(n.has(u)||r.has(f))continue;n.set(u,{kind:a,slot:s,itemId:l,title:typeof g==="string"&&g.trim()?g:dt(e,a,{id:l}),donatedAt:typeof p==="number"&&Number.isFinite(p)&&p>0?p:0}),r.add(f)}return pt(e,[...n.values()])}function pt(e,t){let n=new Map(e.map((r,o)=>[r.name,o]));return[...t].sort((r,o)=>(n.get(r.kind)??0)-(n.get(o.kind)??0)||r.slot-o.slot)}function mn(e,t){let n=new Set(e.map((r)=>r.slot));for(let r=0;r<t;r++)if(!n.has(r))return r;return null}function gn(e){return e.reduce((t,n)=>!t||n.donatedAt<t.donatedAt?n:t,null)}function hn(){let e=globalThis.craft;return e&&typeof e==="object"?e.siri:void 0}var bn="stacks_spotlight_index",vn=3000;function uo(e){let t=e.onProblem??((b)=>console.warn(`[spotlight] ${b}`)),n=Array.isArray(e.kinds)?{kinds:[...e.kinds],problems:[]}:ct(e.kinds);for(let b of n.problems)t(b);let r=e.enabled===!1?[]:n.kinds,o=e.storageKey??bn,i=e.legacyStorageKeys??[],a=e.timeoutMs??vn,s=e.now??(()=>Date.now()),l=e.bridge??hn,g=null;function p(){try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function u(){if(g)return g;g=[];let b=p();if(!b)return g;try{let y=[o,...i].map((w)=>b.getItem(w)).find((w)=>w);g=y?fn(r,JSON.parse(y)):[]}catch{g=[]}return g}function f(b){g=b;let y=p();if(!y)return;try{y.setItem(o,JSON.stringify(b));for(let w of i)y.removeItem(w)}catch{}}async function d(b){if(!b)return null;let y;try{return await Promise.race([b,new Promise((w)=>{y=setTimeout(()=>w(null),a)})])}catch{return null}finally{if(y!==void 0)clearTimeout(y)}}let m=Promise.resolve();function h(b){let y=m.then(b,b);return m=y.catch(()=>{return}),y}async function k(b,y){let w=l()?.register;if(!w||r.length===0)return!1;return h(async()=>{let T=un(r,u(),b,y,s()),H=T&&Y(r,b,T.entry.slot);if(!T||!H)return!1;if(!T.changed)return f(T.entries),!0;let K=await d(w(T.entry.title,H))!==null;if(K)f(T.entries);return K})}async function C(b,y){let w=l()?.remove;if(!w)return!1;return h(async()=>{let{entries:T,removed:H}=dn(u(),b,y);if(!H)return!1;let K=Y(r,b,H.slot),St=K?await d(w(K))!==null:!1;return f(T),St})}async function F(b,y){let w=j(r,b)?.slots;if(!w||!l()?.register)return 0;let T=0;for(let H of[...y].slice(0,w).reverse())if(await k(b,H))T++;return T}async function x(){let b=l()?.remove;if(!b)return f([]),0;return h(async()=>{let y=0;for(let w of u()){let T=Y(r,w.kind,w.slot);if(T&&await d(b(T))!==null)y++}return f([]),y})}return{kinds:r,index:k,sync:F,remove:C,clear:x,routeFor:(b)=>pn(r,u(),b),entries:()=>u(),activityTypes:(b)=>ut(r).map((y)=>`${b}.${y}`),reset:()=>{g=null}}}var lt=["craftShortcut","craftSiriShortcut"];function po(e,t){let n=(r)=>{let o=r.detail,i=typeof o==="string"?o:o&&typeof o==="object"?o.action??o.type:null,a=typeof i==="string"?e.routeFor(i):null;if(a)t(a)};if(typeof globalThis.addEventListener!=="function")return()=>{};for(let r of lt)globalThis.addEventListener(r,n);return()=>{for(let r of lt)globalThis.removeEventListener(r,n)}}import{tabBar as yn}from"craft-native/mobile";var Sn=yn;function xn(e){return Array.from(e.querySelectorAll("a[data-native-tab]")).map((t)=>({id:t.getAttribute("href")||"",title:t.getAttribute("data-native-tab")||t.getAttribute("aria-label")||"",symbol:t.getAttribute("data-native-tab-symbol")||"circle",badge:(t.querySelector(".native-tab-badge")?.textContent||"").trim(),current:t.hasAttribute("data-stx-nav-current")||t.classList.contains("is-active")})).filter((t)=>t.id&&t.title)}function wn(e){return{tabs:e.map(({id:n,title:r,symbol:o,badge:i})=>i?{id:n,title:r,symbol:o,badge:i}:{id:n,title:r,symbol:o}),selected:e.find((n)=>n.current)?.id}}function mt(){if(typeof window>"u")return;let e=window.stxRouter;return e&&typeof e==="object"?e:void 0}function An(){return typeof mt()?.selectTab==="function"}function go(e,t={}){let n=(r)=>{if(An()||r.defaultPrevented)return;let o=r.target?.closest?.("a[data-native-tab]");if(!o||!e.contains(o))return;if(!o.hasAttribute("data-stx-nav-current")&&!o.classList.contains("is-active")&&o.getAttribute("aria-current")!=="page")return;r.preventDefault();let i=e.ownerDocument.defaultView;if(t.scrollToTop)t.scrollToTop();else i?.scrollTo?.({top:0,behavior:i.matchMedia?.("(prefers-reduced-motion: reduce)").matches?"auto":"smooth"});i?.dispatchEvent(new CustomEvent("stx:tabreselect",{detail:{href:o.getAttribute("href")||""}}))};return e.addEventListener("click",n),()=>e.removeEventListener("click",n)}function ft(e){let t=e.trim();return/^#[0-9a-f]{6}$/i.test(t)?t:void 0}var we="stacks:tab-bar-cover";function ho(e,t){if(t)e.setAttribute("data-native-covers-tab-bar","");else e.removeAttribute("data-native-covers-tab-bar");e.ownerDocument?.defaultView?.dispatchEvent(new Event(we))}function bo(e,t={}){let n=t.api??Sn;if(!n.isAvailable())return null;let r=t.hidden??(()=>Boolean(e.ownerDocument?.querySelector("[data-native-hide-tab-bar], [data-native-covers-tab-bar]"))),o=typeof getComputedStyle==="function"?getComputedStyle(e):null,i=ft(o?.getPropertyValue("--native-tab-active")||""),a=ft(o?.getPropertyValue("--native-tab-active-dark")||""),s="",l=()=>{if(r()){if(s!=="hidden")n.hide();s="hidden";return}let{tabs:f,selected:d}=wn(xn(e)),m=JSON.stringify({tabs:f,selected:d});if(m===s)return;let h=s&&s!=="hidden"?JSON.parse(s):null;if(h&&d&&JSON.stringify(h.tabs)===JSON.stringify(f))n.select(d);else n.set(f,{selected:d,tint:i,tintDark:a});s=m},g=typeof MutationObserver==="function"?new MutationObserver(l):null;g?.observe(e,{attributes:!0,attributeFilter:["data-stx-nav-current","class"],childList:!0,subtree:!0,characterData:!0});let p=n.onSelect((f)=>{let d=mt();if(d?.selectTab){d.selectTab(f);return}Array.from(e.querySelectorAll("a[data-native-tab]")).find((h)=>h.getAttribute("href")===f)?.click()}),u=()=>l();if(typeof window<"u")window.addEventListener("stx:load",u),window.addEventListener("stx:screen-shown",u),window.addEventListener(we,u);return l(),()=>{if(g?.disconnect(),p(),typeof window<"u")window.removeEventListener("stx:load",u),window.removeEventListener("stx:screen-shown",u),window.removeEventListener(we,u);n.hide()}}var Rn={isAvailable:()=>c(()=>Ae.isAvailable()),getBiometricType:()=>c(()=>Ae.getBiometricType()),authenticate:(e)=>c(()=>Ae.authenticate(e))},Ln={takePicture:(e)=>c(()=>oe.takePicture(e)),pickImage:()=>c(()=>oe.pickImage()),pickMultiple:(e)=>c(()=>oe.pickMultiple(e)),isAvailable:()=>c(()=>oe.isAvailable())},Mn={getInfo:()=>c(()=>D.getInfo()),getCapabilities:()=>c(()=>D.getCapabilities()),isMobile:()=>D.isMobile(),isIOS:()=>D.isIOS(),isAndroid:()=>D.isAndroid(),getLocale:()=>D.getLocale(),getTimezone:()=>D.getTimezone()},Pn=En,Cn={getCurrentPosition:(e)=>c(()=>N.getCurrentPosition(e)),watchPosition:(e,t)=>N.watchPosition(e,t),clearWatch:(e)=>N.clearWatch(e),startRecording:(e)=>c(()=>N.startRecording(e)),pauseRecording:()=>c(()=>N.pauseRecording()),resumeRecording:()=>c(()=>N.resumeRecording()),stopRecording:()=>c(()=>N.stopRecording()),getRecordingState:()=>c(()=>N.getRecordingState()),readRecording:()=>c(()=>N.readRecording())},On={show:(e)=>c(()=>ae.show(e)),schedule:(e)=>c(()=>ae.schedule(e)),cancelAll:()=>c(()=>ae.cancelAll()),setBadge:(e)=>c(()=>ae.setBadge(e))},Nn={check:(e)=>c(()=>G.check(e)),request:(e)=>c(()=>G.request(e)),checkMultiple:(e)=>c(()=>G.checkMultiple(e)),requestMultiple:(e)=>c(()=>G.requestMultiple(e)),openSettings:()=>c(()=>G.openSettings())},In={set:(e,t)=>c(()=>se.set(e,t)),get:(e)=>c(()=>se.get(e)),delete:(e)=>c(()=>se.delete(e)),clear:()=>c(()=>se.clear())},Hn={share:(e)=>c(()=>vt.share(e)),isAvailable:()=>vt.isAvailable()},_n={request:()=>c(()=>kn.request())},ce={impact:(e)=>Promise.resolve().then(()=>ie.impact(e)).catch(()=>{}),notification:(e)=>Promise.resolve().then(()=>ie.notification(e)).catch(()=>{}),selection:()=>Promise.resolve().then(()=>ie.selection()).catch(()=>{}),vibrate:(e)=>Promise.resolve().then(()=>ie.vibrate(e)).catch(()=>{}),prepare:(e)=>{let t=L("haptics.prepare");return t?Promise.resolve().then(()=>t(e)).then(()=>{},()=>{}):Promise.resolve()}};function yt(e){if(typeof e==="string")return e.trim()||null;if(!e||typeof e!=="object")return null;let t=e.url;return typeof t==="string"&&t.trim()?t:null}var Dn={async getInitialURL(){if(!await B())return null;return yt(await gt.getInitialURL?.())},onLink(e){let t=null,n=!1,r=()=>{if(n)return;t=gt.onLink?.((o,i)=>{let a=yt(o);if(a)e(a,{initial:i?.initial===!0})})??null};if(de()?.craft)r();else B().then(r);return()=>{n=!0,t?.()}}},wo={isAvailable:()=>le.isAvailable(),set:(e,t)=>le.set(e,t),remove:(e)=>le.remove(e),clear:()=>le.clear()},Bn={enable:()=>c(()=>ht.enable()),disable:()=>c(()=>ht.disable())},Fn={isAvailable:()=>re.isAvailable(),get:()=>c(()=>re.get()),set:(e)=>c(()=>re.set(e)),restore:()=>c(()=>re.restore())},Kn={isAvailable:()=>P.isAvailable(),supports:(e)=>P.supports(e),getAuthorizationStatus:()=>c(()=>P.getAuthorizationStatus()),requestAuthorization:()=>c(()=>P.requestAuthorization()),getNowPlaying:()=>c(()=>P.getNowPlaying()),play:()=>c(()=>P.play()),pause:()=>c(()=>P.pause()),togglePlayPause:()=>c(()=>P.togglePlayPause()),skipToNext:()=>c(()=>P.skipToNext()),skipToPrevious:(e)=>c(()=>P.skipToPrevious(e)),onChange:(e)=>_(()=>P.onChange(e))},$n={isAvailable:()=>A.isAvailable(),supports:(e)=>A.supports(e),getState:()=>c(()=>A.getState()),requestAuthorization:()=>c(()=>A.requestAuthorization()),scan:(e)=>c(()=>A.scan(e)),stopScan:()=>c(()=>A.stopScan()),getDevices:()=>c(()=>A.getDevices()),connect:(e)=>c(()=>A.connect(e)),reconnect:()=>c(()=>A.reconnect()),disconnect:(e)=>c(()=>A.disconnect(e)),startRecording:()=>c(()=>A.startRecording()),pauseRecording:()=>c(()=>A.pauseRecording()),resumeRecording:()=>c(()=>A.resumeRecording()),stopRecording:()=>c(()=>A.stopRecording()),getRecordingState:()=>c(()=>A.getRecordingState()),readRecording:(e)=>c(()=>A.readRecording(e)),onReading:(e)=>_(()=>A.onReading(e)),onDevice:(e)=>_(()=>A.onDevice(e)),onState:(e)=>_(()=>A.onState(e))},qn={isAvailable:()=>Te.isAvailable(),speak:(e,t)=>c(()=>Te.speak(e,t)),stop:()=>c(()=>Te.stop())},Un={getStatus:()=>c(()=>bt.getStatus()),onChange:(e)=>_(()=>bt.onChange(e))},Wn={register:()=>c(()=>Ee.register()),onToken:(e)=>Ee.onToken(e),onNotification:(e)=>_(()=>Ee.onNotification(e))},zn={requestAuthorization:(e,t)=>c(()=>V.requestAuthorization(e,t)),getData:(e,t)=>c(()=>V.getData(e,t)),saveWorkout:(e)=>c(()=>V.saveWorkout(e)),getWorkouts:(e)=>c(()=>V.getWorkouts(e)),getDailyStatistics:(e,t)=>c(()=>V.getDailyStatistics(e,t)),getHeartRateSamples:(e)=>v("health.getHeartRateSamples",[e??{}],()=>[]).then((t)=>Array.isArray(t)?t:[]),getSleepIntervals:(e)=>v("health.getSleepIntervals",[e??{}],()=>[]).then((t)=>Array.isArray(t)?t:[]),supports:(e)=>L(`health.${e}`)!==null},Yn={start:(e)=>c(()=>ke.start(e)),update:(e)=>c(()=>ke.update(e)),end:()=>c(()=>ke.end())},jn={send:(e)=>c(()=>X.send(e)),updateContext:(e)=>c(()=>X.updateContext(e)),isReachable:()=>c(()=>X.isReachable()),onMessage:(e)=>X.onMessage(e),onReachabilityChange:(e)=>X.onReachabilityChange(e)},Ao=Tn;function de(){return S()}function ue(){let e=de()?.craft;if(!e||typeof e!=="object")return null;if(!("platform"in e)||e.platform!=="ios"&&e.platform!=="android")return null;let t="capabilities"in e?e.capabilities:void 0,n=t&&typeof t==="object"&&!Array.isArray(t)?Object.fromEntries(Object.entries(t).filter(([,r])=>typeof r==="boolean")):{};return{platform:e.platform,capabilities:n}}function Re(){return ue()!==null}function Vn(e=2000){if(Re()||pe())return Promise.resolve(!0);let t=de();if(!t||!(t.craft||t.webkit?.messageHandlers?.craft))return Promise.resolve(!1);return new Promise((n)=>{let r=()=>{clearTimeout(o),t.removeEventListener("craftReady",r),n(Re())},o=setTimeout(r,e);t.addEventListener("craftReady",r,{once:!0})})}function Gn(e){let t=de();if(!t)return()=>{};if(ue()){let r=!1;return queueMicrotask(()=>{if(!r)e(new Event("craftReady"))}),()=>{r=!0}}let n=(r)=>{if(!ue())return;t.removeEventListener("craftReady",n),e(r)};return t.addEventListener("craftReady",n),()=>t.removeEventListener("craftReady",n)}async function Xn(e){await ce.impact("light");try{let t=await e();return await ce.notification("success"),t}catch(t){throw await ce.notification("error"),t}}var ko={get nativeBridge(){return ue()},biometrics:Rn,camera:Ln,device:Mn,haptics:ce,lifecycle:Pn,location:Cn,notifications:On,permissions:Nn,secureStorage:In,share:Hn,appReview:_n,deepLinks:Dn,keepAwake:Bn,brightness:Fn,music:Kn,heartRate:$n,speech:qn,network:Un,pushNotifications:Wn,health:zn,liveActivities:Yn,watchConnectivity:jn,dialog:q,contextMenu:ve,browser:Ke,symbols:$e,statusBar:Q,chrome:U,refresh:I,background:W,clipboard:qe,db:Ue,files:We,shortcuts:ze,widgets:Ye,orientation:je,auth:Ve,storeKit:Ge,isNativeMobile:Re,whenNative:Vn,onReady:Gn,withFeedback:Xn};export{Jn as BRIDGE_WAIT_MS,Hr as HEART_RATE_MATCH_MS,zr as INDOOR_CHECK_AFTER_S,lo as MAX_SPOTLIGHT_SLOTS_PER_KIND,Yt as ROUTE_GAP_S,Qr as SHEET_FLICK_VELOCITY,we as TAB_BAR_COVER_EVENT,c as afterBridge,_n as appReview,nn as applyAppearance,Wt as attachHeartRate,Ve as auth,Lr as backLabelFor,W as background,Rn as biometrics,J as bridgePending,Fn as brightness,Ke as browser,v as callNative,Ln as camera,Kt as canGoBack,U as chrome,qe as clipboard,or as confirmAction,ve as contextMenu,ho as coverTabBar,S as craftHost,xt as craftRoot,Br as createRouteRecorder,uo as createSpotlightIndex,Je as currentAppearance,Ue as db,qt as deepLinkPath,Dn as deepLinks,Mn as device,q as dialog,Rr as enterNavTrail,We as files,Vt as fixDistance,dr as focusSegment,Nr as followDeepLinks,ue as getNativeMobileBridge,Tr as goBack,Cr as goBackToTabRoot,go as handleTabReselect,ce as haptics,pe as hasNativeMobileHost,zn as health,$n as heartRate,Yr as indoorVerdict,ao as installNativeChrome,pr as installPressables,Re as isNativeMobile,Jt as isShown,Bn as keepAwake,Bt as largeTitleMetrics,Pn as lifecycle,to as liftToBody,Yn as liveActivities,Cn as location,eo as lockBackground,bo as mirrorTabBar,ko as mobile,Kn as music,kt as nativeFunction,L as nativeFunctionNow,wn as nativeTabs,Mr as navTrail,Un as network,It as normalizeAppearance,yt as normalizeDeepLinkURL,On as notifications,Ar as observeLargeTitle,lr as observeLongPress,Xr as observeNativeRefresh,_t as observePageScroll,wr as observePullToRefresh,cr as observeSegmentScrub,Zr as observeSheetDrag,Qe as onAppearance,yr as onBackgroundRefresh,O as onCraftEvent,br as onMemoryWarning,Gn as onMobileReady,hr as onResume,vr as onSilentPush,po as onSpotlightTap,je as orientation,_r as paceLabel,on as pageBackground,an as pageIsDark,z as pageScrollTop,$r as pauseSessionClock,Nn as permissions,Mt as placeMenu,un as placeSpotlightItem,Ie as presentActionSheet,Oe as presentAlert,fe as presentChoice,Ne as presentConfirm,He as presentContextMenu,no as presentPageAsCard,Pr as previousScreenPath,Dt as pullDistance,Wn as pushNotifications,fn as readSpotlightEntries,ct as readSpotlightKinds,xn as readTabLinks,I as refresh,dn as removeSpotlightItem,kr as resolveScrollHost,qr as resumeSessionClock,rt as routeStats,An as routerHandlesTabs,tn as rubberBand,In as secureStorage,Nt as segmentAt,ur as segmentForKey,Ur as sessionClockElapsed,en as settleSheet,Hn as share,Zt as sheetStops,ze as shortcuts,ir as showContextMenuFor,wo as snapshots,qn as speech,Dr as speedLabel,Ao as splash,Y as spotlightAction,ut as spotlightActions,co as spotlightActivityTypes,hn as spotlightBridge,j as spotlightKind,pn as spotlightRoute,cn as spotlightSlot,dt as spotlightTitle,Kr as startSessionClock,Q as statusBar,Ge as storeKit,_ as subscribeWhenReady,$e as symbols,Sn as tabBar,be as toNativeRect,Or as trailEntryFor,Lt as trapFocus,jr as typedDistanceKm,Gt as usableFixes,rr as useActionSheet,jn as watchConnectivity,B as whenBridgeReady,Vn as whenNativeMobile,Ye as widgets,Xn as withNativeFeedback};
|
package/dist/route.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import type { Location, LocationApi, LocationOptions, LocationRecordingState } from './types';
|
|
1
|
+
import type { HeartRateRecordingApi, HeartRateSample, Location, LocationApi, LocationOptions, LocationRecordingState } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The fixes with the heart rate of the reading nearest each one, when there
|
|
4
|
+
* is one within `maxGapMs`: a strap reads about once a second, a phone fixes
|
|
5
|
+
* about once a second, and neither waits for the other. A fix with no reading
|
|
6
|
+
* near it (the strap off, or not worn yet) keeps none.
|
|
7
|
+
*/
|
|
8
|
+
export declare function attachHeartRate<T extends RouteFix>(fixes: readonly T[], samples: readonly HeartRateSample[], maxGapMs?: unknown): T[];
|
|
2
9
|
/** Great-circle distance between two fixes, metres. */
|
|
3
10
|
export declare function fixDistance(a: { latitude: number, longitude: number }, b: { latitude: number, longitude: number }): number;
|
|
4
11
|
/** The fixes worth counting, oldest first: a known position, accurate enough. */
|
|
@@ -24,11 +31,14 @@ export declare function speedLabel(metresPerSecond: number | null | undefined):
|
|
|
24
31
|
* in front. Reading pauses with the page hidden; the recording does not.
|
|
25
32
|
*/
|
|
26
33
|
export declare function createRouteRecorder(options: RouteRecorderOptions): RouteRecorder;
|
|
34
|
+
/** A fix and a strap's reading further apart than this, ms, do not belong together. */
|
|
35
|
+
export declare const HEART_RATE_MATCH_MS: 5000;
|
|
27
36
|
/** Fixes further apart than this, seconds, are a break in the route (a pause). */
|
|
28
37
|
export declare const ROUTE_GAP_S: 30;
|
|
29
38
|
/** A fix as Craft records it. */
|
|
30
39
|
export declare interface RouteFix extends Location {
|
|
31
40
|
altitudeAccuracy?: number
|
|
41
|
+
heartRate?: number
|
|
32
42
|
}
|
|
33
43
|
export declare interface RouteStats {
|
|
34
44
|
distanceM: number
|
|
@@ -48,6 +58,7 @@ export declare interface RouteRecorderOptions extends RouteStatsOptions {
|
|
|
48
58
|
onUpdate?: (stats: RouteStats) => void
|
|
49
59
|
location: LocationApi
|
|
50
60
|
locationOptions?: LocationOptions
|
|
61
|
+
heartRate?: HeartRateRecordingApi
|
|
51
62
|
}
|
|
52
63
|
export declare interface RouteRecorder {
|
|
53
64
|
start: () => Promise<RouteStats>
|
|
@@ -58,4 +69,5 @@ export declare interface RouteRecorder {
|
|
|
58
69
|
refresh: () => Promise<RouteStats>
|
|
59
70
|
dispose: () => void
|
|
60
71
|
readonly stats: RouteStats
|
|
72
|
+
readonly heartRate: HeartRateSample[]
|
|
61
73
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export declare interface CraftMobileCapabilities {
|
|
|
22
22
|
orientationLock?: boolean
|
|
23
23
|
deepLinks?: boolean
|
|
24
24
|
flashlight?: boolean
|
|
25
|
+
music?: boolean
|
|
25
26
|
network?: boolean
|
|
26
27
|
deviceInfo?: boolean
|
|
27
28
|
badge?: boolean
|
|
@@ -68,6 +69,8 @@ export declare interface MobileApi {
|
|
|
68
69
|
deepLinks: DeepLinksApi
|
|
69
70
|
keepAwake: KeepAwakeApi
|
|
70
71
|
brightness: BrightnessApi
|
|
72
|
+
music: MusicApi
|
|
73
|
+
heartRate: HeartRateApi
|
|
71
74
|
speech: SpeechApi
|
|
72
75
|
network: NetworkApi
|
|
73
76
|
pushNotifications: PushNotificationsApi
|
|
@@ -257,6 +260,107 @@ export declare interface SpeechApi {
|
|
|
257
260
|
speak: (text: string, options?: SpeechOptions) => Promise<boolean>
|
|
258
261
|
stop: () => Promise<void>
|
|
259
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* What the Music app is playing. The song fields are null without access,
|
|
265
|
+
* with nothing queued, and while another app (Spotify, a podcast) plays; then
|
|
266
|
+
* `otherAudioPlaying` is true.
|
|
267
|
+
*/
|
|
268
|
+
export declare interface NowPlaying {
|
|
269
|
+
available: boolean
|
|
270
|
+
authorization: MusicAuthorization
|
|
271
|
+
source: 'appleMusic' | 'simulated' | null
|
|
272
|
+
playbackState: MusicPlaybackState
|
|
273
|
+
isPlaying: boolean
|
|
274
|
+
itemId: string | null
|
|
275
|
+
title: string | null
|
|
276
|
+
artist: string | null
|
|
277
|
+
album: string | null
|
|
278
|
+
duration: number | null
|
|
279
|
+
position: number | null
|
|
280
|
+
artworkDataURL: string | null
|
|
281
|
+
otherAudioPlaying: boolean
|
|
282
|
+
timestamp: number
|
|
283
|
+
}
|
|
284
|
+
export declare interface MusicSkipOptions {
|
|
285
|
+
restartAfter?: number
|
|
286
|
+
}
|
|
287
|
+
/** A heart-rate strap, or a watch broadcasting its heart rate. */
|
|
288
|
+
export declare interface HeartRateDevice {
|
|
289
|
+
id: string
|
|
290
|
+
name: string
|
|
291
|
+
rssi: number | null
|
|
292
|
+
}
|
|
293
|
+
export declare interface HeartRateRecordingState {
|
|
294
|
+
id: string | null
|
|
295
|
+
active: boolean
|
|
296
|
+
paused: boolean
|
|
297
|
+
startedAt: number | null
|
|
298
|
+
sampleCount: number | null
|
|
299
|
+
}
|
|
300
|
+
export declare interface HeartRateState {
|
|
301
|
+
available: boolean
|
|
302
|
+
bluetooth: BluetoothState
|
|
303
|
+
authorization: HeartRateAuthorization
|
|
304
|
+
scanning: boolean
|
|
305
|
+
connection: HeartRateConnection
|
|
306
|
+
device: HeartRateDevice | null
|
|
307
|
+
lastDevice: HeartRateDevice | null
|
|
308
|
+
bpm: number | null
|
|
309
|
+
lastReadingAt: number | null
|
|
310
|
+
recording: HeartRateRecordingState
|
|
311
|
+
}
|
|
312
|
+
export declare interface HeartRateReading {
|
|
313
|
+
bpm: number
|
|
314
|
+
rrIntervals: number[]
|
|
315
|
+
contact: boolean | null
|
|
316
|
+
energyExpended: number | null
|
|
317
|
+
timestamp: number
|
|
318
|
+
deviceId: string | null
|
|
319
|
+
}
|
|
320
|
+
/** A reading as a recording keeps it. */
|
|
321
|
+
export declare interface HeartRateSample {
|
|
322
|
+
timestamp: number
|
|
323
|
+
bpm: number
|
|
324
|
+
rr?: number[]
|
|
325
|
+
}
|
|
326
|
+
/** The recording half of HeartRateApi: what a route recorder drives. */
|
|
327
|
+
export declare interface HeartRateRecordingApi {
|
|
328
|
+
isAvailable: () => boolean
|
|
329
|
+
startRecording: () => Promise<HeartRateRecordingState>
|
|
330
|
+
pauseRecording: () => Promise<HeartRateRecordingState>
|
|
331
|
+
resumeRecording: () => Promise<HeartRateRecordingState>
|
|
332
|
+
stopRecording: () => Promise<HeartRateRecordingState & { samples: HeartRateSample[] }>
|
|
333
|
+
getRecordingState: () => Promise<HeartRateRecordingState>
|
|
334
|
+
readRecording: (options?: { since?: number }) => Promise<HeartRateSample[]>
|
|
335
|
+
}
|
|
336
|
+
export declare interface HeartRateApi extends HeartRateRecordingApi {
|
|
337
|
+
isAvailable: () => boolean
|
|
338
|
+
supports: (method: HeartRateMethod) => boolean
|
|
339
|
+
getState: () => Promise<HeartRateState>
|
|
340
|
+
requestAuthorization: () => Promise<HeartRateAuthorization>
|
|
341
|
+
scan: (options?: { timeout?: number }) => Promise<HeartRateState>
|
|
342
|
+
stopScan: () => Promise<HeartRateState>
|
|
343
|
+
getDevices: () => Promise<HeartRateDevice[]>
|
|
344
|
+
connect: (id: string) => Promise<HeartRateState>
|
|
345
|
+
reconnect: () => Promise<HeartRateState>
|
|
346
|
+
disconnect: (options?: { forget?: boolean }) => Promise<HeartRateState>
|
|
347
|
+
onReading: (callback: (reading: HeartRateReading) => void) => () => void
|
|
348
|
+
onDevice: (callback: (device: HeartRateDevice) => void) => () => void
|
|
349
|
+
onState: (callback: (state: HeartRateState) => void) => () => void
|
|
350
|
+
}
|
|
351
|
+
export declare interface MusicApi {
|
|
352
|
+
isAvailable: () => boolean
|
|
353
|
+
supports: (method: MusicMethod) => boolean
|
|
354
|
+
getAuthorizationStatus: () => Promise<MusicAuthorization>
|
|
355
|
+
requestAuthorization: () => Promise<MusicAuthorization>
|
|
356
|
+
getNowPlaying: () => Promise<NowPlaying>
|
|
357
|
+
play: () => Promise<NowPlaying>
|
|
358
|
+
pause: () => Promise<NowPlaying>
|
|
359
|
+
togglePlayPause: () => Promise<NowPlaying>
|
|
360
|
+
skipToNext: () => Promise<NowPlaying>
|
|
361
|
+
skipToPrevious: (options?: MusicSkipOptions) => Promise<NowPlaying>
|
|
362
|
+
onChange: (callback: (nowPlaying: NowPlaying) => void) => () => void
|
|
363
|
+
}
|
|
260
364
|
export declare interface DeepLinksApi {
|
|
261
365
|
getInitialURL: () => Promise<string | null>
|
|
262
366
|
onLink: (callback: (url: string, link?: { initial: boolean }) => void) => () => void
|
|
@@ -427,6 +531,18 @@ export type PermissionStatus = 'granted' | 'denied' | 'undetermined' | 'restrict
|
|
|
427
531
|
export type BiometricType = 'faceId' | 'touchId' | 'fingerprint' | 'face' | 'iris' | 'none';
|
|
428
532
|
export type AppState = 'active' | 'inactive' | 'background';
|
|
429
533
|
export type HapticKind = 'impact' | 'notification' | 'selection';
|
|
534
|
+
/** Whether the person has let the app see their music. `unavailable` off a phone. */
|
|
535
|
+
export type MusicAuthorization = 'authorized' | 'denied' | 'restricted' | 'notDetermined' | 'unavailable';
|
|
536
|
+
export type MusicPlaybackState = 'stopped' | 'playing' | 'paused' | 'interrupted' | 'seekingForward' | 'seekingBackward' | 'unknown';
|
|
537
|
+
export type MusicMethod = 'getAuthorizationStatus' | 'requestAuthorization' | 'getNowPlaying' | 'play' | 'pause' | 'togglePlayPause' | 'skipToNext' | 'skipToPrevious' | 'observe';
|
|
538
|
+
/** Whether the person has let the app use Bluetooth. `unavailable` off a phone. */
|
|
539
|
+
export type HeartRateAuthorization = 'authorized' | 'denied' | 'restricted' | 'notDetermined' | 'unavailable';
|
|
540
|
+
/** The phone's Bluetooth radio; `unknown` until something has asked for it. */
|
|
541
|
+
export type BluetoothState = 'poweredOn' | 'poweredOff' | 'unauthorized' | 'unsupported' | 'resetting' | 'unknown';
|
|
542
|
+
/** A strap that drops out is asked for again (`reconnecting`) until `disconnect()`. */
|
|
543
|
+
export type HeartRateConnection = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
|
|
544
|
+
export type HeartRateMethod = 'getState' | 'requestAuthorization' | 'scan' | 'stopScan' | 'getDevices' | 'connect' | 'reconnect' | 'disconnect'
|
|
545
|
+
| 'startRecording' | 'pauseRecording' | 'resumeRecording' | 'stopRecording' | 'getRecordingState' | 'readRecording';
|
|
430
546
|
export type HealthDataType = | 'steps'
|
|
431
547
|
| 'heartRate'
|
|
432
548
|
| 'activeEnergy'
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/mobile",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.155",
|
|
6
6
|
"description": "Craft-powered native mobile runtime for Stacks and STX applications",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"license": "MIT",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"test": "bun test"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"craft-native": ">=0.0.
|
|
35
|
+
"craft-native": ">=0.0.152"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@stacksjs/build": "0.75.
|
|
38
|
+
"@stacksjs/build": "0.75.155",
|
|
39
39
|
"better-dx": "^0.2.24"
|
|
40
40
|
}
|
|
41
41
|
}
|