@lo-ink/miniapp-sdk 0.19.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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/dist/adapter.d.ts +15 -0
  4. package/dist/adapter.js +1 -0
  5. package/dist/appearance.d.ts +17 -0
  6. package/dist/appearance.js +59 -0
  7. package/dist/async.d.ts +5 -0
  8. package/dist/async.js +87 -0
  9. package/dist/client.d.ts +17 -0
  10. package/dist/client.js +230 -0
  11. package/dist/errors.d.ts +6 -0
  12. package/dist/errors.js +18 -0
  13. package/dist/features.d.ts +6 -0
  14. package/dist/features.js +41 -0
  15. package/dist/index.d.ts +9 -0
  16. package/dist/index.js +9 -0
  17. package/dist/protocol.d.ts +436 -0
  18. package/dist/protocol.js +43 -0
  19. package/dist/request-options.d.ts +6 -0
  20. package/dist/request-options.js +16 -0
  21. package/dist/session.d.ts +16 -0
  22. package/dist/session.js +56 -0
  23. package/dist/storage.d.ts +25 -0
  24. package/dist/storage.js +27 -0
  25. package/dist-cjs/adapter.d.ts +15 -0
  26. package/dist-cjs/adapter.js +2 -0
  27. package/dist-cjs/appearance.d.ts +17 -0
  28. package/dist-cjs/appearance.js +62 -0
  29. package/dist-cjs/async.d.ts +5 -0
  30. package/dist-cjs/async.js +90 -0
  31. package/dist-cjs/client.d.ts +17 -0
  32. package/dist-cjs/client.js +235 -0
  33. package/dist-cjs/errors.d.ts +6 -0
  34. package/dist-cjs/errors.js +23 -0
  35. package/dist-cjs/features.d.ts +6 -0
  36. package/dist-cjs/features.js +48 -0
  37. package/dist-cjs/index.d.ts +9 -0
  38. package/dist-cjs/index.js +25 -0
  39. package/dist-cjs/package.json +1 -0
  40. package/dist-cjs/protocol.d.ts +436 -0
  41. package/dist-cjs/protocol.js +46 -0
  42. package/dist-cjs/request-options.d.ts +6 -0
  43. package/dist-cjs/request-options.js +19 -0
  44. package/dist-cjs/session.d.ts +16 -0
  45. package/dist-cjs/session.js +59 -0
  46. package/dist-cjs/storage.d.ts +25 -0
  47. package/dist-cjs/storage.js +32 -0
  48. package/package.json +65 -0
