@stacksjs/defaults 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.
@@ -201,6 +201,70 @@ every render would put a record straight back the moment they left it. Donating
201
201
  the same record twice is free, so an effect over the record is the natural call
202
202
  site.
203
203
 
204
+ ## Heart-rate strap (Bluetooth)
205
+
206
+ `heartRate` reads a Bluetooth heart-rate strap (Polar, Garmin, Wahoo), or a
207
+ watch broadcasting its heart rate, through the standard Heart Rate Service.
208
+ `scan` finds straps nearby (`onDevice` hears each), `connect(id)` subscribes
209
+ to its readings (`onReading`: bpm and RR intervals, about once a second) and
210
+ remembers it, so `reconnect()` finds it next time without a scan; a strap that
211
+ drops out is asked for again until `disconnect()`. `startRecording()` keeps
212
+ every reading natively, screen locked or app closed, until `stopRecording()`
213
+ hands them back. iOS only, behind `capabilities.heartRate` (which adds the
214
+ `bluetooth-central` background mode); Bluetooth needs no network.
215
+
216
+ ```ts
217
+ import { createRouteRecorder, heartRate, location } from '@stacksjs/mobile'
218
+
219
+ const stop = heartRate.onDevice(device => list.push(device)) // { id, name, rssi }
220
+ await heartRate.scan({ timeout: 15 }) // can show iOS's Bluetooth prompt
221
+ await heartRate.connect(list[0].id) // rejects TIMEOUT while still asking
222
+ heartRate.onReading(reading => show(reading.bpm))
223
+
224
+ // With a route: the strap records with it, and each fix gets its heart rate.
225
+ const recorder = createRouteRecorder({ location, heartRate })
226
+ await recorder.start()
227
+ const fixes = await recorder.stop() // fixes[i].heartRate
228
+ const samples = recorder.heartRate // every reading: { timestamp, bpm, rr? }
229
+ ```
230
+
231
+ Without a route, record it on its own (`heartRate.startRecording()` /
232
+ `stopRecording()`), and `attachHeartRate(fixes, samples)` pairs readings
233
+ with fixes recorded separately. In a browser and on Android `isAvailable()` is
234
+ false, the state says `available: false` and nothing fires. Word iOS's prompt
235
+ with `ios.usageDescriptions.NSBluetoothAlwaysUsageDescription`.
236
+
237
+ ## Apple Music (now playing)
238
+
239
+ `music` shows what the Music app is playing (title, artist, album, a small
240
+ artwork data URL, duration, position, playback state) and steers it: `play`,
241
+ `pause`, `togglePlayPause`, `skipToNext` and `skipToPrevious`, which restarts
242
+ the song a few seconds in, like the Music app's own button. Changes arrive
243
+ from native as they happen, so a page never polls. iOS only, behind
244
+ `capabilities.appleMusic`; music control is local to the phone, so it works
245
+ offline.
246
+
247
+ ```ts
248
+ import { music } from '@stacksjs/mobile'
249
+
250
+ // From the person's tap, never on load: iOS shows its prompt the first time.
251
+ if (await music.requestAuthorization() === 'authorized') {
252
+ render(await music.getNowPlaying())
253
+ const stop = music.onChange(render) // observes while anyone listens
254
+ await music.togglePlayPause()
255
+ }
256
+ ```
257
+
258
+ Only Apple Music: iOS gives no app the controls of another player, Spotify
259
+ included, so while one plays the song fields are null and `otherAudioPlaying`
260
+ is true; say so rather than show controls that do nothing. Nothing is read
261
+ before access is allowed (`authorization` is `notDetermined`, `denied` or
262
+ `restricted` until then). In a browser and on Android `isAvailable()` is false,
263
+ every call answers `{ available: false }` and `onChange` never fires. Word the
264
+ prompt with `ios.usageDescriptions.NSAppleMusicUsageDescription`. The
265
+ simulator's Music app has nothing to play; launch a simulator build with
266
+ `-CraftFakeMusicPlayer YES` for three made-up songs that play and skip.
267
+
204
268
  ## Runtime API
205
269
 
