@symbiote-native/battery 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +101 -28
  2. package/build/angular/index.d.ts +1 -1
  3. package/build/angular/index.js +1 -1
  4. package/build/angular/services/battery-level.service/index.js +1 -1
  5. package/build/angular/services/battery-state.service/index.js +2 -2
  6. package/build/angular/services/low-power-mode.service/index.js +2 -2
  7. package/build/react/hooks/use-battery-state/index.js +1 -1
  8. package/build/react/hooks/use-low-power-mode/index.js +1 -1
  9. package/build/react/index.d.ts +1 -1
  10. package/build/react/index.js +1 -1
  11. package/build/solid/index.d.ts +4 -0
  12. package/build/solid/index.js +10 -0
  13. package/build/solid/primitives/create-battery-level.d.ts +2 -0
  14. package/build/solid/primitives/create-battery-level.js +35 -0
  15. package/build/solid/primitives/create-battery-state.d.ts +3 -0
  16. package/build/solid/primitives/create-battery-state.js +21 -0
  17. package/build/solid/primitives/create-low-power-mode.d.ts +2 -0
  18. package/build/solid/primitives/create-low-power-mode.js +21 -0
  19. package/build/svelte/index.d.ts +4 -0
  20. package/build/svelte/index.js +9 -0
  21. package/build/svelte/runes/use-battery-level.svelte.d.ts +3 -0
  22. package/build/svelte/runes/use-battery-level.svelte.js +37 -0
  23. package/build/svelte/runes/use-battery-state.svelte.d.ts +4 -0
  24. package/build/svelte/runes/use-battery-state.svelte.js +22 -0
  25. package/build/svelte/runes/use-low-power-mode.svelte.d.ts +3 -0
  26. package/build/svelte/runes/use-low-power-mode.svelte.js +22 -0
  27. package/build/vue/index.d.ts +1 -1
  28. package/build/vue/index.js +1 -1
  29. package/build-ngc/angular/index.d.ts +1 -1
  30. package/build-ngc/angular/index.js +1 -1
  31. package/build-ngc/angular/index.js.map +1 -1
  32. package/build-ngc/angular/services/battery-level.service/index.js +4 -4
  33. package/build-ngc/angular/services/battery-level.service/index.js.map +1 -1
  34. package/build-ngc/angular/services/battery-state.service/index.js +5 -5
  35. package/build-ngc/angular/services/battery-state.service/index.js.map +1 -1
  36. package/build-ngc/angular/services/low-power-mode.service/index.js +5 -5
  37. package/build-ngc/angular/services/low-power-mode.service/index.js.map +1 -1
  38. package/build-ngc/core/native-module.js.map +1 -1
  39. package/package.json +42 -14
  40. package/src/angular/index.ts +1 -17
  41. package/src/angular/services/battery-level.service/index.ts +11 -2
  42. package/src/angular/services/battery-state.service/index.ts +16 -3
  43. package/src/angular/services/low-power-mode.service/index.ts +15 -3
  44. package/src/core/native-module.ts +9 -2
  45. package/src/react/hooks/use-battery-level/index.ts +3 -1
  46. package/src/react/hooks/use-battery-state/index.ts +11 -3
  47. package/src/react/hooks/use-low-power-mode/index.ts +7 -2
  48. package/src/react/index.ts +1 -17
  49. package/src/solid/index.ts +11 -0
  50. package/src/solid/primitives/create-battery-level.ts +45 -0
  51. package/src/solid/primitives/create-battery-state.ts +33 -0
  52. package/src/solid/primitives/create-low-power-mode.ts +30 -0
  53. package/src/svelte/index.ts +10 -0
  54. package/src/svelte/runes/use-battery-level.svelte.ts +45 -0
  55. package/src/svelte/runes/use-battery-state.svelte.ts +30 -0
  56. package/src/svelte/runes/use-low-power-mode.svelte.ts +29 -0
  57. package/src/svelte/svelte-ambient.d.ts +6 -0
  58. package/src/vue/index.ts +1 -17
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Port of [`expo-battery`](https://docs.expo.dev/versions/latest/sdk/battery/) for
4
4
  [SymbioteNative](../../README.md) — battery level and state, low-power-mode detection, reachable
5
- from every adapter (React, Vue, Angular), not just React.
5
+ from every adapter (React, Vue, Svelte, Solid, Angular), not just React.
6
6
 
7
7
  Built the same way as [`@symbiote-native/local-auth`](../local-auth) and
8
8
  [`@symbiote-native/sensors`](../sensors), an `expo-modules-core`-based wrapper (see the
@@ -29,12 +29,12 @@ Unlike a plain RN native module, `expo-battery`'s native code is discovered by
29
29
  into the native host app **once**, covering this package and every other `expo-modules-core`
30
30
  package (`@symbiote-native/sensors`, `@symbiote-native/local-auth`) with zero further changes:
31
31
 
32
- | Platform | Touches |
33
- |---|---|
34
- | iOS | `ios/Podfile` — add `use_expo_modules!` |
35
- | iOS | `AppDelegate.swift` — Expo's runtime-bootstrap hook |
36
- | Android | `settings.gradle` / `app/build.gradle` — resolve and include the Expo Gradle projects |
37
- | Android | `MainApplication.kt` — Expo's bootstrap hook, plus a hand-written native-module name map (there's no `expo` meta-package here to auto-generate one) |
32
+ | Platform | Touches |
33
+ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
34
+ | iOS | `ios/Podfile` — add `use_expo_modules!` |
35
+ | iOS | `AppDelegate.swift` — Expo's runtime-bootstrap hook |
36
+ | Android | `settings.gradle` / `app/build.gradle` — resolve and include the Expo Gradle projects |
37
+ | Android | `MainApplication.kt` — Expo's bootstrap hook, plus a hand-written native-module name map (there's no `expo` meta-package here to auto-generate one) |
38
38
 
