@symbiote-native/network 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 (43) hide show
  1. package/README.md +103 -32
  2. package/build/angular/index.d.ts +1 -1
  3. package/build/angular/index.js +1 -1
  4. package/build/angular/services/network-state.service/index.js +2 -2
  5. package/build/core/index.d.ts +1 -1
  6. package/build/core/index.js +1 -1
  7. package/build/react/hooks/use-network-state/index.js +1 -1
  8. package/build/react/index.d.ts +1 -1
  9. package/build/react/index.js +1 -1
  10. package/build/solid/index.d.ts +2 -0
  11. package/build/solid/index.js +5 -0
  12. package/build/solid/primitives/create-network-state.d.ts +3 -0
  13. package/build/solid/primitives/create-network-state.js +32 -0
  14. package/build/svelte/index.d.ts +2 -0
  15. package/build/svelte/index.js +5 -0
  16. package/build/svelte/runes/use-network-state.svelte.d.ts +4 -0
  17. package/build/svelte/runes/use-network-state.svelte.js +29 -0
  18. package/build/vue/index.d.ts +1 -1
  19. package/build/vue/index.js +1 -1
  20. package/build-ngc/angular/index.d.ts +1 -1
  21. package/build-ngc/angular/index.js +1 -1
  22. package/build-ngc/angular/index.js.map +1 -1
  23. package/build-ngc/angular/services/network-state.service/index.js +5 -5
  24. package/build-ngc/angular/services/network-state.service/index.js.map +1 -1
  25. package/build-ngc/core/index.d.ts +1 -1
  26. package/build-ngc/core/index.js +1 -1
  27. package/build-ngc/core/index.js.map +1 -1
  28. package/build-ngc/core/native-module.js.map +1 -1
  29. package/build-ngc/core/network.js.map +1 -1
  30. package/package.json +42 -14
  31. package/src/angular/index.ts +1 -10
  32. package/src/angular/services/network-state.service/index.ts +16 -3
  33. package/src/core/index.ts +5 -1
  34. package/src/core/native-module.ts +3 -1
  35. package/src/core/network.ts +4 -1
  36. package/src/react/hooks/use-network-state/index.ts +8 -2
  37. package/src/react/index.ts +1 -10
  38. package/src/solid/index.ts +6 -0
  39. package/src/solid/primitives/create-network-state.ts +43 -0
  40. package/src/svelte/index.ts +6 -0
  41. package/src/svelte/runes/use-network-state.svelte.ts +37 -0
  42. package/src/svelte/svelte-ambient.d.ts +6 -0
  43. package/src/vue/index.ts +1 -10
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Port of [`expo-network`](https://docs.expo.dev/versions/latest/sdk/network/) for
4
4
  [SymbioteNative](../../README.md) — network connection state (type/connected/internet-reachable)
5
5
  with a change listener, device IP address, and airplane-mode detection, reachable from every
6
- adapter (React, Vue, Angular), not just React.
6
+ adapter (React, Vue, Svelte, Solid, Angular), not just React.
7
7
 
8
8
  Built the same way as [`@symbiote-native/battery`](../battery) and
9
9
  [`@symbiote-native/local-auth`](../local-auth), an `expo-modules-core`-based wrapper (see the
@@ -31,12 +31,12 @@ into the native host app **once**, covering this package and every other `expo-m
31
31
  package (`@symbiote-native/battery`, `@symbiote-native/sensors`, `@symbiote-native/local-auth`)
32
32
  with zero further changes:
33
33
 
34
- | Platform | Touches |
35
- |---|---|
36
- | iOS | `ios/Podfile` — add `use_expo_modules!` |
37
- | iOS | `AppDelegate.swift` — Expo's runtime-bootstrap hook |
38
- | Android | `settings.gradle` / `app/build.gradle` — resolve and include the Expo Gradle projects |
39
- | 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) |
34
+ | Platform | Touches |
35
+ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
36
+ | iOS | `ios/Podfile` — add `use_expo_modules!` |
37
+ | iOS | `AppDelegate.swift` — Expo's runtime-bootstrap hook |
38
+ | Android | `settings.gradle` / `app/build.gradle` — resolve and include the Expo Gradle projects |
39
+ | 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) |
40
40
 
41
41
  Full mechanics — the Podfile pieces that normally ship inside the `expo` package, the `expo`
42
42
  peer-dependency exclusion list — live in the `symbiote-expo-native-module` skill. Reference
@@ -56,37 +56,50 @@ src/core/ network.ts — get*Async functions + addNetworkStateList
56
56
  NetworkStateEvent, hand-ported from Network.types.ts.
57
57
  src/react/hooks/ @symbiote-native/network/react — useNetworkState
58
58
  src/vue/composables/ @symbiote-native/network/vue — useNetworkState (same name)
59
+ src/svelte/runes/ @symbiote-native/network/svelte — useNetworkState (same name)
60
+ src/solid/primitives/ @symbiote-native/network/solid — createNetworkState (returns an
61
+ Accessor; Solid reserves `use*` for consuming existing state)
59
62
  src/angular/services/ @symbiote-native/network/angular — NetworkStateService (`.connect()`
60
63
  returns a Signal)
61
64
  ```
62
65
 
63
- Each adapter's hook/composable/service is a thin lifecycle wrapper (seed from the one-shot
64
- `getNetworkStateAsync()` call, subscribe to `addNetworkStateListener`, unsubscribe on unmount) over
65
- the same `core` functions — the subscription logic is written once and shared by all three.
66
+ Each adapter's hook/composable/rune/primitive/service is a thin lifecycle wrapper (seed from the
67
+ one-shot `getNetworkStateAsync()` call, subscribe to `addNetworkStateListener`, unsubscribe on
68
+ unmount) over the same `core` functions — the subscription logic is written once and shared by all
69
+ of them.
66
70
 