206
270
  ```ts
@@ -60,7 +60,7 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
60
60
  | `@stacksjs/image` | [`stacks-image`](../stacks-image/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/image/src/index.ts) | 2 |
61
61
  | `@stacksjs/lint` | [`stacks-lint`](../stacks-lint/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/lint/src/index.ts) | 3 |
62
62
  | `@stacksjs/logging` | [`stacks-logging`](../stacks-logging/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/logging/src/index.ts) | 14 |
63
- | `@stacksjs/mobile` | [`stacks-mobile`](../stacks-mobile/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/index.ts) | 13 |
63
+ | `@stacksjs/mobile` | [`stacks-mobile`](../stacks-mobile/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/index.ts) | 15 |
64
64
  | `@stacksjs/model-meta` | [`stacks-models`](../stacks-models/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/model-meta/src/index.ts) | 1 |
65
65
  | `@stacksjs/newsletter` | [`stacks-newsletter`](../stacks-newsletter/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/index.ts) | 7 |
66
66
  | `@stacksjs/notifications` | [`stacks-notifications`](../stacks-notifications/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/notifications/src/index.ts) | 14 |
@@ -579,11 +579,11 @@ Evidence directory: [14 retained tests](https://github.com/stacksjs/stacks/blob/
579
579
 
580
580
  Guidance: [`stacks-mobile`](../stacks-mobile/SKILL.md). Source: [storage/framework/core/mobile/src/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/index.ts).
581
581
 
582
- Declared runtime exports: `appReview`, `biometrics`, `brightness`, `camera`, `deepLinks`, `device`, `getNativeMobileBridge`, `haptics`, `health`, `isNativeMobile`, `keepAwake`, `lifecycle`, `liveActivities`, `location`, `mobile`, `network`, `normalizeDeepLinkURL`, `notifications`, `onMobileReady`, `permissions`, `pushNotifications`, `secureStorage`, `share`, `snapshots`, `speech`, `splash`, `watchConnectivity`, `whenNativeMobile`, `withNativeFeedback`.
582
+ Declared runtime exports: `appReview`, `biometrics`, `brightness`, `camera`, `deepLinks`, `device`, `getNativeMobileBridge`, `haptics`, `health`, `heartRate`, `isNativeMobile`, `keepAwake`, `lifecycle`, `liveActivities`, `location`, `mobile`, `music`, `network`, `normalizeDeepLinkURL`, `notifications`, `onMobileReady`, `permissions`, `pushNotifications`, `secureStorage`, `share`, `snapshots`, `speech`, `splash`, `watchConnectivity`, `whenNativeMobile`, `withNativeFeedback`.
583
583
 
584
584
  Local source modules: [src/bridge.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/bridge.ts), [src/controls.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/controls.ts), [src/events.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/events.ts), [src/gestures.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/gestures.ts), [src/indoor.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/indoor.ts), [src/native.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/native.ts), [src/navigation.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/navigation.ts), [src/refresh-control.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/refresh-control.ts), [src/route.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/route.ts), [src/session-clock.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/session-clock.ts), [src/sheet-gesture.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/sheet-gesture.ts), [src/sheets.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/sheets.ts), [src/shell.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/shell.ts), [src/spotlight.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/spotlight.ts), [src/tab-bar.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/tab-bar.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/src/types.ts).
585
585
 
586
- Evidence directory: [13 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
586
+ Evidence directory: [15 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/mobile/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
587
587
 
588
588
  ### @stacksjs/model-meta
589
589
 
@@ -2,7 +2,7 @@
2
2
  "publisher": "Stacks",
3
3
  "name": "vscode-stacks",
4
4
  "displayName": "Stacks",
5
- "version": "0.75.153",
5
+ "version": "0.75.155",
6
6
  "description": "Stacks, built into VS Code: stx templates, pickier linting and formatting, encrypted env files, the dev server preview and every buddy command. No other extensions required.",
7
7
  "license": "MIT",
8
8
  "funding": "https://github.com/sponsors/chrisbbreuer",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/defaults",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.153",
5
+ "version": "0.75.155",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/stacksjs/stacks.git",
@@ -55,7 +55,7 @@
55
55
  "dependencies": {
56
56
  "@iconify-json/f7": "^1.2.2",
57
57
  "@iconify-json/hugeicons": "^1.2.35",
58
- "@stacksjs/mobile": "0.75.153",
58
+ "@stacksjs/mobile": "0.75.155",
59
59
  "@stacksjs/sanitizer": "^0.2.483",
60
60
  "@xterm/addon-fit": "^0.11.0",
61
61
  "@xterm/xterm": "^6.0.0",