39
39
  Full mechanics — the Podfile pieces that normally ship inside the `expo` package, the `expo`
40
40
  peer-dependency exclusion list — live in the `symbiote-expo-native-module` skill. Reference
@@ -55,33 +55,44 @@ src/core/ Battery.ts — one-shot get*Async functions + addListene
55
55
  src/react/hooks/ @symbiote-native/battery/react — useBatteryLevel, useBatteryState,
56
56
  useLowPowerMode
57
57
  src/vue/composables/ @symbiote-native/battery/vue — same three names, Vue lifecycle
58
+ src/svelte/runes/ @symbiote-native/battery/svelte — same three names, read as `.current`
59
+ src/solid/primitives/ @symbiote-native/battery/solid — createBatteryLevel, createBatteryState,
60
+ createLowPowerMode (each returns an Accessor)
58
61
  src/angular/services/ @symbiote-native/battery/angular — BatteryLevelService, BatteryStateService,
59
62
  LowPowerModeService (`.connect()` returns a Signal)
60
63
  ```
61
64
 
62
- Each adapter's hook/composable/service is a thin lifecycle wrapper (seed from the one-shot
63
- `get*Async` call, subscribe to the matching listener, unsubscribe on unmount/cleanup) over the
64
- same `core` functions — the subscription and fallback logic is written once and shared by all
65
- three.
65
+ Each adapter's hook/composable/rune/primitive/service is a thin lifecycle wrapper (seed from the
66
+ one-shot `get*Async` call, subscribe to the matching listener, unsubscribe on unmount/cleanup)
67
+ over the same `core` functions — the subscription and fallback logic is written once and shared
68
+ by every adapter. Solid's naming differs on purpose: `create*`, not `use*`, which Solid reserves
69
+ for consuming something that already exists.
66
70
 
67
71
  ## Use it
68
72
 
69
73
  ```tsx
70
74
  // React — examples/expo-react/screens/BatteryScreen.tsx
71
- import { useBatteryLevel, useBatteryState, useLowPowerMode } from '@symbiote-native/battery/react';
75
+ import {
76
+ useBatteryLevel,
77
+ useBatteryState,
78
+ useLowPowerMode,
79
+ } from '@symbiote-native/battery/react';
72
80
  import { BatteryState } from '@symbiote-native/battery';
73
81
 