67
71
  ## Use it
68
72
 
69
73
  ```tsx
70
74
  // React — examples/expo-react/screens/NetworkScreen.tsx
71
75
  import { useEffect, useState } from 'react';
72
- import { getIpAddressAsync, isAirplaneModeEnabledAsync } from '@symbiote-native/network';
76
+ import {
77
+ getIpAddressAsync,
78
+ isAirplaneModeEnabledAsync,
79
+ } from '@symbiote-native/network';
73
80
  import { useNetworkState } from '@symbiote-native/network/react';
74
81
 
75
82
  function NetworkScreen() {
76
- const networkState = useNetworkState(); // { type, isConnected, isInternetReachable }
83
+ const networkState = useNetworkState(); // { type, isConnected, isInternetReachable }
77
84
  const [ipAddress, setIpAddress] = useState<string | null>(null);
78
85
  const [isAirplaneMode, setIsAirplaneMode] = useState<boolean | null>(null);
79
86
 
80
87
  useEffect(() => {
81
- Promise.all([getIpAddressAsync(), isAirplaneModeEnabledAsync()]).then(([ip, airplaneMode]) => {
82
- setIpAddress(ip);
83
- setIsAirplaneMode(airplaneMode);
84
- });
88
+ Promise.all([getIpAddressAsync(), isAirplaneModeEnabledAsync()]).then(
89
+ ([ip, airplaneMode]) => {
90
+ setIpAddress(ip);
91
+ setIsAirplaneMode(airplaneMode);
92
+ },
93
+ );
85
94
  }, [networkState]);
86
95
 
87
96
  return (
88
97
  <>
89
- <Text>{networkState.isConnected ? `Connected via ${networkState.type}` : 'Offline'}</Text>
98
+ <Text>
99
+ {networkState.isConnected
100
+ ? `Connected via ${networkState.type}`
101
+ : 'Offline'}
102
+ </Text>
90
103
  <Text>{ipAddress ?? 'checking…'}</Text>
91
104
  <Text>{isAirplaneMode ? 'Airplane mode: On' : 'Airplane mode: Off'}</Text>
92
105
  </>
@@ -99,26 +112,33 @@ function NetworkScreen() {
99
112
  <script setup lang="ts">
100
113
  import { ref, watch } from 'vue';
101
114
  import { Text } from '@symbiote-native/vue';
102
- import { getIpAddressAsync, isAirplaneModeEnabledAsync } from '@symbiote-native/network';
115
+ import {
116
+ getIpAddressAsync,
117
+ isAirplaneModeEnabledAsync,
118
+ } from '@symbiote-native/network';
103
119
  import { useNetworkState } from '@symbiote-native/network/vue';
104
120
 
105
- const networkState = useNetworkState(); // Ref<NetworkState>
121
+ const networkState = useNetworkState(); // Ref<NetworkState>
106
122
  const ipAddress = ref<string | null>(null);
107
123
  const isAirplaneMode = ref<boolean | null>(null);
108
124
 
109
125
  watch(
110
126
  networkState,
111
127
  () => {
112
- void Promise.all([getIpAddressAsync(), isAirplaneModeEnabledAsync()]).then(([ip, airplaneMode]) => {
113
- ipAddress.value = ip;
114
- isAirplaneMode.value = airplaneMode;
115
- });
128
+ void Promise.all([getIpAddressAsync(), isAirplaneModeEnabledAsync()]).then(
129
+ ([ip, airplaneMode]) => {
130
+ ipAddress.value = ip;
131
+ isAirplaneMode.value = airplaneMode;
132
+ },
133
+ );
116
134
  },
117
135
  { immediate: true },
118
136
  );
119
137
  </script>
120
138
  <template>
121
- <Text>{{ networkState.isConnected ? `Connected via ${networkState.type}` : 'Offline' }}</Text>
139
+ <Text>{{
140
+ networkState.isConnected ? `Connected via ${networkState.type}` : 'Offline'
141
+ }}</Text>
122
142
  <Text>{{ ipAddress ?? 'checking…' }}</Text>
123
143
  </template>
124
144
  ```
@@ -145,15 +165,59 @@ export class NetworkScreen {
145
165
  constructor() {
146
166
  effect(() => {
147
167
  this.networkState();
148
- Promise.all([getIpAddressAsync(), isAirplaneModeEnabledAsync()]).then(([ip]) => {
149
- this.ipAddress.set(ip);
150
- });
168
+ Promise.all([getIpAddressAsync(), isAirplaneModeEnabledAsync()]).then(
169
+ ([ip]) => {
170
+ this.ipAddress.set(ip);
171
+ },
172
+ );
151
173
  });
152
174
  }
153
175
  }
