@diffenderfer-games/hub 2.0.0-next.1 → 2.0.0-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -6
- package/README.md +25 -10
- package/dist/auto.d.ts +7 -7
- package/dist/auto.js +3 -3
- package/dist/doctor/cli.mjs +14 -7
- package/dist/doctor/cli.mjs.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +3 -3
- package/dist/input.d.ts +2 -2
- package/dist/input.js +2 -2
- package/dist/mp.d.ts +3 -3
- package/dist/race.d.ts +1 -1
- package/dist/rooms.d.ts +3 -3
- package/dist/shared/bridge.js +9 -3
- package/dist/shared/bridge.js.map +1 -1
- package/dist/shared/client-version.gen.js +1 -1
- package/dist/shared/daily.d.ts +10 -4
- package/dist/shared/daily.d.ts.map +1 -1
- package/dist/shared/daily.js +12 -2
- package/dist/shared/daily.js.map +1 -1
- package/dist/shared/index.d.ts +315 -36
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/input.d.ts +47 -5
- package/dist/shared/input.d.ts.map +1 -1
- package/dist/shared/input.js +139 -23
- package/dist/shared/input.js.map +1 -1
- package/dist/shared/latest-state.js +1 -1
- package/dist/shared/mp.js +10 -2
- package/dist/shared/mp.js.map +1 -1
- package/dist/shared/multiplayer-types.d.ts +15 -2
- package/dist/shared/multiplayer-types.d.ts.map +1 -1
- package/dist/shared/race-types.d.ts +1 -1
- package/dist/shared/race.js +1 -1
- package/dist/shared/room-types.d.ts +28 -3
- package/dist/shared/room-types.d.ts.map +1 -1
- package/dist/shared/rooms.d.ts.map +1 -1
- package/dist/shared/rooms.js +10 -2
- package/dist/shared/rooms.js.map +1 -1
- package/dist/shared/runtime-opener.js +1 -1
- package/dist/shared/social.d.ts +23 -8
- package/dist/shared/social.d.ts.map +1 -1
- package/dist/shared/social.js +6 -1
- package/dist/shared/social.js.map +1 -1
- package/dist/shared/src.js +1588 -388
- package/dist/shared/src.js.map +1 -1
- package/dist/shared/wire-types.d.ts +6 -2
- package/dist/shared/wire-types.d.ts.map +1 -1
- package/dist/social.d.ts +5 -5
- package/dist/social.js +1 -1
- package/package.json +2 -2
- package/src/core/connection.ts +187 -92
- package/src/core/game-data.ts +11 -9
- package/src/core/hub-economy.ts +47 -10
- package/src/core/hub-progress.ts +13 -16
- package/src/core/hub.ts +4 -2
- package/src/core/offline/hub-kinds/daily-kind.ts +68 -0
- package/src/core/offline/hub-kinds/economy-kinds.ts +86 -0
- package/src/core/offline/hub-kinds/game-fields.ts +2 -0
- package/src/core/offline/hub-kinds/index.ts +35 -0
- package/src/core/offline/hub-kinds/legacy-ops.ts +37 -0
- package/src/core/offline/hub-kinds/progress-kinds.ts +148 -0
- package/src/core/offline/kind-adapters.ts +48 -0
- package/src/core/offline/local-inventory.ts +64 -0
- package/src/core/offline/local-store.ts +20 -22
- package/src/core/offline/offline-api.ts +65 -0
- package/src/core/offline/outbox-entry.ts +59 -0
- package/src/core/offline/outbox-kinds.ts +78 -0
- package/src/core/offline/outbox-merge.ts +39 -0
- package/src/core/offline/outbox-replayer.ts +141 -0
- package/src/core/offline/outbox-store.ts +85 -0
- package/src/core/offline/outbox.ts +232 -0
- package/src/core/offline/queue.ts +4 -49
- package/src/core/offline/replay-lease.ts +87 -0
- package/src/core/offline/replay-policy.ts +52 -0
- package/src/core/rest/rest-client.ts +14 -3
- package/src/core/rest/routes.gen.ts +108 -87
- package/src/core/storage/json-guards.ts +6 -0
- package/src/core/version/client-version.gen.ts +1 -1
- package/src/daily/daily-system.ts +8 -1
- package/src/daily/types.ts +3 -2
- package/src/doctor/checks.ts +10 -2
- package/src/index.ts +6 -1
- package/src/input/focus-ring.ts +13 -0
- package/src/input/input-registry.ts +9 -2
- package/src/input/input-system.ts +4 -0
- package/src/input/modality.ts +122 -0
- package/src/input/nav-state.ts +13 -4
- package/src/input/zero-config.ts +1 -14
- package/src/input.ts +3 -0
- package/src/mp.ts +1 -1
- package/src/overlay/overlay.ts +5 -3
- package/src/overlay/styles.ts +4 -3
- package/src/realtime/bridge.ts +5 -0
- package/src/realtime/multiplayer-forwarder.ts +13 -1
- package/src/realtime/multiplayer-types.ts +15 -1
- package/src/realtime/room-types.ts +28 -2
- package/src/realtime/rooms-forwarder.ts +13 -1
- package/src/realtime/runtime-api.ts +19 -8
- package/src/realtime/social-forwarder.ts +5 -0
- package/src/realtime/social-types.ts +8 -0
- package/src/realtime/wire-types.ts +7 -0
- package/src/rooms.ts +1 -1
package/dist/shared/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { s as DailySystem } from "./daily.js";
|
|
2
|
-
import {
|
|
2
|
+
import { O as InputSystem, n as getUiStack } from "./input.js";
|
|
3
3
|
import { o as multiplayerForwarder } from "./mp.js";
|
|
4
4
|
import { f as raceForwarder } from "./race.js";
|
|
5
5
|
import { n as roomsForwarder } from "./rooms.js";
|
|
6
6
|
import { Q as socialForwarder, X as notifyForwarder, Z as presenceForwarder } from "./social.js";
|
|
7
|
-
import { Board, Board as Board$1, ErrorCode, GameInfo, GameLeaderboards, GameRecords, HubVersion, Inventory, Json, Json as Json$1, LeaderboardEntry, Metrics, Metrics as Metrics$1, PublicEndpoints, RejectReason, SessionUser, SortDir, SortDir as SortDir$1, Stats, Stats as Stats$1 } from "@diffenderfer-games/hub-contract";
|
|
7
|
+
import { Board, Board as Board$1, ErrorCode, GameInfo, GameLeaderboards, GameRecords, HubVersion, Inventory, Inventory as Inventory$1, Json, Json as Json$1, LeaderboardEntry, Metrics, Metrics as Metrics$1, PublicEndpoints, RejectReason, SessionUser, SortDir, SortDir as SortDir$1, Stats, Stats as Stats$1 } from "@diffenderfer-games/hub-contract";
|
|
8
8
|
import { CallReturn, ClientData } from "@ayepi/core/client";
|
|
9
9
|
//#region src/core/storage/key-value.d.ts
|
|
10
10
|
/**
|
|
@@ -234,7 +234,6 @@ type StatUpdateMode = 'set' | 'incr' | 'max';
|
|
|
234
234
|
declare class LocalStore {
|
|
235
235
|
private readonly prefix;
|
|
236
236
|
private readonly store;
|
|
237
|
-
private sequence;
|
|
238
237
|
/** The cache for game `slug` in `store` (default: `localStorage`, or memory without it). */
|
|
239
238
|
constructor(slug: string, store?: KeyValueStore);
|
|
240
239
|
private readStored;
|
|
@@ -267,14 +266,12 @@ declare class LocalStore {
|
|
|
267
266
|
getBoard(key: string): LocalBoard | null;
|
|
268
267
|
/** Record a score locally, keeping the best one; returns the board and best. */
|
|
269
268
|
submitScore(key: string, score: number, options: QueuedScoreOptions): LocalBoard;
|
|
270
|
-
/** The queued writes,
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
|
|
276
|
-
/** Queue a write, collapsing it with a compatible queued one. */
|
|
277
|
-
enqueue(input: QueueOpInput): void;
|
|
269
|
+
/** The v1 client's queued writes, removed from storage (the caller moves them into the outbox). */
|
|
270
|
+
takeLegacyQueue(): QueueOp[];
|
|
271
|
+
/** This game's cached inventory (empty when none is cached). */
|
|
272
|
+
getInventory(): Inventory;
|
|
273
|
+
/** Store this game's inventory and return it. */
|
|
274
|
+
setInventory(inventory: Inventory): Inventory;
|
|
278
275
|
/** The buffered analytics events, oldest first. */
|
|
279
276
|
getEvents(): BufferedEvent[];
|
|
280
277
|
/** Replace the event buffer. */
|
|
@@ -296,21 +293,270 @@ interface RestClient {
|
|
|
296
293
|
readonly apiBase: string;
|
|
297
294
|
/** Call an endpoint; resolves with its reply body, rejects with a {@link HubError}. */
|
|
298
295
|
call<K extends EndpointName>(name: K, ...fieldsArgument: CallArguments<K>): Promise<EndpointReply<K>>;
|
|
296
|
+
/**
|
|
297
|
+
* Call an endpoint as part of an offline operation: an endpoint marked for
|
|
298
|
+
* offline replay gets `opKey` in the operation header, so the hub runs it
|
|
299
|
+
* once however often it is sent; any other endpoint is called as usual.
|
|
300
|
+
*/
|
|
301
|
+
callOnce<K extends EndpointName>(opKey: string, name: K, ...fieldsArgument: CallArguments<K>): Promise<EndpointReply<K>>;
|
|
302
|
+
}
|
|
303
|
+
//#endregion
|
|
304
|
+
//#region src/core/offline/outbox-entry.d.ts
|
|
305
|
+
/** A queued operation. */
|
|
306
|
+
interface OutboxEntry {
|
|
307
|
+
/** Unique and sortable by queue time: replay runs in `id` order. Also the base of its operation keys. */
|
|
308
|
+
readonly id: string;
|
|
309
|
+
/** Which handler performs it (`hub.save`, `hub.stat`, or a game's own kind). */
|
|
310
|
+
readonly kind: string;
|
|
311
|
+
/** The handler's input. */
|
|
312
|
+
readonly payload: Json;
|
|
313
|
+
/** When it was queued (epoch ms). */
|
|
314
|
+
readonly createdAt: number;
|
|
315
|
+
/** How many times replay has started it. A started entry never absorbs a later one. */
|
|
316
|
+
readonly attempts: number;
|
|
317
|
+
/** Not before this time (epoch ms); 0 means as soon as possible. */
|
|
318
|
+
readonly retryAt: number;
|
|
319
|
+
/** The last failure's message, when it has failed before. */
|
|
320
|
+
readonly lastError?: string;
|
|
321
|
+
}
|
|
322
|
+
//#endregion
|
|
323
|
+
//#region src/core/offline/outbox-kinds.d.ts
|
|
324
|
+
/** What a kind's handler gets besides its payload. */
|
|
325
|
+
interface ReplayContext {
|
|
326
|
+
/** The operation's id (stable across retries). */
|
|
327
|
+
readonly opId: string;
|
|
328
|
+
/** Which try this is, from 1. */
|
|
329
|
+
readonly attempt: number;
|
|
330
|
+
/** `false` when the op runs at once (online, nothing waiting); `true` when it runs from the queue. */
|
|
331
|
+
readonly isReplay: boolean;
|
|
332
|
+
/**
|
|
333
|
+
* Call a hub endpoint. Calls to endpoints marked for offline replay carry
|
|
334
|
+
* an operation key made from the op id and the call's position in the
|
|
335
|
+
* handler, so a retried op whose earlier calls already landed gets their
|
|
336
|
+
* remembered replies instead of running them twice. Make the same calls in
|
|
337
|
+
* the same order on every try.
|
|
338
|
+
*/
|
|
339
|
+
call<K extends EndpointName>(name: K, ...fieldsArgument: CallArguments<K>): Promise<EndpointReply<K>>;
|
|
340
|
+
/** A key for `step` of this op that is the same on every try: send it to a game server to deduplicate there. */
|
|
341
|
+
key(step: string): string;
|
|
342
|
+
}
|
|
343
|
+
/** Performs one operation of a kind. Throw to fail it (see the docs for which failures retry). */
|
|
344
|
+
type OfflineHandler<Payload> = (payload: Payload, context: ReplayContext) => Promise<Json | undefined> | Json | undefined;
|
|
345
|
+
/** A kind, with optional rules for folding new operations into waiting ones. */
|
|
346
|
+
interface OfflineKindDefinition<Payload> {
|
|
347
|
+
/** Perform one operation. */
|
|
348
|
+
readonly run: OfflineHandler<Payload>;
|
|
349
|
+
/**
|
|
350
|
+
* Operations with the same merge key may fold together. Without one, every
|
|
351
|
+
* operation replays on its own.
|
|
352
|
+
*/
|
|
353
|
+
readonly mergeKey?: (payload: Payload) => string;
|
|
354
|
+
/**
|
|
355
|
+
* Fold `incoming` into the newest waiting operation with the same merge key
|
|
356
|
+
* (in its place in the queue); `undefined` to queue it separately.
|
|
357
|
+
*/
|
|
358
|
+
readonly merge?: (waiting: Payload, incoming: Payload) => Payload | undefined;
|
|
359
|
+
/** `true`: a new operation replaces every waiting one with the same merge key and goes last (a save slot's last write wins). */
|
|
360
|
+
readonly replaces?: boolean;
|
|
361
|
+
}
|
|
362
|
+
/** A kind as the outbox runs it: payloads are the stored JSON. */
|
|
363
|
+
interface RegisteredKind {
|
|
364
|
+
/** Perform one operation (malformed payloads are refused before this). */
|
|
365
|
+
readonly run: (payload: Json, context: ReplayContext) => Promise<Json | undefined> | Json | undefined;
|
|
366
|
+
/** Whether a stored payload is well formed for this kind. */
|
|
367
|
+
readonly accepts: (payload: Json) => boolean;
|
|
368
|
+
readonly mergeKey?: (payload: Json) => string;
|
|
369
|
+
readonly merge?: (waiting: Json, incoming: Json) => Json | undefined;
|
|
370
|
+
readonly replaces: boolean;
|
|
371
|
+
}
|
|
372
|
+
/** The registered kinds of one client. */
|
|
373
|
+
declare class KindRegistry {
|
|
374
|
+
private readonly kinds;
|
|
375
|
+
/** Register (or replace) a kind. */
|
|
376
|
+
register(kind: string, definition: RegisteredKind): void;
|
|
377
|
+
/** A registered kind, or `undefined`. */
|
|
378
|
+
get(kind: string): RegisteredKind | undefined;
|
|
379
|
+
}
|
|
380
|
+
//#endregion
|
|
381
|
+
//#region src/core/offline/outbox-store.d.ts
|
|
382
|
+
/** The most entries one game's outbox holds. */
|
|
383
|
+
declare const OUTBOX_MAX_ENTRIES = 500;
|
|
384
|
+
/** The most stored characters one game's outbox holds (about 2 MB of `localStorage`). */
|
|
385
|
+
declare const OUTBOX_MAX_CHARS = 1000000;
|
|
386
|
+
/** One game's outbox. */
|
|
387
|
+
declare class OutboxStore {
|
|
388
|
+
/** The key prefix of this game's entries. */
|
|
389
|
+
readonly prefix: string;
|
|
390
|
+
private readonly store;
|
|
391
|
+
/** The outbox for game `slug` in `store`. */
|
|
392
|
+
constructor(slug: string, store: KeyValueStore);
|
|
393
|
+
/** Every well-formed entry, oldest first. Malformed ones are removed. */
|
|
394
|
+
list(): OutboxEntry[];
|
|
395
|
+
/** How many entries are queued. */
|
|
396
|
+
count(): number;
|
|
397
|
+
/** One entry, or `undefined` once it is gone (replayed, or removed by another tab). */
|
|
398
|
+
get(id: string): OutboxEntry | undefined;
|
|
399
|
+
/** Whether `extra` more stored characters in one more entry still fit under the caps. */
|
|
400
|
+
fits(extraChars: number): boolean;
|
|
401
|
+
/** Store an entry (new or updated); `false` when the storage refused it (full or blocked). */
|
|
402
|
+
put(entry: OutboxEntry): boolean;
|
|
403
|
+
/** Forget an entry. */
|
|
404
|
+
remove(id: string): void;
|
|
405
|
+
/** Whether a storage key belongs to this outbox (for cross-tab `storage` events). */
|
|
406
|
+
owns(key: string | null): boolean;
|
|
407
|
+
private entryKeys;
|
|
408
|
+
}
|
|
409
|
+
//#endregion
|
|
410
|
+
//#region src/core/offline/outbox-replayer.d.ts
|
|
411
|
+
/** An op dropped during replay, with why. */
|
|
412
|
+
interface ReplayFailure {
|
|
413
|
+
/** The dropped op. */
|
|
414
|
+
readonly entry: OutboxEntry;
|
|
415
|
+
/** Why it was dropped (the hub's message, or the handler's). */
|
|
416
|
+
readonly error: string;
|
|
417
|
+
}
|
|
418
|
+
/** Why a replay stopped before the outbox was empty. */
|
|
419
|
+
type ReplayStop = 'connection' | 'backoff' | 'unknown-kind' | 'lease';
|
|
420
|
+
/** What one replay did. */
|
|
421
|
+
interface ReplayReport {
|
|
422
|
+
/** The ops that landed, in order. */
|
|
423
|
+
readonly replayed: OutboxEntry[];
|
|
424
|
+
/** The ops dropped. */
|
|
425
|
+
readonly failed: ReplayFailure[];
|
|
426
|
+
/** Why it stopped early, or `undefined` when the outbox is empty. */
|
|
427
|
+
readonly stoppedBy?: ReplayStop;
|
|
428
|
+
}
|
|
429
|
+
//#endregion
|
|
430
|
+
//#region src/core/offline/outbox.d.ts
|
|
431
|
+
/** A queued operation, as `hub.offline` reports it. */
|
|
432
|
+
type OfflineOp = OutboxEntry;
|
|
433
|
+
/** Each outbox event's detail. */
|
|
434
|
+
interface OfflineEventDetails {
|
|
435
|
+
/** An op was queued (or folded into a waiting one, which is then the `op`). */
|
|
436
|
+
queued: {
|
|
437
|
+
readonly op: OfflineOp;
|
|
438
|
+
};
|
|
439
|
+
/** An op landed; `result` is what its handler returned. */
|
|
440
|
+
replayed: {
|
|
441
|
+
readonly op: OfflineOp;
|
|
442
|
+
readonly result?: Json;
|
|
443
|
+
};
|
|
444
|
+
/** An op was dropped: the hub refused it, or it kept failing. */
|
|
445
|
+
failed: {
|
|
446
|
+
readonly op: OfflineOp;
|
|
447
|
+
readonly error: string;
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
/** An outbox event's name. */
|
|
451
|
+
type OfflineEventName = keyof OfflineEventDetails;
|
|
452
|
+
/** An outbox event listener. */
|
|
453
|
+
type OfflineListener<Name extends OfflineEventName> = (detail: OfflineEventDetails[Name]) => void;
|
|
454
|
+
/** The code of the error `add` throws when the outbox is full. */
|
|
455
|
+
declare const OUTBOX_FULL_CODE = "offline_queue_full";
|
|
456
|
+
/** What the outbox needs from its client. */
|
|
457
|
+
interface OutboxOptions {
|
|
458
|
+
/** The game whose outbox it is. */
|
|
459
|
+
readonly slug: string;
|
|
460
|
+
/** Where it lives (`localStorage`, or memory). */
|
|
461
|
+
readonly store: KeyValueStore;
|
|
462
|
+
/** The REST client its handlers call through. */
|
|
463
|
+
readonly rest: RestClient;
|
|
464
|
+
/** Fire a window event (the menu listens). */
|
|
465
|
+
readonly emit: (name: string, detail: OfflineEventDetails[OfflineEventName]) => void;
|
|
466
|
+
/** The hub couldn't be reached during a replay. */
|
|
467
|
+
readonly onUnreachable: () => void;
|
|
468
|
+
/** The queue length may have changed. */
|
|
469
|
+
readonly onChange: () => void;
|
|
470
|
+
/** A retry is due: replay again. */
|
|
471
|
+
readonly onRetryDue: () => void;
|
|
472
|
+
readonly now?: () => number;
|
|
473
|
+
}
|
|
474
|
+
/** One game's outbox. */
|
|
475
|
+
declare class Outbox {
|
|
476
|
+
/** The kinds this client can perform. */
|
|
477
|
+
readonly kinds: KindRegistry;
|
|
478
|
+
/** The stored entries. */
|
|
479
|
+
readonly entries: OutboxStore;
|
|
480
|
+
private readonly options;
|
|
481
|
+
private readonly replayer;
|
|
482
|
+
private readonly now;
|
|
483
|
+
private sequence;
|
|
484
|
+
private retryTimer;
|
|
485
|
+
private retryAt;
|
|
486
|
+
private readonly listeners;
|
|
487
|
+
/** The outbox for `options.slug`. */
|
|
488
|
+
constructor(options: OutboxOptions);
|
|
489
|
+
/** Register a kind. */
|
|
490
|
+
define(kind: string, definition: RegisteredKind): void;
|
|
491
|
+
/** A new, not yet stored, op of `kind`. */
|
|
492
|
+
stamp(kind: string, payload: Json): OutboxEntry;
|
|
493
|
+
/**
|
|
494
|
+
* Queue an op, folding it into a waiting one where its kind says so.
|
|
495
|
+
* Throws a {@link HubError} (code {@link OUTBOX_FULL_CODE}) when the
|
|
496
|
+
* outbox is full or the storage refuses it.
|
|
497
|
+
*/
|
|
498
|
+
add(op: OutboxEntry): void;
|
|
499
|
+
/** Perform an op now, without queueing it (the online path); throws what its handler throws. */
|
|
500
|
+
runNow(op: OutboxEntry): Promise<Json | undefined>;
|
|
501
|
+
/** Replay what is due, in order. `isEager`: the connection just came back, so ops waiting for it go at once. */
|
|
502
|
+
replay(isEager?: boolean): Promise<ReplayReport>;
|
|
503
|
+
/** The waiting ops, oldest first. */
|
|
504
|
+
pending(): OfflineOp[];
|
|
505
|
+
/** How many ops are waiting. */
|
|
506
|
+
count(): number;
|
|
507
|
+
/** Listen for an event; returns the unsubscribe function. */
|
|
508
|
+
on<Name extends OfflineEventName>(name: Name, listener: OfflineListener<Name>): () => void;
|
|
509
|
+
private fire;
|
|
510
|
+
private contextFor;
|
|
511
|
+
private scheduleRetry;
|
|
512
|
+
private clearRetry;
|
|
513
|
+
}
|
|
514
|
+
//#endregion
|
|
515
|
+
//#region src/core/offline/offline-api.d.ts
|
|
516
|
+
/** What `hub.offline` drives. */
|
|
517
|
+
interface OfflineHost {
|
|
518
|
+
/** The game's outbox. */
|
|
519
|
+
readonly outbox: Outbox;
|
|
520
|
+
/** Replay now when the hub is reachable (and nothing else is replaying). */
|
|
521
|
+
requestSync(): void;
|
|
522
|
+
}
|
|
523
|
+
/** The game-facing outbox API. */
|
|
524
|
+
declare class OfflineApi {
|
|
525
|
+
private readonly host;
|
|
526
|
+
/** The API over `host`. */
|
|
527
|
+
constructor(host: OfflineHost);
|
|
528
|
+
/**
|
|
529
|
+
* Define what an operation of `kind` does when it replays. Define every
|
|
530
|
+
* kind at load, before or after enqueueing: waiting ops of an undefined
|
|
531
|
+
* kind hold the queue until it is defined. `hub.*` kinds are the hub's own.
|
|
532
|
+
*/
|
|
533
|
+
define<Payload extends GamePayload>(kind: string, definition: OfflineHandler<Payload> | OfflineKindDefinition<Payload>): void;
|
|
534
|
+
/**
|
|
535
|
+
* Queue an operation of `kind` and replay it as soon as the hub is
|
|
536
|
+
* reachable (at once when online). Resolves the queued op; its outcome
|
|
537
|
+
* arrives as a `replayed` or `failed` event. Throws a `HubError` (code
|
|
538
|
+
* `offline_queue_full`) when the outbox is full.
|
|
539
|
+
*/
|
|
540
|
+
enqueue(kind: string, payload: GamePayload): OfflineOp;
|
|
541
|
+
/** The waiting operations (the hub's and the game's), oldest first. */
|
|
542
|
+
pending(): OfflineOp[];
|
|
543
|
+
/** Listen for `queued`, `replayed` or `failed`; returns the unsubscribe function. */
|
|
544
|
+
on<Name extends OfflineEventName>(name: Name, listener: OfflineListener<Name>): () => void;
|
|
299
545
|
}
|
|
300
546
|
//#endregion
|
|
301
547
|
//#region src/core/connection.d.ts
|
|
302
|
-
/** A queued
|
|
548
|
+
/** A queued op the hub refused during a sync (or that kept failing): dropped, with the reason. */
|
|
303
549
|
interface SyncConflict {
|
|
304
|
-
/** The
|
|
305
|
-
readonly op:
|
|
306
|
-
/** The hub's message. */
|
|
550
|
+
/** The dropped op. */
|
|
551
|
+
readonly op: OfflineOp;
|
|
552
|
+
/** The hub's (or the handler's) message. */
|
|
307
553
|
readonly error?: string;
|
|
308
554
|
}
|
|
309
555
|
/** What one `sync()` did. */
|
|
310
556
|
interface SyncResult {
|
|
311
|
-
/** Queued
|
|
557
|
+
/** Queued ops that landed. */
|
|
312
558
|
readonly flushed: number;
|
|
313
|
-
/** Queued
|
|
559
|
+
/** Queued ops that were dropped. */
|
|
314
560
|
readonly conflicts: SyncConflict[];
|
|
315
561
|
}
|
|
316
562
|
/** The game slug's path field, or a {@link HubError} when the slug is unknown. */
|
|
@@ -326,12 +572,18 @@ declare class HubConnection {
|
|
|
326
572
|
readonly apiBase: string;
|
|
327
573
|
/** Typed REST calls to {@link apiBase}. */
|
|
328
574
|
protected readonly rest: RestClient;
|
|
329
|
-
/** This game's offline cache
|
|
575
|
+
/** This game's offline cache and event buffer. */
|
|
330
576
|
protected readonly store: LocalStore;
|
|
577
|
+
/** This game's queued operations. */
|
|
578
|
+
protected readonly outbox: Outbox;
|
|
331
579
|
private readonly offlineMode;
|
|
332
580
|
private isReachable;
|
|
333
|
-
private
|
|
581
|
+
private runningSync;
|
|
582
|
+
private followingSync;
|
|
583
|
+
private isFollowingEager;
|
|
584
|
+
private directSend;
|
|
334
585
|
private lastPrefetchAt;
|
|
586
|
+
private offlineApi;
|
|
335
587
|
private readonly statusListeners;
|
|
336
588
|
/** A connection for `options` (slug and API base default to the page's). */
|
|
337
589
|
constructor(options?: HubOptions);
|
|
@@ -339,13 +591,18 @@ declare class HubConnection {
|
|
|
339
591
|
get isOffline(): boolean;
|
|
340
592
|
/** `true` while the hub is reachable. */
|
|
341
593
|
get isOnline(): boolean;
|
|
342
|
-
/**
|
|
594
|
+
/**
|
|
595
|
+
* The offline outbox: define your own kinds of operation, queue them, and
|
|
596
|
+
* hear how they replay (`hub.offline.define`, `enqueue`, `pending`, `on`).
|
|
597
|
+
*/
|
|
598
|
+
get offline(): OfflineApi;
|
|
599
|
+
/** Queued operations plus buffered analytics events waiting to sync. */
|
|
343
600
|
pending(): number;
|
|
344
601
|
/** Subscribe to connection and sync status changes; returns the unsubscribe function. */
|
|
345
602
|
onStatus(listener: (status: HubStatus) => void): () => void;
|
|
346
603
|
/** Tell `onStatus` listeners and the page (`hub:status`) the current status. */
|
|
347
604
|
protected notifyStatus(): void;
|
|
348
|
-
/** Record reachability; coming back online
|
|
605
|
+
/** Record reachability; coming back online replays the outbox and re-warms the cache. */
|
|
349
606
|
protected setReachable(isReachableNow: boolean): void;
|
|
350
607
|
/** `{ slug }` for this game's endpoints; throws when the slug is unknown. */
|
|
351
608
|
protected gameFields(): GameFields;
|
|
@@ -355,23 +612,38 @@ declare class HubConnection {
|
|
|
355
612
|
* status) always reach the caller.
|
|
356
613
|
*/
|
|
357
614
|
protected withFallback<Reply>(networkCall: () => Promise<Reply>, offlineAnswer: () => Reply): Promise<Reply>;
|
|
358
|
-
/** Send one queued write. */
|
|
359
|
-
private sendOp;
|
|
360
615
|
/**
|
|
361
|
-
* Apply a write to the offline cache at once, then
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
616
|
+
* Apply a write to the offline cache at once, then perform it as an op of
|
|
617
|
+
* `kind`: sent now when online with nothing waiting, else queued behind
|
|
618
|
+
* the others. Resolves with the local answer (or, sent now, with
|
|
619
|
+
* `replyAnswer`'s reading of the hub's reply). A real API error on the
|
|
620
|
+
* direct path reaches the caller and is not queued; a transport failure
|
|
621
|
+
* queues the op under the same id, so if the request did land, its replay
|
|
622
|
+
* is recognised by the hub and not applied twice.
|
|
365
623
|
*/
|
|
366
|
-
protected
|
|
624
|
+
protected mutateOffline<Reply>(kind: string, payload: Json, localAnswer: () => Reply, replyAnswer?: (result: Json | undefined) => Reply | undefined): Promise<Reply>;
|
|
367
625
|
/**
|
|
368
|
-
* Replay the
|
|
369
|
-
* transport failure (offline again: the rest stays queued);
|
|
370
|
-
* refuses is dropped and reported as a conflict.
|
|
626
|
+
* Replay the outbox, then the buffered events, in order. Stops at the
|
|
627
|
+
* first transport failure (offline again: the rest stays queued); an op
|
|
628
|
+
* the hub refuses is dropped and reported as a conflict.
|
|
371
629
|
*/
|
|
372
630
|
sync(): Promise<SyncResult>;
|
|
631
|
+
/** A retry came due: try again even when the hub was last unreachable (the try is the probe), unless the browser itself is offline. */
|
|
632
|
+
private retrySync;
|
|
633
|
+
/**
|
|
634
|
+
* One replay at a time per client. A call during one queues a single
|
|
635
|
+
* follow-up replay (eager if any caller asked for that), so an op queued
|
|
636
|
+
* or a reconnect that happens mid-replay is never missed.
|
|
637
|
+
*/
|
|
638
|
+
private replayAll;
|
|
639
|
+
private startReplay;
|
|
640
|
+
private runReplay;
|
|
373
641
|
/** Send the buffered analytics events; a refused one is dropped (telemetry never blocks). */
|
|
374
642
|
private flushEvents;
|
|
643
|
+
/** Move a v1 copy's queued writes into the outbox, in their order. */
|
|
644
|
+
private importLegacyQueue;
|
|
645
|
+
/** Follow the browser's connection, other tabs' outbox changes, and replay what an earlier page left queued. */
|
|
646
|
+
private listenToPage;
|
|
375
647
|
/**
|
|
376
648
|
* Warm the offline cache for every game the player has touched, in one
|
|
377
649
|
* request, so going offline later still shows complete progress.
|
|
@@ -509,7 +781,7 @@ declare class HubEconomy extends HubProgress {
|
|
|
509
781
|
favorites(): Promise<{
|
|
510
782
|
games: string[];
|
|
511
783
|
}>;
|
|
512
|
-
/** Star (`isOn = true`) or unstar a game.
|
|
784
|
+
/** Star (`isOn = true`) or unstar a game. Offline, the local list changes at once and the hub's when it is back. */
|
|
513
785
|
setFavorite(slug: string, isOn: boolean): Promise<{
|
|
514
786
|
games: string[];
|
|
515
787
|
}>;
|
|
@@ -519,9 +791,16 @@ declare class HubEconomy extends HubProgress {
|
|
|
519
791
|
getInventory(): Promise<InventorySnapshot>;
|
|
520
792
|
/** Another player's available holdings (to compose a trade). */
|
|
521
793
|
playerInventory(userId: number): Promise<InventorySnapshot>;
|
|
522
|
-
/**
|
|
794
|
+
/**
|
|
795
|
+
* Add goods to the player (gameplay rewards); answers the new holdings.
|
|
796
|
+
* Offline, the cached holdings change at once and the grant replays later.
|
|
797
|
+
*/
|
|
523
798
|
grant(bundle: GrantBundle): Promise<EndpointReply<'grantInventoryItems'>>;
|
|
524
|
-
/**
|
|
799
|
+
/**
|
|
800
|
+
* An atomic swap with the house: remove `take`, add `give`. Offline it is
|
|
801
|
+
* checked against the cached holdings (409 when they can't cover `take`),
|
|
802
|
+
* applied to them at once, and replayed later; the hub has the last word.
|
|
803
|
+
*/
|
|
525
804
|
exchange(take?: TradeBundle, give?: TradeBundle): Promise<EndpointReply<'exchangeInventoryItems'>>;
|
|
526
805
|
/** Sell items to the house for coins. */
|
|
527
806
|
sell(items: Record<string, number>, coins: number): Promise<EndpointReply<'exchangeInventoryItems'>>;
|
|
@@ -700,7 +979,7 @@ declare class ContentRejectedError extends HubError {
|
|
|
700
979
|
//#endregion
|
|
701
980
|
//#region src/core/version/client-version.gen.d.ts
|
|
702
981
|
/** This client's package version, sent as `x-hub-client` on REST calls and `client` in `hello`. */
|
|
703
|
-
declare const HUB_CLIENT_VERSION = "2.0.0-next.
|
|
982
|
+
declare const HUB_CLIENT_VERSION = "2.0.0-next.3";
|
|
704
983
|
//#endregion
|
|
705
|
-
export {
|
|
984
|
+
export { LeaderboardResult as $, OUTBOX_MAX_ENTRIES as A, Board$1 as B, OfflineApi as C, OfflineListener as D, OfflineEventName as E, ProfilePatch as F, GameRecords as G, GameAnalytics as H, QueueOp as I, HubStatus as J, GlobalAnalytics as K, QueueOpInput as L, OfflineKindDefinition as M, ReplayContext as N, OfflineOp as O, CLIENT_VERSION_HEADER as P, LeaderboardEntry as Q, QueuedScoreOptions as R, SyncResult as S, OfflineEventDetails as T, GameInfo$1 as U, BoardWithTop as V, GameLeaderboards as W, InventorySnapshot as X, Inventory$1 as Y, Json$1 as Z, TradeNoteOptions as _, HubErrorDetails as a, SaveMeta as at, StatResult as b, Hub as c, Stats$1 as ct, ClientSupport as d, User as dt, MeResponse as et, HubMenuControl as f, EndpointFields as ft, TradeListOptions as g, TradeId as h, GamePayload as ht, HubErrorCode as i, Save as it, OfflineHandler as j, OUTBOX_MAX_CHARS as k, createHub as l, SubmitScoreOptions as lt, TradeBundle as m, EndpointReply as mt, ContentRejectedError as n, Profile as nt, OfflineError as o, SnapshotResponse as ot, GrantBundle as p, EndpointName as pt, HubOptions as q, HubError as r, ProfileSummary as rt, UNSUPPORTED_BY_HUB as s, SortDir$1 as st, HUB_CLIENT_VERSION as t, Metrics$1 as tt, hub as u, SubmitScoreResult as ut, AuthResponse as v, OUTBOX_FULL_CODE as w, SyncConflict as x, ProfileUpdate as y, BufferedEvent as z };
|
|
706
985
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":["GameInfo","ContractGameInfo","GameInfo","presence","social","mp","rooms","notify","race"],"sources":["../../src/core/storage/key-value.ts","../../src/core/game-data.ts","../../src/core/rest/endpoint-types.ts","../../src/core/types.ts","../../src/core/offline/events.ts","../../src/core/offline/queue.ts","../../src/core/offline/local-store.ts","../../src/core/rest/rest-client.ts","../../src/core/connection.ts","../../src/core/hub-progress.ts","../../src/core/hub-economy.ts","../../src/core/menu-control.ts","../../src/core/version/hub-version.ts","../../src/core/hub.ts","../../src/core/errors.ts","../../src/core/version/client-version.gen.ts"],"mappings":";;;;;;;;;;;;;;;;UAQiB;;EAEf,KAAK;;EAEL,MAAM,aAAa;;EAEnB,OAAO;;EAEP;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":["GameInfo","ContractGameInfo","GameInfo","presence","social","mp","rooms","notify","race"],"sources":["../../src/core/storage/key-value.ts","../../src/core/game-data.ts","../../src/core/rest/endpoint-types.ts","../../src/core/types.ts","../../src/core/offline/events.ts","../../src/core/offline/queue.ts","../../src/core/offline/local-store.ts","../../src/core/rest/rest-client.ts","../../src/core/offline/outbox-entry.ts","../../src/core/offline/outbox-kinds.ts","../../src/core/offline/outbox-store.ts","../../src/core/offline/outbox-replayer.ts","../../src/core/offline/outbox.ts","../../src/core/offline/offline-api.ts","../../src/core/connection.ts","../../src/core/hub-progress.ts","../../src/core/hub-economy.ts","../../src/core/menu-control.ts","../../src/core/version/hub-version.ts","../../src/core/hub.ts","../../src/core/errors.ts","../../src/core/version/client-version.gen.ts"],"mappings":"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"}
|
package/dist/shared/input.d.ts
CHANGED
|
@@ -375,6 +375,7 @@ declare class InputSystem implements ControlsPanelHost, PageInputControl {
|
|
|
375
375
|
private activeSource;
|
|
376
376
|
private isPageOwner;
|
|
377
377
|
private pageOwner;
|
|
378
|
+
private readonly modality;
|
|
378
379
|
constructor(host: InputHost, options?: InputSystemOptions);
|
|
379
380
|
/** Whether this page counts as a touch device. */
|
|
380
381
|
get touchDevice(): boolean;
|
|
@@ -491,11 +492,52 @@ declare function parseInputOverrides(saved: unknown): InputOverrides;
|
|
|
491
492
|
*/
|
|
492
493
|
declare function getInput(options?: InputOptions): InputSystem;
|
|
493
494
|
//#endregion
|
|
495
|
+
//#region src/input/focus-ring.d.ts
|
|
496
|
+
/**
|
|
497
|
+
* The hub's focus ring: a two-tone box-shadow (a dark gap, then a light ring)
|
|
498
|
+
* that follows the element's own border-radius and shows on light and dark
|
|
499
|
+
* buttons alike. Pages tune it with CSS variables:
|
|
500
|
+
* `--hub-focus-color` (the ring), `--hub-focus-inner` (the gap),
|
|
501
|
+
* `--hub-focus-width` and `--hub-focus-gap`.
|
|
502
|
+
*/
|
|
503
|
+
/** The ring as a `box-shadow` value. */
|
|
504
|
+
declare const FOCUS_RING_SHADOW = "0 0 0 var(--hub-focus-gap, 2px) var(--hub-focus-inner, rgba(13, 15, 20, 0.85)), 0 0 0 calc(var(--hub-focus-gap, 2px) + var(--hub-focus-width, 3px)) var(--hub-focus-color, #fff)";
|
|
505
|
+
//#endregion
|
|
506
|
+
//#region src/input/modality.d.ts
|
|
507
|
+
/** `keys`: keyboard or gamepad. `pointer`: mouse or pen. `touch`: a finger. */
|
|
508
|
+
type InputModality = 'keys' | 'pointer' | 'touch';
|
|
509
|
+
/** The `<html>` attribute that holds the modality. */
|
|
510
|
+
declare const MODALITY_ATTRIBUTE = "data-hub-input";
|
|
511
|
+
/** Where the modality is stored: `<html>`, or a fake in tests. */
|
|
512
|
+
interface ModalityRoot {
|
|
513
|
+
getAttribute(name: string): string | null;
|
|
514
|
+
setAttribute(name: string, value: string): void;
|
|
515
|
+
}
|
|
516
|
+
/** Reads and writes the page's modality attribute. */
|
|
517
|
+
declare class ModalityTracker {
|
|
518
|
+
private readonly root;
|
|
519
|
+
/** Start at `initial` unless another copy already set the attribute. */
|
|
520
|
+
constructor(root: ModalityRoot, initial: InputModality);
|
|
521
|
+
/** The last modality used. */
|
|
522
|
+
get current(): InputModality;
|
|
523
|
+
/** Whether focus should show: the last input was a keyboard or gamepad. */
|
|
524
|
+
get showsFocus(): boolean;
|
|
525
|
+
/** Record the modality the player just used. */
|
|
526
|
+
set(modality: InputModality): void;
|
|
527
|
+
/** A key went down (`isTyping`: in a text field). */
|
|
528
|
+
noteKey(key: string, isTyping: boolean): void;
|
|
529
|
+
/** A pointer went down. */
|
|
530
|
+
notePointer(pointerType: string): void;
|
|
531
|
+
private readAttribute;
|
|
532
|
+
}
|
|
533
|
+
/** Track the page's modality (once per bundle) and add the focus styles (once per page). */
|
|
534
|
+
declare function trackInputModality(): ModalityTracker;
|
|
535
|
+
//#endregion
|
|
494
536
|
//#region src/input/nav-state.d.ts
|
|
495
537
|
/** What a navigable list draws with (the overlay). */
|
|
496
538
|
interface NavHighlighter {
|
|
497
|
-
/** Ring the highlighted element. */
|
|
498
|
-
showHighlight(bounds: Rect): void;
|
|
539
|
+
/** Ring the highlighted element, following its corner radius (a CSS `border-radius`, or empty). */
|
|
540
|
+
showHighlight(bounds: Rect, radius: string): void;
|
|
499
541
|
/** Remove the ring. */
|
|
500
542
|
hideHighlight(): void;
|
|
501
543
|
/** Open the on-screen keyboard for a text field. */
|
|
@@ -591,8 +633,8 @@ declare class Overlay implements NavHighlighter {
|
|
|
591
633
|
setInsets(insets: Partial<Insets>): void;
|
|
592
634
|
/** Re-place every control for the current viewport, keeping the player's dragged spots. */
|
|
593
635
|
layout(): void;
|
|
594
|
-
/** Ring the highlighted element. */
|
|
595
|
-
showHighlight(bounds: Rect): void;
|
|
636
|
+
/** Ring the highlighted element, for keyboard and gamepad players only (never after a tap or click). */
|
|
637
|
+
showHighlight(bounds: Rect, radius: string): void;
|
|
596
638
|
/** Remove the ring. */
|
|
597
639
|
hideHighlight(): void;
|
|
598
640
|
/** Open the on-screen keyboard for a text field. */
|
|
@@ -726,5 +768,5 @@ declare function getUiStack(): UiStack;
|
|
|
726
768
|
/** Bump when the UiStack contract gains behaviour; idle older instances are replaced. */
|
|
727
769
|
declare const UI_STACK_VERSION = 1;
|
|
728
770
|
//#endregion
|
|
729
|
-
export {
|
|
771
|
+
export { NavigableDef as $, PageInputControl as A, InputDef as B, INPUT_SINGLETON_API as C, parseInputOverrides as D, isInputSystem as E, DraggedSpot as F, InputSource as G, InputHost as H, EdgeOffsets as I, NavBlurEvent as J, MenuBridge as K, GamepadMapping as L, Anchor as M, AxisDef as N, InputSystem as O, AxisSide as P, NavTarget as Q, GroupDef as R, FOCUS_RING_SHADOW as S, getInput as T, InputOverrides as U, InputEvents as V, InputReading as W, NavElementKind as X, NavElement as Y, NavFocusEvent as Z, boxesTouch as _, OverlayEdge as a, VirtualInputs as at, MODALITY_ATTRIBUTE as b, OverlayReason as c, LayoutOptions as d, Rect as et, layoutControls as f, LayoutItem as g, LayoutBox as h, AutoPauseOptions as i, VirtualDef as it, isPageInputControl as j, InputSystemOptions as k, UiStack as l, Insets as m, getUiStack as n, Vector as nt, OverlayEvent as o, VirtualOverride as ot, Overlay as p, MouseMapping as q, isUiStack as r, VirtualControlType as rt, OverlayListener as s, UI_STACK_VERSION as t, TouchMapping as tt, UiStackHandoff as u, controlSize as v, InputOptions as w, trackInputModality as x, InputModality as y, InputConfig as z };
|
|
730
772
|
//# sourceMappingURL=input.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.d.ts","names":[],"sources":["../../src/input/types.ts","../../src/overlay/controls-panel.ts","../../src/input/page-control.ts","../../src/input/input-system.ts","../../src/input/page-input.ts","../../src/input/nav-state.ts","../../src/overlay/layout-geometry.ts","../../src/overlay/virtual-controls.ts","../../src/overlay/overlay.ts","../../src/overlay/layout.ts","../../src/uistack/types.ts","../../src/uistack/page-stack.ts","../../src/uistack/ui-stack.ts"],"mappings":";;;;;;;KAOY;;KAGA;;UAGK;;EAEf;;EAEA;;EAEA;;EAEA,aAAa;;EAEb;;EAEA,WAAW;;EAEX;;EAEA,QAAQ;;;UAIO;;EAEf;;EAEA,gBAAgB;;;UAID;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA,aAAa;;;UAIE;;EAEf;;EAEA,QAAQ;;EAER,UAAU;;EAEV,QAAQ;;;;;;UAOO;;EAEf;;EAEA;;;KAIU;;KAMA;;UAGK;;EAEf;;EAEA;;EAEA;;EAEA;;;UAIe;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;;UAIe;;EAEf;;EAEA,MAAM;;EAEN,OAAO;;;;;EAKP,MAAM;;;;;;EAMN;IAAW;IAAY;;;EAEvB;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA,SAAS;;;UAIM;;EAEf;;EAEA;;EAEA;;EAEA;;;KAIU;;UAGK;;EAEf;;EAEA,OAAO;;EAEP,KAAK;;EAEL,kBAAkB;;EAElB;;EAEA;;EAEA;;;KAIU,YAAY,cAAc;;UAGrB;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA,gBAAgB;;EAEhB;;;UAIe;;EAEf,QAAQ,eAAe;;EAEvB,OAAO,eAAe;;EAEtB,UAAU;;EAEV,YAAY;;EAEZ;;;UAIe;;EAEf,QAAQ,eAAe;;;UAIR;;EAEf;;EAEA;;EAEA;;EAEA;;;UAIe;;EAEf;;EAEA;;EAEA;;;UAIe;;EAEf;;EAEA;;;KAIU,kBAAkB,QAAQ,cAAc;;UAGnC;;EAEf,WAAW,eAAe,QAAQ;;EAElC,UAAU,eAAe;;EAEzB;;;UAIe;;EAEf;;EAEA;;EAEA;;EAEA,MAAM;;;UAIS;;EAEf;;EAEA,KAAK;;EAEL,OAAO;;EAEP;;;UAIe;;EAEf;;EAEA;;;UAIe;;EAEf,OAAO;;EAEP,MAAM;;EAEN,KAAK;;EAEL,cAAc;;EAEd,UAAU;;;UAIK;;WAEN;;EAET,iBAAiB;;EAEjB,cAAc,WAAW;;;;;UChUV;;WAEN;;EAET,YAAY;;EAEZ,kBAAkB;;EAElB,OAAO,mBAAmB,OAAO,QAAQ;;EAEzC;;EAEA,aAAa;;;;;UCVE;;WAEN;;EAET,WAAW,QAAQ;;EAGnB,kBAAkB;;EAElB;;EAEA,UAAU;;EAEV,OAAO;;EAEP,QAAQ;;EAER,aAAa,0BAA0B,cAAc;IAAY;;;EAEjE;;EAEA,aAAa,OAAO;;;iBAQN,mBAAmB,qBAAqB,aAAa;;;;
|
|
1
|
+
{"version":3,"file":"input.d.ts","names":[],"sources":["../../src/input/types.ts","../../src/overlay/controls-panel.ts","../../src/input/page-control.ts","../../src/input/input-system.ts","../../src/input/page-input.ts","../../src/input/focus-ring.ts","../../src/input/modality.ts","../../src/input/nav-state.ts","../../src/overlay/layout-geometry.ts","../../src/overlay/virtual-controls.ts","../../src/overlay/overlay.ts","../../src/overlay/layout.ts","../../src/uistack/types.ts","../../src/uistack/page-stack.ts","../../src/uistack/ui-stack.ts"],"mappings":";;;;;;;KAOY;;KAGA;;UAGK;;EAEf;;EAEA;;EAEA;;EAEA,aAAa;;EAEb;;EAEA,WAAW;;EAEX;;EAEA,QAAQ;;;UAIO;;EAEf;;EAEA,gBAAgB;;;UAID;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA,aAAa;;;UAIE;;EAEf;;EAEA,QAAQ;;EAER,UAAU;;EAEV,QAAQ;;;;;;UAOO;;EAEf;;EAEA;;;KAIU;;KAMA;;UAGK;;EAEf;;EAEA;;EAEA;;EAEA;;;UAIe;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;;UAIe;;EAEf;;EAEA,MAAM;;EAEN,OAAO;;;;;EAKP,MAAM;;;;;;EAMN;IAAW;IAAY;;;EAEvB;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA,SAAS;;;UAIM;;EAEf;;EAEA;;EAEA;;EAEA;;;KAIU;;UAGK;;EAEf;;EAEA,OAAO;;EAEP,KAAK;;EAEL,kBAAkB;;EAElB;;EAEA;;EAEA;;;KAIU,YAAY,cAAc;;UAGrB;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA,gBAAgB;;EAEhB;;;UAIe;;EAEf,QAAQ,eAAe;;EAEvB,OAAO,eAAe;;EAEtB,UAAU;;EAEV,YAAY;;EAEZ;;;UAIe;;EAEf,QAAQ,eAAe;;;UAIR;;EAEf;;EAEA;;EAEA;;EAEA;;;UAIe;;EAEf;;EAEA;;EAEA;;;UAIe;;EAEf;;EAEA;;;KAIU,kBAAkB,QAAQ,cAAc;;UAGnC;;EAEf,WAAW,eAAe,QAAQ;;EAElC,UAAU,eAAe;;EAEzB;;;UAIe;;EAEf;;EAEA;;EAEA;;EAEA,MAAM;;;UAIS;;EAEf;;EAEA,KAAK;;EAEL,OAAO;;EAEP;;;UAIe;;EAEf;;EAEA;;;UAIe;;EAEf,OAAO;;EAEP,MAAM;;EAEN,KAAK;;EAEL,cAAc;;EAEd,UAAU;;;UAIK;;WAEN;;EAET,iBAAiB;;EAEjB,cAAc,WAAW;;;;;UChUV;;WAEN;;EAET,YAAY;;EAEZ,kBAAkB;;EAElB,OAAO,mBAAmB,OAAO,QAAQ;;EAEzC;;EAEA,aAAa;;;;;UCVE;;WAEN;;EAET,WAAW,QAAQ;;EAGnB,kBAAkB;;EAElB;;EAEA,UAAU;;EAEV,OAAO;;EAEP,QAAQ;;EAER,aAAa,0BAA0B,cAAc;IAAY;;;EAEjE;;EAEA,aAAa,OAAO;;;iBAQN,mBAAmB,qBAAqB,aAAa;;;;UCVpD;;EAEf;;EAEA,aAAa,QAAQ,gBAAgB;;;cAO1B,uBAAuB,mBAAmB;mBACpC;mBACA;UACT;mBACS;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;UACT;UACA;UAEA;UACA;UACA;UACA;mBACS;EAEL,YAAA,MAAM,WAAW,UAAS;;MAwBlC;;EAKJ,OAAO,QAAQ;;MAmBX;;EAKJ,OAAO;;EAOP,QAAQ;;EAOR,UAAU;;EAKV,MAAM;;EAKN,IAAI,eAAe;;EAKnB,KAAK;;EAKL,GAAG;;EAKH,QAAQ;;EAKR,KAAK,cAAc;;EAKnB,OAAO,eAAe;;MAKlB,UAAU;;EAKd,GAAG,mBAAmB,aAAa,OAAO,MAAM,WAAW,SAAS,YAAY;;EAKhF,eAAe,YAAY;;EAK3B,YAAY;;EAOZ;;EAKA,kBAAkB;;EAKlB,kBAAkB;;;;;;;EAUlB,UAAU;IAAU;IAAc;IAAgB;IAAiB;;;MAK/D;;EAKJ,OAAO,mBAAmB,OAAO,QAAQ;;EASzC,WAAW,YAAY,OAAO;;EAM9B;;EASA;;EASA,aAAa;;EAKb,WAAW,QAAQ;;EAUnB,kBAAkB;;;;;;;EAelB,aAAa,0BAA0B,cAAc;IAAY;;;EAKjE;;;;;EAQA,YAAY,OAAO;UAQX;UAeA;UASA;UAsBA;;UAqBA;;;;;cCpWG;;iBAWG,cAAc,qBAAqB,aAAa;;UAK/C;;EAEf;;EAEA,eAAe,WAAW;;;iBAkDZ,oBAAoB,iBAAiB;;;;;;;;iBA6FrC,SAAS,UAAS,eAAoB;;;;;;;;;;;cCvKzC;;;;KCFD;;cAGC;;UA4BI;EACf,aAAa;EACb,aAAa,cAAc;;;cAIhB;mBACM;;EAGL,YAAA,MAAM,cAAc,SAAS;;MAQrC,WAAW;;MAKX;;EAKJ,IAAI,UAAU;;EAOd,QAAQ,aAAa;;EAQrB,YAAY;UAIJ;;;iBASM,sBAAsB;;;;UCvFrB;;EAEf,cAAc,QAAQ,MAAM;;EAE5B;;EAEA,aAAa,QAAQ,mBAAmB;;;;;UCTzB;EACf;EACA;EACA;EACA;;;UAIe;;EAEf;;EAEA,MAAM;;EAEN,OAAO;;EAEP;;EAEA;;EAEA,MAAM;;EAEN,SAAS;;EAET;IAAa;IAAW;;;;UAIT;EACf;EACA;EACA;EACA;;;iBAiCc,YAAY,YAAY,KAAK;EAAsD;EAAW;;;iBAe9F,WAAW,OAAO,WAAW,QAAQ,WAAW;;;;UC3E/C;;EAEf,aAAa;;EAEb,WAAW;;EAEX,QAAQ,YAAY,cAAc;;EAElC;;EAEA,UAAU,YAAY;IAAQ;IAAW;;;;;;cCoB9B,mBAAmB;mBACb;mBACA;mBACA;mBACA;mBACA;mBACA;UACT;UACA;UACA;UACA;UACA;UACA;;;EAoCR,MAAM,QAAQ,aAAa,WAAW,gBAAgB,WAAW;;EAoBjE,eAAe,YAAY;;EAQ3B,kBAAkB,oBAAoB,eAAe;;EAQrD,UAAU,QAAQ,QAAQ;;EAM1B;;EAgCA,cAAc,QAAQ,MAAM;;EAU5B;;EAKA,aAAa,QAAQ,mBAAmB;;MAKpC;;EAKJ,eAAe,QAAQ,oBAAoB,MAAM;;EAKjD;;UAKQ;;;;;UCzLO;;EAEf,SAAS,QAAQ;;EAEjB,OAAO,QAAQ;;EAEf;;EAEA;;;;;;;;;;;;;;;iBAqDc,eAAe,gBAAgB,cAAc,uBAAuB,wBAAwB,UAAS,gBAAqB,eAAe;;;;;;;;KCrE7I;;KAGA;;UAGK;;EAEf,QAAQ;;;;;EAKR;;;UAIe;;EAEf;;EAEA;;;;;;EAMA;;;KAIU,mBAAmB,OAAO;;UAGrB;;EAEf;IAAa,MAAM;IAAmB,OAAO;;;EAE7C;;;;;;;;UASe;;WAEN;;EAET,KAAK,QAAQ;;WAEJ;;WAEA;;WAEA;;EAET,GAAG,MAAM,aAAa,UAAU;;;;;EAKhC,UAAU,SAAS;;EAEnB,YAAY;;EAEZ,WAAW;;;;QC9DL;YACI;IAER;;;;iBAMY,UAAU,qBAAqB,aAAa;;;;;iBAU5C,cAAc;;;;cCrBjB"}
|