74
82
  function BatteryScreen() {
75
- const batteryLevel = useBatteryLevel(); // number, -1 until the first reading arrives
76
- const batteryState = useBatteryState(); // BatteryState, UNKNOWN until the first reading
77
- const lowPowerMode = useLowPowerMode(); // boolean, false until the first reading
83
+ const batteryLevel = useBatteryLevel(); // number, -1 until the first reading arrives
84
+ const batteryState = useBatteryState(); // BatteryState, UNKNOWN until the first reading
85
+ const lowPowerMode = useLowPowerMode(); // boolean, false until the first reading
78
86
 
79
- const batteryLevelLabel = batteryLevel < 0 ? 'unknown' : `${Math.round(batteryLevel * 100)}%`;
87
+ const batteryLevelLabel =
88
+ batteryLevel < 0 ? 'unknown' : `${Math.round(batteryLevel * 100)}%`;
80
89
 
81
90
  return (
82
91
  <>
83
92
  <Text>{batteryLevelLabel}</Text>
84
- <Text>{batteryState === BatteryState.CHARGING ? 'Charging' : 'Not charging'}</Text>
93
+ <Text>
94
+ {batteryState === BatteryState.CHARGING ? 'Charging' : 'Not charging'}
95
+ </Text>
85
96
  <Text>{lowPowerMode ? 'On' : 'Off'}</Text>
86
97
  </>
87
98
  );
@@ -92,14 +103,20 @@ function BatteryScreen() {
92
103
  <!-- Vue — examples/expo-vue-sfc/screens/BatteryScreen.vue -->
93
104
  <script setup lang="ts">
94
105
  import { computed } from 'vue';
95
- import { useBatteryLevel, useBatteryState, useLowPowerMode } from '@symbiote-native/battery/vue';
106
+ import {
107
+ useBatteryLevel,
108
+ useBatteryState,
109
+ useLowPowerMode,
110
+ } from '@symbiote-native/battery/vue';
96
111
 
97
112
  const batteryLevel = useBatteryLevel(); // Ref<number>
98
113
  const batteryState = useBatteryState(); // Ref<BatteryState>
99
114
  const lowPowerMode = useLowPowerMode(); // Ref<boolean>
100
115
 
101
116
  const batteryLevelText = computed(() =>
102
- batteryLevel.value < 0 ? 'unknown' : `${Math.round(batteryLevel.value * 100)}%`,
117
+ batteryLevel.value < 0
118
+ ? 'unknown'
119
+ : `${Math.round(batteryLevel.value * 100)}%`,
103
120
  );
104
121
  </script>
105
122
  <template>
@@ -108,16 +125,51 @@ const batteryLevelText = computed(() =>
108
125
  </template>
109
126
  ```
110
127
 
128
+ ```tsx
129
+ // Solid — an accessor per value; call it to read, so a component body that runs once still
130
+ // re-renders the leaf that reads it.
131
+ import {
132
+ createBatteryLevel,
133
+ createBatteryState,
134
+ createLowPowerMode,
135
+ } from '@symbiote-native/battery/solid';
136
+ import { BatteryState } from '@symbiote-native/battery';
137
+
138
+ function BatteryScreen() {
139
+ const batteryLevel = createBatteryLevel(); // Accessor<number>, -1 until the first reading
140
+ const batteryState = createBatteryState(); // Accessor<BatteryState>
141
+ const lowPowerMode = createLowPowerMode(); // Accessor<boolean>
142
+
143
+ return (
144
+ <>
145
+ <Text>
146
+ {batteryLevel() < 0
147
+ ? 'unknown'
148
+ : `${Math.round(batteryLevel() * 100)}%`}
149
+ </Text>
150
+ <Text>
151
+ {batteryState() === BatteryState.CHARGING ? 'Charging' : 'Not charging'}
152
+ </Text>
153
+ <Text>{lowPowerMode() ? 'On' : 'Off'}</Text>
154
+ </>
155
+ );
156
+ }
157
+ ```
158
+
111
159
  ```ts
112
160
  // Angular — examples/expo-angular/src/screens/BatteryScreen.ts
113
161
  import { Component, inject } from '@angular/core';
114
- import { BatteryLevelService, BatteryStateService, LowPowerModeService } from '@symbiote-native/battery/angular';
162
+ import {
163
+ BatteryLevelService,
164
+ BatteryStateService,
165
+ LowPowerModeService,
166
+ } from '@symbiote-native/battery/angular';
115
167
 
116
- @Component({ /* ... */ })
168
+ @Component({/* ... */})
117
169
  export class BatteryScreen {
118
- readonly batteryLevel = inject(BatteryLevelService).connect(); // Signal<number>
119
- readonly batteryState = inject(BatteryStateService).connect(); // Signal<BatteryState>
120
- readonly lowPowerMode = inject(LowPowerModeService).connect(); // Signal<boolean>
170
+ readonly batteryLevel = inject(BatteryLevelService).connect(); // Signal<number>
171
+ readonly batteryState = inject(BatteryStateService).connect(); // Signal<BatteryState>
172
+ readonly lowPowerMode = inject(LowPowerModeService).connect(); // Signal<boolean>
121
173
 
122
174
  batteryLevelLabel(): string {
123
175
  const level = this.batteryLevel();
@@ -156,12 +208,33 @@ Plus `BatteryState` (enum), `PowerState`, `BatteryLevelEvent`, `BatteryStateEven
156
208
  `PowerModeEvent` — ported from upstream's `Battery.types.ts`.
157
209
 
158
210
  ```ts
159
- import { getBatteryLevelAsync, addBatteryLevelListener } from '@symbiote-native/battery';
211
+ import {
212
+ getBatteryLevelAsync,
213
+ addBatteryLevelListener,
214
+ } from '@symbiote-native/battery';
160
215
 
161
216
  // framework-scoped entry points re-export the same free functions, plus a lifecycle
162
217
  // hook/composable/service per listener:
163
- import { useBatteryLevel, useBatteryState, useLowPowerMode } from '@symbiote-native/battery/react';
164
- import { useBatteryLevel, useBatteryState, useLowPowerMode } from '@symbiote-native/battery/vue';
218
+ import {
219
+ useBatteryLevel,
220
+ useBatteryState,
221
+ useLowPowerMode,
222
+ } from '@symbiote-native/battery/react';
223
+ import {
224
+ useBatteryLevel,
225
+ useBatteryState,
226
+ useLowPowerMode,
227
+ } from '@symbiote-native/battery/vue';
228
+ import {
229
+ useBatteryLevel,
230
+ useBatteryState,
231
+ useLowPowerMode,
232
+ } from '@symbiote-native/battery/svelte';
233
+ import {
234
+ createBatteryLevel,
235
+ createBatteryState,
236
+ createLowPowerMode,
237
+ } from '@symbiote-native/battery/solid';
165
238
  import {
166
239
  BatteryLevelService,
167
240
  BatteryStateService,
@@ -179,7 +252,7 @@ unsubscribes on unmount — mirroring upstream's own `useBatteryLevel`/`useBatte
179
252
  No Fabric/Descriptor angle at all — battery is a pure async-function + `EventEmitter` listener
180
253
  surface, never a view. Tests inject a fake native-module object in place of the real
181
254
  `requireNativeModule` resolution (`src/core/battery.test.ts`,
182
- `src/{react,vue,angular}/**/*.test.{ts,tsx}`, `vitest`), the same pattern
255
+ `src/{react,vue,svelte,solid,angular}/**/*.test.{ts,tsx}`, `vitest`), the same pattern
183
256
  `@symbiote-native/sensors` and `@symbiote-native/local-auth` use — no `installFabric()`, no
184
257
  ViewConfig. Native rendering itself is verified on-device — see the parent
185
258
  [README](../../README.md).
@@ -1,4 +1,4 @@
1
1
  export { BatteryLevelService } from './services/battery-level.service';
2
2
  export { BatteryStateService } from './services/battery-state.service';
3
3
  export { LowPowerModeService } from './services/low-power-mode.service';
4
- export { isAvailableAsync, getBatteryLevelAsync, getBatteryStateAsync, isLowPowerModeEnabledAsync, isBatteryOptimizationEnabledAsync, getPowerStateAsync, addBatteryLevelListener, addBatteryStateListener, addLowPowerModeListener, BatteryState, type PowerState, type BatteryLevelEvent, type BatteryStateEvent, type PowerModeEvent, type EventSubscription, } from '../core';
4
+ export * from '../core';
@@ -5,4 +5,4 @@
5
5
  export { BatteryLevelService } from './services/battery-level.service/index.js';
6
6
  export { BatteryStateService } from './services/battery-state.service/index.js';
7
7
  export { LowPowerModeService } from './services/low-power-mode.service/index.js';
8
- export { isAvailableAsync, getBatteryLevelAsync, getBatteryStateAsync, isLowPowerModeEnabledAsync, isBatteryOptimizationEnabledAsync, getPowerStateAsync, addBatteryLevelListener, addBatteryStateListener, addLowPowerModeListener, BatteryState, } from '../core/index.js';
8
+ export * from '../core/index.js';
@@ -32,7 +32,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
32
32
  }
33
33
  return useValue ? value : void 0;
34
34
  };
35
- import { effect, inject, Injectable, Injector, signal } from '@angular/core';
35
+ import { effect, inject, Injectable, Injector, signal, } from '@angular/core';
36
36
  import { addBatteryLevelListener, getBatteryLevelAsync } from '../../../core/index.js';
37
37
  // Angular twin of React's `useBatteryLevel` hook and Vue's `useBatteryLevel` composable.
38
38
  // Angular has no per-instance hook — state and lifecycle live in DI instead, so `connect()`
@@ -32,8 +32,8 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
32
32
  }
33
33
  return useValue ? value : void 0;
34
34
  };
35
- import { effect, inject, Injectable, Injector, signal } from '@angular/core';
36
- import { addBatteryStateListener, BatteryState, getBatteryStateAsync } from '../../../core/index.js';
35
+ import { effect, inject, Injectable, Injector, signal, } from '@angular/core';
36
+ import { addBatteryStateListener, BatteryState, getBatteryStateAsync, } from '../../../core/index.js';
37
37
  // Angular twin of React's `useBatteryState` hook and Vue's `useBatteryState` composable. See
38
38
  // BatteryLevelService for the `connect()` pattern rationale.
39
39
  //
@@ -32,8 +32,8 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
32
32
  }