154
176
  ```
155
177
 
156
- Each of the three demo screens above also re-fetches the IP address and airplane-mode card
178
+ ```tsx
179
+ // Solid — the accessor is CALLED; a Solid component body runs once, so a snapshot would freeze.
180
+ import { createSignal, onMount } from 'solid-js';
181
+ import { Text } from '@symbiote-native/solid';
182
+ import {
183
+ getIpAddressAsync,
184
+ isAirplaneModeEnabledAsync,
185
+ } from '@symbiote-native/network';
186
+ import { createNetworkState } from '@symbiote-native/network/solid';
187
+
188
+ function NetworkScreen() {
189
+ const networkState = createNetworkState(); // Accessor<NetworkState>
190
+ const [ipAddress, setIpAddress] = createSignal<string | null>(null);
191
+ const [isAirplaneMode, setIsAirplaneMode] = createSignal<boolean | null>(
192
+ null,
193
+ );
194
+
195
+ onMount(() => {
196
+ void Promise.all([getIpAddressAsync(), isAirplaneModeEnabledAsync()]).then(
197
+ ([ip, airplaneMode]) => {
198
+ setIpAddress(ip);
199
+ setIsAirplaneMode(airplaneMode);
200
+ },
201
+ );
202
+ });
203
+
204
+ return (
205
+ <>
206
+ <Text>
207
+ {networkState().isConnected
208
+ ? `Connected via ${networkState().type}`
209
+ : 'Offline'}
210
+ </Text>
211
+ <Text>{ipAddress() ?? 'checking…'}</Text>
212
+ <Text>
213
+ {isAirplaneMode() ? 'Airplane mode: On' : 'Airplane mode: Off'}
214
+ </Text>
215
+ </>
216
+ );
217
+ }
218
+ ```
219
+
220
+ Each of the demo screens above also re-fetches the IP address and airplane-mode card
157
221
  whenever the live network state changes (toggling Wi-Fi/airplane mode on the device updates both
158
222
  cards together) — see the linked files for the full version, including the connection-type label
159
223
  switch and the layout around it.
@@ -174,18 +238,25 @@ Plus `NetworkStateType` (enum: `NONE`/`UNKNOWN`/`CELLULAR`/`WIFI`/`BLUETOOTH`/`E
174
238
  `VPN`/`OTHER`), `NetworkState`, `NetworkStateEvent` — ported from upstream's `Network.types.ts`.
175
239
 
176
240
  ```ts
177
- import { getNetworkStateAsync, addNetworkStateListener } from '@symbiote-native/network';
241
+ import {
242
+ getNetworkStateAsync,
243
+ addNetworkStateListener,
244
+ } from '@symbiote-native/network';
178
245
 
179
246
  // framework-scoped entry points re-export the same free functions, plus a lifecycle
180
247
  // hook/composable/service:
181
248
  import { useNetworkState } from '@symbiote-native/network/react';
182
249
  import { useNetworkState } from '@symbiote-native/network/vue';
250
+ import { useNetworkState } from '@symbiote-native/network/svelte';
251
+ import { createNetworkState } from '@symbiote-native/network/solid';
183
252
  import { NetworkStateService } from '@symbiote-native/network/angular';
184
253
  ```
185
254
 
186
- `useNetworkState` seeds its initial value from a one-shot `getNetworkStateAsync()` call, then
187
- subscribes to `addNetworkStateListener` for updates, and unsubscribes on unmount — mirroring
188
- upstream's own `useNetworkState`.
255
+ `useNetworkState` (Solid: `createNetworkState`) seeds its initial value from a one-shot
256
+ `getNetworkStateAsync()` call, then subscribes to `addNetworkStateListener` for updates, and
257
+ unsubscribes on unmount — mirroring upstream's own `useNetworkState`. The Solid primitive returns
258
+ an `Accessor<NetworkState>` and subscribes from its body rather than an effect, so nothing can slip
259
+ between the seed and the subscription.
189
260
 
190
261
  ## Test it
191
262
 
@@ -1,2 +1,2 @@
1
1
  export { NetworkStateService } from './services/network-state.service';
2
- export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, NetworkStateType, type NetworkState, type NetworkStateEvent, type EventSubscription, } from '../core';
2
+ export * from '../core';
@@ -1,4 +1,4 @@
1
1
  // NetworkStateService is the Angular-only lifecycle half; the free functions and event
2
2
  // subscription plumbing all live in core, shared with React/Vue.
3
3
  export { NetworkStateService } from './services/network-state.service/index.js';
4
- export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, NetworkStateType, } from '../core/index.js';
4
+ export * from '../core/index.js';
@@ -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 { addNetworkStateListener, getNetworkStateAsync } from '../../../core/index.js';
35
+ import { effect, inject, Injectable, Injector, signal, } from '@angular/core';
36
+ import { addNetworkStateListener, getNetworkStateAsync, } from '../../../core/index.js';
37
37
  // Angular twin of React's `useNetworkState` hook and Vue's `useNetworkState` composable.
38
38
  //
39
39
  // readonly networkState = inject(NetworkStateService).connect();
@@ -1,3 +1,3 @@
1
1
  export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, } from './network';
2
- export { NetworkStateType, type NetworkState, type NetworkStateEvent } from './types';
2
+ export { NetworkStateType, type NetworkState, type NetworkStateEvent, } from './types';
3
3
  export type { EventSubscription } from 'expo-modules-core';
@@ -1,2 +1,2 @@
1
1
  export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, } from './network.js';
2
- export { NetworkStateType } from './types.js';
2
+ export { NetworkStateType, } from './types.js';
@@ -2,7 +2,7 @@
2
2
  // value with a one-shot getNetworkStateAsync() call before the first native event fires, matching
3
3
  // upstream's own useNetworkState.
4
4
  import { useEffect, useState } from 'react';