@@ -0,0 +1,436 @@
1
+ /** Stable, platform-neutral features a host can advertise. */
2
+ export declare const MINI_APP_CAPABILITIES: readonly ["ready", "expand", "fullscreen", "hideKeyboard", "orientation", "backButton", "mainButton", "secondaryButton", "settingsButton", "closingConfirmation", "headerColor", "backgroundColor", "bottomBarColor", "haptics", "popup", "openLink", "sendData", "switchInlineQuery", "clipboard", "location", "biometry", "sensors", "downloadFile", "qrScanner", "requestWriteAccess", "requestContact", "shareMessage", "shareToStory", "invoice", "cloudStorage", "deviceStorage", "secureStorage"];
3
+ export type Capability = (typeof MINI_APP_CAPABILITIES)[number];
4
+ export declare const MINI_APP_PROTOCOL_VERSION: 1;
5
+ export declare const MINI_APP_LIMITS: Readonly<{
6
+ envelopeBytes: 65536;
7
+ sendDataBytes: 4096;
8
+ inlineQueryLength: 256;
9
+ qrPromptLength: 64;
10
+ preparedMessageIdLength: 128;
11
+ }>;
12
+ export type Insets = {
13
+ top: number;
14
+ right: number;
15
+ bottom: number;
16
+ left: number;
17
+ };
18
+ export type ColorScheme = "light" | "dark";
19
+ export type ThemeColors = {
20
+ background?: string;
21
+ text?: string;
22
+ mutedText?: string;
23
+ link?: string;
24
+ action?: string;
25
+ actionText?: string;
26
+ secondaryBackground?: string;
27
+ headerBackground?: string;
28
+ accentText?: string;
29
+ sectionBackground?: string;
30
+ sectionHeaderText?: string;
31
+ subtitleText?: string;
32
+ destructiveText?: string;
33
+ bottomBarBackground?: string;
34
+ };
35
+ export type HostSnapshot = {
36
+ colorScheme?: ColorScheme;
37
+ theme?: Readonly<ThemeColors>;
38
+ viewportHeight?: number;
39
+ stableViewportHeight?: number;
40
+ safeArea?: Insets;
41
+ contentSafeArea?: Insets;
42
+ isFullscreen?: boolean;
43
+ isOrientationLocked?: boolean;
44
+ };
45
+ export type MiniAppEventMap = {
46
+ activated: undefined;
47
+ deactivated: undefined;
48
+ themeChanged: HostSnapshot;
49
+ viewportChanged: HostSnapshot;
50
+ safeAreaChanged: Insets;
51
+ contentSafeAreaChanged: Insets;
52
+ fullscreenChanged: boolean;
53
+ fullscreenFailed: {
54
+ reason?: string;
55
+ };
56
+ backButtonClicked: undefined;
57
+ mainButtonClicked: undefined;
58
+ secondaryButtonClicked: undefined;
59
+ settingsButtonClicked: undefined;
60
+ qrTextReceived: {
61
+ data: string;
62
+ };
63
+ qrScannerClosed: undefined;
64
+ accelerometerChanged: {
65
+ x: number;
66
+ y: number;
67
+ z: number;
68
+ };
69
+ accelerometerFailed: {
70
+ reason?: string;
71
+ };
72
+ gyroscopeChanged: {
73
+ x: number;
74
+ y: number;
75
+ z: number;
76
+ };
77
+ gyroscopeFailed: {
78
+ reason?: string;
79
+ };
80
+ orientationFailed: {
81
+ reason?: string;
82
+ };
83
+ orientationChanged: {
84
+ absolute: boolean;
85
+ alpha: number;
86
+ beta: number;
87
+ gamma: number;
88
+ };
89
+ };
90
+ export type MiniAppEvent = keyof MiniAppEventMap;
91
+ export type ButtonId = "back" | "main" | "secondary" | "settings";
92
+ export type ButtonParams = {
93
+ text?: string;
94
+ active?: boolean;
95
+ visible?: boolean;
96
+ progressVisible?: boolean;
97
+ color?: string;
98
+ textColor?: string;
99
+ shine?: boolean;
100
+ position?: "left" | "right" | "top" | "bottom";
101
+ };
102
+ export type StoryShareParams = {
103
+ text?: string;
104
+ link?: {
105
+ url: string;
106
+ name?: string;
107
+ };
108
+ };
109
+ export type LocationData = {
110
+ latitude: number;
111
+ longitude: number;
112
+ altitude: number | null;
113
+ course: number | null;
114
+ speed: number | null;
115
+ horizontalAccuracy: number | null;
116
+ verticalAccuracy: number | null;
117
+ courseAccuracy: number | null;
118
+ speedAccuracy: number | null;
119
+ };
120
+ export type BiometryInfo = {
121
+ available: boolean;
122
+ type: "finger" | "face" | "unknown";
123
+ accessRequested: boolean;
124
+ accessGranted: boolean;
125
+ tokenSaved: boolean;
126
+ deviceId: string;
127
+ };
128
+ export type SensorOptions = {
129
+ refreshRate?: number;
130
+ };
131
+ export type InvoiceStatus = "paid" | "cancelled" | "failed" | "pending";
132
+ export type RequestContext = {
133
+ signal?: AbortSignal;
134
+ };
135
+ export type MiniAppOperationMap = {
136
+ ready: {
137
+ input: undefined;
138
+ output: void;
139
+ };
140
+ expand: {
141
+ input: undefined;
142
+ output: void;
143
+ };
144
+ requestFullscreen: {
145
+ input: undefined;
146
+ output: void;
147
+ };
148
+ exitFullscreen: {
149
+ input: undefined;
150
+ output: void;
151
+ };
152
+ hideKeyboard: {
153
+ input: undefined;
154
+ output: void;
155
+ };
156
+ setOrientationLock: {
157
+ input: {
158
+ locked: boolean;
159
+ };
160
+ output: void;
161
+ };
162
+ setButton: {
163
+ input: {
164
+ button: ButtonId;
165
+ params: ButtonParams;
166
+ };
167
+ output: void;
168
+ };
169
+ setClosingConfirmation: {
170
+ input: {
171
+ enabled: boolean;
172
+ };
173
+ output: void;
174
+ };
175
+ setHeaderColor: {
176
+ input: {
177
+ color: string;
178
+ };
179
+ output: void;
180
+ };
181
+ setBackgroundColor: {
182
+ input: {
183
+ color: string;
184
+ };
185
+ output: void;
186
+ };
187
+ setBottomBarColor: {
188
+ input: {
189
+ color: string;
190
+ };
191
+ output: void;
192
+ };
193
+ haptic: {
194
+ input: {
195
+ kind: "success" | "warning" | "error" | "light" | "medium" | "heavy" | "rigid" | "soft";
196
+ };
197
+ output: void;
198
+ };
199
+ showPopup: {
200
+ input: {
201
+ title?: string;
202
+ message: string;
203
+ buttons?: readonly {
204
+ id?: string;
205
+ text?: string;
206
+ kind?: "default" | "ok" | "close" | "cancel" | "destructive";
207
+ }[];
208
+ };
209
+ output: string | undefined;
210
+ };
211
+ openLink: {
212
+ input: {
213
+ url: string;
214
+ instantView?: boolean;
215
+ externalBrowser?: boolean;
216
+ };
217
+ output: void;
218
+ };
219
+ sendData: {
220
+ input: {
221
+ data: string;
222
+ };
223
+ output: void;
224
+ };
225
+ switchInlineQuery: {
226
+ input: {
227
+ query: string;
228
+ chatTypes?: readonly ("users" | "bots" | "groups" | "channels")[];
229
+ };
230
+ output: void;
231
+ };
232
+ readClipboard: {
233
+ input: undefined;
234
+ output: string | null;
235
+ };
236
+ getLocation: {
237
+ input: undefined;
238
+ output: LocationData | null;
239
+ };
240
+ openLocationSettings: {
241
+ input: undefined;
242
+ output: void;
243
+ };
244
+ getBiometryInfo: {
245
+ input: undefined;
246
+ output: BiometryInfo;
247
+ };
248
+ requestBiometryAccess: {
249
+ input: {
250
+ reason?: string;
251
+ };
252
+ output: boolean;
253
+ };
254
+ authenticateBiometry: {
255
+ input: {
256
+ reason?: string;
257
+ };
258
+ output: {
259
+ authenticated: boolean;
260
+ token?: string;
261
+ };
262
+ };
263
+ updateBiometryToken: {
264
+ input: {
265
+ token: string;
266
+ };
267
+ output: boolean;
268
+ };
269
+ openBiometrySettings: {
270
+ input: undefined;
271
+ output: void;
272
+ };
273
+ startAccelerometer: {
274
+ input: SensorOptions;
275
+ output: boolean;
276
+ };
277
+ stopAccelerometer: {
278
+ input: undefined;
279
+ output: boolean;
280
+ };
281
+ startGyroscope: {
282
+ input: SensorOptions;
283
+ output: boolean;
284
+ };
285
+ stopGyroscope: {
286
+ input: undefined;
287
+ output: boolean;
288
+ };
289
+ startDeviceOrientation: {
290
+ input: SensorOptions & {
291
+ absolute?: boolean;
292
+ };
293
+ output: boolean;
294
+ };
295
+ stopDeviceOrientation: {
296
+ input: undefined;
297
+ output: boolean;
298
+ };
299
+ downloadFile: {
300
+ input: {
301
+ url: string;
302
+ fileName: string;
303
+ };
304
+ output: boolean;
305
+ };
306
+ openQrScanner: {
307
+ input: {
308
+ text?: string;
309
+ };
310
+ output: void;
311
+ };
312
+ closeQrScanner: {
313
+ input: undefined;
314
+ output: void;
315
+ };
316
+ requestWriteAccess: {
317
+ input: undefined;
318
+ output: boolean;
319
+ };
320
+ requestContact: {
321
+ input: undefined;
322
+ output: boolean;
323
+ };
324
+ shareMessage: {
325
+ input: {
326
+ id: string;
327
+ };
328
+ output: boolean;
329
+ };
330
+ shareToStory: {
331
+ input: {
332
+ mediaUrl: string;
333
+ params?: StoryShareParams;
334
+ };
335
+ output: void;
336
+ };
337
+ openInvoice: {
338
+ input: {
339
+ url: string;
340
+ };
341
+ output: InvoiceStatus;
342
+ };
343
+ cloudStorageSet: {
344
+ input: {
345
+ key: string;
346
+ value: string;
347
+ };
348
+ output: boolean;
349
+ };
350
+ cloudStorageGet: {
351
+ input: {
352
+ key: string;
353
+ };
354
+ output: string;
355
+ };
356
+ cloudStorageGetMany: {
357
+ input: {
358
+ keys: readonly string[];
359
+ };
360
+ output: Record<string, string>;
361
+ };
362
+ cloudStorageRemove: {
363
+ input: {
364
+ key: string;
365
+ };
366
+ output: boolean;
367
+ };
368
+ cloudStorageRemoveMany: {
369
+ input: {
370
+ keys: readonly string[];
371
+ };
372
+ output: boolean;
373
+ };
374
+ cloudStorageKeys: {
375
+ input: undefined;
376
+ output: string[];
377
+ };
378
+ deviceStorageSet: {
379
+ input: {
380
+ key: string;
381
+ value: string;
382
+ };
383
+ output: boolean;
384
+ };
385
+ deviceStorageGet: {
386
+ input: {
387
+ key: string;
388
+ };
389
+ output: string | null;
390
+ };
391
+ deviceStorageRemove: {
392
+ input: {
393
+ key: string;
394
+ };
395
+ output: boolean;
396
+ };
397
+ deviceStorageClear: {
398
+ input: undefined;
399
+ output: boolean;
400
+ };
401
+ secureStorageSet: {
402
+ input: {
403
+ key: string;
404
+ value: string;
405
+ };
406
+ output: boolean;
407
+ };
408
+ secureStorageGet: {
409
+ input: {
410
+ key: string;
411
+ };
412
+ output: {
413
+ value: string | null;
414
+ canRestore: boolean;
415
+ };
416
+ };
417
+ secureStorageRestore: {
418
+ input: {
419
+ key: string;
420
+ };
421
+ output: string;
422
+ };
423
+ secureStorageRemove: {
424
+ input: {
425
+ key: string;
426
+ };
427
+ output: boolean;
428
+ };
429
+ secureStorageClear: {
430
+ input: undefined;
431
+ output: boolean;
432
+ };
433
+ };
434
+ export type MiniAppOperation = keyof MiniAppOperationMap;
435
+ export type OperationInput<K extends MiniAppOperation> = MiniAppOperationMap[K]["input"];
436
+ export type OperationOutput<K extends MiniAppOperation> = MiniAppOperationMap[K]["output"];
@@ -0,0 +1,43 @@
1
+ /** Stable, platform-neutral features a host can advertise. */
2
+ export const MINI_APP_CAPABILITIES = [
3
+ "ready",
4
+ "expand",
5
+ "fullscreen",
6
+ "hideKeyboard",
7
+ "orientation",
8
+ "backButton",
9
+ "mainButton",
10
+ "secondaryButton",
11
+ "settingsButton",
12
+ "closingConfirmation",
13
+ "headerColor",
14
+ "backgroundColor",
15
+ "bottomBarColor",
16
+ "haptics",
17
+ "popup",
18
+ "openLink",
19
+ "sendData",
20
+ "switchInlineQuery",
21
+ "clipboard",
22
+ "location",
23
+ "biometry",
24
+ "sensors",
25
+ "downloadFile",
26
+ "qrScanner",
27
+ "requestWriteAccess",
28
+ "requestContact",
29
+ "shareMessage",
30
+ "shareToStory",
31
+ "invoice",
32
+ "cloudStorage",
33
+ "deviceStorage",
34
+ "secureStorage",
35
+ ];
36
+ export const MINI_APP_PROTOCOL_VERSION = 1;
37
+ export const MINI_APP_LIMITS = Object.freeze({
38
+ envelopeBytes: 65_536,
39
+ sendDataBytes: 4_096,
40
+ inlineQueryLength: 256,
41
+ qrPromptLength: 64,
42
+ preparedMessageIdLength: 128,
43
+ });
@@ -0,0 +1,6 @@
1
+ export type RequestOptions = {
2
+ signal?: AbortSignal;
3
+ timeoutMs?: number;
4
+ };
5
+ /** Snapshot caller-owned options before a request acquires timers or listeners. */
6
+ export declare function readRequestOptions(options: RequestOptions): RequestOptions;
@@ -0,0 +1,16 @@
1
+ /** Snapshot caller-owned options before a request acquires timers or listeners. */
2
+ export function readRequestOptions(options) {
3
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
4
+ throw new TypeError("Request options must be an object");
5
+ }
6
+ const { signal, timeoutMs } = options;
7
+ if (signal !== undefined &&
8
+ (signal === null ||
9
+ typeof signal !== "object" ||
10
+ typeof signal.aborted !== "boolean" ||
11
+ typeof signal.addEventListener !== "function" ||
12
+ typeof signal.removeEventListener !== "function")) {
13
+ throw new TypeError("signal must be an AbortSignal");
14
+ }
15
+ return { signal, timeoutMs };
16
+ }
@@ -0,0 +1,16 @@
1
+ import type { MiniAppAdapter } from "./adapter.js";
2
+ export interface AppSession {
3
+ token: string;
4
+ startParam: string;
5
+ }
6
+ /** Cache entries are hints. The server must validate launch data and cached sessions. */
7
+ export declare function authenticate<T extends AppSession>(adapter: MiniAppAdapter, options: {
8
+ storageKey: string;
9
+ authenticate: (launch: {
10
+ adapterId: string;
11
+ launchData: string;
12
+ }) => Promise<T>;
13
+ validate: (token: string) => Promise<unknown>;
14
+ isUnauthorized: (error: unknown) => boolean;
15
+ storage?: Storage | null;
16
+ }): Promise<AppSession>;
@@ -0,0 +1,56 @@
1
+ /** Cache entries are hints. The server must validate launch data and cached sessions. */
2
+ export async function authenticate(adapter, options) {
3
+ let fingerprint = "";
4
+ if (globalThis.crypto?.subtle) {
5
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(adapter.launchData));
6
+ fingerprint = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
7
+ }
8
+ const storage = options.storage ?? null;
9
+ let cached;
10
+ try {
11
+ cached = JSON.parse(storage?.getItem(options.storageKey) ?? "null");
12
+ }
13
+ catch {
14
+ /* untrusted */
15
+ }
16
+ if (fingerprint && cached && typeof cached === "object") {
17
+ const value = cached;
18
+ if (value.fingerprint === fingerprint &&
19
+ value.adapterId === adapter.id &&
20
+ typeof value.token === "string" &&
21
+ value.token &&
22
+ typeof value.startParam === "string") {
23
+ try {
24
+ await options.validate(value.token);
25
+ return { token: value.token, startParam: value.startParam };
26
+ }
27
+ catch (error) {
28
+ if (!options.isUnauthorized(error))
29
+ throw error;
30
+ }
31
+ }
32
+ }
33
+ const session = await options.authenticate({
34
+ adapterId: adapter.id,
35
+ launchData: adapter.launchData,
36
+ });
37
+ if (typeof session.token !== "string" ||
38
+ !session.token ||
39
+ typeof session.startParam !== "string") {
40
+ throw new TypeError("Invalid application session");
41
+ }
42
+ if (fingerprint) {
43
+ try {
44
+ storage?.setItem(options.storageKey, JSON.stringify({
45
+ adapterId: adapter.id,
46
+ fingerprint,
47
+ token: session.token,
48
+ startParam: session.startParam,
49
+ }));
50
+ }
51
+ catch {
52
+ /* optional */
53
+ }
54
+ }
55
+ return { token: session.token, startParam: session.startParam };
56
+ }
@@ -0,0 +1,25 @@
1
+ import type { MiniAppClient, CallOptions } from "./client.js";
2
+ export declare function cloudStorage(client: MiniAppClient): {
3
+ setItem: (key: string, value: string, options?: CallOptions) => Promise<boolean>;
4
+ getItem: (key: string, options?: CallOptions) => Promise<string>;
5
+ getItems: (keys: readonly string[], options?: CallOptions) => Promise<Record<string, string>>;
6
+ removeItem: (key: string, options?: CallOptions) => Promise<boolean>;
7
+ removeItems: (keys: readonly string[], options?: CallOptions) => Promise<boolean>;
8
+ getKeys: (options?: CallOptions) => Promise<string[]>;
9
+ };
10
+ export declare function deviceStorage(client: MiniAppClient): {
11
+ setItem: (key: string, value: string, options?: CallOptions) => Promise<boolean>;
12
+ getItem: (key: string, options?: CallOptions) => Promise<string | null>;
13
+ removeItem: (key: string, options?: CallOptions) => Promise<boolean>;
14
+ clear: (options?: CallOptions) => Promise<boolean>;
15
+ };
16
+ export declare function secureStorage(client: MiniAppClient): {
17
+ setItem: (key: string, value: string, options?: CallOptions) => Promise<boolean>;
18
+ getItem: (key: string, options?: CallOptions) => Promise<{
19
+ value: string | null;
20
+ canRestore: boolean;
21
+ }>;
22
+ restoreItem: (key: string, options?: CallOptions) => Promise<string>;
23
+ removeItem: (key: string, options?: CallOptions) => Promise<boolean>;
24
+ clear: (options?: CallOptions) => Promise<boolean>;
25
+ };
@@ -0,0 +1,27 @@
1
+ export function cloudStorage(client) {
2
+ return {
3
+ setItem: (key, value, options) => client.call("cloudStorageSet", { key, value }, options),
4
+ getItem: (key, options) => client.call("cloudStorageGet", { key }, options),
5
+ getItems: (keys, options) => client.call("cloudStorageGetMany", { keys }, options),
6
+ removeItem: (key, options) => client.call("cloudStorageRemove", { key }, options),
7
+ removeItems: (keys, options) => client.call("cloudStorageRemoveMany", { keys }, options),
8
+ getKeys: (options) => client.call("cloudStorageKeys", undefined, options),
9
+ };
10
+ }
11
+ export function deviceStorage(client) {
12
+ return {
13
+ setItem: (key, value, options) => client.call("deviceStorageSet", { key, value }, options),
14
+ getItem: (key, options) => client.call("deviceStorageGet", { key }, options),
15
+ removeItem: (key, options) => client.call("deviceStorageRemove", { key }, options),
16
+ clear: (options) => client.call("deviceStorageClear", undefined, options),
17
+ };
18
+ }
19
+ export function secureStorage(client) {
20
+ return {
21
+ setItem: (key, value, options) => client.call("secureStorageSet", { key, value }, options),
22
+ getItem: (key, options) => client.call("secureStorageGet", { key }, options),
23
+ restoreItem: (key, options) => client.call("secureStorageRestore", { key }, options),
24
+ removeItem: (key, options) => client.call("secureStorageRemove", { key }, options),
25
+ clear: (options) => client.call("secureStorageClear", undefined, options),
26
+ };
27
+ }
@@ -0,0 +1,15 @@
1
+ import type { Capability, HostSnapshot, MiniAppEvent, MiniAppEventMap, MiniAppOperation, OperationInput, OperationOutput, RequestContext } from "./protocol.js";
2
+ export type AdapterRequest<T> = {
3
+ promise: PromiseLike<T>;
4
+ /** Releases callback/event resources. Safe to call more than once. */
5
+ cleanup?: () => void;
6
+ };
7
+ /** Platform boundary implemented by host-specific packages. */
8
+ export interface MiniAppAdapter {
9
+ readonly id: string;
10
+ readonly launchData: string;
11
+ readonly capabilities: ReadonlySet<Capability>;
12
+ snapshot(): HostSnapshot;
13
+ subscribe<K extends MiniAppEvent>(event: K, listener: (payload: MiniAppEventMap[K]) => void): () => void;
14
+ execute<K extends MiniAppOperation>(operation: K, input: OperationInput<K>, context: RequestContext): AdapterRequest<OperationOutput<K>> | PromiseLike<OperationOutput<K>>;
15
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,17 @@
1
+ import type { MiniAppClient } from "./client.js";
2
+ type AppearanceEnvironment = {
3
+ root: {
4
+ dataset: Record<string, string | undefined>;
5
+ style: {
6
+ setProperty(name: string, value: string): void;
7
+ };
8
+ };
9
+ prefersDark(): boolean;
10
+ background(variable: string): string;
11
+ onPreferenceChange(listener: () => void): () => void;
12
+ };
13
+ /** Binds normalized host appearance without reading a platform global. */
14
+ export declare function bindAppearance(client: MiniAppClient | null, environment: AppearanceEnvironment, options?: {
15
+ backgroundVariable?: string;
16
+ }): () => void;
17
+ export {};