@lingxia/types 0.10.0 → 0.12.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 (142) hide show
  1. package/dist/automation/index.d.ts +1228 -0
  2. package/dist/automation/index.d.ts.map +1 -0
  3. package/dist/automation/index.js +13 -0
  4. package/dist/automation/index.js.map +1 -0
  5. package/dist/automation-test-globals.d.ts +14 -0
  6. package/dist/error.d.ts +13 -0
  7. package/dist/error.d.ts.map +1 -1
  8. package/dist/error.js +47 -1
  9. package/dist/error.js.map +1 -1
  10. package/dist/generated/i18n.d.ts +1 -1
  11. package/dist/generated/i18n.d.ts.map +1 -1
  12. package/dist/generated/i18n.js +37 -0
  13. package/dist/generated/i18n.js.map +1 -1
  14. package/dist/generated/logic-web.d.ts +305 -0
  15. package/dist/generated/logic.d.ts +2502 -0
  16. package/dist/generated/logic.d.ts.map +1 -0
  17. package/dist/generated/logic.js +5 -0
  18. package/dist/generated/logic.js.map +1 -0
  19. package/dist/index.d.ts +25 -313
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +3 -16
  22. package/dist/index.js.map +1 -1
  23. package/dist/logic-globals.d.ts +1 -0
  24. package/dist/process.d.ts +117 -0
  25. package/dist/process.d.ts.map +1 -0
  26. package/dist/process.js +10 -0
  27. package/dist/process.js.map +1 -0
  28. package/dist/testing/public-api.d.ts +429 -0
  29. package/dist/testing/public-api.d.ts.map +1 -0
  30. package/dist/testing/public-api.js +588 -0
  31. package/dist/testing/public-api.js.map +1 -0
  32. package/dist/testing/public-api.mjs +584 -0
  33. package/package.json +83 -48
  34. package/src/automation/index.ts +1370 -0
  35. package/src/error.ts +47 -1
  36. package/src/generated/i18n.ts +37 -0
  37. package/src/generated/logic-web.d.ts +305 -0
  38. package/src/generated/logic.ts +2753 -0
  39. package/src/index.ts +34 -459
  40. package/src/logic-globals.d.ts +1 -0
  41. package/src/process.ts +135 -0
  42. package/src/testing/public-api.ts +716 -0
  43. package/dist/app/index.d.ts +0 -328
  44. package/dist/app/index.d.ts.map +0 -1
  45. package/dist/app/index.js +0 -6
  46. package/dist/app/index.js.map +0 -1
  47. package/dist/device/actions.d.ts +0 -7
  48. package/dist/device/actions.d.ts.map +0 -1
  49. package/dist/device/actions.js +0 -6
  50. package/dist/device/actions.js.map +0 -1
  51. package/dist/device/index.d.ts +0 -5
  52. package/dist/device/index.d.ts.map +0 -1
  53. package/dist/device/index.js +0 -21
  54. package/dist/device/index.js.map +0 -1
  55. package/dist/device/info.d.ts +0 -16
  56. package/dist/device/info.d.ts.map +0 -1
  57. package/dist/device/info.js +0 -6
  58. package/dist/device/info.js.map +0 -1
  59. package/dist/device/network.d.ts +0 -12
  60. package/dist/device/network.d.ts.map +0 -1
  61. package/dist/device/network.js +0 -6
  62. package/dist/device/network.js.map +0 -1
  63. package/dist/device/wifi.d.ts +0 -20
  64. package/dist/device/wifi.d.ts.map +0 -1
  65. package/dist/device/wifi.js +0 -6
  66. package/dist/device/wifi.js.map +0 -1
  67. package/dist/display/index.d.ts +0 -8
  68. package/dist/display/index.d.ts.map +0 -1
  69. package/dist/display/index.js +0 -6
  70. package/dist/display/index.js.map +0 -1
  71. package/dist/env/index.d.ts +0 -8
  72. package/dist/env/index.d.ts.map +0 -1
  73. package/dist/env/index.js +0 -6
  74. package/dist/env/index.js.map +0 -1
  75. package/dist/file/index.d.ts +0 -146
  76. package/dist/file/index.d.ts.map +0 -1
  77. package/dist/file/index.js +0 -6
  78. package/dist/file/index.js.map +0 -1
  79. package/dist/input/index.d.ts +0 -18
  80. package/dist/input/index.d.ts.map +0 -1
  81. package/dist/input/index.js +0 -8
  82. package/dist/input/index.js.map +0 -1
  83. package/dist/location/index.d.ts +0 -19
  84. package/dist/location/index.d.ts.map +0 -1
  85. package/dist/location/index.js +0 -6
  86. package/dist/location/index.js.map +0 -1
  87. package/dist/lxapp/index.d.ts +0 -11
  88. package/dist/lxapp/index.d.ts.map +0 -1
  89. package/dist/lxapp/index.js +0 -6
  90. package/dist/lxapp/index.js.map +0 -1
  91. package/dist/media/index.d.ts +0 -372
  92. package/dist/media/index.d.ts.map +0 -1
  93. package/dist/media/index.js +0 -6
  94. package/dist/media/index.js.map +0 -1
  95. package/dist/navigator/index.d.ts +0 -14
  96. package/dist/navigator/index.d.ts.map +0 -1
  97. package/dist/navigator/index.js +0 -6
  98. package/dist/navigator/index.js.map +0 -1
  99. package/dist/share/index.d.ts +0 -90
  100. package/dist/share/index.d.ts.map +0 -1
  101. package/dist/share/index.js +0 -6
  102. package/dist/share/index.js.map +0 -1
  103. package/dist/storage/index.d.ts +0 -13
  104. package/dist/storage/index.d.ts.map +0 -1
  105. package/dist/storage/index.js +0 -6
  106. package/dist/storage/index.js.map +0 -1
  107. package/dist/system/index.d.ts +0 -9
  108. package/dist/system/index.d.ts.map +0 -1
  109. package/dist/system/index.js +0 -6
  110. package/dist/system/index.js.map +0 -1
  111. package/dist/transfer/index.d.ts +0 -166
  112. package/dist/transfer/index.d.ts.map +0 -1
  113. package/dist/transfer/index.js +0 -6
  114. package/dist/transfer/index.js.map +0 -1
  115. package/dist/ui/index.d.ts +0 -134
  116. package/dist/ui/index.d.ts.map +0 -1
  117. package/dist/ui/index.js +0 -6
  118. package/dist/ui/index.js.map +0 -1
  119. package/dist/update/index.d.ts +0 -17
  120. package/dist/update/index.d.ts.map +0 -1
  121. package/dist/update/index.js +0 -6
  122. package/dist/update/index.js.map +0 -1
  123. package/src/app/index.ts +0 -378
  124. package/src/device/actions.ts +0 -7
  125. package/src/device/index.ts +0 -4
  126. package/src/device/info.ts +0 -17
  127. package/src/device/network.ts +0 -23
  128. package/src/device/wifi.ts +0 -23
  129. package/src/display/index.ts +0 -9
  130. package/src/env/index.ts +0 -8
  131. package/src/file/index.ts +0 -171
  132. package/src/input/index.ts +0 -19
  133. package/src/location/index.ts +0 -20
  134. package/src/lxapp/index.ts +0 -12
  135. package/src/media/index.ts +0 -411
  136. package/src/navigator/index.ts +0 -16
  137. package/src/share/index.ts +0 -97
  138. package/src/storage/index.ts +0 -13
  139. package/src/system/index.ts +0 -9
  140. package/src/transfer/index.ts +0 -194
  141. package/src/ui/index.ts +0 -165
  142. package/src/update/index.ts +0 -19