5
- import { addNetworkStateListener, getNetworkStateAsync } from '../../../core/index.js';
5
+ import { addNetworkStateListener, getNetworkStateAsync, } from '../../../core/index.js';
6
6
  export function useNetworkState() {
7
7
  const [networkState, setNetworkState] = useState({});
8
8
  useEffect(() => {
@@ -1,2 +1,2 @@
1
1
  export { useNetworkState } from './hooks/use-network-state';
2
- export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, NetworkStateType, type NetworkState, type NetworkStateEvent, type EventSubscription, } from '../core';
2
+ export * from '../core';
@@ -1,3 +1,3 @@
1
1
  // @symbiote-native/network/react: the React entry over the framework-agnostic core.
2
2
  export { useNetworkState } from './hooks/use-network-state/index.js';
3
- export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, NetworkStateType, } from '../core/index.js';
3
+ export * from '../core/index.js';
@@ -0,0 +1,2 @@
1
+ export { createNetworkState } from './primitives/create-network-state';
2
+ export * from '../core';
@@ -0,0 +1,5 @@
1
+ // @symbiote-native/network/solid: the Solid entry over the framework-agnostic core — mirrors the
2
+ // lifecycle-bucket naming convention of adapters/solid/src/primitives (never `hooks`/`composables`/
3
+ // `runes`, those are React's, Vue's and Svelte's terms).
4
+ export { createNetworkState } from './primitives/create-network-state.js';
5
+ export * from '../core/index.js';
@@ -0,0 +1,3 @@
1
+ import { type Accessor } from 'solid-js';
2
+ import { type NetworkState } from '../../core';
3
+ export declare function createNetworkState(): Accessor<NetworkState>;
@@ -0,0 +1,32 @@
1
+ // createNetworkState — the Solid twin of React's `useNetworkState` hook, Vue's composable and
2
+ // Svelte's rune, over the framework-agnostic core (core/network.ts). Seeds with a one-shot
3
+ // getNetworkStateAsync() call before the first native event fires, matching upstream's own
4
+ // useNetworkState.
5
+ //
6
+ // `primitives/` and `create*`, never `hooks/`+`use*`: Solid's ecosystem calls a composable
7
+ // reactive function a PRIMITIVE and reserves `use*` for consuming something that already exists.
8
+ // Full rationale in adapters/solid/src/primitives/create-color-scheme.ts.
9
+ //
10
+ // Returns an ACCESSOR, never a snapshot: a Solid component body runs ONCE, so a returned object
11
+ // would pin the caller to the empty seed forever.
12
+ //
13
+ // Outside a component or `createRoot` there is no owner for `onCleanup` — Solid warns and the
14
+ // native listener lives for the process. The accessor still tracks; only the teardown is lost.
15
+ import { createSignal, onCleanup } from 'solid-js';
16
+ import { addNetworkStateListener, getNetworkStateAsync, } from '../../core/index.js';
17
+ export function createNetworkState() {
18
+ const [networkState, setNetworkState] = createSignal({});
19
+ getNetworkStateAsync().then(state => {
20
+ setNetworkState(state);
21
+ });
22
+ // Subscribed from the primitive body, not from an effect: React/Vue/Svelte start listening a
23
+ // tick after their seed runs, so a change landing in that window is lost. Both statements here
24
+ // run in one synchronous tick and nothing can interleave.
25
+ const subscription = addNetworkStateListener(event => {
26
+ setNetworkState(event);
27
+ });
28
+ onCleanup(() => {
29
+ subscription.remove();
30
+ });
31
+ return networkState;
32
+ }
@@ -0,0 +1,2 @@
1
+ export { useNetworkState } from './runes/use-network-state.svelte';
2
+ export * from '../core';
@@ -0,0 +1,5 @@
1
+ // @symbiote-native/network/svelte: the Svelte entry over the framework-agnostic core — mirrors the
2
+ // lifecycle-bucket naming convention of adapters/svelte/src/runes (never `hooks`/`composables`,
3
+ // those are React's and Vue's terms).
4
+ export { useNetworkState } from './runes/use-network-state.svelte';
5
+ export * from '../core/index.js';
@@ -0,0 +1,4 @@
1
+ import { type NetworkState } from '../../core';
2
+ export declare function useNetworkState(): {
3
+ readonly current: NetworkState;
4
+ };
@@ -0,0 +1,29 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic core (core/network.ts). Seeds the initial
2
+ // value with a one-shot getNetworkStateAsync() call before the first native event fires, matching
3
+ // upstream's own useNetworkState and the Vue composable's onMounted half.
4
+ //
5
+ // `.svelte.ts` extension: runes ($state/$effect) only work there outside a `.svelte` component;
6
+ // `runes/` is Svelte's name for the lifecycle bucket (React's `hooks/`, Vue's `composables/`).
7
+ // Returns a boxed getter, not a bare `$state`: Svelte 5 reactivity is lexically scoped to the
8
+ // declaring module and doesn't survive being returned raw from a plain function, so the caller
9
+ // reads `.current` like unwrapping Vue's `Ref` via `.value`.
10
+ import { addNetworkStateListener, getNetworkStateAsync, } from '../../core/index.js';
11
+ export function useNetworkState() {
12
+ let networkState = $state({});
13
+ $effect(() => {
14
+ // Write-only touches of `networkState`, so the effect has no dependency on it and runs once
15
+ // per mount - the twin of Vue's onMounted/onUnmounted pair.
16
+ getNetworkStateAsync().then(state => {
17
+ networkState = state;
18
+ });
19
+ const subscription = addNetworkStateListener(event => {
20
+ networkState = event;
21
+ });
22
+ return () => subscription.remove();
23
+ });
24
+ return {
25
+ get current() {
26
+ return networkState;
27
+ },
28
+ };
29
+ }
@@ -1,2 +1,2 @@
1
1
  export { useNetworkState } from './composables/use-network-state';
2
- export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, NetworkStateType, type NetworkState, type NetworkStateEvent, type EventSubscription, } from '../core';
2
+ export * from '../core';
@@ -1,3 +1,3 @@
1
1
  // @symbiote-native/network/vue: the Vue entry over the framework-agnostic core.