33
33
  return useValue ? value : void 0;
34
34
  };
35
- import { effect, inject, Injectable, Injector, signal } from '@angular/core';
36
- import { addLowPowerModeListener, isLowPowerModeEnabledAsync } from '../../../core/index.js';
35
+ import { effect, inject, Injectable, Injector, signal, } from '@angular/core';
36
+ import { addLowPowerModeListener, isLowPowerModeEnabledAsync, } from '../../../core/index.js';
37
37
  // Angular twin of React's `useLowPowerMode` hook and Vue's `useLowPowerMode` composable. See
38
38
  // BatteryLevelService for the `connect()` pattern rationale.
39
39
  //
@@ -2,7 +2,7 @@
2
2
  // use-battery-level's shape. Seeds the initial value with a one-shot getBatteryStateAsync()
3
3
  // call before the first native event fires, matching upstream's own useBatteryState.
4
4
  import { useEffect, useState } from 'react';
5
- import { addBatteryStateListener, BatteryState, getBatteryStateAsync } from '../../../core/index.js';
5
+ import { addBatteryStateListener, BatteryState, getBatteryStateAsync, } from '../../../core/index.js';
6
6
  export function useBatteryState() {
7
7
  const [batteryState, setBatteryState] = useState(BatteryState.UNKNOWN);
8
8
  useEffect(() => {
@@ -3,7 +3,7 @@
3
3
  // isLowPowerModeEnabledAsync() call before the first native event fires, matching upstream's
4
4
  // own useLowPowerMode.
5
5
  import { useEffect, useState } from 'react';
6
- import { addLowPowerModeListener, isLowPowerModeEnabledAsync } from '../../../core/index.js';
6
+ import { addLowPowerModeListener, isLowPowerModeEnabledAsync, } from '../../../core/index.js';
7
7
  export function useLowPowerMode() {
8
8
  const [lowPowerMode, setLowPowerMode] = useState(false);
9
9
  useEffect(() => {
@@ -1,4 +1,4 @@
1
1
  export { useBatteryLevel } from './hooks/use-battery-level';
2
2
  export { useBatteryState } from './hooks/use-battery-state';
3
3
  export { useLowPowerMode } from './hooks/use-low-power-mode';
4
- export { isAvailableAsync, getBatteryLevelAsync, getBatteryStateAsync, isLowPowerModeEnabledAsync, isBatteryOptimizationEnabledAsync, getPowerStateAsync, addBatteryLevelListener, addBatteryStateListener, addLowPowerModeListener, BatteryState, type PowerState, type BatteryLevelEvent, type BatteryStateEvent, type PowerModeEvent, type EventSubscription, } from '../core';
4
+ export * from '../core';
@@ -6,4 +6,4 @@
6
6
  export { useBatteryLevel } from './hooks/use-battery-level/index.js';
7
7
  export { useBatteryState } from './hooks/use-battery-state/index.js';
8
8
  export { useLowPowerMode } from './hooks/use-low-power-mode/index.js';
9
- export { isAvailableAsync, getBatteryLevelAsync, getBatteryStateAsync, isLowPowerModeEnabledAsync, isBatteryOptimizationEnabledAsync, getPowerStateAsync, addBatteryLevelListener, addBatteryStateListener, addLowPowerModeListener, BatteryState, } from '../core/index.js';
9
+ export * from '../core/index.js';
@@ -0,0 +1,4 @@
1
+ export { createBatteryLevel } from './primitives/create-battery-level';
2
+ export { createBatteryState } from './primitives/create-battery-state';
3
+ export { createLowPowerMode } from './primitives/create-low-power-mode';
4
+ export * from '../core';
@@ -0,0 +1,10 @@
1
+ // @symbiote-native/battery/solid: the Solid entry over the framework-agnostic core. Battery's
2
+ // three subscription-backed values (level/state/low-power-mode) each get their own primitive,
3
+ // matching upstream's own useBatteryLevel/useBatteryState/useLowPowerMode being three separate
4
+ // hooks, not one combined hook — mirrors the lifecycle-bucket naming of
5
+ // adapters/solid/src/primitives (never `hooks/`/`composables/`/`runes/`, and `create*` rather
6
+ // than `use*`, which Solid reserves for consuming something that already exists).
7
+ export { createBatteryLevel } from './primitives/create-battery-level.js';
8
+ export { createBatteryState } from './primitives/create-battery-state.js';
9
+ export { createLowPowerMode } from './primitives/create-low-power-mode.js';
10
+ export * from '../core/index.js';
@@ -0,0 +1,2 @@
1
+ import { type Accessor } from 'solid-js';
2
+ export declare function createBatteryLevel(): Accessor<number>;
@@ -0,0 +1,35 @@
1
+ // Solid lifecycle wiring over the framework-agnostic core (core/battery.ts) — the twin of
2
+ // react/hooks/use-battery-level, vue/composables/use-battery-level and
3
+ // svelte/runes/use-battery-level.svelte. See adapters/solid/src/primitives/create-color-scheme.ts
4
+ // for why the bucket is `primitives/` and the name is `create*` rather than `use*`.
5
+ //
6
+ // Returns an ACCESSOR, never a snapshot: a Solid component body runs ONCE, so a returned number
7
+ // would freeze at the level the screen mounted with.
8
+ //
9
+ // The listener is registered SYNCHRONOUSLY with the body — there is no useEffect/onMounted twin
10
+ // to defer it to, so nothing can arrive before the subscription exists. The seed stays a promise,
11
+ // which leaves one ordering hazard the React and Vue versions both have and neither guards: a
12
+ // native event can land BEFORE getBatteryLevelAsync() resolves, and the late seed would then
13
+ // overwrite the fresher reading with an older one. `hasNativeReading` drops the seed in that case
14
+ // — these two writers are ordered by latency, not by time, so last-write-wins is wrong here.
15
+ import { createSignal, onCleanup } from 'solid-js';
16
+ import { addBatteryLevelListener, getBatteryLevelAsync, } from '../../core/index.js';
17
+ // core/battery.ts's documented sentinel for "no reading yet / this device cannot report a level".
18
+ const UNKNOWN_BATTERY_LEVEL = -1;
19
+ export function createBatteryLevel() {
20
+ const [batteryLevel, setBatteryLevel] = createSignal(UNKNOWN_BATTERY_LEVEL);
21
+ let hasNativeReading = false;
22
+ const subscription = addBatteryLevelListener(event => {
23
+ hasNativeReading = true;
24
+ setBatteryLevel(event.batteryLevel);
25
+ });
26
+ getBatteryLevelAsync().then(level => {
27
+ if (!hasNativeReading) {
28
+ setBatteryLevel(level);
29
+ }
30
+ });
31
+ onCleanup(() => {
32
+ subscription.remove();
33
+ });
34
+ return batteryLevel;
35
+ }
@@ -0,0 +1,3 @@
1
+ import { type Accessor } from 'solid-js';
2
+ import { BatteryState } from '../../core';
3
+ export declare function createBatteryState(): Accessor<BatteryState>;
@@ -0,0 +1,21 @@
1
+ // Solid lifecycle wiring over the framework-agnostic core (core/battery.ts) — mirrors
2
+ // create-battery-level's shape, including the seed-vs-event ordering guard documented there.
3
+ import { createSignal, onCleanup } from 'solid-js';
4
+ import { addBatteryStateListener, BatteryState, getBatteryStateAsync, } from '../../core/index.js';
5
+ export function createBatteryState() {
6
+ const [batteryState, setBatteryState] = createSignal(BatteryState.UNKNOWN);
7
+ let hasNativeReading = false;
8
+ const subscription = addBatteryStateListener(event => {
9
+ hasNativeReading = true;
10
+ setBatteryState(event.batteryState);
11
+ });
12
+ getBatteryStateAsync().then(state => {
13
+ if (!hasNativeReading) {
14
+ setBatteryState(state);
15
+ }
16
+ });
17
+ onCleanup(() => {
18
+ subscription.remove();
19
+ });
20
+ return batteryState;
21
+ }
@@ -0,0 +1,2 @@
1
+ import { type Accessor } from 'solid-js';
2
+ export declare function createLowPowerMode(): Accessor<boolean>;
@@ -0,0 +1,21 @@
1
+ // Solid lifecycle wiring over the framework-agnostic core (core/battery.ts) — mirrors
2
+ // create-battery-level's shape, including the seed-vs-event ordering guard documented there.
3
+ import { createSignal, onCleanup } from 'solid-js';
4
+ import { addLowPowerModeListener, isLowPowerModeEnabledAsync, } from '../../core/index.js';
5
+ export function createLowPowerMode() {
6
+ const [lowPowerMode, setLowPowerMode] = createSignal(false);
7
+ let hasNativeReading = false;
8
+ const subscription = addLowPowerModeListener(event => {
9
+ hasNativeReading = true;
10
+ setLowPowerMode(event.lowPowerMode);
11
+ });
12
+ isLowPowerModeEnabledAsync().then(enabled => {
13
+ if (!hasNativeReading) {
14
+ setLowPowerMode(enabled);
15
+ }
16
+ });
17
+ onCleanup(() => {
18
+ subscription.remove();
19
+ });
20
+ return lowPowerMode;
21
+ }
@@ -0,0 +1,4 @@
1
+ export { useBatteryLevel } from './runes/use-battery-level.svelte';
2
+ export { useBatteryState } from './runes/use-battery-state.svelte';
3
+ export { useLowPowerMode } from './runes/use-low-power-mode.svelte';
4
+ export * from '../core';
@@ -0,0 +1,9 @@
1
+ // @symbiote-native/battery/svelte: the Svelte entry over the framework-agnostic core. Battery's
2
+ // three subscription-backed values (level/state/low-power-mode) each get their own lifecycle
3
+ // rune, matching upstream's own useBatteryLevel/useBatteryState/useLowPowerMode being three
4
+ // separate hooks, not one combined hook — mirrors the lifecycle-bucket naming convention of
5
+ // adapters/svelte/src/runes (never `hooks/`/`composables/`, those are React's and Vue's terms).
6
+ export { useBatteryLevel } from './runes/use-battery-level.svelte';
7
+ export { useBatteryState } from './runes/use-battery-state.svelte';
8
+ export { useLowPowerMode } from './runes/use-low-power-mode.svelte';
9
+ export * from '../core/index.js';
@@ -0,0 +1,3 @@
1
+ export declare function useBatteryLevel(): {
2
+ readonly current: number;
3
+ };
@@ -0,0 +1,37 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic core (core/battery.ts) — the Svelte twin of
2
+ // vue/composables/use-battery-level and react/hooks/use-battery-level. Seeds the initial value
3
+ // with a one-shot getBatteryLevelAsync() call before the first native event fires, matching
4
+ // upstream's own useBatteryLevel.
5
+ //
6
+ // `.svelte.ts` (not `.ts`): runes ($state/$effect) are only usable in a file with this extension
7
+ // outside an actual `.svelte` component. `runes/` is Svelte's own term for the bucket React calls
8
+ // `hooks/` and Vue calls `composables/` — see adapters/svelte/src/runes.
9
+ //
10
+ // Vue's onMounted/onUnmounted pair collapses into ONE `$effect` whose returned function is the
11
+ // teardown. The effect only WRITES `batteryLevel`, never reads it, so its dependency set stays
12
+ // empty: it runs exactly once on mount and cleans up exactly once on unmount.
13
+ //
14
+ // Returns a boxed getter object, NOT a bare `$state`: Svelte 5 reactivity is lexically scoped to
15
+ // the declaring module, so a raw `let x = $state(...)` handed out of a plain function arrives
16
+ // dead at the caller. `{ get current() { … } }` is the sanctioned way across, read as `.current`
17
+ // exactly like Vue's `Ref` is unwrapped via `.value`.
18
+ import { addBatteryLevelListener, getBatteryLevelAsync, } from '../../core/index.js';
19
+ // core/battery.ts's documented sentinel for "this device cannot report a battery level".
20
+ const UNKNOWN_BATTERY_LEVEL = -1;
21
+ export function useBatteryLevel() {
22
+ let batteryLevel = $state(UNKNOWN_BATTERY_LEVEL);
23
+ $effect(() => {
24
+ getBatteryLevelAsync().then(level => {
25
+ batteryLevel = level;
26
+ });
27
+ const subscription = addBatteryLevelListener(event => {
28
+ batteryLevel = event.batteryLevel;
29
+ });
30
+ return () => subscription.remove();
31
+ });
32
+ return {
33
+ get current() {
34
+ return batteryLevel;
35
+ },
36
+ };
37
+ }
@@ -0,0 +1,4 @@
1
+ import { BatteryState } from '../../core';
2
+ export declare function useBatteryState(): {
3
+ readonly current: BatteryState;
4
+ };
@@ -0,0 +1,22 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic core (core/battery.ts) — mirrors
2
+ // use-battery-level.svelte.ts's shape; see its header for the `.svelte.ts`/`runes/`/boxed-getter
3
+ // reasoning. Seeds the initial value with a one-shot getBatteryStateAsync() call before the first
4
+ // native event fires, matching upstream's own useBatteryState.
5
+ import { addBatteryStateListener, BatteryState, getBatteryStateAsync, } from '../../core/index.js';
6
+ export function useBatteryState() {
7
+ let batteryState = $state(BatteryState.UNKNOWN);
8
+ $effect(() => {
9
+ getBatteryStateAsync().then(state => {
10
+ batteryState = state;
11
+ });
12
+ const subscription = addBatteryStateListener(event => {
13
+ batteryState = event.batteryState;
14
+ });
15
+ return () => subscription.remove();
16
+ });
17
+ return {
18
+ get current() {
19
+ return batteryState;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,3 @@
1
+ export declare function useLowPowerMode(): {
2
+ readonly current: boolean;
3
+ };
@@ -0,0 +1,22 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic core (core/battery.ts) — mirrors
2
+ // use-battery-level.svelte.ts's shape; see its header for the `.svelte.ts`/`runes/`/boxed-getter
3
+ // reasoning. Seeds the initial value with a one-shot isLowPowerModeEnabledAsync() call before the
4
+ // first native event fires, matching upstream's own useLowPowerMode.
5
+ import { addLowPowerModeListener, isLowPowerModeEnabledAsync, } from '../../core/index.js';
6
+ export function useLowPowerMode() {
7
+ let lowPowerMode = $state(false);
8
+ $effect(() => {
9
+ isLowPowerModeEnabledAsync().then(enabled => {
10
+ lowPowerMode = enabled;
11
+ });
12
+ const subscription = addLowPowerModeListener(event => {
13
+ lowPowerMode = event.lowPowerMode;
14
+ });
15
+ return () => subscription.remove();
16
+ });
17
+ return {
18
+ get current() {
19
+ return lowPowerMode;
20
+ },
21
+ };
22
+ }
@@ -1,4 +1,4 @@
1
1
  export { useBatteryLevel } from './composables/use-battery-level';
2
2
  export { useBatteryState } from './composables/use-battery-state';
3
3
  export { useLowPowerMode } from './composables/use-low-power-mode';
4
- export { isAvailableAsync, getBatteryLevelAsync, getBatteryStateAsync, isLowPowerModeEnabledAsync, isBatteryOptimizationEnabledAsync, getPowerStateAsync, addBatteryLevelListener, addBatteryStateListener, addLowPowerModeListener, BatteryState, type PowerState, type BatteryLevelEvent, type BatteryStateEvent, type PowerModeEvent, type EventSubscription, } from '../core';
4
+ export * from '../core';
@@ -6,4 +6,4 @@
6
6
  export { useBatteryLevel } from './composables/use-battery-level/index.js';
7
7
  export { useBatteryState } from './composables/use-battery-state/index.js';
8
8
  export { useLowPowerMode } from './composables/use-low-power-mode/index.js';
9
- export { isAvailableAsync, getBatteryLevelAsync, getBatteryStateAsync, isLowPowerModeEnabledAsync, isBatteryOptimizationEnabledAsync, getPowerStateAsync, addBatteryLevelListener, addBatteryStateListener, addLowPowerModeListener, BatteryState, } from '../core/index.js';
9
+ export * from '../core/index.js';
@@ -1,4 +1,4 @@
1
1
  export { BatteryLevelService } from './services/battery-level.service';
2
2
  export { BatteryStateService } from './services/battery-state.service';
3
3
  export { LowPowerModeService } from './services/low-power-mode.service';
4
- export { isAvailableAsync, getBatteryLevelAsync, getBatteryStateAsync, isLowPowerModeEnabledAsync, isBatteryOptimizationEnabledAsync, getPowerStateAsync, addBatteryLevelListener, addBatteryStateListener, addLowPowerModeListener, BatteryState, type PowerState, type BatteryLevelEvent, type BatteryStateEvent, type PowerModeEvent, type EventSubscription, } from '../core';
4
+ export * from '../core';
@@ -5,5 +5,5 @@
5
5
  export { BatteryLevelService } from './services/battery-level.service';
6
6
  export { BatteryStateService } from './services/battery-state.service';
7
7
  export { LowPowerModeService } from './services/low-power-mode.service';
8
- export { isAvailableAsync, getBatteryLevelAsync, getBatteryStateAsync, isLowPowerModeEnabledAsync, isBatteryOptimizationEnabledAsync, getPowerStateAsync, addBatteryLevelListener, addBatteryStateListener, addLowPowerModeListener, BatteryState, } from '../core';
8
+ export * from '../core';
9
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,yFAAyF;AACzF,yFAAyF;AACzF,8EAA8E;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,iCAAiC,EACjC,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,YAAY,GAMb,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,yFAAyF;AACzF,yFAAyF;AACzF,8EAA8E;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,cAAc,SAAS,CAAC"}
@@ -1,4 +1,4 @@
1
- import { effect, inject, Injectable, Injector, signal } from '@angular/core';
1
+ import { effect, inject, Injectable, Injector, signal, } from '@angular/core';
2
2
  import { addBatteryLevelListener, getBatteryLevelAsync } from '../../../core';
3
3
  import * as i0 from "@angular/core";
4
4
  // Angular twin of React's `useBatteryLevel` hook and Vue's `useBatteryLevel` composable.
@@ -23,10 +23,10 @@ export class BatteryLevelService {
23
23
  }, { injector: this.injector });
24
24
  return batteryLevel.asReadonly();
25
25
  }
26
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: BatteryLevelService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
27
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: BatteryLevelService, providedIn: 'root' });
26
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: BatteryLevelService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
27
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: BatteryLevelService, providedIn: 'root' });
28
28
  }
29
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: BatteryLevelService, decorators: [{
29
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: BatteryLevelService, decorators: [{
30
30
  type: Injectable,
31
31
  args: [{ providedIn: 'root' }]
32
32
  }] });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/angular/services/battery-level.service/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAe,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;;AAE9E,yFAAyF;AACzF,4FAA4F;AAC5F,+FAA+F;AAC/F,gCAAgC;AAChC,EAAE;AACF,mEAAmE;AACnE,sCAAsC;AACtC,EAAE;AACF,+FAA+F;AAC/F,+DAA+D;AAE/D,MAAM,OAAO,mBAAmB;IACb,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO;QACL,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC;yFAAC,CAAC;QAEhC,MAAM,CACJ,SAAS,CAAC,EAAE;YACV,oBAAoB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;YAC9D,MAAM,YAAY,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;YAC5F,SAAS,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QACzC,CAAC,EACD,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAC5B,CAAC;QAEF,OAAO,YAAY,CAAC,UAAU,EAAE,CAAC;IACnC,CAAC;uGAhBU,mBAAmB;2GAAnB,mBAAmB,cADN,MAAM;;2FACnB,mBAAmB;kBAD/B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/angular/services/battery-level.service/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,MAAM,EACN,UAAU,EACV,QAAQ,EACR,MAAM,GAEP,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;;AAE9E,yFAAyF;AACzF,4FAA4F;AAC5F,+FAA+F;AAC/F,gCAAgC;AAChC,EAAE;AACF,mEAAmE;AACnE,sCAAsC;AACtC,EAAE;AACF,+FAA+F;AAC/F,+DAA+D;AAE/D,MAAM,OAAO,mBAAmB;IACb,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO;QACL,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC;yFAAC,CAAC;QAEhC,MAAM,CACJ,SAAS,CAAC,EAAE;YACV,oBAAoB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;YAC9D,MAAM,YAAY,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,CACnD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CACrC,CAAC;YACF,SAAS,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QACzC,CAAC,EACD,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAC5B,CAAC;QAEF,OAAO,YAAY,CAAC,UAAU,EAAE,CAAC;IACnC,CAAC;uGAlBU,mBAAmB;2GAAnB,mBAAmB,cADN,MAAM;;2FACnB,mBAAmB;kBAD/B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE"}
@@ -1,5 +1,5 @@
1
- import { effect, inject, Injectable, Injector, signal } from '@angular/core';
2
- import { addBatteryStateListener, BatteryState, getBatteryStateAsync } from '../../../core';
1
+ import { effect, inject, Injectable, Injector, signal, } from '@angular/core';
2
+ import { addBatteryStateListener, BatteryState, getBatteryStateAsync, } from '../../../core';
3
3
  import * as i0 from "@angular/core";
4
4
  // Angular twin of React's `useBatteryState` hook and Vue's `useBatteryState` composable. See
5
5
  // BatteryLevelService for the `connect()` pattern rationale.
@@ -18,10 +18,10 @@ export class BatteryStateService {
18
18
  }, { injector: this.injector });
19
19
  return batteryState.asReadonly();
20
20
  }
21
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: BatteryStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
22
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: BatteryStateService, providedIn: 'root' });
21
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: BatteryStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
22
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: BatteryStateService, providedIn: 'root' });
23
23
  }
24
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: BatteryStateService, decorators: [{
24
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: BatteryStateService, decorators: [{
25
25
  type: Injectable,
26
26
  args: [{ providedIn: 'root' }]
27
27
  }] });