@@ -0,0 +1,2753 @@
1
+ // Generated by rong-typegen from the lingxia module's Rust source.
2
+ // Do not edit by hand — run `npm run gen:logic` in packages/lingxia-types to regenerate.
3
+
4
+ // Keep generic TypeScript-only aliases, correlated overloads, and types owned
5
+ // by external Rong modules in this generated prelude.
6
+ declare const appDownloadPathBrand: unique symbol;
7
+ declare const systemDownloadsPathBrand: unique symbol;
8
+
9
+ export interface PageConfig<TData extends Record<string, unknown> = Record<string, unknown>> {
10
+ data?: TData;
11
+ onLoad?: (options?: PageLoadOptions) => void | Promise<void>;
12
+ onShow?: () => void | Promise<void>;
13
+ onReady?: () => void | Promise<void>;
14
+ onHide?: () => void | Promise<void>;
15
+ onUnload?: () => void | Promise<void>;
16
+ onPullDownRefresh?: () => void | Promise<void>;
17
+ [key: string]: unknown;
18
+ }
19
+
20
+ export interface PageInstance<TData extends Record<string, unknown> = Record<string, unknown>> {
21
+ data: TData;
22
+ route: string;
23
+ /**
24
+ * Available when this page was opened as a surface via
25
+ * `lx.surface.openPage(...)`.
26
+ */
27
+ surface?: PageSurface;
28
+ /**
29
+ * Available when this page was opened by `lx.navigateTo(...)`.
30
+ */
31
+ opener?: PageMessagePort;
32
+ setData(data: Partial<TData> | Record<string, unknown>, callback?: () => void): void;
33
+ }
34
+
35
+ /**
36
+ * Injected by the runtime into methods listed in `stream_handlers` page metadata.
37
+ *
38
+ * Use this when your async source uses callbacks rather than an async iterator.
39
+ * For the generator form (`async *method()`), no handle is needed — the runtime
40
+ * pumps the generator automatically.
41
+ */
42
+ export interface StreamHandle<T = unknown> {
43
+ /** Send a chunk to View. */
44
+ send(payload: T): void;
45
+ /** End the stream with an optional final value. */
46
+ end(result?: unknown): void;
47
+ /** End the stream with an error. */
48
+ error(code: string, message?: string): void;
49
+ }
50
+
51
+ /**
52
+ * Injected by the runtime as the second parameter when View opens a channel.
53
+ *
54
+ * Use `ch.send()` to push data to View, `ch.on()` to receive data/close
55
+ * events from View, and `ch.close()` to shut down the channel.
56
+ */
57
+ export interface ChannelHandle<TSend = unknown, TReceive = unknown> {
58
+ /** Push a message to View. */
59
+ send(payload: TSend): void;
60
+ /** Close the channel from Logic side. */
61
+ close(code?: string, reason?: string): void;
62
+ /** Register a listener for incoming events. */
63
+ on(event: 'data', handler: (payload: TReceive) => void): void;
64
+ on(event: 'close', handler: (info: { code: string; reason: string }) => void): void;
65
+ }
66
+
67
+ /**
68
+ * Download options.
69
+ *
70
+ * - `app`: app-owned temporary output, or durable `lx://userdata` output when
71
+ * `filePath` is set
72
+ * - `downloads`: user-visible system Downloads output, requiring
73
+ * `security.privileges: ["downloads"]` in `lxapp.json`
74
+ *
75
+ * Default: `app`.
76
+ */
77
+ export type DownloadOptions<TDestination extends DownloadDestination = DownloadDestination> =
78
+ TDestination extends 'downloads' ? DownloadsDownloadOptions : AppDownloadOptions;
79
+
80
+ export type DownloadResultForDestination<TDestination extends DownloadDestination> =
81
+ TDestination extends 'downloads' ? DownloadsDownloadResult : AppDownloadResult;
82
+
83
+ export interface DownloadProgressEvent<TResult extends DownloadResult = DownloadResult> {
84
+ kind: 'progress' | 'paused' | 'resumed' | 'canceled' | 'completed';
85
+ downloadedBytes?: number;
86
+ totalBytes?: number;
87
+ /** Present only when the total size is known. */
88
+ progress?: number;
89
+ result?: TResult;
90
+ }
91
+
92
+ export interface DownloadIteratorResult<TResult extends DownloadResult = DownloadResult> {
93
+ done: boolean;
94
+ value?: DownloadProgressEvent<TResult>;
95
+ }
96
+
97
+ export interface DownloadTask<TDownloadResult extends DownloadResult = DownloadResult>
98
+ extends PromiseLike<TDownloadResult>,
99
+ AsyncIterable<DownloadProgressEvent<TDownloadResult>> {
100
+ next(): Promise<DownloadIteratorResult<TDownloadResult>>;
101
+ /** Stops iteration only. Does not cancel the underlying download task. */
102
+ return(): Promise<DownloadIteratorResult<TDownloadResult>>;
103
+ catch<TRejected = never>(
104
+ onrejected?: ((reason: unknown) => TRejected | PromiseLike<TRejected>) | null,
105
+ ): Promise<TDownloadResult | TRejected>;
106
+ finally(onfinally?: (() => void) | null): Promise<TDownloadResult>;
107
+ pause(): Promise<void>;
108
+ resume(): Promise<void>;
109
+ cancel(): Promise<void>;
110
+ /** Alias for cancel(), matching browser/mini-program abort naming. */
111
+ abort(): Promise<void>;
112
+ wait(): Promise<TDownloadResult>;
113
+ }
114
+
115
+ declare global {
116
+ // HostAppApi/LxEnv members are emitted from the Rust js_api metadata; these
117
+ // merges only add what Rong cannot express — the cfg-gated autostart member
118
+ // and doc comments (js_api consts cannot carry docs). envVersion re-declares
119
+ // the generated member doc-only; tsc rejects the merge if the types drift.
120
+ interface HostAppApi {
121
+ /**
122
+ * The build environment from `app.json::envVersion`. It is fixed at boot
123
+ * and defaults to `release` for older artifacts.
124
+ */
125
+ readonly envVersion: HostAppEnvVersion;
126
+
127
+ /**
128
+ * Launch-at-startup control. Absent where the host cannot register a
129
+ * startup item; its presence and `lx.supports({ capability: 'autostart' })` always
130
+ * agree, so `lx.app.autostart?.…` and the query are interchangeable.
131
+ */
132
+ autostart?: AutostartApi;
133
+ }
134
+
135
+ /** Runtime environment constants backed by abstract `lx://` paths. */
136
+ interface LxEnv {}
137
+
138
+ interface Lx {
139
+ /**
140
+ * Terminal product settings. Present only in the host-bundled Terminal
141
+ * Settings lxapp when the host declares `capabilities.terminal`; its
142
+ * presence and `lx.supports({ capability: 'terminal' })` always agree.
143
+ */
144
+ readonly terminal?: TerminalApi;
145
+
146
+ /** Download to the downloads directory. */
147
+ downloadFile(options: DownloadsDownloadOptions): DownloadTask<DownloadsDownloadResult>;
148
+ /** Download to the lxapp-managed app directory. */
149
+ downloadFile(options: AppDownloadOptions): DownloadTask<AppDownloadResult>;
150
+ /** Download with a destination-correlated result type. */
151
+ downloadFile<TDestination extends DownloadDestination = "app">(
152
+ options: DownloadOptions<TDestination>,
153
+ ): DownloadTask<DownloadResultForDestination<TDestination>>;
154
+
155
+ /**
156
+ * Open this lxapp's store with every key's shape pinned on the handle.
157
+ * `get` / `set` / `delete` then share that schema instead of
158
+ * repeating `get<T>()` at each call site.
159
+ */
160
+ getStorage<S extends StorageSchema>(): TypedStorage<S>;
161
+ }
162
+ }
163
+
164
+ /**
165
+ * A map of storage keys to stored value shapes.
166
+ *
167
+ * `object` deliberately accepts both type aliases and interfaces. Requiring a
168
+ * string index signature would reject ordinary interface-based schemas.
169
+ */
170
+ export type StorageSchema = object;
171
+
172
+ type StorageKey<S extends object> = Extract<keyof S, string>;
173
+ type StorageEntry<S extends object> = {
174
+ [K in StorageKey<S>]: [key: K, value: S[K]];
175
+ }[StorageKey<S>];
176
+
177
+ /**
178
+ * Schema-typed view of the same store `lx.getStorage()` returns.
179
+ * Runtime is identical; only the key/value types are pinned.
180
+ *
181
+ * The schema constrains what this handle writes and reads, not what the store
182
+ * contains: a previous app version, or another code path holding the untyped
183
+ * handle, can have written keys outside it. That is why `list` still resolves
184
+ * plain strings — narrowing it to the schema's keys would be the same
185
+ * unchecked assertion this type exists to remove from `get<T>()`.
186
+ */
187
+ export type TypedStorage<S extends object> = {
188
+ get<K extends StorageKey<S>>(key: K): Promise<S[K] | undefined>;
189
+ set(...entry: StorageEntry<S>): Promise<void>;
190
+ delete(key: StorageKey<S>): Promise<void>;
191
+ clear(): Promise<void>;
192
+ list(prefix?: string): Promise<string[]>;
193
+ info(): Promise<StorageInfo>;
194
+ };
195
+
196
+ /**
197
+ * Result of `lx.showActionSheet`. Branch on `canceled` before reading
198
+ * the selected item index.
199
+ */
200
+ export type ActionSheetResult = {
201
+ canceled: false;
202
+ /** Index of the tapped item in `itemList`. */
203
+ index: number;
204
+ } | CanceledResult;
205
+
206
+ /** Every surface handle, narrowable by `kind`. */
207
+ export type AnySurface = PageSurface | DeclaredSurface | AppSurface | TabSurface | BuiltinSurface;
208
+
209
+ export type AppConfig = {
210
+ globalData?: Record<string, unknown>;
211
+ onLaunch?: (options?: AppLaunchOptions) => void | Promise<void>;
212
+ onShow?: (args?: AppLifecycleEventArgs) => void | Promise<void>;
213
+ onHide?: (args?: AppLifecycleEventArgs) => void | Promise<void>;
214
+ onUserCaptureScreen?: () => void | Promise<void>;
215
+ [key: string]: unknown;
216
+ };
217
+
218
+ /** Runtime-managed app download path, usually under `lx://userdata`. */
219
+ export type AppDownloadFilePath = string & {
220
+ readonly [appDownloadPathBrand]: 'app-download-file-path';
221
+ };
222
+
223
+ export type AppDownloadOptions = DownloadOptionsBase & {
224
+ /**
225
+ * Optional app-owned durable output path.
226
+ *
227
+ * Omit `filePath` to receive a temporary result in `tempFilePath`. Relative
228
+ * paths resolve under user data. `lx://` paths must target `lx://userdata`;
229
+ * `lx://usercache` is not accepted here.
230
+ */
231
+ filePath?: string;
232
+ /**
233
+ * App-owned output. Omit to use a temporary output unless `filePath` is set.
234
+ */
235
+ destination?: 'app';
236
+ };
237
+
238
+ export type AppDownloadResult = {
239
+ /**
240
+ * Temporary result.
241
+ *
242
+ * Not durable; move or copy it to `lx://userdata` if you need to keep it.
243
+ *
244
+ * When `filePath` is omitted, the runtime must be able to infer a file
245
+ * type from the URL or the server's `Content-Type` header.
246
+ */
247
+ tempFilePath: string;
248
+ filePath?: never;
249
+ mimeType?: string;
250
+ size: number;
251
+ } | {
252
+ /** Durable destination under `lx://userdata`. */
253
+ filePath: AppDownloadFilePath;
254
+ tempFilePath?: never;
255
+ mimeType?: string;
256
+ size: number;
257
+ };
258
+
259
+ export type AppInstance = AppConfig & {
260
+ globalData: Record<string, unknown>;
261
+ };
262
+
263
+ export type AppLaunchOptions = {
264
+ path?: string;
265
+ query?: Record<string, string>;
266
+ scene?: number;
267
+ referrerInfo?: {
268
+ appId?: string;
269
+ extraData?: Record<string, unknown>;
270
+ };
271
+ };
272
+
273
+ export type AppLifecycleEventArgs = {
274
+ source: 'host' | 'lxapp';
275
+ reason: 'foreground' | 'background' | 'screenshot' | 'open' | 'close' | 'switch_back' | 'switch_away';
276
+ };
277
+
278
+ export type AppScreenshotOptions = {
279
+ /**
280
+ * Platform-specific window id to capture (desktop only). Omit to let the
281
+ * platform pick: the key/main window on desktop, the sole window on mobile.
282
+ */
283
+ windowId?: string;
284
+ };
285
+
286
+ export type AppScreenshotResult = {
287
+ /** `lx://` URI of the captured PNG in the lxapp temp directory. */
288
+ tempFilePath: string;
289
+ /** Image width in pixels, when the runtime could read it from the PNG. */
290
+ width?: number;
291
+ /** Image height in pixels, when the runtime could read it from the PNG. */
292
+ height?: number;
293
+ };
294
+
295
+ /** Another lxapp composed into a shell slot. */
296
+ export type AppSurface = SurfaceBase & SurfaceShowable & {
297
+ readonly kind: 'app';
298
+ readonly realized: 'main' | 'aside';
299
+ };
300
+
301
+ export type AppearanceApi = globalThis.AppearanceApi;
302
+
303
+ export type AppearancePreference = 'auto' | 'light' | 'dark';
304
+
305
+ /**
306
+ * Launch-at-startup control for the host app.
307
+ * Absent (`undefined`) wherever the host cannot register a startup item.
308
+ * `lx.supports({ capability: 'autostart' })` and the member's presence always
309
+ * agree, so either gate works:
310
+ * ```ts
311
+ * if (lx.supports({ capability: 'autostart' })) {
312
+ * // render the "Launch at startup" toggle
313
+ * }
314
+ * ```
315
+ * Requires `capabilities.autostart: true` in `lingxia.yaml`; without it the
316
+ * member is absent on all platforms. Declaring the capability never enables
317
+ * autostart by itself — the SDK registers the app only when `setEnabled(true)`
318
+ * is called, so the decision stays with the user (typically a settings-page
319
+ * toggle, default off).
320
+ * Host-app-level capability: like `checkUpdate` and `screenshot`, the methods
321
+ * are available only to the home lxapp; other lxapps receive a permission
322
+ * error.
323
+ */
324
+ export type AutostartApi = {
325
+ /**
326
+ * Whether the app is currently registered to launch at startup, read from
327
+ * the OS (macOS login items / Windows `Run` registry key) — never a cached
328
+ * preference. The user can flip this outside the app (System Settings on
329
+ * macOS, Task Manager's Startup page on Windows), so re-read it whenever the
330
+ * settings UI is shown.
331
+ */
332
+ isEnabled(): Promise<boolean>;
333
+ /**
334
+ * Register or unregister the app as a startup item for the current user.
335
+ * Idempotent. On macOS the system may notify the user that a login item was
336
+ * added — only call this from an explicit user action.
337
+ */
338
+ setEnabled(on: boolean): Promise<void>;
339
+ };
340
+
341
+ export type BinaryFileData = ArrayBuffer | ArrayBufferView;
342
+
343
+ /**
344
+ * Built-in browser product page. Opening one requires
345
+ * `capabilities.browser` and is restricted to the home lxapp.
346
+ */
347
+ export type BuiltinShellPage = 'settings' | 'downloads';
348
+
349
+ /**
350
+ * A host builtin page such as settings or downloads. The shell owns
351
+ * its lifetime and its visibility, so this handle reports identity:
352
+ * there is no `show` / `hide`, and the inherited `close()` rejects
353
+ * with `unsupported_placement`.
354
+ */
355
+ export type BuiltinSurface = SurfaceBase & {
356
+ readonly kind: 'builtin';
357
+ };
358
+
359
+ /** The user dismissed the operation. Never an error. */
360
+ export type CanceledResult = {
361
+ canceled: true;
362
+ };
363
+
364
+ export type ChooseDirectoryOptions = {
365
+ /** Initial directory the dialog opens in. Platform default if omitted. */
366
+ defaultPath?: string;
367
+ };
368
+
369
+ /**
370
+ * Result of `lx.chooseDirectory`. Branch on `canceled` before reading
371
+ * the selected directory.
372
+ */
373
+ export type ChooseDirectoryResult = {
374
+ canceled: false;
375
+ /** Native-consumable directory reference (path or URI). */
376
+ path: string;
377
+ } | CanceledResult;
378
+
379
+ export type ChooseFileOptions = {
380
+ /** Allow selecting multiple files. Default: false */
381
+ multiple?: boolean;
382
+ /** Optional file filters. Empty or omitted means all file types. */
383
+ filters?: FileDialogFilter[];
384
+ /**
385
+ * Initial directory the dialog opens in.
386
+ *
387
+ * When this resolves to an app-local directory, LingXia may use its internal
388
+ * file picker. When omitted, the platform system file picker is used.
389
+ */
390
+ defaultPath?: string;
391
+ };
392
+
393
+ /**
394
+ * Result of `lx.chooseFile`. Branch on `canceled` before reading the
395
+ * selected paths.
396
+ */
397
+ export type ChooseFileResult = {
398
+ canceled: false;
399
+ /**
400
+ * File paths returned by LingXia; always at least one. Values may be
401
+ * app-local paths, `lx://...` paths, or platform system-picker references.
402
+ * Treat them as opaque strings and pass them back to LingXia APIs such as
403
+ * `lx.share`.
404
+ */
405
+ paths: [string, ...string[]];
406
+ } | CanceledResult;
407
+
408
+ export type ChooseMediaOptions = {
409
+ count?: number;
410
+ mediaType?: ('image' | 'video')[];
411
+ sourceType?: ('album' | 'camera')[];
412
+ camera?: 'back' | 'front';
413
+ maxDuration?: number;
414
+ };
415
+
416
+ /**
417
+ * Result of `lx.chooseMedia`. Branch on `canceled` before reading the
418
+ * selected entries.
419
+ */
420
+ export type ChooseMediaResult = {
421
+ canceled: false;
422
+ /** Picked media; always at least one entry. */
423
+ entries: [ChosenMediaEntry, ...ChosenMediaEntry[]];
424
+ } | CanceledResult;
425
+
426
+ export type ChosenMediaEntry = {
427
+ tempFilePath: string;
428
+ fileType: 'image' | 'video';
429
+ isOriginal: boolean;
430
+ };
431
+
432
+ export type CompressImageOptions = {
433
+ path: string;
434
+ quality?: number;
435
+ compressedWidth?: number;
436
+ compressedHeight?: number;
437
+ };
438
+
439
+ export type CompressImageResult = {
440
+ tempFilePath: string;
441
+ };
442
+
443
+ export type CompressVideoIteratorResult = {
444
+ done: boolean;
445
+ value?: CompressVideoProgressEvent;
446
+ };
447
+
448
+ export type CompressVideoOptions = {
449
+ /**
450
+ * Source video path or `lx://` URI.
451
+ */
452
+ path: string;
453
+ /**
454
+ * Cross-platform note: video compression parameters are best-effort and may map to
455
+ * native presets instead of exact encoder settings.
456
+ *
457
+ * Compression quality preset.
458
+ * When provided, `bitrate`, `fps`, and `resolution` are ignored.
459
+ */
460
+ quality?: VideoCompressQuality;
461
+ /**
462
+ * Preferred target video bitrate in kbps.
463
+ * May be adjusted or ignored by platform codec/runtime limitations.
464
+ */
465
+ bitrate?: number;
466
+ /**
467
+ * Preferred target frame rate in fps.
468
+ * Some platforms may ignore this option.
469
+ */
470
+ fps?: number;
471
+ /**
472
+ * Target resolution scale ratio relative to source size, in range `(0, 1]`.
473
+ * May be approximated or ignored by platform transcoder capabilities.
474
+ */
475
+ resolution?: number;
476
+ /**
477
+ * Optional output path for compressed file.
478
+ */
479
+ outputPath?: string;
480
+ };
481
+
482
+ export type CompressVideoProgressEvent = {
483
+ /** Transcode progress in percent, `0`-`100`. */
484
+ progress: number;
485
+ };
486
+
487
+ export type CompressVideoResult = {
488
+ tempFilePath: string;
489
+ width: number;
490
+ height: number;
491
+ durationMs: number;
492
+ /**
493
+ * Output file size in bytes.
494
+ * Could be close to source size when platform falls back to source content.
495
+ */
496
+ size: number;
497
+ type: string;
498
+ };
499
+
500
+ /**
501
+ * Handle returned by `lx.compressVideo`.
502
+ * Awaiting the task resolves with the final {@link CompressVideoResult}.
503
+ * Iterating it with `for await` yields {@link CompressVideoProgressEvent}s
504
+ * while the transcode runs.
505
+ */
506
+ export type CompressVideoTask = PromiseLike<CompressVideoResult> & AsyncIterable<CompressVideoProgressEvent> & {
507
+ next(): Promise<CompressVideoIteratorResult>;
508
+ /** Stops iteration only. Does not cancel the compression. */
509
+ return(): Promise<CompressVideoIteratorResult>;
510
+ catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<CompressVideoResult | TResult>;
511
+ finally(onfinally?: (() => void) | null): Promise<CompressVideoResult>;
512
+ /**
513
+ * Cancels the transcode and deletes any partial output.
514
+ * The task promise rejects with an `AbortError` (`code: 'E_ABORT'`).
515
+ */
516
+ cancel(): void;
517
+ wait(): Promise<CompressVideoResult>;
518
+ };
519
+
520
+ export type ConnectWifiOptions = {
521
+ SSID: string;
522
+ password?: string;
523
+ };
524
+
525
+ /** A surface declared by the host in `lingxia.yaml`. */
526
+ export type DeclaredSurface = SurfaceBase & SurfaceShowable & {
527
+ readonly kind: 'declared';
528
+ };
529
+
530
+ /** Display and orientation APIs. */
531
+ export type DeviceOrientation = "portrait" | "landscape";
532
+
533
+ export type DeviceOrientationChangeEvent = {
534
+ value: DeviceOrientation;
535
+ };
536
+
537
+ export type DownloadDestination = 'app' | 'downloads';
538
+
539
+ export type DownloadOptionsBase = {
540
+ /** HTTP(S) source URL. */
541
+ url: string;
542
+ /**
543
+ * Optional request headers.
544
+ * Restricted headers such as `Referer` are ignored by the runtime.
545
+ */
546
+ headers?: Record<string, string>;
547
+ /** Request timeout in milliseconds. */
548
+ timeout?: number;
549
+ /** Optional abort signal. */
550
+ signal?: AbortSignal;
551
+ };
552
+
553
+ export type DownloadResult = AppDownloadResult | DownloadsDownloadResult;
554
+
555
+ export type DownloadsDownloadOptions = DownloadOptionsBase & {
556
+ /**
557
+ * Optional filename hint for the system Downloads destination.
558
+ * This is not an app-owned `lx.fs` path.
559
+ */
560
+ filePath?: string;
561
+ /** Save into the user's system Downloads directory. */
562
+ destination: 'downloads';
563
+ };
564
+
565
+ export type DownloadsDownloadResult = {
566
+ /** Native system Downloads path. Do not pass this to `lx.fs`. */
567
+ filePath: SystemDownloadsPath;
568
+ tempFilePath?: never;
569
+ mimeType?: string;
570
+ size: number;
571
+ };
572
+
573
+ export type ExtractVideoThumbnailOptions = {
574
+ /**
575
+ * Source video path or `lx://` URI.
576
+ */
577
+ path: string;
578
+ /**
579
+ * Optional output image path. If omitted, runtime chooses a temporary path.
580
+ */
581
+ outputPath?: string;
582
+ /**
583
+ * Max output width in pixels.
584
+ * Optional; when set with/without `maxHeight`, output keeps aspect ratio (no cropping).
585
+ */
586
+ maxWidth?: number;
587
+ /**
588
+ * Max output height in pixels.
589
+ * Optional; when set with/without `maxWidth`, output keeps aspect ratio (no cropping).
590
+ */
591
+ maxHeight?: number;
592
+ /**
593
+ * Target frame time in milliseconds from video start.
594
+ * `0` means first frame.
595
+ */
596
+ timeMs?: number;
597
+ /**
598
+ * JPEG quality in range `0-100`.
599
+ */
600
+ quality?: number;
601
+ };
602
+
603
+ export type ExtractVideoThumbnailResult = {
604
+ /**
605
+ * Generated thumbnail file path.
606
+ */
607
+ tempFilePath: string;
608
+ /**
609
+ * Output image width in pixels.
610
+ */
611
+ width: number;
612
+ /**
613
+ * Output image height in pixels.
614
+ */
615
+ height: number;
616
+ /**
617
+ * Output MIME type, usually `image/jpeg`.
618
+ */
619
+ type: string;
620
+ };
621
+
622
+ export type FileDialogFilter = {
623
+ /** Optional label shown in the native dialog. */
624
+ name?: string;
625
+ /** Allowed extensions without dots, e.g. ['pdf', 'txt']. */
626
+ extensions: string[];
627
+ };
628
+
629
+ export type FileSystemApi = globalThis.FileSystemApi;
630
+
631
+ export type FsCopyOptions = {
632
+ /** Defaults to false. */
633
+ overwrite?: boolean;
634
+ };
635
+
636
+ export type FsMkdirOptions = {
637
+ recursive?: boolean;
638
+ };
639
+
640
+ export type FsRemoveOptions = {
641
+ recursive?: boolean;
642
+ };
643
+
644
+ export type FsRenameOptions = {
645
+ /** Defaults to false. */
646
+ overwrite?: boolean;
647
+ };
648
+
649
+ export type FsWriteOptions = {
650
+ /**
651
+ * How string input is interpreted. Strings are UTF-8 by default; `base64`
652
+ * decodes the input into raw bytes before writing.
653
+ */
654
+ encoding?: 'utf8' | 'base64';
655
+ /** Defaults to false. */
656
+ overwrite?: boolean;
657
+ };
658
+
659
+ /** Media picker, preview, scan, and file processing APIs. */
660
+ export type GetImageInfoOptions = {
661
+ path: string;
662
+ };
663
+
664
+ /** Location APIs. */
665
+ export type GetLocationOptions = {
666
+ type?: 'wgs84' | 'gcj02';
667
+ altitude?: boolean;
668
+ isHighAccuracy?: boolean;
669
+ highAccuracyExpireTime?: number;
670
+ };
671
+
672
+ export type GetVideoInfoOptions = {
673
+ /**
674
+ * Video file path or `lx://` URI.
675
+ */
676
+ path: string;
677
+ };
678
+
679
+ export type HostAppApi = globalThis.HostAppApi;
680
+
681
+ /**
682
+ * Build-time environment version of the host app.
683
+ * Surfaced via {@link HostAppApi.envVersion}. Mirrors the
684
+ * `crates/lingxia-update::ReleaseType` enum and the `envVersion` field in the
685
+ * generated `app.json`. Pre-envVersion app artifacts are treated as `'release'`.
686
+ * Note: this is *separate* from `LxAppEnvVersion` in the navigator module,
687
+ * which encodes lxapp release channels (`'develop' | 'preview' | 'release'`)
688
+ * for cross-app navigation URLs and uses the truncated `develop` form.
689
+ */
690
+ export type HostAppEnvVersion = 'developer' | 'preview' | 'release';
691
+
692
+ export type HostAppUpdateApplyStage = 'download' | 'install';
693
+
694
+ export type HostAppUpdateCheckResult = {
695
+ hasUpdate: false;
696
+ update?: never;
697
+ } | {
698
+ hasUpdate: true;
699
+ update: HostAppUpdateInfo;
700
+ };
701
+
702
+ export type HostAppUpdateEvent = {
703
+ state: 'downloading';
704
+ downloadedBytes?: number;
705
+ progress?: number;
706
+ } | {
707
+ state: 'downloaded' | 'installRequested';
708
+ } | {
709
+ state: 'failed';
710
+ stage: HostAppUpdateApplyStage;
711
+ error: string;
712
+ };
713
+
714
+ export type HostAppUpdateInfo = {
715
+ version: string;
716
+ size?: number;
717
+ releaseNotes?: string[];
718
+ isForceUpdate: boolean;
719
+ /**
720
+ * Download and apply this checked update.
721
+ *
722
+ * `apply()` is single-use for this update object.
723
+ *
724
+ * The returned task can be awaited directly when progress is not needed, or
725
+ * consumed with `for await...of` to render progress.
726
+ *
727
+ * Requires `lx.supports({ capability: 'selfUpdate' })`. Where the host cannot
728
+ * install its own update it rejects with an unsupported-operation error;
729
+ * use `version` and `releaseNotes` to guide users to the app marketplace.
730
+ */
731
+ apply(): HostAppUpdateTask;
732
+ };
733
+
734
+ export type HostAppUpdateIteratorResult = {
735
+ done: boolean;
736
+ value?: HostAppUpdateEvent;
737
+ };
738
+
739
+ export type HostAppUpdateResult = {
740
+ state: 'installRequested';
741
+ };
742
+
743
+ export type HostAppUpdateTask = PromiseLike<HostAppUpdateResult> & AsyncIterable<HostAppUpdateEvent> & {
744
+ next(): Promise<HostAppUpdateIteratorResult>;
745
+ /** Stops iteration only. It does not cancel an app update already handed to the platform. */
746
+ return(): Promise<HostAppUpdateIteratorResult>;
747
+ catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<HostAppUpdateResult | TResult>;
748
+ finally(onfinally?: (() => void) | null): Promise<HostAppUpdateResult>;
749
+ wait(): Promise<HostAppUpdateResult>;
750
+ };
751
+
752
+ export type InstalledTerminalFont = {
753
+ family: string;
754
+ monospace: boolean;
755
+ ligatures: boolean;
756
+ nerdIcons: boolean;
757
+ };
758
+
759
+ /**
760
+ * Input event APIs.
761
+ * Platform support: Android only
762
+ */
763
+ export type KeyEvent = {
764
+ /** Key value following W3C naming (e.g. "Enter", "ArrowLeft", "a") */
765
+ key: string;
766
+ /** Physical key code (e.g. "ENTER", "DPAD_LEFT") */
767
+ code: string;
768
+ altKey?: boolean;
769
+ ctrlKey?: boolean;
770
+ shiftKey?: boolean;
771
+ metaKey?: boolean;
772
+ repeat?: boolean;
773
+ };
774
+
775
+ export type KeyEventCallback = (event: KeyEvent) => void;
776
+
777
+ export type LxAppEnvVersion = 'release' | 'preview' | 'develop';
778
+
779
+ /** LxApp metadata APIs. */
780
+ export type LxAppReleaseType = 'release' | 'preview' | 'developer';
781
+
782
+ /** Boolean capability names accepted by `lx.supports`. */
783
+ export type LxCapabilityFlag = 'terminal' | 'autostart' | 'notifications' | 'browser' | 'proxy' | 'selfUpdate' | 'process' | 'appUse' | 'computerUse' | 'browserUse' | 'mediaCapture';
784
+
785
+ /**
786
+ * One capability question per call. The catalog is closed, so
787
+ * completion enumerates it and a typo is a type error. `capability`
788
+ * is the discriminant; only the `surface` branch accepts a `value`.
789
+ * Two surface answers describe an *affordance*, not whether the call
790
+ * succeeds: `tab` is "the host has an in-app browser" — without it a
791
+ * url still opens, in the OS browser instead — and `aside` is "a
792
+ * docked region exists right now", while a compact layout still opens
793
+ * the url through the in-app browser's own chrome. Ask them to decide
794
+ * what to render, not whether to call.
795
+ * `chrome` qualifies a window and only a window: it asks whether this
796
+ * host can produce that decoration, not merely a window.
797
+ */
798
+ export type LxCapabilityQuery = {
799
+ capability: 'surface';
800
+ value: 'window';
801
+ chrome?: WindowChrome;
802
+ } | {
803
+ capability: 'surface';
804
+ value: Exclude<LxSurfaceCapability, 'window'>;
805
+ } | {
806
+ capability: LxCapabilityFlag;
807
+ };
808
+
809
+ export type LxEnv = globalThis.LxEnv;
810
+
811
+ /** Surface placements accepted by `lx.supports`. */
812
+ export type LxSurfaceCapability = 'main' | 'aside' | 'float' | 'window' | 'tab';
813
+
814
+ /** Device action APIs. */
815
+ export type MakePhoneCallOptions = {
816
+ phoneNumber: string;
817
+ };
818
+
819
+ export type MediaObjectFit = 'cover' | 'contain' | 'fill' | 'fit';
820
+
821
+ export type MediaRotation = 0 | 90 | 180 | 270;
822
+
823
+ /**
824
+ * Result of `lx.showModal`. `canceled: false` means the user confirmed;
825
+ * there is no third resolved outcome. Presentation failures reject.
826
+ */
827
+ export type ModalResult = {
828
+ canceled: false;
829
+ } | CanceledResult;
830
+
831
+ /**
832
+ * One app-declared action shown in the host-provided More affordance.
833
+ * Mobile hosts render these in the capsule sheet; desktop hosts render
834
+ * them in the lxapp context menu. The native menu is fully dismissed
835
+ * before `onClick` runs.
836
+ */
837
+ export type MoreAction = {
838
+ /** Bundled resource path or an app-accessible local `lx://` path. */
839
+ icon: string;
840
+ /** Visible action label. */
841
+ label: string;
842
+ onClick: () => void | Promise<void>;
843
+ };
844
+
845
+ /**
846
+ * Options for `lx.navigateBack()`. Omit the object or `delta` to pop
847
+ * one page.
848
+ */
849
+ export type NavigateBackOptions = {
850
+ /** Number of pages to pop. Defaults to 1. */
851
+ delta?: number;
852
+ };
853
+
854
+ /**
855
+ * Navigate to another lxapp inside the current App Surface. JavaScript
856
+ * callers address pages by their configured name; page routes are an
857
+ * internal runtime detail and are not accepted as input.
858
+ */
859
+ export type NavigateToAppOptions = {
860
+ appId: string;
861
+ /**
862
+ * Configured page name from the target lxapp's `lxapp.json`. Omit it to
863
+ * open the target app's initial page. Full routes such as
864
+ * `/pages/home/index` are not supported.
865
+ */
866
+ page?: string;
867
+ query?: PageQuery;
868
+ envVersion?: LxAppEnvVersion;
869
+ targetVersion?: string;
870
+ };
871
+
872
+ export type NavigateToOptions = PageTargetOptions;
873
+
874
+ export type NavigationBarApi = globalThis.NavigationBarApi;
875
+
876
+ export type NavigationBarPatch = {
877
+ title?: string | null;
878
+ homeButton?: VisibilityPreference;
879
+ style?: NavigationBarStylePatch | null;
880
+ };
881
+
882
+ export type NavigationBarStylePatch = {
883
+ backgroundColor?: string | null;
884
+ foregroundColor?: string | null;
885
+ dividerColor?: string | null;
886
+ };
887
+
888
+ export type NetworkChangeCallback = (info: NetworkInfo) => void;
889
+
890
+ export type NetworkInfo = {
891
+ isConnected: boolean;
892
+ networkType: NetworkType;
893
+ ipv4: string[];
894
+ ipv6: string[];
895
+ };
896
+
897
+ /** Network status APIs. */
898
+ export type NetworkType = 'none' | 'unknown' | 'wifi' | '2g' | '3g' | '4g' | '5g' | 'ethernet';
899
+
900
+ /** File system APIs. */
901
+ export type OpenFileOptions = {
902
+ /** Local file path or runtime-managed temp path. */
903
+ filePath: string;
904
+ /** Optional coarse file type hint such as `pdf`, `docx`, or `xlsx`. */
905
+ fileType?: string;
906
+ /**
907
+ * `auto`: prefer native review, then fall back to external open.
908
+ * `review`: require native review UI and reject when unsupported.
909
+ * `external`: hand off directly to the system / external app.
910
+ */
911
+ mode?: 'auto' | 'review' | 'external';
912
+ /** Hint for whether the native review UI should expose its action menu when supported. */
913
+ showMenu?: boolean;
914
+ };
915
+
916
+ /**
917
+ * `as` picks the shape. A float anchors and carries no decoration; a
918
+ * window is decorated and does not anchor. The runtime rejects the
919
+ * wrong pairing either way, so the type says it first — except with an
920
+ * ordered preference, where the realized placement is not known up
921
+ * front and both stay open.
922
+ */
923
+ export type OpenPageOptions = (OpenPageShared & {
924
+ /** The default. Rejects when the host cannot float. */
925
+ as?: 'float';
926
+ /** Where the float anchors. */
927
+ position?: SurfaceFloatPosition;
928
+ chrome?: never;
929
+ }) | (OpenPageShared & {
930
+ /** A separate desktop window. Rejects when the host cannot make one. */
931
+ as: 'window';
932
+ /** Window decoration. */
933
+ chrome?: WindowChrome;
934
+ position?: never;
935
+ }) | (OpenPageShared & {
936
+ /**
937
+ * An ordered preference: the first placement the host can realize wins,
938
+ * and `realized` reports which.
939
+ */
940
+ as: readonly ('float' | 'window')[];
941
+ chrome?: WindowChrome;
942
+ position?: SurfaceFloatPosition;
943
+ });
944
+
945
+ export type OpenPageShared = {
946
+ /**
947
+ * A float accepts a percentage; a window is in logical pixels and ignores
948
+ * one. Both live here rather than in two option types, because `as` may be
949
+ * an ordered preference and the realized placement is not known up front.
950
+ */
951
+ size?: OverlaySurfaceSize;
952
+ interaction?: SurfaceInteraction;
953
+ query?: Record<string, unknown>;
954
+ /** Caller-owned identity, for `lx.surface.get(key)` later. */
955
+ key?: string;
956
+ };
957
+
958
+ export type OpenUrlOptions = {
959
+ /**
960
+ * `tab` opens a browser tab; `aside` docks the browser beside the main.
961
+ * Defaults to `'tab'`.
962
+ */
963
+ as?: 'tab' | 'aside' | readonly ('tab' | 'aside')[];
964
+ /** Preferred docking side when the realized placement is an aside. */
965
+ edge?: SurfaceEdge;
966
+ size?: OverlaySurfaceSize;
967
+ /** Stable identity for `lx.surface.get(key)`. */
968
+ key?: string;
969
+ };
970
+
971
+ export type OverlaySurfaceSize = {
972
+ /** Width hint. */
973
+ width?: OverlaySurfaceSizeValue;
974
+ /** Height hint. */
975
+ height?: OverlaySurfaceSizeValue;
976
+ };
977
+
978
+ /**
979
+ * Size hint for an overlay surface (aside / float).
980
+ * - number: absolute px, must be > 0
981
+ * - `${number}%`: percentage of the container, 0 < N ≤ 100
982
+ */
983
+ export type OverlaySurfaceSizeValue = number | `${number}%`;
984
+
985
+ export type PageLoadOptions = {
986
+ [key: string]: string | undefined;
987
+ };
988
+
989
+ export type PageMessagePort = {
990
+ postMessage(message: unknown): void;
991
+ onMessage(handler: (message: unknown) => void): () => void;
992
+ };
993
+
994
+ export type PageQuery = Record<string, PageQueryValue>;
995
+
996
+ export type PageQueryValue = string | number | boolean | null | undefined;
997
+
998
+ /** One of this lxapp's own pages, opened as a float or a window. */
999
+ export type PageSurface = SurfaceBase & SurfaceShowable & SurfaceMessaging & {
1000
+ readonly kind: 'page';
1001
+ readonly realized: 'float' | 'window';
1002
+ };
1003
+
1004
+ /**
1005
+ * Target page for `navigateTo`, `redirectTo`, `switchTab`, and `reLaunch`.
1006
+ * JavaScript navigation accepts only the configured page name; full routes
1007
+ * are internal runtime details. Discover names with `lxdev lxapp pages`.
1008
+ */
1009
+ export type PageTargetOptions = {
1010
+ /** Configured page name from `lingxia.yaml` / `lxapp.json`. */
1011
+ page: string;
1012
+ query?: PageQuery;
1013
+ };
1014
+
1015
+ export type PreviewMediaAdvance = 'manual' | 'next' | 'loop';
1016
+
1017
+ /** One change-stream event / the `current` snapshot. */
1018
+ export type PreviewMediaChange = {
1019
+ index: number;
1020
+ source: PreviewMediaShownSource;
1021
+ };
1022
+
1023
+ export type PreviewMediaCloseReason = 'manual' | 'completed' | 'interrupted' | 'error';
1024
+
1025
+ /**
1026
+ * Handle returned synchronously from `lx.previewMedia(...)` — synchronous so
1027
+ * listeners can be attached before the first event fires:
1028
+ * - `presented` resolves once the first pixel of the underlying media has
1029
+ * been composited to screen. Use this to time the hide of an overlay
1030
+ * surface above the preview so the swap is seamless. Never rejects;
1031
+ * resolves with no value when the first frame is up. Safe to ignore.
1032
+ * - `current` is a live `{ index, source }` snapshot of the item on screen,
1033
+ * updated as the user swipes and as the session auto-advances.
1034
+ * - `onChange(listener)` fires for every item change. Returns an
1035
+ * unsubscribe function.
1036
+ * - `completed` resolves `{ reason, index, source }` when the preview
1037
+ * session ends (manual / auto / interrupted / error), or rejects on abort.
1038
+ * If the call was aborted before any frame was presented, `presented` still
1039
+ * resolves (with no value) once the abort takes effect — it never rejects,
1040
+ * to keep fire-and-forget usage safe.
1041
+ * @example
1042
+ * const preview = lx.previewMedia({ sources, startIndex: 2 });
1043
+ * preview.onChange(({ source }) => markAsViewed(source.path));
1044
+ * const { reason, source } = await preview.completed;
1045
+ */
1046
+ export type PreviewMediaHandle = {
1047
+ readonly presented: Promise<void>;
1048
+ readonly current: PreviewMediaChange;
1049
+ onChange(listener: (change: PreviewMediaChange) => void): () => void;
1050
+ readonly completed: Promise<PreviewMediaResult>;
1051
+ };
1052
+
1053
+ export type PreviewMediaOptions = string | PreviewMediaSingleOptions | PreviewMediaSequenceOptions;
1054
+
1055
+ export type PreviewMediaResult = {
1056
+ /**
1057
+ * Why the preview session finished.
1058
+ */
1059
+ reason: PreviewMediaCloseReason;
1060
+ /**
1061
+ * Index of the item on screen when the session closed.
1062
+ */
1063
+ index: number;
1064
+ /**
1065
+ * The item on screen when the session closed — "what the user just
1066
+ * viewed/played", without mapping `index` back yourself.
1067
+ */
1068
+ source: PreviewMediaShownSource;
1069
+ };
1070
+
1071
+ export type PreviewMediaSequenceOptions = {
1072
+ /**
1073
+ * Preview list. Supports images, videos, or a mixed queue.
1074
+ */
1075
+ sources: PreviewMediaSource[];
1076
+ /**
1077
+ * Initial item index in `sources`.
1078
+ * Must be an integer.
1079
+ * Out-of-range values are clamped by runtime.
1080
+ * Default: `0`.
1081
+ */
1082
+ startIndex?: number;
1083
+ /**
1084
+ * Auto behavior for the preview session.
1085
+ *
1086
+ * - `manual`: never auto-advance
1087
+ * - `next`: advance to the next item; if already on the last item, close the session
1088
+ * - `loop`: advance to the next item; if already on the last item, wrap to the first item
1089
+ *
1090
+ * Default: `manual`
1091
+ */
1092
+ advance?: PreviewMediaAdvance;
1093
+ /**
1094
+ * Optional cancellation signal for the preview request.
1095
+ *
1096
+ * Aborting rejects the returned promise with a cancellation error and requests the active
1097
+ * native preview session to close immediately.
1098
+ */
1099
+ signal?: AbortSignal;
1100
+ /**
1101
+ * Whether to show the top `current/total` indicator.
1102
+ *
1103
+ * Default: `true` when previewing multiple items, otherwise `false`.
1104
+ */
1105
+ showIndexIndicator?: boolean;
1106
+ };
1107
+
1108
+ /**
1109
+ * The item the user is (or was) looking at, handed back as the caller
1110
+ * described it — `path` is returned verbatim, so it can be matched against
1111
+ * the caller's own data without re-indexing an array.
1112
+ */
1113
+ export type PreviewMediaShownSource = {
1114
+ /** The path exactly as passed in the request. */
1115
+ path: string;
1116
+ /** Resolved media kind (after extension inference when `type` was omitted). */
1117
+ type: 'image' | 'video';
1118
+ };
1119
+
1120
+ export type PreviewMediaSingleOptions = PreviewMediaSource & {
1121
+ /**
1122
+ * Auto behavior for the preview session.
1123
+ *
1124
+ * - `manual`: never auto-advance
1125
+ * - `next`: advance to the next item; if already on the last item, close the session
1126
+ * - `loop`: advance to the next item; if already on the last item, wrap to the first item
1127
+ *
1128
+ * Default: `manual`
1129
+ */
1130
+ advance?: PreviewMediaAdvance;
1131
+ /**
1132
+ * Optional cancellation signal for the preview request.
1133
+ *
1134
+ * Aborting rejects the returned promise with a cancellation error and requests the active
1135
+ * native preview session to close immediately.
1136
+ */
1137
+ signal?: AbortSignal;
1138
+ /**
1139
+ * Whether to show the top `current/total` indicator.
1140
+ *
1141
+ * Default: `true` when previewing multiple items, otherwise `false`.
1142
+ */
1143
+ showIndexIndicator?: boolean;
1144
+ };
1145
+
1146
+ export type PreviewMediaSource = {
1147
+ /**
1148
+ * Media source path.
1149
+ * Recommended: `lx://` path (for example `lx://usercache/...`) or a sandbox-local path
1150
+ * that can be resolved by runtime access rules.
1151
+ */
1152
+ path: string;
1153
+ type?: 'image' | 'video';
1154
+ /**
1155
+ * Optional clockwise rotation in degrees (`0 | 90 | 180 | 270`).
1156
+ * Default: when omitted, runtime resolves orientation from media metadata.
1157
+ */
1158
+ rotate?: MediaRotation;
1159
+ /**
1160
+ * Optional display fit mode for video preview.
1161
+ * Default: `contain`.
1162
+ */
1163
+ objectFit?: MediaObjectFit;
1164
+ /**
1165
+ * Display duration in milliseconds.
1166
+ * Effective when preview `advance` is not `manual`.
1167
+ */
1168
+ durationMs?: number;
1169
+ };
1170
+
1171
+ export type ReLaunchOptions = PageTargetOptions;
1172
+
1173
+ export type RedirectToOptions = PageTargetOptions;
1174
+
1175
+ export type ResolvedAppearance = 'light' | 'dark';
1176
+
1177
+ export type SaveMediaOptions = {
1178
+ filePath: string;
1179
+ };
1180
+
1181
+ export type ScanCodeOptions = {
1182
+ onlyFromCamera?: boolean;
1183
+ scanType?: ('barCode' | 'qrCode' | 'datamatrix' | 'pdf417')[];
1184
+ };
1185
+
1186
+ /**
1187
+ * Result of `lx.scanCode`. Branch on `canceled` before reading the scan
1188
+ * payload.
1189
+ */
1190
+ export type ScanCodeResult = {
1191
+ canceled: false;
1192
+ scanResult: string;
1193
+ scanType: string;
1194
+ } | CanceledResult;
1195
+
1196
+ /** Share images, PDFs, or other files. */
1197
+ export type ShareFilesOptions = ShareTitleOptions & {
1198
+ /**
1199
+ * File paths returned by LingXia APIs to share. Images, PDFs, and other
1200
+ * documents are all represented as file paths.
1201
+ *
1202
+ * Use `lx.chooseFile` for system files and `lx.chooseMedia` for picked media;
1203
+ * pass the returned path here without parsing it.
1204
+ * Some platforms or receivers may limit multi-file shares. Share files one
1205
+ * at a time when targeting those receivers.
1206
+ *
1207
+ * `files` and `page` are mutually exclusive.
1208
+ * `text` is intentionally not supported for file shares because system
1209
+ * receivers handle text+attachment inconsistently.
1210
+ */
1211
+ files: string[];
1212
+ page?: never;
1213
+ text?: never;
1214
+ };
1215
+
1216
+ export type ShareOptions = ShareTextOptions | SharePageOptions | ShareFilesOptions;
1217
+
1218
+ export type SharePage = /**
1219
+ * Share the current page.
1220
+ */
1221
+ true
1222
+ /**
1223
+ * Share the current page with query.
1224
+ */
1225
+ | {
1226
+ /**
1227
+ * Query appended to the current page. Query belongs to the page target and is
1228
+ * encoded into the AppLink URL.
1229
+ */
1230
+ query?: ShareQuery;
1231
+ };
1232
+
1233
+ /** Share the current page as an AppLink. */
1234
+ export type SharePageOptions = ShareTextBaseOptions & {
1235
+ /**
1236
+ * Share the current page. The runtime uses the current appId and page path
1237
+ * implicitly and shares it through the host AppLink configuration.
1238
+ *
1239
+ * Rejects when the host app has no `appLinks.hosts` configuration because
1240
+ * receivers would not be able to open the shared page.
1241
+ *
1242
+ * `title` and `text` are presentation hints. Platforms and receivers may
1243
+ * ignore them; on iOS the URL is shared by itself so receivers can render it
1244
+ * as a webpage card when they support that.
1245
+ *
1246
+ * `page` and `files` are mutually exclusive.
1247
+ */
1248
+ page: SharePage;
1249
+ files?: never;
1250
+ };
1251
+
1252
+ /** Share APIs. */
1253
+ export type ShareQuery = Record<string, string | number | boolean>;
1254
+
1255
+ export type ShareResult = {
1256
+ /**
1257
+ * What the share sheet reported. Not part of the `canceled` family: some
1258
+ * platforms only observe that the system UI opened and closed, so the
1259
+ * unknown case is stated rather than hidden in a missing boolean that
1260
+ * every call site would read as "not shared".
1261
+ */
1262
+ outcome: 'completed' | 'dismissed' | 'unknown';
1263
+ };
1264
+
1265
+ export type ShareTextBaseOptions = ShareTitleOptions & {
1266
+ /**
1267
+ * Share text body.
1268
+ */
1269
+ text?: string;
1270
+ };
1271
+
1272
+ /**
1273
+ * Share title/text only. Receiver support is platform/app dependent; some
1274
+ * share extensions may reject text-only shares.
1275
+ */
1276
+ export type ShareTextOptions = ShareTextBaseOptions & {
1277
+ page?: never;
1278
+ files?: never;
1279
+ };
1280
+
1281
+ export type ShareTitleOptions = {
1282
+ /**
1283
+ * Share title.
1284
+ */
1285
+ title?: string;
1286
+ };
1287
+
1288
+ /**
1289
+ * App-owned host-shell chrome. Mutations are available only to the home
1290
+ * lxapp's Logic context; other lxapps receive a permission error.
1291
+ */
1292
+ export type ShellApi = {
1293
+ /**
1294
+ * Declares runtime actions in the desktop shell's sidebar header or footer.
1295
+ * The shell controls layout and only dispatches activation; callbacks own
1296
+ * navigation and all other behavior.
1297
+ */
1298
+ sidebarActions: ShellSidebarActionsApi;
1299
+ /** Compose another lxapp into a shell slot. */
1300
+ openApp(appId: string, options: ShellOpenAppOptions): Promise<AppSurface>;
1301
+ /** Open a host builtin page such as settings or downloads. */
1302
+ openBuiltin(page: BuiltinShellPage): Promise<BuiltinSurface>;
1303
+ /**
1304
+ * Open a declared surface with shell privileges — the same declaration
1305
+ * `lx.surface.openDeclared` opens, plus the keyed multi-instance form and
1306
+ * placement overrides.
1307
+ */
1308
+ openDeclared(id: string, options?: ShellOpenDeclaredOptions): Promise<DeclaredSurface>;
1309
+ /** Re-place a live declared surface: change its role or its edge. */
1310
+ reconfigure(id: string, patch: ShellSurfacePatch): Promise<void>;
1311
+ };
1312
+
1313
+ export type ShellOpenAppOptions = {
1314
+ /** `main` occupies the primary content area; `aside` a companion region. */
1315
+ as: 'main' | 'aside';
1316
+ /** Preferred docking side. Only meaningful with `as: 'aside'`. */
1317
+ edge?: SurfaceEdge;
1318
+ /**
1319
+ * Configured page name from the target lxapp's `lxapp.json`. Omit it to
1320
+ * open that app's initial page. Full page routes are not supported.
1321
+ */
1322
+ page?: string;
1323
+ query?: PageQuery;
1324
+ /** Defaults to 'release'. */
1325
+ envVersion?: LxAppEnvVersion;
1326
+ targetVersion?: string;
1327
+ /** Stable identity for `lx.surface.get(key)`. */
1328
+ key?: string;
1329
+ };
1330
+
1331
+ /**
1332
+ * The declared-surface options only the home lxapp may use.
1333
+ * Creating an extra instance and overriding a placement both mutate
1334
+ * shared shell composition, so they live here and not on
1335
+ * `lx.surface.openDeclared` — which consumes a declaration exactly as
1336
+ * the host authored it, and therefore takes no options at all.
1337
+ */
1338
+ export type ShellOpenDeclaredOptions = {
1339
+ /**
1340
+ * Caller-owned identity, for `lx.surface.get(key)` later — the same key
1341
+ * every opener takes. It carries one extra power here: a declaration can
1342
+ * be opened more than once, and the key is which instance you mean, so a
1343
+ * new key creates one. 1 to 128 UTF-8 bytes. Declarations without
1344
+ * instantiable native providers reject it with `capability_missing`.
1345
+ */
1346
+ key?: string;
1347
+ /**
1348
+ * Open with a role other than the declaration's. Must be realizable by the
1349
+ * declared provider; a stable root rejects anything but `main`. Prefer this
1350
+ * over opening and then calling `reconfigure`, which would present the
1351
+ * wrong role first.
1352
+ */
1353
+ as?: 'main' | 'aside' | 'float';
1354
+ /** Preferred docking side when the effective role is `aside`. */
1355
+ edge?: SurfaceEdge;
1356
+ };
1357
+
1358
+ /**
1359
+ * One app-declared shell sidebar action. It is a stateless command, not a
1360
+ * selectable navigation item: the shell invokes `onActivate` once and
1361
+ * does not infer a target or active state.
1362
+ */
1363
+ export type ShellSidebarAction = {
1364
+ /** Stable, non-empty id; unique across both header and footer actions. */
1365
+ id: string;
1366
+ /**
1367
+ * Initial host-owned region. Use `replace` to move an action. The header
1368
+ * takes at most two; everything else belongs in the footer.
1369
+ */
1370
+ placement: ShellSidebarActionPlacement;
1371
+ /**
1372
+ * Local lxapp-accessible icon. Use a bundled relative path such as
1373
+ * `public/settings.svg`, or an `lx://temp`, `lx://usercache`, or
1374
+ * `lx://userdata` path returned by LingXia file APIs. Native absolute paths,
1375
+ * parent traversal, `file:` URLs, and network URLs are rejected; download a
1376
+ * remote icon before registration. For portable rendering, prefer a square,
1377
+ * transparent, monochrome SVG or PNG designed for a 16-point visual.
1378
+ */
1379
+ icon: string;
1380
+ /**
1381
+ * Visible footer title and the tooltip/accessibility text for every
1382
+ * placement. Long footer labels are kept on one line and tail-truncated.
1383
+ */
1384
+ label: string;
1385
+ /** Visible but non-activatable when true. Defaults to false. */
1386
+ disabled?: boolean;
1387
+ /**
1388
+ * Called once for each enabled mouse, keyboard, accessibility, shortcut, or
1389
+ * automation activation. Explicitly open or navigate to the desired content.
1390
+ */
1391
+ onActivate: () => void;
1392
+ };
1393
+
1394
+ /**
1395
+ * Where the host renders a sidebar action on desktop.
1396
+ * - `header`: icon-only, at most two actions; `label` supplies tooltip
1397
+ * and accessibility text. Hidden in the compact/collapsed shell.
1398
+ * - `footer`: icon and label in the expanded sidebar, icon-only in the
1399
+ * compact rail. The host wraps cells and scrolls after five visible
1400
+ * rows.
1401
+ * Apps cannot configure cell size, row, weight, color, or selected state.
1402
+ * Where an action lives in the sidebar.
1403
+ * `header` is the caption row beside the window controls: at most two
1404
+ * actions, for the ones a person reaches for constantly. Declaring a
1405
+ * third rejects the whole `replace` call rather than hiding one.
1406
+ * `footer` is unbounded and scrolls, and every entry stays visible at
1407
+ * any window size. Anything that must be findable belongs here.
1408
+ */
1409
+ export type ShellSidebarActionPlacement = 'header' | 'footer';
1410
+
1411
+ /**
1412
+ * Mutable presentation fields for an existing sidebar action. The patch
1413
+ * must contain at least one field. Use `replace` to change `placement` or
1414
+ * `onActivate`.
1415
+ */
1416
+ export type ShellSidebarActionUpdate = {
1417
+ /** Replacement local icon, with the same path rules as registration. */
1418
+ icon?: string;
1419
+ /** Replacement non-empty visible/accessibility label. */
1420
+ label?: string;
1421
+ /** Whether the action remains visible but rejects activation. */
1422
+ disabled?: boolean;
1423
+ };
1424
+
1425
+ /**
1426
+ * Role and edge overrides the home lxapp may apply to a live declared
1427
+ * surface. A stable root rejects non-main roles.
1428
+ */
1429
+ export type ShellSurfacePatch = {
1430
+ as?: 'main' | 'aside' | 'float';
1431
+ edge?: SurfaceEdge;
1432
+ };
1433
+
1434
+ export type ShowActionSheetOptions = {
1435
+ itemList: string[];
1436
+ itemColor?: string;
1437
+ };
1438
+
1439
+ export type ShowModalOptions = {
1440
+ title?: string;
1441
+ content?: string;
1442
+ showCancel?: boolean;
1443
+ cancelText?: string;
1444
+ cancelColor?: string;
1445
+ confirmText?: string;
1446
+ confirmColor?: string;
1447
+ };
1448
+
1449
+ /** UI feedback, navigation, and surface control APIs. */
1450
+ export type ShowToastOptions = {
1451
+ title: string;
1452
+ icon?: 'success' | 'error' | 'loading' | 'none';
1453
+ image?: string;
1454
+ duration?: number;
1455
+ mask?: boolean;
1456
+ position?: 'top' | 'center' | 'bottom';
1457
+ };
1458
+
1459
+ /**
1460
+ * Asynchronous persistent key-value storage backed by the lxapp
1461
+ * database. Use `lx.fs` for path-based data.
1462
+ * `get<T>()` is an unchecked assertion at the call site. Pin every
1463
+ * key's shape once with `lx.getStorage<Schema>()` — that returns a
1464
+ * `TypedStorage<Schema>` instead of this untyped handle.
1465
+ */
1466
+ export type Storage = {
1467
+ /**
1468
+ * Reads a stored value. `T` is an unchecked assertion about the stored
1469
+ * shape, exactly like a `JSON.parse` boundary; a missing key resolves
1470
+ * `undefined`, which a stored `null` never does.
1471
+ */
1472
+ get<T = unknown>(key: string): Promise<T | undefined>;
1473
+ set(key: string, value: unknown): Promise<void>;
1474
+ delete(key: string): Promise<void>;
1475
+ clear(): Promise<void>;
1476
+ /** Resolves every key, optionally filtered by prefix. */
1477
+ list(prefix?: string): Promise<string[]>;
1478
+ info(): Promise<StorageInfo>;
1479
+ };
1480
+
1481
+ /** Current persistent-storage usage and configured limits. */
1482
+ export type StorageInfo = {
1483
+ currentSize: number;
1484
+ limitSize: number;
1485
+ keyCount: number;
1486
+ };
1487
+
1488
+ export type StreamSourceOptions = {
1489
+ provider: string;
1490
+ isLive: boolean;
1491
+ duration?: number;
1492
+ params?: Record<string, unknown>;
1493
+ };
1494
+
1495
+ /**
1496
+ * Content-keyed surface composition, callable by any lxapp. Privileged
1497
+ * composition lives on `lx.shell`, so the namespace is the privilege.
1498
+ */
1499
+ export type SurfaceApi = {
1500
+ /** Open one of this lxapp's own pages as a float or a window. */
1501
+ openPage(page: string, options?: OpenPageOptions): Promise<PageSurface>;
1502
+ /** Open external content in the in-app browser. */
1503
+ openUrl(url: string, options?: OpenUrlOptions): Promise<TabSurface>;
1504
+ /**
1505
+ * Open a surface the host declared in `lingxia.yaml`, with the placement
1506
+ * the declaration chose. Instance keys and placement overrides are shell
1507
+ * composition; they live on `lx.shell.openDeclared`.
1508
+ */
1509
+ openDeclared(id: string): Promise<DeclaredSurface>;
1510
+ /**
1511
+ * The live handle for a surface this lxapp opened **with a `key`**, found
1512
+ * by that key or by its `id`. Removes the need to cache handles in order
1513
+ * to reuse or close them. A surface opened without a `key` is not
1514
+ * addressable — nothing else refers to a runtime-assigned id, so nothing
1515
+ * registers it. A key you chose wins over an id it happens to spell.
1516
+ */
1517
+ get(keyOrId: string): AnySurface | undefined;
1518
+ /**
1519
+ * Observe this presentation's viewport. Invoked immediately with the
1520
+ * current context, then again whenever it changes. Returns an unsubscribe
1521
+ * function.
1522
+ */
1523
+ onContext(handler: (context: SurfaceContext) => void): () => void;
1524
+ };
1525
+
1526
+ /** What every surface handle carries, whatever opened it. */
1527
+ export type SurfaceBase = {
1528
+ readonly kind: SurfaceKind;
1529
+ readonly id: string;
1530
+ /** The caller-supplied identity, when this surface was opened with one. */
1531
+ readonly key?: string;
1532
+ /**
1533
+ * The placement the host produced, which an ordered preference may narrow.
1534
+ * Live rather than a snapshot: `lx.shell.reconfigure` updates it on the
1535
+ * handle you already hold.
1536
+ */
1537
+ readonly realized: SurfacePlacement;
1538
+ /** True until `close()` fires; afterwards the page instance is torn down. */
1539
+ readonly alive: boolean;
1540
+ /**
1541
+ * Last-known visibility, kept in sync with the native side. Safe to bind
1542
+ * into declarative UI; for event-driven updates use `onShow` / `onHide`.
1543
+ */
1544
+ readonly visible: boolean;
1545
+ /**
1546
+ * Destroy the surface. The stable root main cannot be closed. Repeated
1547
+ * calls after a successful close are idempotent.
1548
+ */
1549
+ close(): Promise<void>;
1550
+ onClose(handler: (event: SurfaceClosedEvent) => void): () => void;
1551
+ };
1552
+
1553
+ /**
1554
+ * Surfaces (docked asides, floats, windows, browser tabs, declared surfaces)
1555
+ * and the desktop tray — the types behind `lx.surface`, `lx.shell`,
1556
+ * and `lx.tray`.
1557
+ */
1558
+ export type SurfaceCloseReason = 'user' | 'programmatic' | 'owner_closed' | 'app_closed' | 'failed'
1559
+ /**
1560
+ * The SDK reclaimed a long-hidden overlay surface for resource reasons.
1561
+ * Treat as a normal close: the page instance is gone; further postMessage /
1562
+ * show / hide calls will fail. The opener may immediately reopen if needed.
1563
+ */
1564
+ | 'reclaimed' | 'unknown';
1565
+
1566
+ export type SurfaceClosedEvent = {
1567
+ id: string;
1568
+ reason: SurfaceCloseReason;
1569
+ };
1570
+
1571
+ /**
1572
+ * The current surface viewport context, delivered to `lx.surface.onContext()`
1573
+ * so an lxapp can self-adapt (e.g. switch column count by `sizeClass`).
1574
+ */
1575
+ export type SurfaceContext = {
1576
+ /** compact (<600) / medium (600–840) / expanded (>840), with hysteresis. */
1577
+ sizeClass: 'compact' | 'medium' | 'expanded';
1578
+ /** Actual surface viewport width in logical pixels. */
1579
+ width: number;
1580
+ /** Actual surface viewport height in logical pixels. */
1581
+ height: number;
1582
+ };
1583
+
1584
+ /**
1585
+ * Preferred docking side for an aside when the Host has room for a docked
1586
+ * layout. `aside` selects the companion region; `edge` selects a side within
1587
+ * it. Compact Hosts may reproject the same aside as a full-screen overlay.
1588
+ */
1589
+ export type SurfaceEdge = 'left' | 'right' | 'top' | 'bottom';
1590
+
1591
+ /**
1592
+ * A surface rejection. The runtime carries the surface code on
1593
+ * `data.code` — `code` itself is the transport-level host code, shared
1594
+ * with every other `lx` rejection — so read it with
1595
+ * `surfaceErrorCode(error)` and never parse the message.
1596
+ * ```ts
1597
+ * import { surfaceErrorCode } from 'lingxia-types/error';
1598
+ * catch (error) {
1599
+ * if (surfaceErrorCode(error) === 'unsupported_placement') { … }
1600
+ * }
1601
+ * ```
1602
+ */
1603
+ export type SurfaceError = Error & {
1604
+ readonly data?: { readonly code?: SurfaceErrorCode };
1605
+ };
1606
+
1607
+ /**
1608
+ * Why a surface operation was refused. Carried as `code` on every
1609
+ * `SurfaceError`, so no caller has to match on message text.
1610
+ */
1611
+ export type SurfaceErrorCode = /** The placement cannot be realized by this host build. */
1612
+ 'unsupported_placement'
1613
+ /** A privileged operation was called by an lxapp other than the home lxapp. */
1614
+ | 'denied'
1615
+ /** No such declared surface, lxapp, or builtin page. */
1616
+ | 'not_declared'
1617
+ /** The arguments are malformed or combine options that cannot apply together. */
1618
+ | 'invalid_arg'
1619
+ /** The target is already open in a role this call cannot change. */
1620
+ | 'already_open_other_role'
1621
+ /** The surface has been closed; the handle is detached. */
1622
+ | 'closed'
1623
+ /** The host lacks a capability the request needs, such as an instantiable
1624
+ * native provider for a keyed surface. */
1625
+ | 'capability_missing'
1626
+ /** The operation reached the host and failed there. */
1627
+ | 'failed';
1628
+
1629
+ /** Where a float popup anchors (default `center`). */
1630
+ export type SurfaceFloatPosition = 'center' | 'top' | 'bottom' | 'left' | 'right';
1631
+
1632
+ /** Native interaction supplied by the host around page content. */
1633
+ export type SurfaceInteraction = {
1634
+ /** Show the standard circular close button. Default `false`. */
1635
+ closeButton?: boolean;
1636
+ /** Default `tapOutside` for floats and `manual` for windows. */
1637
+ dismiss?: 'tapOutside' | 'manual';
1638
+ /** Block interaction with content below. Default `false`. */
1639
+ modal?: boolean;
1640
+ };
1641
+
1642
+ /**
1643
+ * Where the content came from. The discriminant on every surface
1644
+ * handle, so `AnySurface` narrows without a runtime `typeof` check.
1645
+ */
1646
+ export type SurfaceKind = 'page' | 'declared' | 'app' | 'tab' | 'builtin';
1647
+
1648
+ /** Two-way messaging, available when both sides are lxapp pages. */
1649
+ export type SurfaceMessaging = {
1650
+ /**
1651
+ * Send to the other side. For the opener this targets the opened page;
1652
+ * for the opened page it targets the opener.
1653
+ */
1654
+ postMessage(message: unknown): void;
1655
+ onMessage(handler: (message: unknown) => void): () => void;
1656
+ };
1657
+
1658
+ /**
1659
+ * What the host actually produced. Reported by `realized`, which is
1660
+ * how a caller reads the outcome of an ordered placement preference.
1661
+ */
1662
+ export type SurfacePlacement = 'main' | 'aside' | 'float' | 'window' | 'tab';
1663
+
1664
+ export type SurfacePresentation = 'main' | 'dock' | 'overlay' | 'popover' | 'sheet' | 'window';
1665
+
1666
+ export type SurfaceRole = 'main' | 'aside' | 'float';
1667
+
1668
+ /** Surfaces the host can hide and restore without losing page state. */
1669
+ export type SurfaceShowable = {
1670
+ /**
1671
+ * Restore a hidden surface. The page instance survived, so scroll
1672
+ * position, form input, and JS state come back with it. Idempotent.
1673
+ */
1674
+ show(): Promise<void>;
1675
+ /**
1676
+ * Hide without destroying. Main surfaces cannot be hidden and reject.
1677
+ * Idempotent.
1678
+ */
1679
+ hide(): Promise<void>;
1680
+ /** Fires on a real transition to visible, whichever side drove it. */
1681
+ onShow(handler: (event: SurfaceVisibilityEvent) => void): () => void;
1682
+ /** Fires on a real transition to hidden, whichever side drove it. */
1683
+ onHide(handler: (event: SurfaceVisibilityEvent) => void): () => void;
1684
+ };
1685
+
1686
+ /**
1687
+ * Detail payload for `onShow` / `onHide` events. `source` identifies which
1688
+ * Surface object initiated the visibility change so observers can
1689
+ * distinguish self-driven transitions from peer-driven ones (e.g. an opener
1690
+ * UI that wants to update its own button state only when the page side
1691
+ * toggled visibility). `shell` identifies a host-driven main switch.
1692
+ */
1693
+ export type SurfaceVisibilityEvent = {
1694
+ id: string;
1695
+ source: 'opener' | 'page' | 'shell';
1696
+ };
1697
+
1698
+ export type SwitchTabOptions = PageTargetOptions;
1699
+
1700
+ /** Native system Downloads path. Do not pass this to `lx.fs`. */
1701
+ export type SystemDownloadsPath = string & {
1702
+ readonly [systemDownloadsPathBrand]: 'system-downloads-path';
1703
+ };
1704
+
1705
+ export type TabBarApi = globalThis.TabBarApi;
1706
+
1707
+ export type TabBarItemPatch = {
1708
+ index: number;
1709
+ text?: string | null;
1710
+ iconPath?: string | null;
1711
+ selectedIconPath?: string | null;
1712
+ badge?: string | null;
1713
+ redDot?: boolean;
1714
+ };
1715
+
1716
+ export type TabBarPatch = {
1717
+ visibility?: TabBarVisibilityPreference;
1718
+ style?: TabBarStylePatch | null;
1719
+ items?: readonly TabBarItemPatch[];
1720
+ };
1721
+
1722
+ export type TabBarStylePatch = {
1723
+ foregroundColor?: string | null;
1724
+ selectedForegroundColor?: string | null;
1725
+ };
1726
+
1727
+ export type TabBarVisibilityPreference = 'auto' | 'visible' | 'hidden';
1728
+
1729
+ /** External content in the in-app browser. */
1730
+ export type TabSurface = SurfaceBase & {
1731
+ readonly kind: 'tab';
1732
+ readonly realized: 'tab' | 'aside';
1733
+ /**
1734
+ * `tab` when this handle owns exactly the tab it opened, and `close()` /
1735
+ * `activate()` act on it. `group` when the browser chrome owns the tab
1736
+ * strip: the content is open, but control belongs to that chrome, so both
1737
+ * methods reject with `unsupported_placement`. Branch on this rather than
1738
+ * on the old platform-dependent `null`.
1739
+ */
1740
+ readonly scope: 'tab' | 'group';
1741
+ /** Bring this tab to the front of its browser. `scope: 'group'` rejects. */
1742
+ activate(): Promise<void>;
1743
+ };
1744
+
1745
+ export type TerminalApi = {
1746
+ /** Saved terminal settings, revision-checked on write. */
1747
+ readonly settings: TerminalSettingsApi;
1748
+ /** Installed color schemes, plus import and live preview. */
1749
+ readonly colorSchemes: TerminalColorSchemesApi;
1750
+ /** Terminal fonts installed on this machine. */
1751
+ readonly fonts: TerminalFontsApi;
1752
+ /** Windows-only optional inline-image compatibility runtime. */
1753
+ readonly windows?: WindowsTerminalApi;
1754
+ };
1755
+
1756
+ export type TerminalColorScheme = {
1757
+ name?: string;
1758
+ background: string;
1759
+ foreground: string;
1760
+ cursorColor?: string;
1761
+ selectionBackground?: string;
1762
+ selectionForeground?: string;
1763
+ black: string;
1764
+ red: string;
1765
+ green: string;
1766
+ yellow: string;
1767
+ blue: string;
1768
+ purple: string;
1769
+ cyan: string;
1770
+ white: string;
1771
+ brightBlack: string;
1772
+ brightRed: string;
1773
+ brightGreen: string;
1774
+ brightYellow: string;
1775
+ brightBlue: string;
1776
+ brightPurple: string;
1777
+ brightCyan: string;
1778
+ brightWhite: string;
1779
+ };
1780
+
1781
+ export type TerminalColorSchemeDetails = {
1782
+ name: string;
1783
+ source: 'builtIn' | 'imported';
1784
+ scheme: TerminalColorScheme;
1785
+ };
1786
+
1787
+ export type TerminalColorSchemesApi = {
1788
+ list(): Promise<TerminalColorSchemeDetails[]>;
1789
+ import(options: {
1790
+ text: string;
1791
+ name?: string;
1792
+ /** Existing names are rejected unless overwrite is explicit. */
1793
+ overwrite?: boolean;
1794
+ }): Promise<TerminalColorSchemeDetails>;
1795
+ createPreview(): TerminalPreviewController;
1796
+ };
1797
+
1798
+ export type TerminalFontSettings = {
1799
+ /** Ordered candidates; the first installed monospaced family wins. */
1800
+ family: string[];
1801
+ size: number;
1802
+ lineHeight: number;
1803
+ ligatures: boolean;
1804
+ };
1805
+
1806
+ export type TerminalFontsApi = {
1807
+ list(): Promise<InstalledTerminalFont[]>;
1808
+ };
1809
+
1810
+ export type TerminalPreviewController = {
1811
+ /** Preview a stored name or an unpersisted scheme. Last request wins. */
1812
+ show(scheme: string | TerminalColorScheme): Promise<void>;
1813
+ /** Restore saved settings only when this controller owns the preview. */
1814
+ clear(): Promise<void>;
1815
+ /** Idempotently clear and retire this controller. */
1816
+ close(): Promise<void>;
1817
+ };
1818
+
1819
+ export type TerminalSettingsApi = {
1820
+ get(): Promise<TerminalSettingsSnapshot>;
1821
+ update(
1822
+ patch: TerminalSettingsPatch,
1823
+ options: { ifRevision: number },
1824
+ ): Promise<TerminalSettingsSnapshot>;
1825
+ reset(options: {
1826
+ ifRevision: number;
1827
+ scope?: 'font' | 'theme';
1828
+ }): Promise<TerminalSettingsSnapshot>;
1829
+ /** Fires after saved settings, effective appearance, or fonts change. */
1830
+ onChange(listener: (snapshot: TerminalSettingsSnapshot) => void): () => void;
1831
+ };
1832
+
1833
+ export type TerminalSettingsPatch = {
1834
+ font?: Partial<TerminalFontSettings>;
1835
+ theme?: Partial<TerminalThemeSettings>;
1836
+ };
1837
+
1838
+ export type TerminalSettingsSnapshot = {
1839
+ /** Monotonic process revision used by update/reset compare-and-swap. */
1840
+ revision: number;
1841
+ /** Framework defaults. */
1842
+ defaults: TerminalSettingsValue;
1843
+ /** User-authored fields only. */
1844
+ overrides: TerminalSettingsPatch;
1845
+ /** Resolved configuration after all valid layers. */
1846
+ value: TerminalSettingsValue;
1847
+ effective: {
1848
+ /** Host appearance before applying terminal.theme.mode. */
1849
+ systemAppearance: 'light' | 'dark';
1850
+ appearance: 'light' | 'dark';
1851
+ colorScheme: string | null;
1852
+ font: {
1853
+ family: string;
1854
+ missing: string[];
1855
+ fellBack: boolean;
1856
+ };
1857
+ };
1858
+ warnings: TerminalSettingsWarning[];
1859
+ };
1860
+
1861
+ export type TerminalSettingsValue = {
1862
+ font: TerminalFontSettings;
1863
+ theme: TerminalThemeSettings;
1864
+ };
1865
+
1866
+ export type TerminalSettingsWarning = {
1867
+ code: 'invalidUserFile' | 'missingColorScheme';
1868
+ message: string;
1869
+ };
1870
+
1871
+ export type TerminalThemeMode = 'system' | 'light' | 'dark';
1872
+
1873
+ export type TerminalThemeSettings = {
1874
+ mode: TerminalThemeMode;
1875
+ light: string;
1876
+ dark: string;
1877
+ };
1878
+
1879
+ export type TrayApi = globalThis.TrayApi;
1880
+
1881
+ /**
1882
+ * Runtime control of the menu-bar (macOS) / system-tray (Windows) status item.
1883
+ * The tray is declared in `lingxia.yaml` (`tray:`); these update its dynamic
1884
+ * content at runtime.
1885
+ * **Desktop only.** Mobile platforms have no tray, so every method here is a
1886
+ * no-op there (it never throws) — safe to call from portable code. For an
1887
+ * app-icon badge that *is* cross-platform (including mobile), use
1888
+ * `lx.app.setBadge`.
1889
+ */
1890
+ export type TrayMenuItem = {
1891
+ label: string;
1892
+ /** Invoked when this item is clicked. */
1893
+ onClick?: () => void;
1894
+ enabled?: boolean;
1895
+ checked?: boolean;
1896
+ };
1897
+
1898
+ export type TrayMenuSeparator = {
1899
+ separator: true;
1900
+ };
1901
+
1902
+ export type UpdateFailedInfo = UpdateReadyInfo & {
1903
+ error?: string;
1904
+ };
1905
+
1906
+ /**
1907
+ * Callback-based updates for this lxapp's bundle. Available to every
1908
+ * lxapp. To update the native host app, the home lxapp uses the
1909
+ * task-based `lx.app.checkUpdate()` API instead.
1910
+ */
1911
+ export type UpdateManager = {
1912
+ applyUpdate(): void;
1913
+ /** Subscribes to a ready update and returns the unsubscribe fn. */
1914
+ onUpdateReady(callback: (info: UpdateReadyInfo) => void): () => void;
1915
+ /** Subscribes to a failed update and returns the unsubscribe fn. */
1916
+ onUpdateFailed(callback: (info: UpdateFailedInfo) => void): () => void;
1917
+ };
1918
+
1919
+ export type UpdateReadyInfo = {
1920
+ version?: string;
1921
+ isForceUpdate?: boolean;
1922
+ channel?: "release" | "preview" | "developer" | string;
1923
+ };
1924
+
1925
+ export type UploadIteratorResult = {
1926
+ done: boolean;
1927
+ value?: UploadProgressEvent;
1928
+ };
1929
+
1930
+ export type UploadOptions = {
1931
+ /** HTTP(S) destination URL. */
1932
+ url: string;
1933
+ /** Local file path or runtime-managed URI to upload. */
1934
+ filePath: string;
1935
+ /** Multipart field name. Default: `file`. */
1936
+ name?: string;
1937
+ /**
1938
+ * Optional request headers.
1939
+ * Restricted headers such as `Referer` are ignored by the runtime.
1940
+ */
1941
+ headers?: Record<string, string>;
1942
+ /** Optional extra `multipart/form-data` text fields. */
1943
+ formData?: Record<string, string>;
1944
+ /** Request timeout in milliseconds. */
1945
+ timeout?: number;
1946
+ /** Override multipart filename. */
1947
+ fileName?: string;
1948
+ /** Override file MIME type. */
1949
+ mimeType?: string;
1950
+ /** Optional abort signal. */
1951
+ signal?: AbortSignal;
1952
+ };
1953
+
1954
+ export type UploadProgressEvent = {
1955
+ kind: 'progress' | 'canceled' | 'completed';
1956
+ uploadedBytes?: number;
1957
+ totalBytes?: number;
1958
+ progress?: number;
1959
+ result?: UploadResult;
1960
+ };
1961
+
1962
+ export type UploadResult = {
1963
+ /** HTTP status code returned by the server. */
1964
+ statusCode: number;
1965
+ /** Response body decoded as UTF-8 text. */
1966
+ data: string;
1967
+ };
1968
+
1969
+ export type UploadTask = PromiseLike<UploadResult> & AsyncIterable<UploadProgressEvent> & {
1970
+ next(): Promise<UploadIteratorResult>;
1971
+ /** Stops iteration only. Does not cancel the underlying upload task. */
1972
+ return(): Promise<UploadIteratorResult>;
1973
+ catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<UploadResult | TResult>;
1974
+ finally(onfinally?: (() => void) | null): Promise<UploadResult>;
1975
+ cancel(): Promise<void>;
1976
+ wait(): Promise<UploadResult>;
1977
+ };
1978
+
1979
+ export type VideoCompressQuality = 'low' | 'medium' | 'high';
1980
+
1981
+ export type VideoContext = {
1982
+ play(): void;
1983
+ pause(): void;
1984
+ stop(): void;
1985
+ seek(position: number): void;
1986
+ requestFullScreen(): void;
1987
+ exitFullScreen(): void;
1988
+ setStreamSource(options: StreamSourceOptions): void;
1989
+ };
1990
+
1991
+ /**
1992
+ * Local video metadata for client-side upload preflight and presentation.
1993
+ * Track-level codec and audio fields are best-effort. The receiving service
1994
+ * must still validate the uploaded bytes; this result does not indicate
1995
+ * whether the file already exists in cloud storage.
1996
+ */
1997
+ export type VideoInfo = {
1998
+ /**
1999
+ * Encoded display width in pixels.
2000
+ */
2001
+ width: number;
2002
+ /**
2003
+ * Encoded display height in pixels.
2004
+ */
2005
+ height: number;
2006
+ /**
2007
+ * Video duration in milliseconds.
2008
+ */
2009
+ durationMs: number;
2010
+ /**
2011
+ * Exact local file size in bytes.
2012
+ */
2013
+ size: number;
2014
+ /**
2015
+ * Clockwise rotation in degrees (usually `0 | 90 | 180 | 270`).
2016
+ */
2017
+ rotation?: number;
2018
+ /**
2019
+ * Average bitrate in bits per second (bps).
2020
+ */
2021
+ bitrate?: number;
2022
+ /**
2023
+ * Frame rate in frames per second (fps).
2024
+ */
2025
+ fps?: number;
2026
+ /**
2027
+ * Best-effort container MIME type, e.g. `video/mp4`.
2028
+ * It may be inferred from the file extension when the platform does not expose it.
2029
+ */
2030
+ type?: string;
2031
+ /**
2032
+ * Normalized video-track codec MIME type. Known values include `video/avc`,
2033
+ * `video/hevc`, `video/x-vnd.on2.vp8`, `video/x-vnd.on2.vp9`, `video/av01`,
2034
+ * `video/mp4v-es`, `video/mpeg2`, and `video/mjpeg`. Other valid `video/*`
2035
+ * values may be returned for codecs added by the platform. Omitted when the
2036
+ * platform cannot determine it.
2037
+ */
2038
+ videoCodec?: string;
2039
+ /**
2040
+ * Whether an audio track was detected. Omitted when the platform cannot determine it.
2041
+ */
2042
+ hasAudio?: boolean;
2043
+ /**
2044
+ * Best-effort audio-track codec MIME type, e.g. `audio/mp4a-latm` or `audio/opus`.
2045
+ * Omitted when there is no audio track or the platform cannot determine it.
2046
+ */
2047
+ audioCodec?: string;
2048
+ /**
2049
+ * Resolved path used by runtime (typically `lx://...`).
2050
+ */
2051
+ path: string;
2052
+ };
2053
+
2054
+ export type VisibilityPreference = 'auto' | 'hidden';
2055
+
2056
+ export type WifiConnectedCallback = (info: WifiConnectedInfo) => void;
2057
+
2058
+ export type WifiConnectedInfo = WifiInfo & {
2059
+ connected: boolean;
2060
+ state: string;
2061
+ };
2062
+
2063
+ /**
2064
+ * Window decoration. `system` is the standard title bar. `full`
2065
+ * extends the page to the window edge while keeping the system
2066
+ * minimize, maximize, resize, and drag affordances — the runtime owns
2067
+ * a native drag strip across the top and publishes its height as
2068
+ * `topInset` on the page-chrome snapshot, so a page that does nothing
2069
+ * to opt in still cannot trap the user.
2070
+ */
2071
+ export type WindowChrome = 'system' | 'full';
2072
+
2073
+ export type WindowSurfaceSize = {
2074
+ /** Initial window width in logical pixels. */
2075
+ width?: number;
2076
+ /** Initial window height in logical pixels. */
2077
+ height?: number;
2078
+ };
2079
+
2080
+ export type WindowsTerminalApi = {
2081
+ status(): Promise<WindowsTerminalInlineImageStatus>;
2082
+ /** Verify and install the fixed Microsoft ConPTY package from lxapp temp storage. */
2083
+ install(options: { path: string }): Promise<WindowsTerminalInlineImageStatus>;
2084
+ /** Select the installed runtime for new terminal sessions. */
2085
+ setEnabled(options: { enabled: boolean }): Promise<WindowsTerminalInlineImageStatus>;
2086
+ };
2087
+
2088
+ export type WindowsTerminalInlineImageStatus = {
2089
+ enabled: boolean;
2090
+ installed: boolean;
2091
+ package: {
2092
+ version: string;
2093
+ url: string;
2094
+ sha256: string;
2095
+ bytes: number;
2096
+ };
2097
+ };
2098
+
2099
+ /** Host app base information. */
2100
+ export interface AppBaseInfo {
2101
+ /**
2102
+ * Raw system locale, unaffected by a saved in-app language override.
2103
+ * For the language the UI should actually render in, use
2104
+ * `display_language` instead.
2105
+ */
2106
+ locale: string;
2107
+ /**
2108
+ * Effective display language: a saved user override when set, else
2109
+ * `locale`. This is what native chrome and `lx.*` i18n strings follow.
2110
+ */
2111
+ displayLanguage: string;
2112
+ /**
2113
+ * Platform family: `"iOS"` / `"macOS"` / `"Android"` / `"Windows"` /
2114
+ * `"Harmony"`. Matches the View-side `usePlatform().os` value.
2115
+ */
2116
+ os: string;
2117
+ productName: string;
2118
+ version: string;
2119
+ SDKVersion: string;
2120
+ }
2121
+
2122
+ export interface AppearanceState {
2123
+ preference: AppearancePreference;
2124
+ resolved: ResolvedAppearance;
2125
+ }
2126
+
2127
+ /** Device info APIs. */
2128
+ export interface DeviceInfo {
2129
+ brand: string;
2130
+ model: string;
2131
+ marketName: string;
2132
+ osName: string;
2133
+ osVersion: string;
2134
+ }
2135
+
2136
+ export interface FileStats {
2137
+ isFile: boolean;
2138
+ isDirectory: boolean;
2139
+ isSymlink: boolean;
2140
+ size: number;
2141
+ lastModifiedTime?: number;
2142
+ lastAccessedTime?: number;
2143
+ createTime?: number;
2144
+ }
2145
+
2146
+ export interface ImageInfo {
2147
+ width: number;
2148
+ height: number;
2149
+ type: string;
2150
+ path: string;
2151
+ }
2152
+
2153
+ /** Location information */
2154
+ export interface LocationInfo {
2155
+ /** Latitude, range -90~90, negative for south */
2156
+ latitude: number;
2157
+ /** Longitude, range -180~180, negative for west */
2158
+ longitude: number;
2159
+ /** Speed in m/s */
2160
+ speed?: number;
2161
+ /** Position accuracy in meters (smaller = more accurate) */
2162
+ accuracy?: number;
2163
+ /** Altitude in meters */
2164
+ altitude?: number;
2165
+ /** Vertical accuracy in meters */
2166
+ verticalAccuracy?: number;
2167
+ /** Horizontal accuracy in meters */
2168
+ horizontalAccuracy?: number;
2169
+ }
2170
+
2171
+ export interface LxAppInfo {
2172
+ appId: string;
2173
+ appName: string;
2174
+ version: string;
2175
+ releaseType: LxAppReleaseType;
2176
+ }
2177
+
2178
+ export interface ScreenInfo {
2179
+ width: number;
2180
+ height: number;
2181
+ scale: number;
2182
+ }
2183
+
2184
+ /** System setting status */
2185
+ export interface SystemSettingInfo {
2186
+ bluetoothEnabled: boolean;
2187
+ locationEnabled: boolean;
2188
+ wifiEnabled: boolean;
2189
+ }
2190
+
2191
+ /** Wi-Fi APIs. */
2192
+ export interface WifiInfo {
2193
+ /** Service Set Identifier (network name) */
2194
+ SSID: string;
2195
+ /** Basic Service Set Identifier (MAC address) */
2196
+ BSSID?: string;
2197
+ /** Whether the network is secure (requires password) */
2198
+ secure: boolean;
2199
+ /** Signal strength (0-100, higher is better) */
2200
+ signalStrength: number;
2201
+ /** Center frequency in MHz (if available) */
2202
+ frequency?: number;
2203
+ }
2204
+
2205
+ export declare class DirEntry {
2206
+ private constructor();
2207
+ readonly name: string;
2208
+ readonly isFile: boolean;
2209
+ readonly isDirectory: boolean;
2210
+ readonly isSymlink: boolean;
2211
+ }
2212
+
2213
+ export declare class JSMessagePort {
2214
+ constructor();
2215
+ static postMessage(payload: any): void;
2216
+ static onMessage(handler: (...args: any[]) => any): (...args: any[]) => any;
2217
+ }
2218
+
2219
+ export declare class JSSurface {
2220
+ constructor();
2221
+ close(): Promise<void>;
2222
+ postMessage(payload: any): void;
2223
+ onMessage(handler: (...args: any[]) => any): (...args: any[]) => any;
2224
+ static onClose(handler: (...args: any[]) => any): (...args: any[]) => any;
2225
+ }
2226
+
2227
+ export declare class JSUpdateManager {
2228
+ constructor();
2229
+ /** Apply update by restarting the app */
2230
+ applyUpdate(): void;
2231
+ /** Subscribes to a ready update and returns the unsubscribe fn. */
2232
+ onUpdateReady(cb: (...args: any[]) => any): (...args: any[]) => any;
2233
+ /** Subscribes to a failed update and returns the unsubscribe fn. */
2234
+ onUpdateFailed(cb: (...args: any[]) => any): (...args: any[]) => any;
2235
+ }
2236
+
2237
+ export declare class JSVideoContext {
2238
+ constructor();
2239
+ play(): void;
2240
+ pause(): void;
2241
+ stop(): void;
2242
+ seek(position: number): void;
2243
+ requestFullScreen(): void;
2244
+ exitFullScreen(): void;
2245
+ setStreamSource(options: StreamSourceOptions): void;
2246
+ }
2247
+
2248
+ export declare class LxFile {
2249
+ private constructor();
2250
+ /** The path supplied to `lx.fs.file`. */
2251
+ readonly path: string;
2252
+ /** Read the complete file as strict UTF-8 text. */
2253
+ text(): Promise<string>;
2254
+ /**
2255
+ * Read and parse the complete file as JSON. Stays `unknown`: a class
2256
+ * method cannot carry a type parameter through the binding, so unlike
2257
+ * `lx.getStorage().get<T>()` the assertion is spelled `as` at the call
2258
+ * site rather than passed in.
2259
+ */
2260
+ json(): Promise<unknown>;
2261
+ /** Read the complete file as a Base64 string. */
2262
+ base64(): Promise<string>;
2263
+ /** Read the complete file as bytes. */
2264
+ bytes(): Promise<Uint8Array>;
2265
+ /** Read the complete file as an ArrayBuffer. */
2266
+ arrayBuffer(): Promise<ArrayBuffer>;
2267
+ /** Test whether this managed path currently exists. */
2268
+ exists(): Promise<boolean>;
2269
+ /** Read metadata for this managed path. */
2270
+ stat(): Promise<FileStats>;
2271
+ }
2272
+
2273
+ declare global {
2274
+ interface AppearanceApi {
2275
+ /** Read the appearance preference and the light/dark value it resolves to. */
2276
+ get(): AppearanceState;
2277
+ /** Set the appearance preference to `auto`, `light`, or `dark`. */
2278
+ set(preference: AppearancePreference): Promise<void>;
2279
+ }
2280
+ }
2281
+
2282
+ declare global {
2283
+ interface FileSystemApi {
2284
+ /**
2285
+ * Create a lazy reference to a LingXia-managed path.
2286
+ * Relative paths resolve under `lx.env.USER_DATA_PATH`. Creating a reference
2287
+ * does not require the path to exist.
2288
+ */
2289
+ file(path: string): LxFile;
2290
+ /** Test whether a managed path currently exists. */
2291
+ exists(path: string): Promise<boolean>;
2292
+ /** Read metadata for a managed path. */
2293
+ stat(path: string): Promise<FileStats>;
2294
+ /** The direct children of a managed directory. */
2295
+ readDir(path: string): Promise<DirEntry[]>;
2296
+ /** Create a managed directory. */
2297
+ mkdir(path: string, options?: FsMkdirOptions): Promise<void>;
2298
+ /** Write UTF-8 text or bytes to a managed file. */
2299
+ write(path: string, data: string, options?: FsWriteOptions): Promise<void>;
2300
+ /** Copy a managed file. */
2301
+ copy(source: string, destination: string, options?: FsCopyOptions): Promise<void>;
2302
+ /** Rename or move a managed file or directory. */
2303
+ rename(source: string, destination: string, options?: FsRenameOptions): Promise<void>;
2304
+ /** Remove a managed file or directory. */
2305
+ remove(path: string, options?: FsRemoveOptions): Promise<void>;
2306
+ }
2307
+ }
2308
+
2309
+ declare global {
2310
+ interface HostAppApi {
2311
+ /**
2312
+ * `lx.app.screenshot(options?)` — capture the host app's window as a PNG.
2313
+ * App-level semantics, one level above any page/WebView capture: the image
2314
+ * is what the user sees of the whole app — host-drawn navigation chrome,
2315
+ * native overlays, and every composited WebView, not just this lxapp's web
2316
+ * content. Because that view can include other lxapps' UI, the API is
2317
+ * restricted to the home lxapp, like the other host-level APIs on `lx.app`.
2318
+ */
2319
+ screenshot(options?: AppScreenshotOptions): Promise<AppScreenshotResult>;
2320
+ /**
2321
+ * Check whether the host app has an update.
2322
+ * This host-level capability is restricted to the home lxapp. Calling it opts
2323
+ * the process into custom update handling. Incompatible updates are hidden as
2324
+ * `hasUpdate: false`; platforms that cannot apply a package may still return
2325
+ * metadata and reject when `update.apply()` is invoked.
2326
+ */
2327
+ checkUpdate(): Promise<HostAppUpdateCheckResult>;
2328
+ readonly envVersion: HostAppEnvVersion;
2329
+ /**
2330
+ * Read the host app's identity: locale, display language, OS, product name,
2331
+ * product version, and SDK runtime version.
2332
+ */
2333
+ getBaseInfo(): AppBaseInfo;
2334
+ /**
2335
+ * Follow the host's effective display language.
2336
+ * `getBaseInfo().displayLanguage` answers what it is now; this answers when it
2337
+ * changes. Logic needs both because the strings it hands to native chrome —
2338
+ * navigation bar titles, tab bar labels, modal and action-sheet text — are the
2339
+ * app's own, and nothing re-renders them on its behalf.
2340
+ */
2341
+ onDisplayLanguageChange(callback: (language: string) => void): () => void;
2342
+ /**
2343
+ * Exit the host app immediately without a confirmation dialog.
2344
+ * If the user should confirm first, call `lx.showModal(...)` and invoke this
2345
+ * only after confirmation.
2346
+ */
2347
+ exit(): void;
2348
+ /**
2349
+ * Set the app-icon badge, for example an unread count.
2350
+ * This targets the dock on macOS, taskbar on Windows, and home/launcher icon
2351
+ * on mobile. Null or an empty string clears it. Unsupported platforms treat
2352
+ * the call as a no-op.
2353
+ */
2354
+ setBadge(value: string | number | null): void;
2355
+ }
2356
+ }
2357
+
2358
+ declare global {
2359
+ interface Lx {
2360
+ readonly app: HostAppApi;
2361
+ /**
2362
+ * Whether this host exposes a capability to this Logic context, right now.
2363
+ * Synchronous, because it is meant to be called from render paths. The answer
2364
+ * is live and may be stale by the time you act on it — it is an affordance for
2365
+ * deciding what to render, not a replacement for handling a rejection.
2366
+ * `{ capability: 'surface', value: 'aside' }` in particular changes when a
2367
+ * desktop window crosses the compact breakpoint; pair it with
2368
+ * `lx.surface.onContext` instead of polling. The answer is per runtime context:
2369
+ * a context that does not expose an API reports false for it.
2370
+ */
2371
+ supports(query: LxCapabilityQuery): boolean;
2372
+ /** Vibrate briefly, where the device has a vibrator. */
2373
+ vibrateShort(): boolean;
2374
+ /** Vibrate for a longer pulse, where the device has a vibrator. */
2375
+ vibrateLong(): boolean;
2376
+ /** Hand a number to the system dialer; the user still places the call. */
2377
+ makePhoneCall(options: MakePhoneCallOptions): boolean;
2378
+ /** Read the device and OS facts this host reports. */
2379
+ getDeviceInfo(): DeviceInfo;
2380
+ /** Read the screen geometry and pixel ratio this host reports. */
2381
+ getScreenInfo(): ScreenInfo;
2382
+ /** Read connectivity right now: whether it is connected, its type, and addresses. */
2383
+ getNetworkInfo(): Promise<NetworkInfo>;
2384
+ /** Subscribes to network changes and returns the unsubscribe fn. */
2385
+ onNetworkChange(callback: NetworkChangeCallback): () => void;
2386
+ /** Initialize WiFi module */
2387
+ startWifi(): Promise<void>;
2388
+ /** Stop WiFi module */
2389
+ stopWifi(): Promise<void>;
2390
+ /**
2391
+ * Connect to WiFi (async - waits for request submission, not actual connection)
2392
+ * This function returns when the connection request is successfully submitted to the system.
2393
+ * The actual connection status will be reported via onWifiConnected event.
2394
+ */
2395
+ connectWifi(options: ConnectWifiOptions): Promise<void>;
2396
+ /** Get WiFi list (scan results) */
2397
+ getWifiList(): Promise<WifiInfo[]>;
2398
+ /** Get connected WiFi info */
2399
+ getConnectedWifi(): Promise<WifiInfo>;
2400
+ /** Subscribes to WiFi connection events and returns the unsubscribe fn. */
2401
+ onWifiConnected(callback: WifiConnectedCallback): () => void;
2402
+ /**
2403
+ * Lock this lxapp to `portrait` or `landscape`.
2404
+ * Any other value rejects. Where the host does not report the change back,
2405
+ * the runtime emits the orientation event itself so JS state stays in sync.
2406
+ */
2407
+ setDeviceOrientation(orientation: DeviceOrientation): boolean;
2408
+ /** Subscribes to orientation changes and returns the unsubscribe fn. */
2409
+ onDeviceOrientationChange(callback: (event: DeviceOrientationChangeEvent) => void): () => void;
2410
+ readonly env: LxEnv;
2411
+ downloadFile(options: never): never;
2412
+ /**
2413
+ * Upload a managed file to an ordinary HTTP multipart endpoint.
2414
+ * Returns a task handle synchronously so progress and abort can be wired up
2415
+ * before the transfer starts.
2416
+ */
2417
+ uploadFile(options: UploadOptions): UploadTask;
2418
+ /**
2419
+ * Open a local file with the requested strategy.
2420
+ * Use `mode: "review"` when the UX requires in-app preview; otherwise prefer
2421
+ * `mode: "auto"`.
2422
+ */
2423
+ openFile(options: OpenFileOptions): Promise<void>;
2424
+ /**
2425
+ * Opens a file picker.
2426
+ * Resolves `{ canceled: true }` only when the user dismisses the picker. A
2427
+ * completed selection resolves `{ canceled: false, paths }` with at least one
2428
+ * path. Rejects when the picker fails or returns an invalid payload.
2429
+ */
2430
+ chooseFile(options?: ChooseFileOptions): Promise<ChooseFileResult>;
2431
+ /**
2432
+ * Opens a directory picker.
2433
+ * Resolves `{ canceled: true }` only when the user dismisses the picker. A
2434
+ * completed selection resolves `{ canceled: false, path }`. Rejects when the
2435
+ * picker fails or returns an invalid payload.
2436
+ */
2437
+ chooseDirectory(options?: ChooseDirectoryOptions): Promise<ChooseDirectoryResult>;
2438
+ readonly fs: FileSystemApi;
2439
+ /** Subscribes to key-down events and returns the unsubscribe fn. */
2440
+ onKeyDown(callback: KeyEventCallback): () => void;
2441
+ /** Subscribes to key-up events and returns the unsubscribe fn. */
2442
+ onKeyUp(callback: KeyEventCallback): () => void;
2443
+ /** Get location function */
2444
+ getLocation(options?: GetLocationOptions): Promise<LocationInfo>;
2445
+ /** Identify the running lxapp: its id, display name, version, and release type. */
2446
+ getLxAppInfo(): LxAppInfo;
2447
+ /** Read an image's dimensions, type, and orientation without decoding it into a view. */
2448
+ getImageInfo(options: GetImageInfoOptions): Promise<ImageInfo>;
2449
+ /** Re-encode an image at a lower quality or size, writing a new managed file. */
2450
+ compressImage(options: CompressImageOptions): Promise<CompressImageResult>;
2451
+ /**
2452
+ * Opens the media picker or camera.
2453
+ * Resolves `{ canceled: true }` only when the user dismisses the picker. A
2454
+ * completed selection resolves `{ canceled: false, entries }` with at least one
2455
+ * entry. Rejects when capture or selection fails, or the host returns an invalid
2456
+ * payload.
2457
+ */
2458
+ chooseMedia(options?: ChooseMediaOptions): Promise<ChooseMediaResult>;
2459
+ /**
2460
+ * Synchronously returns a JS handle so listeners can be attached before the
2461
+ * first event fires:
2462
+ * - `presented`: Promise, resolves with no value when the first pixel of the
2463
+ * underlying media is composited to screen. Also resolves unconditionally
2464
+ * once `completed` settles, so consumers can safely ignore it (it never
2465
+ * rejects).
2466
+ * - `current`: `{ index, source }` snapshot of the item on screen, updated
2467
+ * live as the user swipes / the session auto-advances.
2468
+ * - `onChange(listener)`: fires `{ index, source }` for every item change
2469
+ * (the initial item is seeded into `current`, and re-fired by native so
2470
+ * late platforms still converge); returns an unsubscribe function.
2471
+ * - `completed`: Promise resolving `{ reason, index, source }` when the
2472
+ * session ends, or rejecting on abort / error. `source` is the item that
2473
+ * was on screen when the preview closed — handed back verbatim so the
2474
+ * caller never re-indexes their own array.
2475
+ */
2476
+ previewMedia(options: PreviewMediaOptions): PreviewMediaHandle;
2477
+ /** Save an image into the system photo library. */
2478
+ saveImageToPhotosAlbum(options: SaveMediaOptions): Promise<void>;
2479
+ /** Save a video into the system photo library. */
2480
+ saveVideoToPhotosAlbum(options: SaveMediaOptions): Promise<void>;
2481
+ /**
2482
+ * Opens the scanner.
2483
+ * Resolves `{ canceled: true }` only when the user dismisses the scanner. A
2484
+ * completed scan resolves `{ canceled: false, scanResult, scanType }`. Rejects
2485
+ * when scanning fails or the host returns an invalid payload.
2486
+ */
2487
+ scanCode(options?: ScanCodeOptions): Promise<ScanCodeResult>;
2488
+ /** Take a control handle for the `<lx-video>` component with this id. */
2489
+ createVideoContext(componentId: string): VideoContext;
2490
+ /**
2491
+ * Reads local video metadata for upload preflight and presentation.
2492
+ * Size, dimensions, duration, and path form the portable core. Container type,
2493
+ * rotation, and track-level codec/audio fields are best-effort and may be
2494
+ * omitted when the platform cannot determine them. The receiving service must
2495
+ * still validate the uploaded bytes.
2496
+ */
2497
+ getVideoInfo(options: GetVideoInfoOptions): Promise<VideoInfo>;
2498
+ /** Write one frame of a video out as an image file. */
2499
+ extractVideoThumbnail(options: ExtractVideoThumbnailOptions): Promise<ExtractVideoThumbnailResult>;
2500
+ /**
2501
+ * Transcode a video to a smaller file.
2502
+ * Returns a task handle synchronously, so progress and cancellation can be
2503
+ * wired up before transcoding starts.
2504
+ */
2505
+ compressVideo(options: CompressVideoOptions): CompressVideoTask;
2506
+ /**
2507
+ * Open another lxapp, optionally at one of its pages.
2508
+ * Navigating to the lxapp already running is a no-op. Rejects with
2509
+ * `E_SURFACE_CONFLICT` when the target is currently docked as an aside —
2510
+ * close that aside before opening it as a main.
2511
+ */
2512
+ navigateToApp(options: NavigateToAppOptions): Promise<void>;
2513
+ /** Leave this lxapp and reveal the one that opened it. */
2514
+ navigateBackApp(): Promise<void>;
2515
+ /**
2516
+ * Hand content to the system share sheet.
2517
+ * Share text, files, or a page link — files cannot be combined with a page
2518
+ * target or with text; share those separately.
2519
+ */
2520
+ share(options: ShareOptions): Promise<ShareResult>;
2521
+ /**
2522
+ * Open this lxapp's asynchronous persistent key-value store. `get` asserts the
2523
+ * value shape at the call site and resolves `undefined` for a missing key. Use
2524
+ * `lx.fs` instead for path-based data.
2525
+ */
2526
+ getStorage(): Storage;
2527
+ /** `lx.openExternal(url)` — hand the url off to the OS default browser. */
2528
+ openExternal(url: string): void;
2529
+ readonly surface: SurfaceApi;
2530
+ /** Read system switches the lxapp may branch on, such as location and WiFi. */
2531
+ getSystemSetting(): SystemSettingInfo;
2532
+ /**
2533
+ * Shows a list of actions.
2534
+ * Resolves `{ canceled: false, index }` when the user selects an item; `index`
2535
+ * points into `options.itemList`. Resolves `{ canceled: true }` only when the
2536
+ * user dismisses the sheet. Rejects when presentation fails or the host returns
2537
+ * an invalid selection.
2538
+ */
2539
+ showActionSheet(options: ShowActionSheetOptions): Promise<ActionSheetResult>;
2540
+ readonly appearance: AppearanceApi;
2541
+ /**
2542
+ * Shows a confirmation modal.
2543
+ * Resolves `{ canceled: false }` when the user confirms and `{ canceled: true }`
2544
+ * only when the user dismisses or cancels the modal. Rejects when presentation
2545
+ * fails or the host returns an invalid payload.
2546
+ */
2547
+ showModal(options: ShowModalOptions): Promise<ModalResult>;
2548
+ /**
2549
+ * Replace the current lxapp's complete app-declared More action list (seven
2550
+ * entries maximum). Pass an empty array to clear it. Native hosts append these
2551
+ * entries after their own lifecycle actions.
2552
+ */
2553
+ setMoreActions(items: MoreAction[]): void;
2554
+ readonly navigationBar: NavigationBarApi;
2555
+ /**
2556
+ * lx.startPullDownRefresh()
2557
+ * Programmatically start the pull-to-refresh animation.
2558
+ * This will show the refresh indicator and trigger the onPullDownRefresh lifecycle method.
2559
+ */
2560
+ startPullDownRefresh(): void;
2561
+ /**
2562
+ * lx.stopPullDownRefresh()
2563
+ * Stop the pull-to-refresh animation.
2564
+ * This should be called after the refresh operation is complete.
2565
+ */
2566
+ stopPullDownRefresh(): void;
2567
+ /**
2568
+ * Push a configured page onto the stack.
2569
+ * A route can appear on the stack only once. The promise rejects with
2570
+ * `data.reason === "duplicate_route"` when the target is already present,
2571
+ * or `data.reason === "stack_full"` when the ten-page limit is reached.
2572
+ */
2573
+ navigateTo(options: NavigateToOptions): Promise<PageMessagePort>;
2574
+ /**
2575
+ * Pop one or more pages and reveal the destination page.
2576
+ * `options` and `options.delta` are optional; both default to one page. The
2577
+ * promise resolves once the destination WebView is ready, so callers can
2578
+ * safely continue with work that targets the revealed page.
2579
+ */
2580
+ navigateBack(options?: NavigateBackOptions): Promise<void>;
2581
+ /**
2582
+ * Replace the current stack entry with a configured page.
2583
+ * Redirecting to the current route keeps its page instance and runs `onLoad`
2584
+ * again with the new query. Redirecting to a route lower in the stack rejects
2585
+ * with `data.reason === "duplicate_route"`.
2586
+ */
2587
+ redirectTo(options: RedirectToOptions): Promise<void>;
2588
+ /**
2589
+ * Switch to a configured tab page.
2590
+ * The tab page being left is hidden and retained. Non-tab pages pushed above
2591
+ * a tab leave the stack and receive `onUnload`.
2592
+ */
2593
+ switchTab(options: SwitchTabOptions): Promise<void>;
2594
+ /** Clear the page stack and launch a configured page as the new root. */
2595
+ reLaunch(options: ReLaunchOptions): Promise<void>;
2596
+ readonly shell: ShellApi;
2597
+ readonly tabBar: TabBarApi;
2598
+ /** Show toast function */
2599
+ showToast(options: ShowToastOptions): Promise<void>;
2600
+ /** Hide toast function */
2601
+ hideToast(): Promise<void>;
2602
+ readonly tray: TrayApi;
2603
+ /**
2604
+ * Return the callback-based update manager for this lxapp's bundle. This is
2605
+ * available to every lxapp and is distinct from the home-only
2606
+ * `lx.app.checkUpdate()`, which updates the native host app.
2607
+ */
2608
+ getUpdateManager(): UpdateManager;
2609
+ }
2610
+ }
2611
+
2612
+ declare global {
2613
+ interface LxEnv {
2614
+ readonly USER_DATA_PATH: 'lx://userdata';
2615
+ readonly USER_CACHE_PATH: 'lx://usercache';
2616
+ }
2617
+ }
2618
+
2619
+ declare global {
2620
+ interface NavigationBarApi {
2621
+ /** Patch the navigation bar of the active page; unset fields stay as they are. */
2622
+ update(patch: NavigationBarPatch): Promise<void>;
2623
+ }
2624
+ }
2625
+
2626
+ declare global {
2627
+ interface ShellApi {
2628
+ /**
2629
+ * `lx.shell.openApp(appId, options)` — compose another lxapp into a shell
2630
+ * slot. Home-lxapp only; the namespace is the privilege.
2631
+ */
2632
+ openApp(appId: string, options: ShellOpenAppOptions): Promise<AppSurface>;
2633
+ /** `lx.shell.openBuiltin(page)` — a host builtin page. Home-lxapp only. */
2634
+ openBuiltin(page: BuiltinShellPage): Promise<BuiltinSurface>;
2635
+ /**
2636
+ * `lx.shell.openDeclared(id, options?)` — the declared surface, plus the
2637
+ * keyed multi-instance form and placement overrides. Home-lxapp only.
2638
+ */
2639
+ openDeclared(id: string, options?: ShellOpenDeclaredOptions): Promise<DeclaredSurface>;
2640
+ /** `lx.shell.reconfigure(id, patch)` — re-place a live declared surface. */
2641
+ reconfigure(id: string, patch: ShellSurfacePatch): Promise<void>;
2642
+ }
2643
+ }
2644
+
2645
+ declare global {
2646
+ interface ShellSidebarActionsApi {
2647
+ /**
2648
+ * Atomically replaces the complete desktop sidebar action declaration. Only the
2649
+ * home lxapp may call this API. Ids must be non-empty and unique across both
2650
+ * placements; header accepts at most two entries. Icons must be bundled relative
2651
+ * paths or runtime-managed `lx://` paths accessible to the home lxapp.
2652
+ * Every entry is bound to its generation-scoped callback. The shell invokes that
2653
+ * callback but never infers navigation or selected state. Validation or host
2654
+ * projection failure leaves the previous generation active. `replace([])` clears
2655
+ * the chrome explicitly. Declarations are process-local, so call `replace` again
2656
+ * on every Logic launch.
2657
+ */
2658
+ replace(items: ShellSidebarAction[]): void;
2659
+ /**
2660
+ * Atomically updates the icon, label, and/or disabled state of one stable id.
2661
+ * Only the home lxapp may call this API. The patch must be non-empty; unknown
2662
+ * fields are rejected. The callback and placement stay unchanged. Throws
2663
+ * `E_NOT_FOUND` when `id` is not in the current declaration.
2664
+ */
2665
+ update(id: string, patch: ShellSidebarActionUpdate): void;
2666
+ /**
2667
+ * Atomically removes one stable id and its generation-scoped callback. Only the
2668
+ * home lxapp may call this API. Throws `E_NOT_FOUND` when `id` is not in the
2669
+ * current declaration.
2670
+ */
2671
+ remove(id: string): void;
2672
+ /**
2673
+ * Atomically clears every runtime sidebar action and callback. Only the home
2674
+ * lxapp may call this API. Equivalent to `replace([])` and safe when already
2675
+ * empty; the home lxapp must still redeclare actions after the next Logic launch.
2676
+ */
2677
+ clear(): void;
2678
+ }
2679
+ }
2680
+
2681
+ declare global {
2682
+ interface SurfaceApi {
2683
+ /**
2684
+ * `lx.surface.openPage(page, options?)` — one of this lxapp's own pages as a
2685
+ * float or a window. A page can never be an aside: asides carry external
2686
+ * content only, which is why that member does not exist on this signature.
2687
+ */
2688
+ openPage(page: string, options?: OpenPageOptions): Promise<PageSurface>;
2689
+ /**
2690
+ * `lx.surface.openUrl(url, options?)` — external content in the in-app
2691
+ * browser, as a tab or docked as an aside.
2692
+ */
2693
+ openUrl(url: string, options?: OpenUrlOptions): Promise<TabSurface>;
2694
+ /**
2695
+ * `lx.surface.openDeclared(id, options?)` — a surface the host declared in
2696
+ * `lingxia.yaml`, opened with the declaration's own presentation.
2697
+ */
2698
+ openDeclared(id: string): Promise<DeclaredSurface>;
2699
+ /**
2700
+ * `lx.surface.get(keyOrId)` — the live handle for a surface this lxapp opened
2701
+ * **with a `key`**, so no caller has to cache one in order to reuse or close
2702
+ * it. An unkeyed surface is not addressable: nothing registers it, because
2703
+ * holding one for the session costs its closures and its message port and
2704
+ * nobody can look up a uuid they never chose.
2705
+ * A `key` you chose wins over a runtime-assigned `id`, so a key that happens
2706
+ * to spell another surface's id still finds yours.
2707
+ */
2708
+ get(keyOrId: string): AnySurface | undefined;
2709
+ /**
2710
+ * `lx.surface.onContext(handler)` — register a JS callback (scoped to this
2711
+ * lxapp's JS context), invoke it immediately, then again whenever that
2712
+ * presentation's actual viewport changes. Returns an unsubscribe fn.
2713
+ */
2714
+ onContext(handler: (context: SurfaceContext) => void): () => void;
2715
+ }
2716
+ }
2717
+
2718
+ declare global {
2719
+ interface TabBarApi {
2720
+ /** Patch this lxapp's tab bar; unset fields stay as they are. */
2721
+ update(patch: TabBarPatch): Promise<void>;
2722
+ }
2723
+ }
2724
+
2725
+ declare global {
2726
+ interface TrayApi {
2727
+ /** lx.tray.setBadge(value) — the menu-bar / system-tray badge. Null/empty clears it. */
2728
+ setBadge(value: string | number | null): void;
2729
+ /** lx.tray.setIcon(icon) — replace the tray icon (a resource path). */
2730
+ setIcon(icon: string): void;
2731
+ /** lx.tray.setTitle(text) — text shown beside the icon (macOS). Empty clears it. */
2732
+ setTitle(text: string | null): void;
2733
+ /**
2734
+ * lx.tray.setMenu(items) — replace the tray dropdown menu. Each item is
2735
+ * `{ label, onClick?, enabled?, checked? }` or `{ separator: true }`. The native
2736
+ * menu is built from labels; clicks are routed back to each item's `onClick` by
2737
+ * index over the app event bus.
2738
+ */
2739
+ setMenu(items: Array<TrayMenuItem | TrayMenuSeparator>): void;
2740
+ /**
2741
+ * lx.tray.onClick(handler) — left-click on the tray icon. While at least one
2742
+ * handler is registered, the left-click runs only the handler(s); the tray's
2743
+ * configured surface action is suppressed. Returns an unsubscribe function.
2744
+ */
2745
+ onClick(handler: () => void): () => void;
2746
+ /** lx.tray.show() — show the tray status item. */
2747
+ show(): void;
2748
+ /** lx.tray.hide() — hide the tray status item. */
2749
+ hide(): void;
2750
+ }
2751
+ }
2752
+
2753
+ export {};