2
2
  export { useNetworkState } from './composables/use-network-state/index.js';
3
- export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, NetworkStateType, } from '../core/index.js';
3
+ export * from '../core/index.js';
@@ -1,2 +1,2 @@
1
1
  export { NetworkStateService } from './services/network-state.service';
2
- export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, NetworkStateType, type NetworkState, type NetworkStateEvent, type EventSubscription, } from '../core';
2
+ export * from '../core';
@@ -1,5 +1,5 @@
1
1
  // NetworkStateService is the Angular-only lifecycle half; the free functions and event
2
2
  // subscription plumbing all live in core, shared with React/Vue.
3
3
  export { NetworkStateService } from './services/network-state.service';
4
- export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, NetworkStateType, } from '../core';
4
+ export * from '../core';
5
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,iEAAiE;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,0BAA0B,EAC1B,uBAAuB,EACvB,gBAAgB,GAIjB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,iEAAiE;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,cAAc,SAAS,CAAC"}
@@ -1,5 +1,5 @@
1
- import { effect, inject, Injectable, Injector, signal } from '@angular/core';
2
- import { addNetworkStateListener, getNetworkStateAsync } from '../../../core';
1
+ import { effect, inject, Injectable, Injector, signal, } from '@angular/core';
2
+ import { addNetworkStateListener, getNetworkStateAsync, } from '../../../core';
3
3
  import * as i0 from "@angular/core";
4
4
  // Angular twin of React's `useNetworkState` hook and Vue's `useNetworkState` composable.
5
5
  //
@@ -17,10 +17,10 @@ export class NetworkStateService {
17
17
  }, { injector: this.injector });
18
18
  return networkState.asReadonly();
19
19
  }
20
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NetworkStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
21
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NetworkStateService, providedIn: 'root' });
20
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: NetworkStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
21
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: NetworkStateService, providedIn: 'root' });
22
22
  }
23
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NetworkStateService, decorators: [{
23
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: NetworkStateService, decorators: [{
24
24
  type: Injectable,
25
25
  args: [{ providedIn: 'root' }]
26
26
  }] });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/angular/services/network-state.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,EAAqB,MAAM,eAAe,CAAC;;AAEjG,yFAAyF;AACzF,EAAE;AACF,mEAAmE;AACnE,2CAA2C;AAE3C,MAAM,OAAO,mBAAmB;IACb,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO;QACL,MAAM,YAAY,GAAG,MAAM,CAAe,EAAE;yFAAC,CAAC;QAE9C,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,CAAC,CAAC;YAC/E,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/network-state.service/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,MAAM,EACN,UAAU,EACV,QAAQ,EACR,MAAM,GAEP,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GAErB,MAAM,eAAe,CAAC;;AAEvB,yFAAyF;AACzF,EAAE;AACF,mEAAmE;AACnE,2CAA2C;AAE3C,MAAM,OAAO,mBAAmB;IACb,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO;QACL,MAAM,YAAY,GAAG,MAAM,CAAe,EAAE;yFAAC,CAAC;QAE9C,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,CACxB,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,3 +1,3 @@
1
1
  export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, } from './network';
2
- export { NetworkStateType, type NetworkState, type NetworkStateEvent } from './types';
2
+ export { NetworkStateType, type NetworkState, type NetworkStateEvent, } from './types';
3
3
  export type { EventSubscription } from 'expo-modules-core';
@@ -1,3 +1,3 @@
1
1
  export { getNetworkStateAsync, getIpAddressAsync, isAirplaneModeEnabledAsync, addNetworkStateListener, } from './network';
