@symbiote-native/localization 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.
- package/README.md +54 -17
- package/build/angular/index.d.ts +1 -1
- package/build/angular/index.js +1 -1
- package/build/angular/services/calendars.service/index.js +2 -2
- package/build/angular/services/locales.service/index.js +1 -1
- package/build/core/index.d.ts +1 -1
- package/build/core/index.js +1 -1
- package/build/core/native-module.js +4 -6
- package/build/react/hooks/use-calendars/index.js +1 -1
- package/build/react/index.d.ts +1 -1
- package/build/react/index.js +1 -1
- package/build/solid/index.d.ts +3 -0
- package/build/solid/index.js +8 -0
- package/build/solid/primitives/create-calendars.d.ts +3 -0
- package/build/solid/primitives/create-calendars.js +14 -0
- package/build/solid/primitives/create-locales.d.ts +3 -0
- package/build/solid/primitives/create-locales.js +24 -0
- package/build/svelte/index.d.ts +3 -0
- package/build/svelte/index.js +8 -0
- package/build/svelte/runes/use-calendars.svelte.d.ts +4 -0
- package/build/svelte/runes/use-calendars.svelte.js +21 -0
- package/build/svelte/runes/use-locales.svelte.d.ts +4 -0
- package/build/svelte/runes/use-locales.svelte.js +27 -0
- package/build/vue/composables/use-locales/index.js +1 -1
- package/build/vue/index.d.ts +1 -1
- package/build/vue/index.js +1 -1
- package/build-ngc/angular/index.d.ts +1 -1
- package/build-ngc/angular/index.js +1 -1
- package/build-ngc/angular/index.js.map +1 -1
- package/build-ngc/angular/services/calendars.service/index.js +5 -5
- package/build-ngc/angular/services/calendars.service/index.js.map +1 -1
- package/build-ngc/angular/services/locales.service/index.js +4 -4
- package/build-ngc/angular/services/locales.service/index.js.map +1 -1
- package/build-ngc/core/index.d.ts +1 -1
- package/build-ngc/core/index.js +1 -1
- package/build-ngc/core/index.js.map +1 -1
- package/build-ngc/core/localization.js.map +1 -1
- package/build-ngc/core/native-module.js +4 -6
- package/build-ngc/core/native-module.js.map +1 -1
- package/package.json +42 -14
- package/src/angular/index.ts +1 -11
- package/src/angular/services/calendars.service/index.ts +16 -3
- package/src/angular/services/locales.service/index.ts +8 -1
- package/src/core/index.ts +6 -1
- package/src/core/localization.ts +2 -1
- package/src/core/native-module.ts +15 -9
- package/src/react/hooks/use-calendars/index.ts +5 -1
- package/src/react/index.ts +1 -11
- package/src/solid/index.ts +9 -0
- package/src/solid/primitives/create-calendars.ts +23 -0
- package/src/solid/primitives/create-locales.ts +33 -0
- package/src/svelte/index.ts +9 -0
- package/src/svelte/runes/use-calendars.svelte.ts +29 -0
- package/src/svelte/runes/use-locales.svelte.ts +35 -0
- package/src/svelte/svelte-ambient.d.ts +6 -0
- package/src/vue/composables/use-locales/index.ts +6 -1
- package/src/vue/index.ts +1 -11
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Port of [`expo-localization`](https://docs.expo.dev/versions/latest/sdk/localization/) for
|
|
4
4
|
[SymbioteNative](../../README.md) — the device's locale list and preferred calendar settings,
|
|
5
|
-
reachable from every adapter (React, Vue, Angular), not just React.
|
|
5
|
+
reachable from every adapter (React, Vue, Svelte, Solid, Angular), not just React.
|
|
6
6
|
|
|
7
7
|
Built the same way as [`@symbiote-native/battery`](../battery) and
|
|
8
8
|
[`@symbiote-native/device`](../device), an `expo-modules-core`-based wrapper (see the
|
|
@@ -29,12 +29,12 @@ Unlike a plain RN native module, `expo-localization`'s native code is discovered
|
|
|
29
29
|
into the native host app **once**, covering this package and every other `expo-modules-core`
|
|
30
30
|
package (`@symbiote-native/battery`, `@symbiote-native/device`, ...) with zero further changes:
|
|
31
31
|
|
|
32
|
-
| Platform | Touches
|
|
33
|
-
|
|
34
|
-
| iOS
|
|
35
|
-
| iOS
|
|
36
|
-
| Android
|
|
37
|
-
| Android
|
|
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,13 +55,18 @@ src/core/ types.ts — Locale, Weekday, CalendarIdentifier, Calend
|
|
|
55
55
|
native module.
|
|
56
56
|
src/react/hooks/ @symbiote-native/localization/react — useLocales, useCalendars
|
|
57
57
|
src/vue/composables/ @symbiote-native/localization/vue — same two names, Vue lifecycle
|
|
58
|
+
src/svelte/runes/ @symbiote-native/localization/svelte — same two names, read as `.current`
|
|
59
|
+
src/solid/primitives/ @symbiote-native/localization/solid — createLocales, createCalendars
|
|
60
|
+
(each returns an Accessor)
|
|
58
61
|
src/angular/services/ @symbiote-native/localization/angular — LocalesService, CalendarsService
|
|
59
62
|
(`.connect()` returns a Signal)
|
|
60
63
|
```
|
|
61
64
|
|
|
62
65
|
Two independent getters, each with its own native change listener and its own reactive hook per
|
|
63
66
|
adapter — mirroring `@symbiote-native/battery`'s shape of shipping several distinct hooks in one
|
|
64
|
-
package, not one combined hook.
|
|
67
|
+
package, not one combined hook. Solid's naming differs on purpose: `create*`, not `use*`, which
|
|
68
|
+
Solid reserves for consuming something that already exists. Each hook/composable/rune/primitive/
|
|
69
|
+
service seeds its return value from the
|
|
65
70
|
matching synchronous `get*()` call (no initial "loading" state needed — the native call is
|
|
66
71
|
sync, not async) and recomputes it whenever the matching listener fires.
|
|
67
72
|
|
|
@@ -72,8 +77,8 @@ sync, not async) and recomputes it whenever the matching listener fires.
|
|
|
72
77
|
import { useLocales, useCalendars } from '@symbiote-native/localization/react';
|
|
73
78
|
|
|
74
79
|
function LocalizationScreen() {
|
|
75
|
-
const locales = useLocales();
|
|
76
|
-
const calendars = useCalendars();
|
|
80
|
+
const locales = useLocales(); // Locale[], guaranteed at least 1 element
|
|
81
|
+
const calendars = useCalendars(); // Calendar[], guaranteed at least 1 element
|
|
77
82
|
|
|
78
83
|
return (
|
|
79
84
|
<>
|
|
@@ -89,7 +94,7 @@ function LocalizationScreen() {
|
|
|
89
94
|
<script setup lang="ts">
|
|
90
95
|
import { useLocales, useCalendars } from '@symbiote-native/localization/vue';
|
|
91
96
|
|
|
92
|
-
const locales = useLocales();
|
|
97
|
+
const locales = useLocales(); // Ref<Locale[]>
|
|
93
98
|
const calendars = useCalendars(); // Ref<Calendar[]>
|
|
94
99
|
</script>
|
|
95
100
|
<template>
|
|
@@ -98,15 +103,39 @@ const calendars = useCalendars(); // Ref<Calendar[]>
|
|
|
98
103
|
</template>
|
|
99
104
|
```
|
|
100
105
|
|
|
106
|
+
```tsx
|
|
107
|
+
// Solid — an accessor per getter; call it to read, so a component body that runs once still
|
|
108
|
+
// re-renders the leaf that reads it.
|
|
109
|
+
import {
|
|
110
|
+
createLocales,
|
|
111
|
+
createCalendars,
|
|
112
|
+
} from '@symbiote-native/localization/solid';
|
|
113
|
+
|
|
114
|
+
function LocalizationScreen() {
|
|
115
|
+
const locales = createLocales(); // Accessor<Locale[]>
|
|
116
|
+
const calendars = createCalendars(); // Accessor<Calendar[]>
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<>
|
|
120
|
+
<Text>{locales()[0].languageTag}</Text>
|
|
121
|
+
<Text>{calendars()[0].timeZone}</Text>
|
|
122
|
+
</>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
101
127
|
```ts
|
|
102
128
|
// Angular — examples/expo-angular/src/screens/LocalizationScreen.ts
|
|
103
129
|
import { Component, inject } from '@angular/core';
|
|
104
|
-
import {
|
|
130
|
+
import {
|
|
131
|
+
LocalesService,
|
|
132
|
+
CalendarsService,
|
|
133
|
+
} from '@symbiote-native/localization/angular';
|
|
105
134
|
|
|
106
|
-
@Component({
|
|
135
|
+
@Component({/* ... */})
|
|
107
136
|
export class LocalizationScreen {
|
|
108
|
-
readonly locales = inject(LocalesService).connect();
|
|
109
|
-
readonly calendars = inject(CalendarsService).connect();
|
|
137
|
+
readonly locales = inject(LocalesService).connect(); // Signal<Locale[]>
|
|
138
|
+
readonly calendars = inject(CalendarsService).connect(); // Signal<Calendar[]>
|
|
110
139
|
}
|
|
111
140
|
```
|
|
112
141
|
|
|
@@ -134,7 +163,15 @@ import { getLocales, getCalendars } from '@symbiote-native/localization';
|
|
|
134
163
|
// hook/composable/service per getter:
|
|
135
164
|
import { useLocales, useCalendars } from '@symbiote-native/localization/react';
|
|
136
165
|
import { useLocales, useCalendars } from '@symbiote-native/localization/vue';
|
|
137
|
-
import {
|
|
166
|
+
import { useLocales, useCalendars } from '@symbiote-native/localization/svelte';
|
|
167
|
+
import {
|
|
168
|
+
createLocales,
|
|
169
|
+
createCalendars,
|
|
170
|
+
} from '@symbiote-native/localization/solid';
|
|
171
|
+
import {
|
|
172
|
+
LocalesService,
|
|
173
|
+
CalendarsService,
|
|
174
|
+
} from '@symbiote-native/localization/angular';
|
|
138
175
|
```
|
|
139
176
|
|
|
140
177
|
Each hook/composable/service seeds its initial value from the matching synchronous `get*()`
|
|
@@ -146,7 +183,7 @@ mirroring upstream's own `useLocales`/`useCalendars`.
|
|
|
146
183
|
No Fabric/Descriptor angle at all — localization is a pure synchronous-function + `EventEmitter`
|
|
147
184
|
listener surface, never a view. Tests inject a fake native-module object in place of the real
|
|
148
185
|
`requireNativeModule` resolution (`src/core/localization.test.ts`,
|
|
149
|
-
`src/{react,vue,angular}/**/*.test.{ts,tsx}`, `vitest`), the same pattern
|
|
186
|
+
`src/{react,vue,svelte,solid,angular}/**/*.test.{ts,tsx}`, `vitest`), the same pattern
|
|
150
187
|
`@symbiote-native/battery` and `@symbiote-native/device` use — no `installFabric()`, no
|
|
151
188
|
ViewConfig for the core test; the adapter hook/composable/service tests do use `installFabric()`
|
|
152
189
|
purely to mount a host component, same as every other sibling package. Native rendering itself is
|
package/build/angular/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { LocalesService } from './services/locales.service';
|
|
2
2
|
export { CalendarsService } from './services/calendars.service';
|
|
3
|
-
export
|
|
3
|
+
export * from '../core';
|
package/build/angular/index.js
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
// hooks.
|
|
5
5
|
export { LocalesService } from './services/locales.service/index.js';
|
|
6
6
|
export { CalendarsService } from './services/calendars.service/index.js';
|
|
7
|
-
export
|
|
7
|
+
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 { addCalendarListener, getCalendars } from '../../../core/index.js';
|
|
35
|
+
import { effect, inject, Injectable, Injector, signal, } from '@angular/core';
|
|
36
|
+
import { addCalendarListener, getCalendars, } from '../../../core/index.js';
|
|
37
37
|
// Angular twin of React's `useCalendars` hook and Vue's `useCalendars` composable — mirrors
|
|
38
38
|
// LocalesService's shape exactly.
|
|
39
39
|
//
|
|
@@ -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 { addLocaleListener, getLocales } from '../../../core/index.js';
|
|
37
37
|
// Angular twin of React's `useLocales` hook and Vue's `useLocales` composable. See
|
|
38
38
|
// packages/battery's BatteryStateService for the `connect()` pattern rationale. getLocales() is
|
package/build/core/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { getLocales, getCalendars } from './localization';
|
|
2
2
|
export { addLocaleListener, addCalendarListener } from './native-module';
|
|
3
|
-
export { Weekday, CalendarIdentifier, type Locale, type Calendar } from './types';
|
|
3
|
+
export { Weekday, CalendarIdentifier, type Locale, type Calendar, } from './types';
|
|
4
4
|
export type { EventSubscription } from 'expo-modules-core';
|
package/build/core/index.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
// Hand-ported from .vendors/expo/packages/expo-localization/src/ExpoLocalization.native.ts
|
|
2
|
-
// (sdk-57). getLocales()/getCalendars() are synchronous, JSI-bridged native calls (no await)
|
|
3
|
-
//
|
|
4
|
-
// read pattern this repo already uses for expo-device's eagerly-resolved fields
|
|
2
|
+
// (sdk-57). getLocales()/getCalendars() are synchronous, JSI-bridged native calls (no await) -
|
|
3
|
+
// same constants-style read pattern as expo-device's eagerly-resolved fields
|
|
5
4
|
// (packages/device/src/core/native-module.ts). One native module fans out two independent event
|
|
6
|
-
// streams (locale
|
|
7
|
-
//
|
|
8
|
-
// packages/battery/src/core/native-module.ts.
|
|
5
|
+
// streams (locale vs calendar settings) through the same addListener, keyed by event name -
|
|
6
|
+
// mirrors the overload trick in packages/battery/src/core/native-module.ts.
|
|
9
7
|
import { requireNativeModule } from 'expo-modules-core';
|
|
10
8
|
const EXPO_LOCALIZATION_MODULE_NAME = 'ExpoLocalization';
|
|
11
9
|
const ExpoLocalizationModule = requireNativeModule(EXPO_LOCALIZATION_MODULE_NAME);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// React lifecycle wiring over the framework-agnostic core — mirrors use-locales' shape exactly.
|
|
2
2
|
// Ported from expo-localization's own useCalendars hook (sdk-57).
|
|
3
3
|
import { useEffect, useMemo, useReducer } from 'react';
|
|
4
|
-
import { addCalendarListener, getCalendars } from '../../../core/index.js';
|
|
4
|
+
import { addCalendarListener, getCalendars, } from '../../../core/index.js';
|
|
5
5
|
export function useCalendars() {
|
|
6
6
|
const [invalidationKey, invalidate] = useReducer((key) => key + 1, 0);
|
|
7
7
|
const calendars = useMemo(() => getCalendars(), [invalidationKey]);
|
package/build/react/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { useLocales } from './hooks/use-locales';
|
|
2
2
|
export { useCalendars } from './hooks/use-calendars';
|
|
3
|
-
export
|
|
3
|
+
export * from '../core';
|
package/build/react/index.js
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
// naming convention of adapters/react/src/hooks (never `composables`, that's Vue's term).
|
|
5
5
|
export { useLocales } from './hooks/use-locales/index.js';
|
|
6
6
|
export { useCalendars } from './hooks/use-calendars/index.js';
|
|
7
|
-
export
|
|
7
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// @symbiote-native/localization/solid: the Solid entry over the framework-agnostic core. Locales
|
|
2
|
+
// and calendars each get their own primitive, matching upstream's own useLocales/useCalendars
|
|
3
|
+
// being two separate hooks, not one combined hook — mirrors the lifecycle-bucket naming of
|
|
4
|
+
// adapters/solid/src/primitives (never `hooks/`/`composables/`/`runes/`, and `create*` rather
|
|
5
|
+
// than `use*`, which Solid reserves for consuming something that already exists).
|
|
6
|
+
export { createLocales } from './primitives/create-locales.js';
|
|
7
|
+
export { createCalendars } from './primitives/create-calendars.js';
|
|
8
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Solid lifecycle wiring over the framework-agnostic core (core/localization.ts) — mirrors
|
|
2
|
+
// create-locales' shape exactly, including why no seed-vs-event guard is needed here.
|
|
3
|
+
import { createSignal, onCleanup } from 'solid-js';
|
|
4
|
+
import { addCalendarListener, getCalendars, } from '../../core/index.js';
|
|
5
|
+
export function createCalendars() {
|
|
6
|
+
const [calendars, setCalendars] = createSignal(getCalendars());
|
|
7
|
+
const subscription = addCalendarListener(() => {
|
|
8
|
+
setCalendars(getCalendars());
|
|
9
|
+
});
|
|
10
|
+
onCleanup(() => {
|
|
11
|
+
subscription.remove();
|
|
12
|
+
});
|
|
13
|
+
return calendars;
|
|
14
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Solid lifecycle wiring over the framework-agnostic core (core/localization.ts) — the twin of
|
|
2
|
+
// react/hooks/use-locales, vue/composables/use-locales and svelte/runes/use-locales.svelte. See
|
|
3
|
+
// adapters/solid/src/primitives/create-color-scheme.ts for why the bucket is `primitives/` and
|
|
4
|
+
// the name is `create*` rather than `use*`.
|
|
5
|
+
//
|
|
6
|
+
// Returns an ACCESSOR, never a snapshot: a Solid component body runs ONCE, so a returned array
|
|
7
|
+
// would pin the screen to the locale list the app booted with.
|
|
8
|
+
//
|
|
9
|
+
// getLocales() is a SYNCHRONOUS native read, so seed and subscribe both happen inline in the body
|
|
10
|
+
// and there is no seed-vs-event race to guard (unlike the battery primitives, whose seed is a
|
|
11
|
+
// promise) — and no re-read on mount either, which the Vue and Svelte twins need only because
|
|
12
|
+
// their subscription is deferred to an effect.
|
|
13
|
+
import { createSignal, onCleanup } from 'solid-js';
|
|
14
|
+
import { addLocaleListener, getLocales, } from '../../core/index.js';
|
|
15
|
+
export function createLocales() {
|
|
16
|
+
const [locales, setLocales] = createSignal(getLocales());
|
|
17
|
+
const subscription = addLocaleListener(() => {
|
|
18
|
+
setLocales(getLocales());
|
|
19
|
+
});
|
|
20
|
+
onCleanup(() => {
|
|
21
|
+
subscription.remove();
|
|
22
|
+
});
|
|
23
|
+
return locales;
|
|
24
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// @symbiote-native/localization/svelte: the Svelte entry over the framework-agnostic core. Locales
|
|
2
|
+
// and calendars each get their own lifecycle rune, matching upstream's own useLocales/
|
|
3
|
+
// useCalendars being two separate hooks, not one combined hook — mirrors the lifecycle-bucket
|
|
4
|
+
// naming convention of adapters/svelte/src/runes (never `hooks`/`composables`, those are React's
|
|
5
|
+
// and Vue's terms).
|
|
6
|
+
export { useLocales } from './runes/use-locales.svelte';
|
|
7
|
+
export { useCalendars } from './runes/use-calendars.svelte';
|
|
8
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Svelte lifecycle wiring over the framework-agnostic core — mirrors use-locales' shape exactly.
|
|
2
|
+
// See use-locales.svelte.ts's header for why this lives in `runes/` with a `.svelte.ts` extension
|
|
3
|
+
// and returns a boxed getter object instead of a bare `$state` variable.
|
|
4
|
+
import { addCalendarListener, getCalendars, } from '../../core/index.js';
|
|
5
|
+
export function useCalendars() {
|
|
6
|
+
let calendars = $state(getCalendars());
|
|
7
|
+
$effect(() => {
|
|
8
|
+
// Write-only touch of `calendars` (see use-locales.svelte.ts) — the effect stays
|
|
9
|
+
// dependency-free and so runs once on mount, cleaning up once on unmount.
|
|
10
|
+
calendars = getCalendars();
|
|
11
|
+
const subscription = addCalendarListener(() => {
|
|
12
|
+
calendars = getCalendars();
|
|
13
|
+
});
|
|
14
|
+
return () => subscription.remove();
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
get current() {
|
|
18
|
+
return calendars;
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Svelte lifecycle wiring over the framework-agnostic core (core/localization.ts). getLocales()
|
|
2
|
+
// is a synchronous native call, so state is seeded at call time - the `$effect` only wires the
|
|
3
|
+
// change listener, the twin of Vue's onMounted/onUnmounted pair.
|
|
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 { addLocaleListener, getLocales, } from '../../core/index.js';
|
|
11
|
+
export function useLocales() {
|
|
12
|
+
let locales = $state(getLocales());
|
|
13
|
+
$effect(() => {
|
|
14
|
+
// Re-read on mount in case locales changed between this call and the effect running. This
|
|
15
|
+
// write never reads `locales`, so the effect has no dependency on it and fires once per mount.
|
|
16
|
+
locales = getLocales();
|
|
17
|
+
const subscription = addLocaleListener(() => {
|
|
18
|
+
locales = getLocales();
|
|
19
|
+
});
|
|
20
|
+
return () => subscription.remove();
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
get current() {
|
|
24
|
+
return locales;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// setup — onMounted only wires the change listener, mirroring use-network-state's
|
|
5
5
|
// onMounted/onUnmounted subscription shape otherwise.
|
|
6
6
|
import { onMounted, onUnmounted, ref } from '@vue/runtime-core';
|
|
7
|
-
import { addLocaleListener, getLocales } from '../../../core/index.js';
|
|
7
|
+
import { addLocaleListener, getLocales, } from '../../../core/index.js';
|
|
8
8
|
export function useLocales() {
|
|
9
9
|
const locales = ref(getLocales());
|
|
10
10
|
let subscription;
|
package/build/vue/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { useLocales } from './composables/use-locales';
|
|
2
2
|
export { useCalendars } from './composables/use-calendars';
|
|
3
|
-
export
|
|
3
|
+
export * from '../core';
|
package/build/vue/index.js
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
// naming convention of adapters/vue/src/composables (never `hooks`, that's React's term).
|
|
5
5
|
export { useLocales } from './composables/use-locales/index.js';
|
|
6
6
|
export { useCalendars } from './composables/use-calendars/index.js';
|
|
7
|
-
export
|
|
7
|
+
export * from '../core/index.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { LocalesService } from './services/locales.service';
|
|
2
2
|
export { CalendarsService } from './services/calendars.service';
|
|
3
|
-
export
|
|
3
|
+
export * from '../core';
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
// hooks.
|
|
5
5
|
export { LocalesService } from './services/locales.service';
|
|
6
6
|
export { CalendarsService } from './services/calendars.service';
|
|
7
|
-
export
|
|
7
|
+
export * from '../core';
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,6FAA6F;AAC7F,iGAAiG;AACjG,SAAS;AACT,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,6FAA6F;AAC7F,iGAAiG;AACjG,SAAS;AACT,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,cAAc,SAAS,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { effect, inject, Injectable, Injector, signal } from '@angular/core';
|
|
2
|
-
import { addCalendarListener, getCalendars } from '../../../core';
|
|
1
|
+
import { effect, inject, Injectable, Injector, signal, } from '@angular/core';
|
|
2
|
+
import { addCalendarListener, getCalendars, } from '../../../core';
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
4
|
// Angular twin of React's `useCalendars` hook and Vue's `useCalendars` composable — mirrors
|
|
5
5
|
// LocalesService's shape exactly.
|
|
@@ -17,10 +17,10 @@ export class CalendarsService {
|
|
|
17
17
|
}, { injector: this.injector });
|
|
18
18
|
return calendars.asReadonly();
|
|
19
19
|
}
|
|
20
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
21
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.
|
|
20
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CalendarsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
21
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CalendarsService, providedIn: 'root' });
|
|
22
22
|
}
|
|
23
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
23
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CalendarsService, 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/calendars.service/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/angular/services/calendars.service/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,MAAM,EACN,UAAU,EACV,QAAQ,EACR,MAAM,GAEP,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,mBAAmB,EACnB,YAAY,GAEb,MAAM,eAAe,CAAC;;AAEvB,4FAA4F;AAC5F,kCAAkC;AAClC,EAAE;AACF,6DAA6D;AAC7D,mCAAmC;AAEnC,MAAM,OAAO,gBAAgB;IACV,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO;QACL,MAAM,SAAS,GAAG,MAAM,CAAa,YAAY,EAAE;sFAAC,CAAC;QAErD,MAAM,CACJ,SAAS,CAAC,EAAE;YACV,MAAM,YAAY,GAAG,mBAAmB,CAAC,GAAG,EAAE,CAC5C,SAAS,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAC9B,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,SAAS,CAAC,UAAU,EAAE,CAAC;IAChC,CAAC;uGAjBU,gBAAgB;2GAAhB,gBAAgB,cADH,MAAM;;2FACnB,gBAAgB;kBAD5B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE"}
|
|
@@ -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 { addLocaleListener, getLocales } from '../../../core';
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
4
|
// Angular twin of React's `useLocales` hook and Vue's `useLocales` composable. See
|
|
@@ -18,10 +18,10 @@ export class LocalesService {
|
|
|
18
18
|
}, { injector: this.injector });
|
|
19
19
|
return locales.asReadonly();
|
|
20
20
|
}
|
|
21
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
22
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.
|
|
21
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: LocalesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
22
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: LocalesService, providedIn: 'root' });
|
|
23
23
|
}
|
|
24
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
24
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: LocalesService, decorators: [{
|
|
25
25
|
type: Injectable,
|
|
26
26
|
args: [{ providedIn: 'root' }]
|
|
27
27
|
}] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/angular/services/locales.service/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/angular/services/locales.service/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,MAAM,EACN,UAAU,EACV,QAAQ,EACR,MAAM,GAEP,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAe,MAAM,eAAe,CAAC;;AAE3E,mFAAmF;AACnF,gGAAgG;AAChG,0FAA0F;AAC1F,EAAE;AACF,yDAAyD;AACzD,iCAAiC;AAEjC,MAAM,OAAO,cAAc;IACR,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO;QACL,MAAM,OAAO,GAAG,MAAM,CAAW,UAAU,EAAE;oFAAC,CAAC;QAE/C,MAAM,CACJ,SAAS,CAAC,EAAE;YACV,MAAM,YAAY,GAAG,iBAAiB,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YACxE,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,OAAO,CAAC,UAAU,EAAE,CAAC;IAC9B,CAAC;uGAfU,cAAc;2GAAd,cAAc,cADD,MAAM;;2FACnB,cAAc;kBAD1B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { getLocales, getCalendars } from './localization';
|
|
2
2
|
export { addLocaleListener, addCalendarListener } from './native-module';
|
|
3
|
-
export { Weekday, CalendarIdentifier, type Locale, type Calendar } from './types';
|
|
3
|
+
export { Weekday, CalendarIdentifier, type Locale, type Calendar, } from './types';
|
|
4
4
|
export type { EventSubscription } from 'expo-modules-core';
|
package/build-ngc/core/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { getLocales, getCalendars } from './localization';
|
|
2
2
|
export { addLocaleListener, addCalendarListener } from './native-module';
|
|
3
|
-
export { Weekday, CalendarIdentifier } from './types';
|
|
3
|
+
export { Weekday, CalendarIdentifier, } from './types';
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EACL,OAAO,EACP,kBAAkB,GAGnB,MAAM,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localization.js","sourceRoot":"","sources":["../../src/core/localization.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,gGAAgG;AAChG,+BAA+B;AAC/B,OAAO,sBAAsB,MAAM,iBAAiB,CAAC;AAGrD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAmB,sBAAsB,CAAC,UAAU,CAAC;AAE5E;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"localization.js","sourceRoot":"","sources":["../../src/core/localization.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,gGAAgG;AAChG,+BAA+B;AAC/B,OAAO,sBAAsB,MAAM,iBAAiB,CAAC;AAGrD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAmB,sBAAsB,CAAC,UAAU,CAAC;AAE5E;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GACvB,sBAAsB,CAAC,YAAY,CAAC"}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
// Hand-ported from .vendors/expo/packages/expo-localization/src/ExpoLocalization.native.ts
|
|
2
|
-
// (sdk-57). getLocales()/getCalendars() are synchronous, JSI-bridged native calls (no await)
|
|
3
|
-
//
|
|
4
|
-
// read pattern this repo already uses for expo-device's eagerly-resolved fields
|
|
2
|
+
// (sdk-57). getLocales()/getCalendars() are synchronous, JSI-bridged native calls (no await) -
|
|
3
|
+
// same constants-style read pattern as expo-device's eagerly-resolved fields
|
|
5
4
|
// (packages/device/src/core/native-module.ts). One native module fans out two independent event
|
|
6
|
-
// streams (locale
|
|
7
|
-
//
|
|
8
|
-
// packages/battery/src/core/native-module.ts.
|
|
5
|
+
// streams (locale vs calendar settings) through the same addListener, keyed by event name -
|
|
6
|
+
// mirrors the overload trick in packages/battery/src/core/native-module.ts.
|
|
9
7
|
import { requireNativeModule } from 'expo-modules-core';
|
|
10
8
|
const EXPO_LOCALIZATION_MODULE_NAME = 'ExpoLocalization';
|
|
11
9
|
const ExpoLocalizationModule = requireNativeModule(EXPO_LOCALIZATION_MODULE_NAME);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-module.js","sourceRoot":"","sources":["../../src/core/native-module.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,+FAA+F;AAC/F
|
|
1
|
+
{"version":3,"file":"native-module.js","sourceRoot":"","sources":["../../src/core/native-module.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,+FAA+F;AAC/F,6EAA6E;AAC7E,gGAAgG;AAChG,4FAA4F;AAC5F,4EAA4E;AAC5E,OAAO,EAA0B,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGhF,MAAM,6BAA6B,GAAG,kBAAkB,CAAC;AAezD,MAAM,sBAAsB,GAAG,mBAAmB,CAChD,6BAA6B,CAC9B,CAAC;AAEF,MAAM,UAAU,iBAAiB;AAC/B,oFAAoF;AACpF,iFAAiF;AACjF,QAAmC;IAEnC,OAAO,sBAAsB,CAAC,WAAW,CACvC,yBAAyB,EACzB,QAAQ,CACT,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,QAAmC;IAEnC,OAAO,sBAAsB,CAAC,WAAW,CACvC,2BAA2B,EAC3B,QAAQ,CACT,CAAC;AACJ,CAAC;AAED,eAAe,sBAAsB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/localization",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "expo-localization wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, and Angular adapters. Two independent synchronous getters (getLocales, getCalendars), each with its own native change listener and its own reactive hook per adapter.",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "expo-localization wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. Two independent synchronous getters (getLocales, getCalendars), each with its own native change listener and its own reactive hook per adapter.",
|
|
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
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
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": "
|
|
91
|
-
"@angular/compiler-cli": "
|
|
92
|
-
"@angular/core": "
|
|
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.
|
|
99
|
-
"@symbiote-native/engine": "0.
|
|
100
|
-
"@symbiote-native/react": "0.
|
|
101
|
-
"@symbiote-native/
|
|
102
|
-
"@symbiote-native/
|
|
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",
|
package/src/angular/index.ts
CHANGED
|
@@ -4,14 +4,4 @@
|
|
|
4
4
|
// hooks.
|
|
5
5
|
export { LocalesService } from './services/locales.service';
|
|
6
6
|
export { CalendarsService } from './services/calendars.service';
|
|
7
|
-
export
|
|
8
|
-
getLocales,
|
|
9
|
-
getCalendars,
|
|
10
|
-
addLocaleListener,
|
|
11
|
-
addCalendarListener,
|
|
12
|
-
Weekday,
|
|
13
|
-
CalendarIdentifier,
|
|
14
|
-
type Locale,
|
|
15
|
-
type Calendar,
|
|
16
|
-
type EventSubscription,
|
|
17
|
-
} from '../core';
|
|
7
|
+
export * from '../core';
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
effect,
|
|
3
|
+
inject,
|
|
4
|
+
Injectable,
|
|
5
|
+
Injector,
|
|
6
|
+
signal,
|
|
7
|
+
type Signal,
|
|
8
|
+
} from '@angular/core';
|
|
9
|
+
import {
|
|
10
|
+
addCalendarListener,
|
|
11
|
+
getCalendars,
|
|
12
|
+
type Calendar,
|
|
13
|
+
} from '../../../core';
|
|
3
14
|
|
|
4
15
|
// Angular twin of React's `useCalendars` hook and Vue's `useCalendars` composable — mirrors
|
|
5
16
|
// LocalesService's shape exactly.
|
|
@@ -15,7 +26,9 @@ export class CalendarsService {
|
|
|
15
26
|
|
|
16
27
|
effect(
|
|
17
28
|
onCleanup => {
|
|
18
|
-
const subscription = addCalendarListener(() =>
|
|
29
|
+
const subscription = addCalendarListener(() =>
|
|
30
|
+
calendars.set(getCalendars()),
|
|
31
|
+
);
|
|
19
32
|
onCleanup(() => subscription.remove());
|
|
20
33
|
},
|
|
21
34
|
{ injector: this.injector },
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
effect,
|
|
3
|
+
inject,
|
|
4
|
+
Injectable,
|
|
5
|
+
Injector,
|
|
6
|
+
signal,
|
|
7
|
+
type Signal,
|
|
8
|
+
} from '@angular/core';
|
|
2
9
|
import { addLocaleListener, getLocales, type Locale } from '../../../core';
|
|
3
10
|
|
|
4
11
|
// Angular twin of React's `useLocales` hook and Vue's `useLocales` composable. See
|
package/src/core/index.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export { getLocales, getCalendars } from './localization';
|
|
2
2
|
export { addLocaleListener, addCalendarListener } from './native-module';
|
|
3
|
-
export {
|
|
3
|
+
export {
|
|
4
|
+
Weekday,
|
|
5
|
+
CalendarIdentifier,
|
|
6
|
+
type Locale,
|
|
7
|
+
type Calendar,
|
|
8
|
+
} from './types';
|
|
4
9
|
export type { EventSubscription } from 'expo-modules-core';
|
package/src/core/localization.ts
CHANGED
|
@@ -42,4 +42,5 @@ export const getLocales: () => Locale[] = ExpoLocalizationModule.getLocales;
|
|
|
42
42
|
* }]
|
|
43
43
|
* ```
|
|
44
44
|
*/
|
|
45
|
-
export const getCalendars: () => Calendar[] =
|
|
45
|
+
export const getCalendars: () => Calendar[] =
|
|
46
|
+
ExpoLocalizationModule.getCalendars;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
// Hand-ported from .vendors/expo/packages/expo-localization/src/ExpoLocalization.native.ts
|
|
2
|
-
// (sdk-57). getLocales()/getCalendars() are synchronous, JSI-bridged native calls (no await)
|
|
3
|
-
//
|
|
4
|
-
// read pattern this repo already uses for expo-device's eagerly-resolved fields
|
|
2
|
+
// (sdk-57). getLocales()/getCalendars() are synchronous, JSI-bridged native calls (no await) -
|
|
3
|
+
// same constants-style read pattern as expo-device's eagerly-resolved fields
|
|
5
4
|
// (packages/device/src/core/native-module.ts). One native module fans out two independent event
|
|
6
|
-
// streams (locale
|
|
7
|
-
//
|
|
8
|
-
// packages/battery/src/core/native-module.ts.
|
|
5
|
+
// streams (locale vs calendar settings) through the same addListener, keyed by event name -
|
|
6
|
+
// mirrors the overload trick in packages/battery/src/core/native-module.ts.
|
|
9
7
|
import { type EventSubscription, requireNativeModule } from 'expo-modules-core';
|
|
10
8
|
import type { Calendar, Locale } from './types';
|
|
11
9
|
|
|
@@ -33,11 +31,19 @@ export function addLocaleListener(
|
|
|
33
31
|
// invalidate signal for useLocales/the Vue composable/the Angular service below.
|
|
34
32
|
listener: (event?: unknown) => void,
|
|
35
33
|
): EventSubscription {
|
|
36
|
-
return ExpoLocalizationModule.addListener(
|
|
34
|
+
return ExpoLocalizationModule.addListener(
|
|
35
|
+
'onLocaleSettingsChanged',
|
|
36
|
+
listener,
|
|
37
|
+
);
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
export function addCalendarListener(
|
|
40
|
-
|
|
40
|
+
export function addCalendarListener(
|
|
41
|
+
listener: (event?: unknown) => void,
|
|
42
|
+
): EventSubscription {
|
|
43
|
+
return ExpoLocalizationModule.addListener(
|
|
44
|
+
'onCalendarSettingsChanged',
|
|
45
|
+
listener,
|
|
46
|
+
);
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
export default ExpoLocalizationModule;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
// React lifecycle wiring over the framework-agnostic core — mirrors use-locales' shape exactly.
|
|
2
2
|
// Ported from expo-localization's own useCalendars hook (sdk-57).
|
|
3
3
|
import { useEffect, useMemo, useReducer } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
addCalendarListener,
|
|
6
|
+
getCalendars,
|
|
7
|
+
type Calendar,
|
|
8
|
+
} from '../../../core';
|
|
5
9
|
|
|
6
10
|
export function useCalendars(): Calendar[] {
|
|
7
11
|
const [invalidationKey, invalidate] = useReducer((key: number) => key + 1, 0);
|
package/src/react/index.ts
CHANGED
|
@@ -5,14 +5,4 @@
|
|
|
5
5
|
|
|
6
6
|
export { useLocales } from './hooks/use-locales';
|
|
7
7
|
export { useCalendars } from './hooks/use-calendars';
|
|
8
|
-
export
|
|
9
|
-
getLocales,
|
|
10
|
-
getCalendars,
|
|
11
|
-
addLocaleListener,
|
|
12
|
-
addCalendarListener,
|
|
13
|
-
Weekday,
|
|
14
|
-
CalendarIdentifier,
|
|
15
|
-
type Locale,
|
|
16
|
-
type Calendar,
|
|
17
|
-
type EventSubscription,
|
|
18
|
-
} from '../core';
|
|
8
|
+
export * from '../core';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// @symbiote-native/localization/solid: the Solid entry over the framework-agnostic core. Locales
|
|
2
|
+
// and calendars each get their own primitive, matching upstream's own useLocales/useCalendars
|
|
3
|
+
// being two separate hooks, not one combined hook — mirrors the lifecycle-bucket naming of
|
|
4
|
+
// adapters/solid/src/primitives (never `hooks/`/`composables/`/`runes/`, and `create*` rather
|
|
5
|
+
// than `use*`, which Solid reserves for consuming something that already exists).
|
|
6
|
+
|
|
7
|
+
export { createLocales } from './primitives/create-locales';
|
|
8
|
+
export { createCalendars } from './primitives/create-calendars';
|
|
9
|
+
export * from '../core';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Solid lifecycle wiring over the framework-agnostic core (core/localization.ts) — mirrors
|
|
2
|
+
// create-locales' shape exactly, including why no seed-vs-event guard is needed here.
|
|
3
|
+
import { createSignal, onCleanup, type Accessor } from 'solid-js';
|
|
4
|
+
import {
|
|
5
|
+
addCalendarListener,
|
|
6
|
+
getCalendars,
|
|
7
|
+
type Calendar,
|
|
8
|
+
type EventSubscription,
|
|
9
|
+
} from '../../core';
|
|
10
|
+
|
|
11
|
+
export function createCalendars(): Accessor<Calendar[]> {
|
|
12
|
+
const [calendars, setCalendars] = createSignal<Calendar[]>(getCalendars());
|
|
13
|
+
|
|
14
|
+
const subscription: EventSubscription = addCalendarListener(() => {
|
|
15
|
+
setCalendars(getCalendars());
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
onCleanup(() => {
|
|
19
|
+
subscription.remove();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return calendars;
|
|
23
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Solid lifecycle wiring over the framework-agnostic core (core/localization.ts) — the twin of
|
|
2
|
+
// react/hooks/use-locales, vue/composables/use-locales and svelte/runes/use-locales.svelte. See
|
|
3
|
+
// adapters/solid/src/primitives/create-color-scheme.ts for why the bucket is `primitives/` and
|
|
4
|
+
// the name is `create*` rather than `use*`.
|
|
5
|
+
//
|
|
6
|
+
// Returns an ACCESSOR, never a snapshot: a Solid component body runs ONCE, so a returned array
|
|
7
|
+
// would pin the screen to the locale list the app booted with.
|
|
8
|
+
//
|
|
9
|
+
// getLocales() is a SYNCHRONOUS native read, so seed and subscribe both happen inline in the body
|
|
10
|
+
// and there is no seed-vs-event race to guard (unlike the battery primitives, whose seed is a
|
|
11
|
+
// promise) — and no re-read on mount either, which the Vue and Svelte twins need only because
|
|
12
|
+
// their subscription is deferred to an effect.
|
|
13
|
+
import { createSignal, onCleanup, type Accessor } from 'solid-js';
|
|
14
|
+
import {
|
|
15
|
+
addLocaleListener,
|
|
16
|
+
getLocales,
|
|
17
|
+
type EventSubscription,
|
|
18
|
+
type Locale,
|
|
19
|
+
} from '../../core';
|
|
20
|
+
|
|
21
|
+
export function createLocales(): Accessor<Locale[]> {
|
|
22
|
+
const [locales, setLocales] = createSignal<Locale[]>(getLocales());
|
|
23
|
+
|
|
24
|
+
const subscription: EventSubscription = addLocaleListener(() => {
|
|
25
|
+
setLocales(getLocales());
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
onCleanup(() => {
|
|
29
|
+
subscription.remove();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return locales;
|
|
33
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// @symbiote-native/localization/svelte: the Svelte entry over the framework-agnostic core. Locales
|
|
2
|
+
// and calendars each get their own lifecycle rune, matching upstream's own useLocales/
|
|
3
|
+
// useCalendars being two separate hooks, not one combined hook — mirrors the lifecycle-bucket
|
|
4
|
+
// naming convention of adapters/svelte/src/runes (never `hooks`/`composables`, those are React's
|
|
5
|
+
// and Vue's terms).
|
|
6
|
+
|
|
7
|
+
export { useLocales } from './runes/use-locales.svelte';
|
|
8
|
+
export { useCalendars } from './runes/use-calendars.svelte';
|
|
9
|
+
export * from '../core';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Svelte lifecycle wiring over the framework-agnostic core — mirrors use-locales' shape exactly.
|
|
2
|
+
// See use-locales.svelte.ts's header for why this lives in `runes/` with a `.svelte.ts` extension
|
|
3
|
+
// and returns a boxed getter object instead of a bare `$state` variable.
|
|
4
|
+
import {
|
|
5
|
+
addCalendarListener,
|
|
6
|
+
getCalendars,
|
|
7
|
+
type Calendar,
|
|
8
|
+
type EventSubscription,
|
|
9
|
+
} from '../../core';
|
|
10
|
+
|
|
11
|
+
export function useCalendars(): { readonly current: Calendar[] } {
|
|
12
|
+
let calendars = $state<Calendar[]>(getCalendars());
|
|
13
|
+
|
|
14
|
+
$effect(() => {
|
|
15
|
+
// Write-only touch of `calendars` (see use-locales.svelte.ts) — the effect stays
|
|
16
|
+
// dependency-free and so runs once on mount, cleaning up once on unmount.
|
|
17
|
+
calendars = getCalendars();
|
|
18
|
+
const subscription: EventSubscription = addCalendarListener(() => {
|
|
19
|
+
calendars = getCalendars();
|
|
20
|
+
});
|
|
21
|
+
return () => subscription.remove();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
get current(): Calendar[] {
|
|
26
|
+
return calendars;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Svelte lifecycle wiring over the framework-agnostic core (core/localization.ts). getLocales()
|
|
2
|
+
// is a synchronous native call, so state is seeded at call time - the `$effect` only wires the
|
|
3
|
+
// change listener, the twin of Vue's onMounted/onUnmounted pair.
|
|
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
|
+
addLocaleListener,
|
|
12
|
+
getLocales,
|
|
13
|
+
type EventSubscription,
|
|
14
|
+
type Locale,
|
|
15
|
+
} from '../../core';
|
|
16
|
+
|
|
17
|
+
export function useLocales(): { readonly current: Locale[] } {
|
|
18
|
+
let locales = $state<Locale[]>(getLocales());
|
|
19
|
+
|
|
20
|
+
$effect(() => {
|
|
21
|
+
// Re-read on mount in case locales changed between this call and the effect running. This
|
|
22
|
+
// write never reads `locales`, so the effect has no dependency on it and fires once per mount.
|
|
23
|
+
locales = getLocales();
|
|
24
|
+
const subscription: EventSubscription = addLocaleListener(() => {
|
|
25
|
+
locales = getLocales();
|
|
26
|
+
});
|
|
27
|
+
return () => subscription.remove();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
get current(): Locale[] {
|
|
32
|
+
return locales;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -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" />
|
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
// setup — onMounted only wires the change listener, mirroring use-network-state's
|
|
5
5
|
// onMounted/onUnmounted subscription shape otherwise.
|
|
6
6
|
import { onMounted, onUnmounted, ref, type Ref } from '@vue/runtime-core';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
addLocaleListener,
|
|
9
|
+
getLocales,
|
|
10
|
+
type EventSubscription,
|
|
11
|
+
type Locale,
|
|
12
|
+
} from '../../../core';
|
|
8
13
|
|
|
9
14
|
export function useLocales(): Ref<Locale[]> {
|
|
10
15
|
const locales = ref<Locale[]>(getLocales());
|
package/src/vue/index.ts
CHANGED
|
@@ -5,14 +5,4 @@
|
|
|
5
5
|
|
|
6
6
|
export { useLocales } from './composables/use-locales';
|
|
7
7
|
export { useCalendars } from './composables/use-calendars';
|
|
8
|
-
export
|
|
9
|
-
getLocales,
|
|
10
|
-
getCalendars,
|
|
11
|
-
addLocaleListener,
|
|
12
|
-
addCalendarListener,
|
|
13
|
-
Weekday,
|
|
14
|
-
CalendarIdentifier,
|
|
15
|
-
type Locale,
|
|
16
|
-
type Calendar,
|
|
17
|
-
type EventSubscription,
|
|
18
|
-
} from '../core';
|
|
8
|
+
export * from '../core';
|