@sigx/lynx-appearance 0.4.1
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/LICENSE +21 -0
- package/android/com/sigx/appearance/AppearanceModule.kt +160 -0
- package/android/com/sigx/appearance/AppearancePublisher.kt +113 -0
- package/dist/globals.d.ts +21 -0
- package/dist/globals.d.ts.map +1 -0
- package/dist/globals.js +25 -0
- package/dist/globals.js.map +1 -0
- package/dist/hooks.d.ts +25 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +38 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/injectable.d.ts +16 -0
- package/dist/injectable.d.ts.map +1 -0
- package/dist/injectable.js +10 -0
- package/dist/injectable.js.map +1 -0
- package/dist/provider.d.ts +27 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +59 -0
- package/dist/provider.js.map +1 -0
- package/dist/setters.d.ts +58 -0
- package/dist/setters.d.ts.map +1 -0
- package/dist/setters.js +87 -0
- package/dist/setters.js.map +1 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/ios/AppearanceModule.swift +130 -0
- package/ios/AppearancePublisher.swift +86 -0
- package/package.json +61 -0
- package/signalx-module.json +22 -0
- package/src/globals.ts +40 -0
- package/src/hooks.ts +46 -0
- package/src/index.ts +33 -0
- package/src/injectable.ts +20 -0
- package/src/provider.tsx +89 -0
- package/src/setters.ts +87 -0
- package/src/types.ts +25 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 Andreas Ekdahl
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
package com.sigx.appearance
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.ContextWrapper
|
|
6
|
+
import android.content.res.Configuration
|
|
7
|
+
import android.graphics.Color
|
|
8
|
+
import android.os.Build
|
|
9
|
+
import android.util.Log
|
|
10
|
+
import androidx.core.view.WindowCompat
|
|
11
|
+
import androidx.core.view.WindowInsetsControllerCompat
|
|
12
|
+
import com.lynx.jsbridge.LynxMethod
|
|
13
|
+
import com.lynx.jsbridge.LynxModule
|
|
14
|
+
import com.lynx.react.bridge.Callback
|
|
15
|
+
import com.lynx.react.bridge.JavaOnlyMap
|
|
16
|
+
import com.lynx.react.bridge.ReadableMap
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* System-bar appearance setters + a sync getter for the current color scheme.
|
|
20
|
+
* JS usage:
|
|
21
|
+
* NativeModules.Appearance.setStatusBarStyle({ "style": "light" }, callback)
|
|
22
|
+
* NativeModules.Appearance.getColorScheme(callback)
|
|
23
|
+
*
|
|
24
|
+
* Status-bar / nav-bar style maps to `WindowInsetsControllerCompat`:
|
|
25
|
+
* - "light" style ⇒ light icons on a dark background ⇒
|
|
26
|
+
* isAppearanceLightStatusBars = false (the FLAG_LIGHT_STATUS_BAR meaning
|
|
27
|
+
* is inverse of its name — it controls whether the *background* is light,
|
|
28
|
+
* i.e. icons go dark).
|
|
29
|
+
* - "dark" style ⇒ dark icons ⇒ isAppearanceLightStatusBars = true.
|
|
30
|
+
*/
|
|
31
|
+
class AppearanceModule(context: Context) : LynxModule(context) {
|
|
32
|
+
|
|
33
|
+
private companion object {
|
|
34
|
+
const val TAG = "AppearanceModule"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@LynxMethod
|
|
38
|
+
fun setStatusBarStyle(params: ReadableMap?, callback: Callback?) {
|
|
39
|
+
val style = params?.getString("style") ?: "default"
|
|
40
|
+
val activity = findActivity(mContext)
|
|
41
|
+
if (activity == null) {
|
|
42
|
+
callback?.invoke(errorMap("No hosting Activity found"))
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
activity.runOnUiThread {
|
|
46
|
+
try {
|
|
47
|
+
val controller = controller(activity)
|
|
48
|
+
controller.isAppearanceLightStatusBars = style == "dark"
|
|
49
|
+
callback?.invoke(okMap())
|
|
50
|
+
} catch (e: Throwable) {
|
|
51
|
+
Log.w(TAG, "setStatusBarStyle failed: ${e.message}")
|
|
52
|
+
callback?.invoke(errorMap(e.message ?: "setStatusBarStyle failed"))
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@LynxMethod
|
|
58
|
+
fun setStatusBarBackgroundColor(params: ReadableMap?, callback: Callback?) {
|
|
59
|
+
val color = params?.getString("color")
|
|
60
|
+
val activity = findActivity(mContext)
|
|
61
|
+
if (activity == null) {
|
|
62
|
+
callback?.invoke(errorMap("No hosting Activity found"))
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
activity.runOnUiThread {
|
|
66
|
+
try {
|
|
67
|
+
// Setting statusBarColor on API 35+ (Android 15) does nothing —
|
|
68
|
+
// edge-to-edge is enforced and the system bar background is
|
|
69
|
+
// always transparent. Callers should overlay their own
|
|
70
|
+
// background view instead.
|
|
71
|
+
@Suppress("DEPRECATION")
|
|
72
|
+
activity.window.statusBarColor = parseColorOrTransparent(color)
|
|
73
|
+
callback?.invoke(okMap())
|
|
74
|
+
} catch (e: Throwable) {
|
|
75
|
+
Log.w(TAG, "setStatusBarBackgroundColor failed: ${e.message}")
|
|
76
|
+
callback?.invoke(errorMap(e.message ?: "setStatusBarBackgroundColor failed"))
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@LynxMethod
|
|
82
|
+
fun setNavigationBarStyle(params: ReadableMap?, callback: Callback?) {
|
|
83
|
+
val style = params?.getString("style") ?: "default"
|
|
84
|
+
val color = if (params?.hasKey("color") == true) params.getString("color") else null
|
|
85
|
+
val activity = findActivity(mContext)
|
|
86
|
+
if (activity == null) {
|
|
87
|
+
callback?.invoke(errorMap("No hosting Activity found"))
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
activity.runOnUiThread {
|
|
91
|
+
try {
|
|
92
|
+
val controller = controller(activity)
|
|
93
|
+
controller.isAppearanceLightNavigationBars = style == "dark"
|
|
94
|
+
if (color != null) {
|
|
95
|
+
@Suppress("DEPRECATION")
|
|
96
|
+
activity.window.navigationBarColor = parseColorOrTransparent(color)
|
|
97
|
+
}
|
|
98
|
+
callback?.invoke(okMap())
|
|
99
|
+
} catch (e: Throwable) {
|
|
100
|
+
Log.w(TAG, "setNavigationBarStyle failed: ${e.message}")
|
|
101
|
+
callback?.invoke(errorMap(e.message ?: "setNavigationBarStyle failed"))
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@LynxMethod
|
|
107
|
+
fun getColorScheme(callback: Callback?) {
|
|
108
|
+
val night = mContext.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
|
|
109
|
+
val scheme = if (night == Configuration.UI_MODE_NIGHT_YES) "dark" else "light"
|
|
110
|
+
val map = JavaOnlyMap()
|
|
111
|
+
map.putString("colorScheme", scheme)
|
|
112
|
+
callback?.invoke(map)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private fun controller(activity: Activity): WindowInsetsControllerCompat {
|
|
116
|
+
// WindowCompat.getInsetsController is the public-API-version-agnostic
|
|
117
|
+
// path; under the hood it uses WindowInsetsControllerCompat which
|
|
118
|
+
// delegates to WindowInsetsController on R+ and the deprecated
|
|
119
|
+
// SystemUiVisibility flags below.
|
|
120
|
+
return WindowCompat.getInsetsController(activity.window, activity.window.decorView)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private fun parseColorOrTransparent(hex: String?): Int {
|
|
124
|
+
if (hex.isNullOrBlank()) return Color.TRANSPARENT
|
|
125
|
+
return try {
|
|
126
|
+
Color.parseColor(hex)
|
|
127
|
+
} catch (_: IllegalArgumentException) {
|
|
128
|
+
Color.TRANSPARENT
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
private fun findActivity(ctx: Context?): Activity? {
|
|
133
|
+
var cur: Context? = ctx
|
|
134
|
+
while (cur is ContextWrapper) {
|
|
135
|
+
if (cur is Activity) return cur
|
|
136
|
+
cur = cur.baseContext
|
|
137
|
+
}
|
|
138
|
+
return null
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private fun okMap(): JavaOnlyMap {
|
|
142
|
+
val m = JavaOnlyMap()
|
|
143
|
+
m.putBoolean("ok", true)
|
|
144
|
+
return m
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private fun errorMap(message: String): JavaOnlyMap {
|
|
148
|
+
val m = JavaOnlyMap()
|
|
149
|
+
m.putBoolean("ok", false)
|
|
150
|
+
m.putString("reason", message)
|
|
151
|
+
return m
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Keep API 35+ awareness from triggering a "field never used" warning on
|
|
155
|
+
// older toolchains.
|
|
156
|
+
@Suppress("unused")
|
|
157
|
+
private fun targetsApi35Plus(activity: Activity): Boolean =
|
|
158
|
+
Build.VERSION.SDK_INT >= 35 &&
|
|
159
|
+
activity.applicationInfo.targetSdkVersion >= 35
|
|
160
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
package com.sigx.appearance
|
|
2
|
+
|
|
3
|
+
import android.content.ComponentCallbacks
|
|
4
|
+
import android.content.ComponentCallbacks2
|
|
5
|
+
import android.content.Context
|
|
6
|
+
import android.content.res.Configuration
|
|
7
|
+
import android.util.Log
|
|
8
|
+
import android.view.View
|
|
9
|
+
import com.lynx.react.bridge.JavaOnlyArray
|
|
10
|
+
import com.lynx.react.bridge.JavaOnlyMap
|
|
11
|
+
import com.lynx.tasm.LynxView
|
|
12
|
+
import com.lynx.tasm.TemplateData
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Publishes the host's current system color scheme (`light` / `dark`) to JS via:
|
|
16
|
+
*
|
|
17
|
+
* 1. **`lynx.__globalProps.appearance`** — populated synchronously via
|
|
18
|
+
* [LynxView.updateGlobalProps] before MT first paint, so apps render the
|
|
19
|
+
* correct theme on cold start with no flash.
|
|
20
|
+
*
|
|
21
|
+
* 2. **`appearanceChanged` global event** — fired via [LynxView.sendGlobalEvent]
|
|
22
|
+
* after each republish. The JS `<AppearanceProvider>` subscribes via
|
|
23
|
+
* `lynx.getJSModule("GlobalEventEmitter").addListener` and updates its
|
|
24
|
+
* reactive signal so consumers (`<ThemeProvider followSystem>`) swap themes
|
|
25
|
+
* live when the user toggles dark mode in system settings.
|
|
26
|
+
*
|
|
27
|
+
* Lifecycle: one publisher per LynxView. [attach] is called by the autolinker
|
|
28
|
+
* via `GeneratedLifecyclePublishers.attachAll(lynxView)`. We register a
|
|
29
|
+
* `ComponentCallbacks2` on the application context to catch
|
|
30
|
+
* `onConfigurationChanged` (the only reliable signal for runtime dark-mode
|
|
31
|
+
* flips) and unregister on view detach.
|
|
32
|
+
*/
|
|
33
|
+
class AppearancePublisher(private val lynxView: LynxView) {
|
|
34
|
+
|
|
35
|
+
private companion object {
|
|
36
|
+
const val TAG = "AppearancePublisher"
|
|
37
|
+
const val EVENT_NAME = "appearanceChanged"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private var lastScheme: String = ""
|
|
41
|
+
private var callbacks: ComponentCallbacks? = null
|
|
42
|
+
|
|
43
|
+
fun attach() {
|
|
44
|
+
// Seed synchronously so __globalProps is populated before MT first
|
|
45
|
+
// paint reads it. Reading the LynxView's own resources gives the host
|
|
46
|
+
// window's effective configuration (accounts for app-level
|
|
47
|
+
// android:configChanges and overrideConfiguration on the activity).
|
|
48
|
+
publish(lynxView.resources.configuration)
|
|
49
|
+
|
|
50
|
+
// Register ComponentCallbacks2 on the application so we get
|
|
51
|
+
// onConfigurationChanged when the user flips system dark mode in
|
|
52
|
+
// Settings → Display while the app is foregrounded. View-level
|
|
53
|
+
// dispatch is unreliable: onConfigurationChanged on a View only fires
|
|
54
|
+
// if the Activity declares android:configChanges, which most apps
|
|
55
|
+
// don't (and shouldn't).
|
|
56
|
+
val appCtx = lynxView.context.applicationContext
|
|
57
|
+
val cb = object : ComponentCallbacks2 {
|
|
58
|
+
override fun onConfigurationChanged(newConfig: Configuration) {
|
|
59
|
+
publish(newConfig)
|
|
60
|
+
}
|
|
61
|
+
override fun onLowMemory() {}
|
|
62
|
+
override fun onTrimMemory(level: Int) {}
|
|
63
|
+
}
|
|
64
|
+
appCtx.registerComponentCallbacks(cb)
|
|
65
|
+
callbacks = cb
|
|
66
|
+
|
|
67
|
+
// Detach safely when the LynxView leaves the window — covers
|
|
68
|
+
// activity recreation, single-LynxView teardown during HMR, etc.
|
|
69
|
+
lynxView.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
|
|
70
|
+
override fun onViewAttachedToWindow(v: View) {}
|
|
71
|
+
override fun onViewDetachedFromWindow(v: View) {
|
|
72
|
+
detach(appCtx)
|
|
73
|
+
v.removeOnAttachStateChangeListener(this)
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private fun detach(appCtx: Context) {
|
|
79
|
+
callbacks?.let {
|
|
80
|
+
try {
|
|
81
|
+
appCtx.unregisterComponentCallbacks(it)
|
|
82
|
+
} catch (_: Throwable) {
|
|
83
|
+
// unregister can throw if the callback was never registered;
|
|
84
|
+
// ignore — there's nothing the host can do about it.
|
|
85
|
+
}
|
|
86
|
+
callbacks = null
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private fun publish(config: Configuration) {
|
|
91
|
+
val night = config.uiMode and Configuration.UI_MODE_NIGHT_MASK
|
|
92
|
+
val scheme = if (night == Configuration.UI_MODE_NIGHT_YES) "dark" else "light"
|
|
93
|
+
if (scheme == lastScheme) return
|
|
94
|
+
lastScheme = scheme
|
|
95
|
+
|
|
96
|
+
val map: Map<String, Any> = mapOf("colorScheme" to scheme)
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
// Channel 1: __globalProps — sync MT read at first paint.
|
|
100
|
+
lynxView.updateGlobalProps(TemplateData.fromMap(mapOf("appearance" to map)))
|
|
101
|
+
|
|
102
|
+
// Channel 2: appearanceChanged event — live BG update.
|
|
103
|
+
val payload = JavaOnlyMap().apply { putString("colorScheme", scheme) }
|
|
104
|
+
val params = JavaOnlyArray().apply { pushMap(payload) }
|
|
105
|
+
lynxView.sendGlobalEvent(EVENT_NAME, params)
|
|
106
|
+
} catch (e: Throwable) {
|
|
107
|
+
// Defensive — bridge calls during teardown can throw. The next
|
|
108
|
+
// configuration change will republish, so a dropped publish here
|
|
109
|
+
// is non-fatal.
|
|
110
|
+
Log.w(TAG, "publish failed: ${e.message}")
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ColorScheme } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Key under `lynx.__globalProps` where the native publisher writes the
|
|
4
|
+
* appearance map. Single string shared by iOS / Android publishers, the JS
|
|
5
|
+
* reader, and tests.
|
|
6
|
+
*/
|
|
7
|
+
export declare const GLOBAL_PROPS_KEY = "appearance";
|
|
8
|
+
export interface RawAppearanceProps {
|
|
9
|
+
colorScheme?: ColorScheme;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Synchronously read the current system color scheme from
|
|
13
|
+
* `lynx.__globalProps`. Returns `null` when the publisher hasn't populated
|
|
14
|
+
* yet (early cold start) or when running outside a Lynx host (web preview,
|
|
15
|
+
* SSR, tests). Callers should treat `null` as "unknown — fall back to your
|
|
16
|
+
* default theme".
|
|
17
|
+
*
|
|
18
|
+
* Safe on both BG and MT threads — `__globalProps` is mirrored across both.
|
|
19
|
+
*/
|
|
20
|
+
export declare function readGlobalColorScheme(): ColorScheme | null;
|
|
21
|
+
//# sourceMappingURL=globals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"globals.d.ts","sourceRoot":"","sources":["../src/globals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAYD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,IAAI,WAAW,GAAG,IAAI,CAO1D"}
|
package/dist/globals.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key under `lynx.__globalProps` where the native publisher writes the
|
|
3
|
+
* appearance map. Single string shared by iOS / Android publishers, the JS
|
|
4
|
+
* reader, and tests.
|
|
5
|
+
*/
|
|
6
|
+
export const GLOBAL_PROPS_KEY = 'appearance';
|
|
7
|
+
/**
|
|
8
|
+
* Synchronously read the current system color scheme from
|
|
9
|
+
* `lynx.__globalProps`. Returns `null` when the publisher hasn't populated
|
|
10
|
+
* yet (early cold start) or when running outside a Lynx host (web preview,
|
|
11
|
+
* SSR, tests). Callers should treat `null` as "unknown — fall back to your
|
|
12
|
+
* default theme".
|
|
13
|
+
*
|
|
14
|
+
* Safe on both BG and MT threads — `__globalProps` is mirrored across both.
|
|
15
|
+
*/
|
|
16
|
+
export function readGlobalColorScheme() {
|
|
17
|
+
const lynxObj = typeof lynx !== 'undefined'
|
|
18
|
+
? lynx
|
|
19
|
+
: undefined;
|
|
20
|
+
const raw = lynxObj?.__globalProps?.[GLOBAL_PROPS_KEY];
|
|
21
|
+
if (!raw || typeof raw !== 'object')
|
|
22
|
+
return null;
|
|
23
|
+
return raw.colorScheme === 'dark' ? 'dark' : raw.colorScheme === 'light' ? 'light' : null;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=globals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"globals.js","sourceRoot":"","sources":["../src/globals.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAY,CAAC;AAgB7C;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,OAAO,GAA+B,OAAO,IAAI,KAAK,WAAW;QACrE,CAAC,CAAE,IAAkC;QACrC,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,GAAG,GAAG,OAAO,EAAE,aAAa,EAAE,CAAC,gBAAgB,CAAmC,CAAC;IACzF,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACjD,OAAO,GAAG,CAAC,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5F,CAAC"}
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Computed, type PrimitiveSignal } from '@sigx/reactivity';
|
|
2
|
+
import type { ColorScheme } from './types.js';
|
|
3
|
+
type ColorSchemeRead = PrimitiveSignal<ColorScheme> | Computed<ColorScheme>;
|
|
4
|
+
/**
|
|
5
|
+
* BG-side reactive read of the current system color scheme. Returns the
|
|
6
|
+
* live signal — components calling this re-render when the user flips dark
|
|
7
|
+
* mode in system settings.
|
|
8
|
+
*
|
|
9
|
+
* If no `<AppearanceProvider>` is in scope, returns a fallback signal seeded
|
|
10
|
+
* from `lynx.__globalProps` once at first call (still gives the correct
|
|
11
|
+
* value on cold start; just doesn't update live). This lets ThemeProvider
|
|
12
|
+
* use the hook even when its consumer hasn't mounted `<AppearanceProvider>`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useSystemColorScheme(): ColorSchemeRead;
|
|
15
|
+
/**
|
|
16
|
+
* MT-thread synchronous read of the current system color scheme. For use
|
|
17
|
+
* inside `'main thread'`-marked worklet bodies. Reads `lynx.__globalProps`
|
|
18
|
+
* directly — no subscription, callers re-evaluate per worklet invocation.
|
|
19
|
+
*
|
|
20
|
+
* Returns `'light'` when the publisher hasn't populated yet (cold start before
|
|
21
|
+
* first publish, or non-Lynx hosts).
|
|
22
|
+
*/
|
|
23
|
+
export declare function useSystemColorSchemeMT(): ColorScheme;
|
|
24
|
+
export type { PrimitiveSignal, Computed } from '@sigx/reactivity';
|
|
25
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAG/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,KAAK,eAAe,GAAG,eAAe,CAAC,WAAW,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;AAE5E;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,IAAI,eAAe,CAItD;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,IAAI,WAAW,CAEpD;AAYD,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { signal } from '@sigx/reactivity';
|
|
2
|
+
import { useAppearanceContext } from './injectable.js';
|
|
3
|
+
import { readGlobalColorScheme } from './globals.js';
|
|
4
|
+
/**
|
|
5
|
+
* BG-side reactive read of the current system color scheme. Returns the
|
|
6
|
+
* live signal — components calling this re-render when the user flips dark
|
|
7
|
+
* mode in system settings.
|
|
8
|
+
*
|
|
9
|
+
* If no `<AppearanceProvider>` is in scope, returns a fallback signal seeded
|
|
10
|
+
* from `lynx.__globalProps` once at first call (still gives the correct
|
|
11
|
+
* value on cold start; just doesn't update live). This lets ThemeProvider
|
|
12
|
+
* use the hook even when its consumer hasn't mounted `<AppearanceProvider>`.
|
|
13
|
+
*/
|
|
14
|
+
export function useSystemColorScheme() {
|
|
15
|
+
const ctx = useAppearanceContext();
|
|
16
|
+
if (ctx)
|
|
17
|
+
return ctx.colorScheme;
|
|
18
|
+
return fallbackSignal();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* MT-thread synchronous read of the current system color scheme. For use
|
|
22
|
+
* inside `'main thread'`-marked worklet bodies. Reads `lynx.__globalProps`
|
|
23
|
+
* directly — no subscription, callers re-evaluate per worklet invocation.
|
|
24
|
+
*
|
|
25
|
+
* Returns `'light'` when the publisher hasn't populated yet (cold start before
|
|
26
|
+
* first publish, or non-Lynx hosts).
|
|
27
|
+
*/
|
|
28
|
+
export function useSystemColorSchemeMT() {
|
|
29
|
+
return readGlobalColorScheme() ?? 'light';
|
|
30
|
+
}
|
|
31
|
+
let _fallback;
|
|
32
|
+
function fallbackSignal() {
|
|
33
|
+
if (!_fallback) {
|
|
34
|
+
_fallback = signal(readGlobalColorScheme() ?? 'light');
|
|
35
|
+
}
|
|
36
|
+
return _fallback;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAuC,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAKrD;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,GAAG,GAAG,oBAAoB,EAAE,CAAC;IACnC,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC,WAAW,CAAC;IAChC,OAAO,cAAc,EAAE,CAAC;AAC1B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO,qBAAqB,EAAE,IAAI,OAAO,CAAC;AAC5C,CAAC;AAED,IAAI,SAAmD,CAAC;AACxD,SAAS,cAAc;IACrB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,SAAS,GAAG,MAAM,CAAc,qBAAqB,EAAE,IAAI,OAAO,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { AppearanceProvider, APPEARANCE_EVENT } from './provider.js';
|
|
2
|
+
export type { AppearanceProviderProps } from './provider.js';
|
|
3
|
+
export { useAppearanceContext } from './injectable.js';
|
|
4
|
+
export type { AppearanceContextValue } from './injectable.js';
|
|
5
|
+
export { useSystemColorScheme, useSystemColorSchemeMT, } from './hooks.js';
|
|
6
|
+
export { setStatusBarStyle, setStatusBarBackgroundColor, setNavigationBarStyle, setSystemBarsStyle, isAvailable, } from './setters.js';
|
|
7
|
+
export { readGlobalColorScheme, GLOBAL_PROPS_KEY, } from './globals.js';
|
|
8
|
+
export type { RawAppearanceProps } from './globals.js';
|
|
9
|
+
export type { ColorScheme, SystemBarStyle, SystemBarsStyleInput, SetterResult, } from './types.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACrE,YAAY,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,qBAAqB,EACrB,kBAAkB,EAClB,WAAW,GACZ,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,YAAY,EACV,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,YAAY,GACb,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Public API for @sigx/lynx-appearance.
|
|
2
|
+
export { AppearanceProvider, APPEARANCE_EVENT } from './provider.js';
|
|
3
|
+
export { useAppearanceContext } from './injectable.js';
|
|
4
|
+
export { useSystemColorScheme, useSystemColorSchemeMT, } from './hooks.js';
|
|
5
|
+
export { setStatusBarStyle, setStatusBarBackgroundColor, setNavigationBarStyle, setSystemBarsStyle, isAvailable, } from './setters.js';
|
|
6
|
+
export { readGlobalColorScheme, GLOBAL_PROPS_KEY, } from './globals.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AAExC,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAGvD,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,qBAAqB,EACrB,kBAAkB,EAClB,WAAW,GACZ,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PrimitiveSignal } from '@sigx/reactivity';
|
|
2
|
+
import type { ColorScheme } from './types.js';
|
|
3
|
+
/** DI shape exposed by `<AppearanceProvider>`. */
|
|
4
|
+
export interface AppearanceContextValue {
|
|
5
|
+
/** BG-side reactive color scheme. Re-renders consumers on system flip. */
|
|
6
|
+
readonly colorScheme: PrimitiveSignal<ColorScheme>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The DI handle for the appearance context.
|
|
10
|
+
*
|
|
11
|
+
* Factory returns `null` so consumers outside a provider get a clear signal
|
|
12
|
+
* (vs. a phantom `'light'` signal that silently never updates). Hooks in
|
|
13
|
+
* `./hooks.ts` wrap this with the null-check + fallback signal.
|
|
14
|
+
*/
|
|
15
|
+
export declare const useAppearanceContext: import("@sigx/runtime-core").InjectableFunction<AppearanceContextValue | null>;
|
|
16
|
+
//# sourceMappingURL=injectable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"injectable.d.ts","sourceRoot":"","sources":["../src/injectable.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,kDAAkD;AAClD,MAAM,WAAW,sBAAsB;IACrC,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC;CACpD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,gFAEhC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineInjectable } from '@sigx/lynx';
|
|
2
|
+
/**
|
|
3
|
+
* The DI handle for the appearance context.
|
|
4
|
+
*
|
|
5
|
+
* Factory returns `null` so consumers outside a provider get a clear signal
|
|
6
|
+
* (vs. a phantom `'light'` signal that silently never updates). Hooks in
|
|
7
|
+
* `./hooks.ts` wrap this with the null-check + fallback signal.
|
|
8
|
+
*/
|
|
9
|
+
export const useAppearanceContext = defineInjectable(() => null);
|
|
10
|
+
//# sourceMappingURL=injectable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"injectable.js","sourceRoot":"","sources":["../src/injectable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAU9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAClD,GAAG,EAAE,CAAC,IAAI,CACX,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Define } from '@sigx/lynx';
|
|
2
|
+
/**
|
|
3
|
+
* Event name fired by the native publisher (iOS `AppearancePublisher.swift`,
|
|
4
|
+
* Android `AppearancePublisher.kt`) via `GlobalEventEmitter` every time the
|
|
5
|
+
* host's system color scheme flips. Payload mirrors the same map stored under
|
|
6
|
+
* `lynx.__globalProps.appearance`.
|
|
7
|
+
*
|
|
8
|
+
* Kept as a constant so iOS/Android publishers and the JS listener agree on
|
|
9
|
+
* a single string.
|
|
10
|
+
*/
|
|
11
|
+
export declare const APPEARANCE_EVENT = "appearanceChanged";
|
|
12
|
+
export type AppearanceProviderProps = Define.Prop<'class', string, false> & Define.Prop<'style', Record<string, string | number>, false> & Define.Slot<'default'>;
|
|
13
|
+
/**
|
|
14
|
+
* Mount near the root of an app (above any consumer of `useSystemColorScheme`).
|
|
15
|
+
* Cheap — just one BG signal + one GlobalEventEmitter subscription. The
|
|
16
|
+
* native publisher writes `lynx.__globalProps.appearance` before MT first
|
|
17
|
+
* paint, so the initial value is correct on cold start with no flash.
|
|
18
|
+
*
|
|
19
|
+
* On platforms where the publisher isn't wired (web preview, tests),
|
|
20
|
+
* `readGlobalColorScheme()` returns `null` and we seed `'light'` as a safe
|
|
21
|
+
* default. Consumers can detect the unwired case via the live-update
|
|
22
|
+
* subscription never firing.
|
|
23
|
+
*/
|
|
24
|
+
export declare const AppearanceProvider: import("@sigx/runtime-core").ComponentFactory<AppearanceProviderProps, void, {
|
|
25
|
+
default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
|
|
26
|
+
}>;
|
|
27
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,MAAM,EACZ,MAAM,YAAY,CAAC;AAKpB;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AAapD,MAAM,MAAM,uBAAuB,GAC/B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,GACnC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,KAAK,CAAC,GAC5D,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAE3B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB;;EAgC7B,CAAC"}
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
|
|
2
|
+
import { component, defineProvide, signal, onMounted, onUnmounted, } from '@sigx/lynx';
|
|
3
|
+
import { useAppearanceContext } from './injectable.js';
|
|
4
|
+
import { readGlobalColorScheme } from './globals.js';
|
|
5
|
+
/**
|
|
6
|
+
* Event name fired by the native publisher (iOS `AppearancePublisher.swift`,
|
|
7
|
+
* Android `AppearancePublisher.kt`) via `GlobalEventEmitter` every time the
|
|
8
|
+
* host's system color scheme flips. Payload mirrors the same map stored under
|
|
9
|
+
* `lynx.__globalProps.appearance`.
|
|
10
|
+
*
|
|
11
|
+
* Kept as a constant so iOS/Android publishers and the JS listener agree on
|
|
12
|
+
* a single string.
|
|
13
|
+
*/
|
|
14
|
+
export const APPEARANCE_EVENT = 'appearanceChanged';
|
|
15
|
+
/**
|
|
16
|
+
* Mount near the root of an app (above any consumer of `useSystemColorScheme`).
|
|
17
|
+
* Cheap — just one BG signal + one GlobalEventEmitter subscription. The
|
|
18
|
+
* native publisher writes `lynx.__globalProps.appearance` before MT first
|
|
19
|
+
* paint, so the initial value is correct on cold start with no flash.
|
|
20
|
+
*
|
|
21
|
+
* On platforms where the publisher isn't wired (web preview, tests),
|
|
22
|
+
* `readGlobalColorScheme()` returns `null` and we seed `'light'` as a safe
|
|
23
|
+
* default. Consumers can detect the unwired case via the live-update
|
|
24
|
+
* subscription never firing.
|
|
25
|
+
*/
|
|
26
|
+
export const AppearanceProvider = component(({ props, slots }) => {
|
|
27
|
+
const initial = readGlobalColorScheme() ?? 'light';
|
|
28
|
+
const colorScheme = signal(initial);
|
|
29
|
+
const ctx = { colorScheme };
|
|
30
|
+
defineProvide(useAppearanceContext, () => ctx);
|
|
31
|
+
let listener;
|
|
32
|
+
let emitter;
|
|
33
|
+
onMounted(() => {
|
|
34
|
+
const lynxObj = typeof lynx !== 'undefined'
|
|
35
|
+
? lynx
|
|
36
|
+
: undefined;
|
|
37
|
+
emitter = lynxObj?.getJSModule?.('GlobalEventEmitter');
|
|
38
|
+
if (!emitter)
|
|
39
|
+
return;
|
|
40
|
+
listener = (raw) => {
|
|
41
|
+
const next = normaliseScheme(raw);
|
|
42
|
+
if (next && next !== colorScheme.value)
|
|
43
|
+
colorScheme.value = next;
|
|
44
|
+
};
|
|
45
|
+
emitter.addListener(APPEARANCE_EVENT, listener);
|
|
46
|
+
});
|
|
47
|
+
onUnmounted(() => {
|
|
48
|
+
if (emitter && listener)
|
|
49
|
+
emitter.removeListener(APPEARANCE_EVENT, listener);
|
|
50
|
+
});
|
|
51
|
+
return () => (_jsx("view", { class: props.class, style: props.style, children: slots.default?.() }));
|
|
52
|
+
});
|
|
53
|
+
function normaliseScheme(raw) {
|
|
54
|
+
if (!raw || typeof raw !== 'object')
|
|
55
|
+
return null;
|
|
56
|
+
const v = raw['colorScheme'];
|
|
57
|
+
return v === 'dark' ? 'dark' : v === 'light' ? 'light' : null;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,SAAS,EACT,aAAa,EACb,MAAM,EACN,SAAS,EACT,WAAW,GAEZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAA+B,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGrD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AAkBpD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAA0B,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;IACxF,MAAM,OAAO,GAAgB,qBAAqB,EAAE,IAAI,OAAO,CAAC;IAChE,MAAM,WAAW,GAAG,MAAM,CAAc,OAAO,CAAC,CAAC;IAEjD,MAAM,GAAG,GAA2B,EAAE,WAAW,EAAE,CAAC;IACpD,aAAa,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAE/C,IAAI,QAAiD,CAAC;IACtD,IAAI,OAA2C,CAAC;IAEhD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAyB,OAAO,IAAI,KAAK,WAAW;YAC/D,CAAC,CAAE,IAA4B;YAC/B,CAAC,CAAC,SAAS,CAAC;QACd,OAAO,GAAG,OAAO,EAAE,WAAW,EAAE,CAAC,oBAAoB,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,QAAQ,GAAG,CAAC,GAAY,EAAE,EAAE;YAC1B,MAAM,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,IAAI,IAAI,IAAI,KAAK,WAAW,CAAC,KAAK;gBAAE,WAAW,CAAC,KAAK,GAAG,IAAI,CAAC;QACnE,CAAC,CAAC;QACF,OAAO,CAAC,WAAW,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,WAAW,CAAC,GAAG,EAAE;QACf,IAAI,OAAO,IAAI,QAAQ;YAAE,OAAO,CAAC,cAAc,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,EAAE,CAAC,CACX,eAAM,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,YACzC,KAAK,CAAC,OAAO,EAAE,EAAE,GACb,CACR,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,SAAS,eAAe,CAAC,GAAY;IACnC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,CAAC,GAAI,GAA+B,CAAC,aAAa,CAAC,CAAC;IAC1D,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { SetterResult, SystemBarStyle, SystemBarsStyleInput } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Set the status-bar *content* tint (clock + icons).
|
|
4
|
+
*
|
|
5
|
+
* - `'light'` = light content (white-ish icons) — use when behind a dark theme.
|
|
6
|
+
* - `'dark'` = dark content — use when behind a light theme.
|
|
7
|
+
*
|
|
8
|
+
* On iOS the host VC must forward `preferredStatusBarStyle` to
|
|
9
|
+
* `AppearanceModule.preferredStatusBarStyle` for this to take effect — the
|
|
10
|
+
* lynx-cli iOS template wires that automatically.
|
|
11
|
+
*
|
|
12
|
+
* Resolves `{ ok: false, reason: 'unsupported' }` (never rejects) when the
|
|
13
|
+
* native module isn't registered — typical in web preview, SSR, tests, or
|
|
14
|
+
* apps that don't link the module. Fire-and-forget callers can therefore
|
|
15
|
+
* `void setStatusBarStyle(...)` without risking unhandled rejections.
|
|
16
|
+
*/
|
|
17
|
+
export declare function setStatusBarStyle(style: SystemBarStyle): Promise<SetterResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Android only — set the status-bar background color. Pass `null` (or
|
|
20
|
+
* omit / pass `'transparent'`) to clear. iOS resolves `{ ok: false,
|
|
21
|
+
* reason: 'unsupported' }` since iOS has no separate status-bar background.
|
|
22
|
+
*
|
|
23
|
+
* On Android 15+ (API 35) edge-to-edge is enforced and this call is a no-op
|
|
24
|
+
* at the system level — callers should overlay their own background view
|
|
25
|
+
* inside the safe-area top padding.
|
|
26
|
+
*
|
|
27
|
+
* Resolves `{ ok: false, reason: 'unsupported' }` (never rejects) when the
|
|
28
|
+
* native module isn't registered. See `setStatusBarStyle` for the rationale.
|
|
29
|
+
*/
|
|
30
|
+
export declare function setStatusBarBackgroundColor(color: string | null): Promise<SetterResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Android only — set the navigation-bar content tint + optional background.
|
|
33
|
+
* iOS resolves `{ ok: false, reason: 'unsupported' }` since there's no
|
|
34
|
+
* separate navigation bar.
|
|
35
|
+
*
|
|
36
|
+
* Resolves `{ ok: false, reason: 'unsupported' }` (never rejects) when the
|
|
37
|
+
* native module isn't registered. See `setStatusBarStyle` for the rationale.
|
|
38
|
+
*/
|
|
39
|
+
export declare function setNavigationBarStyle(opts: {
|
|
40
|
+
style: SystemBarStyle;
|
|
41
|
+
color?: string;
|
|
42
|
+
}): Promise<SetterResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Convenience: apply status-bar tint + (optionally) status-bar background +
|
|
45
|
+
* nav-bar tint in one call. Resolves to the aggregate result — `ok: false`
|
|
46
|
+
* if any leg returned a non-`unsupported` failure, with the first such
|
|
47
|
+
* failure's reason. `unsupported` legs (e.g. status-bar background on iOS)
|
|
48
|
+
* are intentionally ignored so a partially-supported platform can still
|
|
49
|
+
* report success for the legs that do apply.
|
|
50
|
+
*
|
|
51
|
+
* Fields are optional; omitting any leaves that surface untouched. Order is
|
|
52
|
+
* deterministic (statusBar → statusBarBackground → navigationBar) so the
|
|
53
|
+
* resolved reason on partial failure is unambiguous.
|
|
54
|
+
*/
|
|
55
|
+
export declare function setSystemBarsStyle(opts: SystemBarsStyleInput): Promise<SetterResult>;
|
|
56
|
+
/** Quick check whether the native Appearance module is registered. */
|
|
57
|
+
export declare function isAvailable(): boolean;
|
|
58
|
+
//# sourceMappingURL=setters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setters.d.ts","sourceRoot":"","sources":["../src/setters.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAMrF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAG9E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAGvF;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAG5G;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,YAAY,CAAC,CAY1F;AAED,sEAAsE;AACtE,wBAAgB,WAAW,IAAI,OAAO,CAErC"}
|