2
- export { NetworkStateType } from './types';
2
+ export { NetworkStateType, } from './types';
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,gBAAgB,EAA6C,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,gBAAgB,GAGjB,MAAM,SAAS,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"native-module.js","sourceRoot":"","sources":["../../src/core/native-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAIxD,MAAM,wBAAwB,GAAG,aAAa,CAAC;AAc/C,MAAM,CAAC,MAAM,WAAW,GAAG,mBAAmB,CAAuB,wBAAwB,CAAC,CAAC"}
1
+ {"version":3,"file":"native-module.js","sourceRoot":"","sources":["../../src/core/native-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAIxD,MAAM,wBAAwB,GAAG,aAAa,CAAC;AAc/C,MAAM,CAAC,MAAM,WAAW,GAAG,mBAAmB,CAC5C,wBAAwB,CACzB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/core/network.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,0FAA0F;AAC1F,2DAA2D;AAC3D,OAAO,EAAE,mBAAmB,EAA0B,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAE1C,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,IAAI,CAAC,WAAW,CAAC,oBAAoB,EAAE,CAAC;QACtC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,sBAAsB,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,WAAW,CAAC,oBAAoB,EAAE,CAAC;AAC5C,CAAC;AAED,gGAAgG;AAChG,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC;QACnC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,WAAW,CAAC,iBAAiB,EAAE,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B;IAC9C,IAAI,CAAC,WAAW,CAAC,0BAA0B,EAAE,CAAC;QAC5C,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,4BAA4B,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,WAAW,CAAC,0BAA0B,EAAE,CAAC;AAClD,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,uBAAuB,CACrC,QAA4C;IAE5C,OAAO,WAAW,CAAC,WAAW,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAC;AACpE,CAAC"}
1
+ {"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/core/network.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,0FAA0F;AAC1F,2DAA2D;AAC3D,OAAO,EAAE,mBAAmB,EAA0B,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAE1C,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,IAAI,CAAC,WAAW,CAAC,oBAAoB,EAAE,CAAC;QACtC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,sBAAsB,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,WAAW,CAAC,oBAAoB,EAAE,CAAC;AAC5C,CAAC;AAED,gGAAgG;AAChG,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC;QACnC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,WAAW,CAAC,iBAAiB,EAAE,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B;IAC9C,IAAI,CAAC,WAAW,CAAC,0BAA0B,EAAE,CAAC;QAC5C,MAAM,IAAI,mBAAmB,CAC3B,kBAAkB,EAClB,4BAA4B,CAC7B,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC,0BAA0B,EAAE,CAAC;AAClD,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,uBAAuB,CACrC,QAA4C;IAE5C,OAAO,WAAW,CAAC,WAAW,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAC;AACpE,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@symbiote-native/network",
3
- "version": "0.1.0",
4
- "description": "expo-network wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, and Angular adapters. Network state (type/connected/internet-reachable) with a change listener, device IP address, and airplane-mode detection.",
3
+ "version": "0.3.0",
4
+ "description": "expo-network wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. Network state (type/connected/internet-reachable) with a change listener, device IP address, and airplane-mode detection.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -30,6 +30,14 @@
30
30
  "types": "./build/react/index.d.ts",
31
31
  "default": "./build/react/index.js"
32
32
  },
33
+ "./svelte": {
34
+ "types": "./build/svelte/index.d.ts",
35
+ "default": "./build/svelte/index.js"
36
+ },
37
+ "./solid": {
38
+ "types": "./build/solid/index.d.ts",
39
+ "default": "./build/solid/index.js"
40
+ },
33
41
  "./angular": {
34
42
  "types": "./build-ngc/angular/index.d.ts",
35
43
  "react-native": "./build-ngc/angular/index.js",
@@ -53,15 +61,19 @@
53
61
  "expo-modules-core": "57.0.5"
54
62
  },
55
63
  "peerDependencies": {
64
+ "@symbiote-native/angular": ">=0.6.2",
56
65
  "@symbiote-native/engine": ">=0.1.7",
66
+ "@symbiote-native/react": ">=0.2.8",
67
+ "@symbiote-native/solid": ">=0.0.1",
68
+ "@symbiote-native/svelte": ">=0.1.0",
69
+ "@symbiote-native/vue": ">=0.3.8",
57
70
  "@angular/core": ">=20",
58
71
  "@vue/runtime-core": "^3.5.13",
59
72
  "react": ">=19.0.0",
60
73
  "react-native": ">=0.86",
61
- "vue": ">=3.5.0",
62
- "@symbiote-native/angular": "0.6.2",
63
- "@symbiote-native/react": "0.2.8",
64
- "@symbiote-native/vue": "0.3.8"
74
+ "solid-js": ">=1.9.0",
75
+ "svelte": ">=5.56.0",
76
+ "vue": ">=3.5.0"
65
77
  },
66
78
  "peerDependenciesMeta": {
67
79
  "@symbiote-native/angular": {
@@ -70,6 +82,12 @@
70
82
  "@symbiote-native/react": {
71
83
  "optional": true
72
84
  },
85
+ "@symbiote-native/solid": {
86
+ "optional": true
87
+ },
88
+ "@symbiote-native/svelte": {
89
+ "optional": true
90
+ },
73
91
  "@symbiote-native/vue": {
74
92
  "optional": true
75
93
  },
@@ -82,24 +100,34 @@
82
100
  "react": {
83
101
  "optional": true
84
102
  },
103
+ "solid-js": {
104
+ "optional": true
105
+ },
106
+ "svelte": {
107
+ "optional": true
108
+ },
85
109
  "vue": {
86
110
  "optional": true
87
111
  }
88
112
  },
89
113
  "devDependencies": {
90
- "@angular/compiler": "^22",
91
- "@angular/compiler-cli": "^22",
92
- "@angular/core": "^22",
114
+ "@angular/compiler": "~22.0.8",
115
+ "@angular/compiler-cli": "~22.0.8",
116
+ "@angular/core": "~22.0.8",
93
117
  "@types/node": "^26.0.0",
94
118
  "@types/react": "^19.2.0",
95
119
  "@vue/runtime-core": "^3.5.13",
96
120
  "react": "19.2.3",
121
+ "solid-js": "^1.9.14",
122
+ "svelte": "^5.56.0",
97
123
  "typescript": "~6.0.0",
98
- "@symbiote-native/angular": "0.6.2",
99
- "@symbiote-native/engine": "0.1.7",
100
- "@symbiote-native/react": "0.2.8",
101
- "@symbiote-native/test-utils": "0.1.6",
102
- "@symbiote-native/vue": "0.3.8"
124
+ "@symbiote-native/angular": "0.8.0",
125
+ "@symbiote-native/engine": "0.3.0",
126
+ "@symbiote-native/react": "0.4.0",
127
+ "@symbiote-native/solid": "0.1.0",
128
+ "@symbiote-native/svelte": "0.3.0",
129
+ "@symbiote-native/test-utils": "0.2.0",
130
+ "@symbiote-native/vue": "0.5.0"
103
131
  },
104
132
  "scripts": {
105
133
  "typecheck": "tsc --build",
@@ -1,13 +1,4 @@
1
1
  // NetworkStateService is the Angular-only lifecycle half; the free functions and event
2
2
  // subscription plumbing all live in core, shared with React/Vue.
3
3
  export { NetworkStateService } from './services/network-state.service';
4
- export {
5
- getNetworkStateAsync,
6
- getIpAddressAsync,
7
- isAirplaneModeEnabledAsync,
8
- addNetworkStateListener,
9
- NetworkStateType,
10
- type NetworkState,
11
- type NetworkStateEvent,
12
- type EventSubscription,
13
- } from '../core';
4
+ export * from '../core';
@@ -1,5 +1,16 @@
1
- import { effect, inject, Injectable, Injector, signal, type Signal } from '@angular/core';
2
- import { addNetworkStateListener, getNetworkStateAsync, type NetworkState } from '../../../core';
1
+ import {
2
+ effect,
3
+ inject,
4
+ Injectable,
5
+ Injector,
6
+ signal,
7
+ type Signal,
8
+ } from '@angular/core';
9
+ import {
10
+ addNetworkStateListener,
11
+ getNetworkStateAsync,
12
+ type NetworkState,
13
+ } from '../../../core';
3
14
 
4
15
  // Angular twin of React's `useNetworkState` hook and Vue's `useNetworkState` composable.
5
16
  //
@@ -15,7 +26,9 @@ export class NetworkStateService {
15
26
  effect(
16
27
  onCleanup => {
17
28
  getNetworkStateAsync().then(state => networkState.set(state));
18
- const subscription = addNetworkStateListener(event => networkState.set(event));
29
+ const subscription = addNetworkStateListener(event =>
30
+ networkState.set(event),
31
+ );
19
32
  onCleanup(() => subscription.remove());
20
33
  },
21
34
  { injector: this.injector },
package/src/core/index.ts CHANGED
@@ -4,5 +4,9 @@ export {
4
4
  isAirplaneModeEnabledAsync,
5
5
  addNetworkStateListener,
6
6
  } from './network';
7
- export { NetworkStateType, type NetworkState, type NetworkStateEvent } from './types';
7
+ export {
8
+ NetworkStateType,
9
+ type NetworkState,
10
+ type NetworkStateEvent,
11
+ } from './types';
8
12
  export type { EventSubscription } from 'expo-modules-core';
@@ -16,4 +16,6 @@ export type INativeNetworkModule = {
16
16
  ): EventSubscription;
17
17
  };
18
18
 
19
- export const expoNetwork = requireNativeModule<INativeNetworkModule>(EXPO_NETWORK_MODULE_NAME);
19
+ export const expoNetwork = requireNativeModule<INativeNetworkModule>(
20
+ EXPO_NETWORK_MODULE_NAME,
21
+ );
@@ -29,7 +29,10 @@ export async function getIpAddressAsync(): Promise<string> {
29
29
  */
30
30
  export async function isAirplaneModeEnabledAsync(): Promise<boolean> {
31
31
  if (!expoNetwork.isAirplaneModeEnabledAsync) {
32
- throw new UnavailabilityError(NATIVE_MODULE_NAME, 'isAirplaneModeEnabledAsync');
32
+ throw new UnavailabilityError(
33
+ NATIVE_MODULE_NAME,
34
+ 'isAirplaneModeEnabledAsync',
35
+ );
33
36
  }
34
37
  return expoNetwork.isAirplaneModeEnabledAsync();
35
38
  }
@@ -2,14 +2,20 @@
2
2
  // value with a one-shot getNetworkStateAsync() call before the first native event fires, matching
3
3
  // upstream's own useNetworkState.
4
4
  import { useEffect, useState } from 'react';
5
- import { addNetworkStateListener, getNetworkStateAsync, type NetworkState } from '../../../core';
5
+ import {
6
+ addNetworkStateListener,
7
+ getNetworkStateAsync,
8
+ type NetworkState,
9
+ } from '../../../core';
6
10
 
7
11
  export function useNetworkState(): NetworkState {
8
12
  const [networkState, setNetworkState] = useState<NetworkState>({});
9
13
 
10
14
  useEffect(() => {
11
15
  getNetworkStateAsync().then(setNetworkState);
12
- const subscription = addNetworkStateListener(event => setNetworkState(event));
16
+ const subscription = addNetworkStateListener(event =>
17
+ setNetworkState(event),
18
+ );
13
19
  return () => subscription.remove();
14
20
  }, []);
15
21
 
@@ -1,13 +1,4 @@
1
1
  // @symbiote-native/network/react: the React entry over the framework-agnostic core.
2
2
 
3
3
  export { useNetworkState } from './hooks/use-network-state';
4
- export {
5
- getNetworkStateAsync,
6
- getIpAddressAsync,
7
- isAirplaneModeEnabledAsync,
8
- addNetworkStateListener,
9
- NetworkStateType,
10
- type NetworkState,
11
- type NetworkStateEvent,
12
- type EventSubscription,
13
- } from '../core';
4
+ export * from '../core';
@@ -0,0 +1,6 @@
1
+ // @symbiote-native/network/solid: the Solid entry over the framework-agnostic core — mirrors the
2
+ // lifecycle-bucket naming convention of adapters/solid/src/primitives (never `hooks`/`composables`/
3
+ // `runes`, those are React's, Vue's and Svelte's terms).
4
+
5
+ export { createNetworkState } from './primitives/create-network-state';
6
+ export * from '../core';
@@ -0,0 +1,43 @@
1
+ // createNetworkState — the Solid twin of React's `useNetworkState` hook, Vue's composable and
2
+ // Svelte's rune, over the framework-agnostic core (core/network.ts). Seeds with a one-shot
3
+ // getNetworkStateAsync() call before the first native event fires, matching upstream's own
4
+ // useNetworkState.
5
+ //
6
+ // `primitives/` and `create*`, never `hooks/`+`use*`: Solid's ecosystem calls a composable
7
+ // reactive function a PRIMITIVE and reserves `use*` for consuming something that already exists.
8
+ // Full rationale in adapters/solid/src/primitives/create-color-scheme.ts.
9
+ //
10
+ // Returns an ACCESSOR, never a snapshot: a Solid component body runs ONCE, so a returned object
11
+ // would pin the caller to the empty seed forever.
12
+ //
13
+ // Outside a component or `createRoot` there is no owner for `onCleanup` — Solid warns and the
14
+ // native listener lives for the process. The accessor still tracks; only the teardown is lost.
15
+
16
+ import { createSignal, onCleanup, type Accessor } from 'solid-js';
17
+ import {
18
+ addNetworkStateListener,
19
+ getNetworkStateAsync,
20
+ type EventSubscription,
21
+ type NetworkState,
22
+ } from '../../core';
23
+
24
+ export function createNetworkState(): Accessor<NetworkState> {
25
+ const [networkState, setNetworkState] = createSignal<NetworkState>({});
26
+
27
+ getNetworkStateAsync().then(state => {
28
+ setNetworkState(state);
29
+ });
30
+
31
+ // Subscribed from the primitive body, not from an effect: React/Vue/Svelte start listening a
32
+ // tick after their seed runs, so a change landing in that window is lost. Both statements here
33
+ // run in one synchronous tick and nothing can interleave.
34
+ const subscription: EventSubscription = addNetworkStateListener(event => {
35
+ setNetworkState(event);
36
+ });
37
+
38
+ onCleanup(() => {
39
+ subscription.remove();
40
+ });
41
+
42
+ return networkState;
43
+ }
@@ -0,0 +1,6 @@
1
+ // @symbiote-native/network/svelte: the Svelte entry over the framework-agnostic core — mirrors the
2
+ // lifecycle-bucket naming convention of adapters/svelte/src/runes (never `hooks`/`composables`,
3
+ // those are React's and Vue's terms).
4
+
5
+ export { useNetworkState } from './runes/use-network-state.svelte';
6
+ export * from '../core';
@@ -0,0 +1,37 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic core (core/network.ts). Seeds the initial
2
+ // value with a one-shot getNetworkStateAsync() call before the first native event fires, matching
3
+ // upstream's own useNetworkState and the Vue composable's onMounted half.
4
+ //
5
+ // `.svelte.ts` extension: runes ($state/$effect) only work there outside a `.svelte` component;
6
+ // `runes/` is Svelte's name for the lifecycle bucket (React's `hooks/`, Vue's `composables/`).
7
+ // Returns a boxed getter, not a bare `$state`: Svelte 5 reactivity is lexically scoped to the
8
+ // declaring module and doesn't survive being returned raw from a plain function, so the caller
9
+ // reads `.current` like unwrapping Vue's `Ref` via `.value`.
10
+ import {
11
+ addNetworkStateListener,
12
+ getNetworkStateAsync,
13
+ type EventSubscription,
14
+ type NetworkState,
15
+ } from '../../core';
16
+
17
+ export function useNetworkState(): { readonly current: NetworkState } {
18
+ let networkState = $state<NetworkState>({});
19
+
20
+ $effect(() => {
21
+ // Write-only touches of `networkState`, so the effect has no dependency on it and runs once
22
+ // per mount - the twin of Vue's onMounted/onUnmounted pair.
23
+ getNetworkStateAsync().then(state => {
24
+ networkState = state;
25
+ });
26
+ const subscription: EventSubscription = addNetworkStateListener(event => {
27
+ networkState = event;
28
+ });
29
+ return () => subscription.remove();
30
+ });
31
+
32
+ return {
33
+ get current(): NetworkState {
34
+ return networkState;
35
+ },
36
+ };
37
+ }
@@ -0,0 +1,6 @@
1
+ // Pulls in svelte's ambient global declarations ($state/$effect/...) for this package's tsc
2
+ // program. adapters/svelte gets these for free because render.ts does a real value import from
3
+ // 'svelte' (any file in a program importing a module loads its ambient globals for the whole
4
+ // program); this package has no such import, so a triple-slash reference does the same job
5
+ // explicitly rather than relying on an incidental side-effect.
6
+ /// <reference types="svelte" />
package/src/vue/index.ts CHANGED
@@ -1,13 +1,4 @@
1
1
  // @symbiote-native/network/vue: the Vue entry over the framework-agnostic core.
2
2
 
3
3
  export { useNetworkState } from './composables/use-network-state';
4
- export {
5
- getNetworkStateAsync,
6
- getIpAddressAsync,
7
- isAirplaneModeEnabledAsync,
8
- addNetworkStateListener,
9
- NetworkStateType,
10
- type NetworkState,
11
- type NetworkStateEvent,
12
- type EventSubscription,
13
- } from '../core';
4
+ export * from '../core';