tempest-react-sdk 0.20.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -61
- package/dist/sw.cjs +1 -1
- package/dist/sw.cjs.map +1 -1
- package/dist/sw.d.ts +26 -0
- package/dist/sw.js +90 -74
- package/dist/sw.js.map +1 -1
- package/dist/tempest-react-sdk.cjs +3 -3
- package/dist/tempest-react-sdk.cjs.map +1 -1
- package/dist/tempest-react-sdk.d.ts +489 -0
- package/dist/tempest-react-sdk.js +3404 -3153
- package/dist/tempest-react-sdk.js.map +1 -1
- package/package.json +2 -1
|
@@ -38,6 +38,7 @@ import { LabelHTMLAttributes } from 'react';
|
|
|
38
38
|
import { lazy } from 'react';
|
|
39
39
|
import { Link } from 'react-router-dom';
|
|
40
40
|
import { MemoryRouter } from 'react-router-dom';
|
|
41
|
+
import { MouseEvent as MouseEvent_2 } from 'react';
|
|
41
42
|
import { MouseEventHandler } from 'react';
|
|
42
43
|
import { Navigate } from 'react-router-dom';
|
|
43
44
|
import { NavigateOptions } from 'react-router-dom';
|
|
@@ -67,6 +68,7 @@ import { Table as Table_2 } from 'dexie';
|
|
|
67
68
|
import { TextareaHTMLAttributes } from 'react';
|
|
68
69
|
import { To } from 'react-router-dom';
|
|
69
70
|
import { ToggleEventHandler } from 'react';
|
|
71
|
+
import { TouchEvent as TouchEvent_2 } from 'react';
|
|
70
72
|
import { TouchEventHandler } from 'react';
|
|
71
73
|
import { TransitionEventHandler } from 'react';
|
|
72
74
|
import { UIEventHandler } from 'react';
|
|
@@ -580,6 +582,24 @@ export declare type BannerVariant = "info" | "success" | "warning" | "danger";
|
|
|
580
582
|
*/
|
|
581
583
|
export declare function bearingDeg(origin: Coordinate, destination: Coordinate): number;
|
|
582
584
|
|
|
585
|
+
/**
|
|
586
|
+
* The Chromium-only `beforeinstallprompt` event. iOS Safari never fires it —
|
|
587
|
+
* for those users the app falls back to manual "Add to Home Screen"
|
|
588
|
+
* instructions. Ported into the SDK so consumers get the type without a global
|
|
589
|
+
* augmentation.
|
|
590
|
+
*/
|
|
591
|
+
export declare interface BeforeInstallPromptEvent extends Event {
|
|
592
|
+
/** Platforms the prompt can target (e.g. `["web", "android"]`). */
|
|
593
|
+
readonly platforms: readonly string[];
|
|
594
|
+
/** Resolves once the user accepts or dismisses the prompt. */
|
|
595
|
+
readonly userChoice: Promise<{
|
|
596
|
+
outcome: "accepted" | "dismissed";
|
|
597
|
+
platform: string;
|
|
598
|
+
}>;
|
|
599
|
+
/** Shows the native install prompt. */
|
|
600
|
+
prompt: () => Promise<void>;
|
|
601
|
+
}
|
|
602
|
+
|
|
583
603
|
/**
|
|
584
604
|
* Fixed-bottom mobile tab bar. 3–5 items recommended. Pair with
|
|
585
605
|
* `<Show below="md">` to render only on mobile.
|
|
@@ -723,6 +743,16 @@ export declare function buildApiError(status: number, body: unknown, headers?: H
|
|
|
723
743
|
get(name: string): string | null;
|
|
724
744
|
}, sentRequestId?: string): ApiError;
|
|
725
745
|
|
|
746
|
+
/**
|
|
747
|
+
* Builds an `intent://` URL that re-opens the current page inside Chrome on
|
|
748
|
+
* Android. When Chrome is missing, the fallback URL points to the Play Store so
|
|
749
|
+
* the user can still recover. Returns `null` outside Android.
|
|
750
|
+
*
|
|
751
|
+
* @returns The `intent://` URL, or `null` when not on Android or without a DOM.
|
|
752
|
+
* @see https://developer.chrome.com/docs/multidevice/android/intents
|
|
753
|
+
*/
|
|
754
|
+
export declare function buildOpenInChromeIntent(): string | null;
|
|
755
|
+
|
|
726
756
|
/**
|
|
727
757
|
* Primary action button with variants, sizes and a loading state that
|
|
728
758
|
* preserves layout via an absolutely-positioned spinner.
|
|
@@ -1531,6 +1561,44 @@ export declare interface CreateLoggerOptions {
|
|
|
1531
1561
|
*/
|
|
1532
1562
|
export declare function createOfflineStore<TItem, TKey extends string | number = string>(config: OfflineStoreConfig<TItem>): OfflineStore<TItem, TKey>;
|
|
1533
1563
|
|
|
1564
|
+
/**
|
|
1565
|
+
* Create an offline-first sync engine over an IndexedDB outbox.
|
|
1566
|
+
*
|
|
1567
|
+
* The engine drains queued mutations to the server (`deliver`) and pulls the
|
|
1568
|
+
* server delta back (`pullPage` + `applyRemote`), advancing a watermark so each
|
|
1569
|
+
* run only fetches what changed. `flush` is single-flight and skips cleanly
|
|
1570
|
+
* while offline; failed deliveries stay queued with their attempt count bumped.
|
|
1571
|
+
*
|
|
1572
|
+
* Dexie is an **optional peer dependency** (via {@link createOfflineStore}) —
|
|
1573
|
+
* install it (`npm i dexie`) when you use this engine.
|
|
1574
|
+
*
|
|
1575
|
+
* @typeParam TPayload - Record snapshot carried by outbox entries.
|
|
1576
|
+
* @typeParam TRemote - Server item shape returned by `pullPage`.
|
|
1577
|
+
* @param config - Transport callbacks + outbox/watermark configuration.
|
|
1578
|
+
* @returns The sync handle (`enqueue`, `flush`, `pendingCount`, …).
|
|
1579
|
+
*
|
|
1580
|
+
* @example
|
|
1581
|
+
* const sync = createOfflineSync<Note, NoteDto>({
|
|
1582
|
+
* databaseName: "NotesOutbox",
|
|
1583
|
+
* watermark: { storageKey: "notes.watermark" },
|
|
1584
|
+
* deliver: async (entry) => {
|
|
1585
|
+
* if (entry.op === "delete") return api.remove(entry.recordId);
|
|
1586
|
+
* await api.upsert(entry.recordId, entry.payload!);
|
|
1587
|
+
* },
|
|
1588
|
+
* pullPage: async (since, cursor) => {
|
|
1589
|
+
* const page = await api.changes(since, cursor);
|
|
1590
|
+
* return { items: page.items, nextCursor: page.next, serverTime: page.now };
|
|
1591
|
+
* },
|
|
1592
|
+
* applyRemote: async (dto) => {
|
|
1593
|
+
* if (dto.deleted) return localStore.remove(dto.id);
|
|
1594
|
+
* await localStore.save(fromDto(dto));
|
|
1595
|
+
* },
|
|
1596
|
+
* });
|
|
1597
|
+
* await sync.enqueue("create", note.id, note);
|
|
1598
|
+
* await sync.flush("after-mutation");
|
|
1599
|
+
*/
|
|
1600
|
+
export declare function createOfflineSync<TPayload = unknown, TRemote = unknown>(config: OfflineSyncConfig<TPayload, TRemote>): OfflineSync<TPayload>;
|
|
1601
|
+
|
|
1534
1602
|
/**
|
|
1535
1603
|
* Build a {@link RoutingBackend} backed by an OSRM server **you host**. OSRM
|
|
1536
1604
|
* only serves a driving profile, so motorcycle/bus durations are derived by
|
|
@@ -3368,6 +3436,17 @@ export declare interface InstallButtonProps extends Omit<ButtonProps, "onClick"
|
|
|
3368
3436
|
onResult?: (outcome: InstallOutcome) => void;
|
|
3369
3437
|
}
|
|
3370
3438
|
|
|
3439
|
+
/**
|
|
3440
|
+
* Strategy the UI should use to install the app:
|
|
3441
|
+
*
|
|
3442
|
+
* - `"native"`: trigger `BeforeInstallPromptEvent.prompt()`.
|
|
3443
|
+
* - `"ios"`: show iOS Safari Share → Add to Home Screen instructions.
|
|
3444
|
+
* - `"manual"`: show generic browser-menu instructions (Chromium forks that
|
|
3445
|
+
* strip the prompt API, plus the timeout fallback when no event arrives).
|
|
3446
|
+
* - `"none"`: nothing to offer (already installed or unsupported runtime).
|
|
3447
|
+
*/
|
|
3448
|
+
export declare type InstallMethod = "native" | "ios" | "manual" | "none";
|
|
3449
|
+
|
|
3371
3450
|
/**
|
|
3372
3451
|
* Install a `notificationclick` handler that focuses an existing client when
|
|
3373
3452
|
* possible and falls back to opening a new window.
|
|
@@ -3447,6 +3526,22 @@ export declare function installSkipWaitingListener(): void;
|
|
|
3447
3526
|
|
|
3448
3527
|
export declare type InterpolationValues = Record<string, string | number>;
|
|
3449
3528
|
|
|
3529
|
+
/**
|
|
3530
|
+
* Detects any Android browser.
|
|
3531
|
+
*
|
|
3532
|
+
* @returns `true` when the user agent reports Android.
|
|
3533
|
+
*/
|
|
3534
|
+
export declare function isAndroid(): boolean;
|
|
3535
|
+
|
|
3536
|
+
/**
|
|
3537
|
+
* Detects Android browsers that ship a Chromium fork with the
|
|
3538
|
+
* `beforeinstallprompt` event stripped or unreliable. Those users must install
|
|
3539
|
+
* via the browser menu manually, identical to iOS Safari.
|
|
3540
|
+
*
|
|
3541
|
+
* @returns `true` when running on such an Android browser.
|
|
3542
|
+
*/
|
|
3543
|
+
export declare function isAndroidWithoutPromptApi(): boolean;
|
|
3544
|
+
|
|
3450
3545
|
/**
|
|
3451
3546
|
* Type guard for the {@link ApiError} shape. Matches both {@link TempestApiError}
|
|
3452
3547
|
* instances and plain objects carrying `status` + `detail`.
|
|
@@ -3501,6 +3596,14 @@ export declare function isDefined<T>(value: T | null | undefined): value is T;
|
|
|
3501
3596
|
*/
|
|
3502
3597
|
export declare function isEmpty(value: unknown): boolean;
|
|
3503
3598
|
|
|
3599
|
+
/**
|
|
3600
|
+
* Detects iOS / iPadOS Safari, including modern iPads that report `MacIntel`
|
|
3601
|
+
* plus multi-touch instead of an `iPad` user agent.
|
|
3602
|
+
*
|
|
3603
|
+
* @returns `true` when running on iOS/iPadOS.
|
|
3604
|
+
*/
|
|
3605
|
+
export declare function isIOS(): boolean;
|
|
3606
|
+
|
|
3504
3607
|
/**
|
|
3505
3608
|
* Return true when the JWT's `exp` claim is in the past (or missing).
|
|
3506
3609
|
*
|
|
@@ -3550,6 +3653,15 @@ export declare function isPushSupported(): boolean;
|
|
|
3550
3653
|
/** True when the Web Share API is available in this environment. */
|
|
3551
3654
|
export declare function isShareSupported(): boolean;
|
|
3552
3655
|
|
|
3656
|
+
/**
|
|
3657
|
+
* Reports whether the app is running as an installed PWA (Android Chrome, iOS,
|
|
3658
|
+
* or desktop). Use it to suppress install CTAs once the user is already in the
|
|
3659
|
+
* standalone shell.
|
|
3660
|
+
*
|
|
3661
|
+
* @returns `true` when the display mode is standalone or iOS reports standalone.
|
|
3662
|
+
*/
|
|
3663
|
+
export declare function isStandalone(): boolean;
|
|
3664
|
+
|
|
3553
3665
|
/**
|
|
3554
3666
|
* Type guard asserting a value is a string primitive.
|
|
3555
3667
|
*
|
|
@@ -3761,6 +3873,27 @@ export declare interface LoggerSink {
|
|
|
3761
3873
|
|
|
3762
3874
|
export declare type LogLevel = "debug" | "info" | "warn" | "error";
|
|
3763
3875
|
|
|
3876
|
+
/**
|
|
3877
|
+
* DOM event handlers produced by {@link useLongPressHandlers}, ready to spread
|
|
3878
|
+
* onto a JSX element (`<div {...handlers}>`).
|
|
3879
|
+
*/
|
|
3880
|
+
export declare interface LongPressHandlers {
|
|
3881
|
+
/** Starts the hold timer on mouse press. */
|
|
3882
|
+
onMouseDown: (event: MouseEvent_2) => void;
|
|
3883
|
+
/** Cancels the pending hold when the mouse is released. */
|
|
3884
|
+
onMouseUp: () => void;
|
|
3885
|
+
/** Cancels the pending hold when the pointer leaves the element. */
|
|
3886
|
+
onMouseLeave: () => void;
|
|
3887
|
+
/** Starts the hold timer on touch start. */
|
|
3888
|
+
onTouchStart: (event: TouchEvent_2) => void;
|
|
3889
|
+
/** Cancels the pending hold when the touch ends. */
|
|
3890
|
+
onTouchEnd: () => void;
|
|
3891
|
+
/** Cancels the pending hold when the finger moves. */
|
|
3892
|
+
onTouchMove: () => void;
|
|
3893
|
+
/** Fires the long-press immediately (desktop right-click parity). */
|
|
3894
|
+
onContextMenu: (event: MouseEvent_2) => void;
|
|
3895
|
+
}
|
|
3896
|
+
|
|
3764
3897
|
/**
|
|
3765
3898
|
* Memoize only the most recent call of `fn`, keyed by shallow-equal arguments.
|
|
3766
3899
|
*
|
|
@@ -4226,6 +4359,85 @@ export declare interface OfflineStoreConfig<TItem> {
|
|
|
4226
4359
|
ownerField?: keyof TItem & string;
|
|
4227
4360
|
}
|
|
4228
4361
|
|
|
4362
|
+
/**
|
|
4363
|
+
* Offline-first sync engine: a durable outbox plus a paginated delta pull.
|
|
4364
|
+
*
|
|
4365
|
+
* @typeParam TPayload - Record snapshot carried by outbox entries.
|
|
4366
|
+
*/
|
|
4367
|
+
export declare interface OfflineSync<TPayload> {
|
|
4368
|
+
/**
|
|
4369
|
+
* Queue a mutation. Returns the generated entry id.
|
|
4370
|
+
*
|
|
4371
|
+
* @param op - The mutation kind.
|
|
4372
|
+
* @param recordId - Primary key of the affected record.
|
|
4373
|
+
* @param payload - Record snapshot (for `create`/`update`).
|
|
4374
|
+
*/
|
|
4375
|
+
enqueue: (op: OutboxOp, recordId: string, payload?: TPayload) => Promise<string>;
|
|
4376
|
+
/**
|
|
4377
|
+
* Run a full sync (drain the outbox, then pull the delta). Concurrent
|
|
4378
|
+
* calls share one in-flight promise, so triggers never overlap.
|
|
4379
|
+
*
|
|
4380
|
+
* @param trigger - Label for why the run happened. Default `"manual"`.
|
|
4381
|
+
*/
|
|
4382
|
+
flush: (trigger?: SyncTrigger) => Promise<SyncRunSummary>;
|
|
4383
|
+
/** Number of mutations still queued. */
|
|
4384
|
+
pendingCount: () => Promise<number>;
|
|
4385
|
+
/** The queued mutations in FIFO order. */
|
|
4386
|
+
listPending: () => Promise<OutboxEntry<TPayload>[]>;
|
|
4387
|
+
/** Drop every queued mutation (e.g. on logout). */
|
|
4388
|
+
clearOutbox: () => Promise<void>;
|
|
4389
|
+
/** Reset the pull watermark (e.g. on logout / account switch). */
|
|
4390
|
+
resetWatermark: () => void;
|
|
4391
|
+
}
|
|
4392
|
+
|
|
4393
|
+
/**
|
|
4394
|
+
* Configuration for {@link createOfflineSync}.
|
|
4395
|
+
*
|
|
4396
|
+
* The engine owns the outbox, the single-flight flush, the offline guard, the
|
|
4397
|
+
* paginated pull loop and the watermark; the three transport callbacks
|
|
4398
|
+
* (`deliver`, `pullPage`, `applyRemote`) are where the app plugs in its own
|
|
4399
|
+
* endpoints, record shape and conflict resolution.
|
|
4400
|
+
*
|
|
4401
|
+
* @typeParam TPayload - Record snapshot carried by outbox entries.
|
|
4402
|
+
* @typeParam TRemote - Server item shape returned by `pullPage`.
|
|
4403
|
+
*/
|
|
4404
|
+
export declare interface OfflineSyncConfig<TPayload, TRemote> {
|
|
4405
|
+
/** IndexedDB database name for the outbox (kept separate per queue). */
|
|
4406
|
+
databaseName: string;
|
|
4407
|
+
/** Outbox object-store name. Default `"outbox"`. */
|
|
4408
|
+
tableName?: string;
|
|
4409
|
+
/** Outbox schema version. Default `1`. */
|
|
4410
|
+
version?: number;
|
|
4411
|
+
/** Prefix for generated entry ids. Default `"outbox"`. */
|
|
4412
|
+
idPrefix?: string;
|
|
4413
|
+
/**
|
|
4414
|
+
* Deliver one queued mutation to the server. Throwing keeps the entry
|
|
4415
|
+
* queued (its `attempts`/`lastError` are bumped) for the next run.
|
|
4416
|
+
*/
|
|
4417
|
+
deliver: (entry: OutboxEntry<TPayload>) => Promise<void>;
|
|
4418
|
+
/** Fetch one page of the server delta since `since`, from `cursor`. */
|
|
4419
|
+
pullPage: (since: string | null, cursor: string | null) => Promise<PullPage<TRemote>>;
|
|
4420
|
+
/**
|
|
4421
|
+
* Merge one pulled item into the local store. The app owns conflict
|
|
4422
|
+
* resolution here (e.g. last-write-wins, keeping newer local pending
|
|
4423
|
+
* edits, resolving tombstones and downloading blobs).
|
|
4424
|
+
*/
|
|
4425
|
+
applyRemote: (item: TRemote) => Promise<void>;
|
|
4426
|
+
/** Watermark persistence, or `{ storageKey }` for a `localStorage` default. */
|
|
4427
|
+
watermark: WatermarkStore | {
|
|
4428
|
+
storageKey: string;
|
|
4429
|
+
};
|
|
4430
|
+
/** Called after an entry is delivered and acked. */
|
|
4431
|
+
onEntryDelivered?: (entry: OutboxEntry<TPayload>) => void | Promise<void>;
|
|
4432
|
+
/** Called after an entry fails delivery (it stays queued). */
|
|
4433
|
+
onEntryFailed?: (entry: OutboxEntry<TPayload>, error: unknown) => void | Promise<void>;
|
|
4434
|
+
/**
|
|
4435
|
+
* Connectivity check. Default reads `navigator.onLine` (always online in
|
|
4436
|
+
* non-browser environments). When it returns `false`, `flush` is skipped.
|
|
4437
|
+
*/
|
|
4438
|
+
isOnline?: () => boolean;
|
|
4439
|
+
}
|
|
4440
|
+
|
|
4229
4441
|
/** Offset-paginated response envelope (fastapi-pagination `Page[T]`). */
|
|
4230
4442
|
export declare interface OffsetPage<T> {
|
|
4231
4443
|
/** The rows for the current page. */
|
|
@@ -4314,6 +4526,39 @@ export declare interface OSRMBackendOptions {
|
|
|
4314
4526
|
modeDurationFactors?: Partial<Record<TravelMode, number>>;
|
|
4315
4527
|
}
|
|
4316
4528
|
|
|
4529
|
+
/**
|
|
4530
|
+
* A single queued mutation.
|
|
4531
|
+
*
|
|
4532
|
+
* @typeParam TPayload - The record snapshot shape carried by
|
|
4533
|
+
* `create`/`update` entries (omitted for `delete`).
|
|
4534
|
+
*/
|
|
4535
|
+
export declare interface OutboxEntry<TPayload = unknown> {
|
|
4536
|
+
/** Stable per-entry id (generated with {@link randomId}). */
|
|
4537
|
+
id: string;
|
|
4538
|
+
/** The mutation kind. */
|
|
4539
|
+
op: OutboxOp;
|
|
4540
|
+
/** Primary key of the record the mutation targets. */
|
|
4541
|
+
recordId: string;
|
|
4542
|
+
/** Epoch milliseconds when the mutation was queued. */
|
|
4543
|
+
enqueuedAt: number;
|
|
4544
|
+
/** How many delivery attempts have been made so far. */
|
|
4545
|
+
attempts: number;
|
|
4546
|
+
/** Last delivery error message, kept for UI/debug. */
|
|
4547
|
+
lastError?: string;
|
|
4548
|
+
/** Record snapshot for `create`/`update`. Omitted for `delete`. */
|
|
4549
|
+
payload?: TPayload;
|
|
4550
|
+
}
|
|
4551
|
+
|
|
4552
|
+
/**
|
|
4553
|
+
* Mutation kinds queued in the outbox.
|
|
4554
|
+
*
|
|
4555
|
+
* `create`/`update` carry a snapshot of the record; `delete` needs only the
|
|
4556
|
+
* record id. The distinction between `create` and `update` is advisory — the
|
|
4557
|
+
* engine treats both as "deliver this record" and leaves the create-vs-update
|
|
4558
|
+
* decision to the app's `deliver` callback (a `PUT` upsert usually ignores it).
|
|
4559
|
+
*/
|
|
4560
|
+
export declare type OutboxOp = "create" | "update" | "delete";
|
|
4561
|
+
|
|
4317
4562
|
export { Outlet }
|
|
4318
4563
|
|
|
4319
4564
|
/**
|
|
@@ -4657,6 +4902,23 @@ export declare type ProgressVariant = "primary" | "success" | "warning" | "dange
|
|
|
4657
4902
|
*/
|
|
4658
4903
|
export declare function projectMercator(coord: Coordinate): MercatorPoint;
|
|
4659
4904
|
|
|
4905
|
+
/**
|
|
4906
|
+
* One page of the server delta pull.
|
|
4907
|
+
*
|
|
4908
|
+
* @typeParam TRemote - The server-side item shape.
|
|
4909
|
+
*/
|
|
4910
|
+
export declare interface PullPage<TRemote> {
|
|
4911
|
+
/** Items changed since the watermark, in this page. */
|
|
4912
|
+
items: TRemote[];
|
|
4913
|
+
/** Cursor for the next page, or `null` when this is the last page. */
|
|
4914
|
+
nextCursor: string | null;
|
|
4915
|
+
/**
|
|
4916
|
+
* Server clock to persist as the next watermark once the whole delta is
|
|
4917
|
+
* applied. `null` leaves the watermark unchanged.
|
|
4918
|
+
*/
|
|
4919
|
+
serverTime: string | null;
|
|
4920
|
+
}
|
|
4921
|
+
|
|
4660
4922
|
/**
|
|
4661
4923
|
* Service-worker context helpers for handling `push` and `notificationclick`
|
|
4662
4924
|
* events. Import these inside your own `sw.ts` — they expect to run in the
|
|
@@ -4847,6 +5109,11 @@ export declare interface RefreshIndicatorProps {
|
|
|
4847
5109
|
* app keeps full control over the SW file — this helper only handles the
|
|
4848
5110
|
* boilerplate around `register()` and `updatefound`.
|
|
4849
5111
|
*
|
|
5112
|
+
* With `autoUpdate` enabled it additionally polls `registration.update()` on
|
|
5113
|
+
* an interval and (by default) reloads the page when a freshly activated worker
|
|
5114
|
+
* takes control — a framework-agnostic equivalent of `vite-plugin-pwa`'s
|
|
5115
|
+
* auto-update client, implemented directly on `navigator.serviceWorker`.
|
|
5116
|
+
*
|
|
4850
5117
|
* @returns The registration when it succeeds, or `null` when unsupported.
|
|
4851
5118
|
*/
|
|
4852
5119
|
export declare function registerServiceWorker(options: RegisterServiceWorkerOptions): Promise<ServiceWorkerRegistration | null>;
|
|
@@ -4866,6 +5133,27 @@ export declare interface RegisterServiceWorkerOptions {
|
|
|
4866
5133
|
onUpdate?: (waiting: ServiceWorker, registration: ServiceWorkerRegistration) => void;
|
|
4867
5134
|
/** Called on registration failure. */
|
|
4868
5135
|
onError?: (error: unknown) => void;
|
|
5136
|
+
/**
|
|
5137
|
+
* When `true`, poll the server for a fresh service worker on an interval
|
|
5138
|
+
* (see {@link RegisterServiceWorkerOptions.updateIntervalMs}) and, unless
|
|
5139
|
+
* {@link RegisterServiceWorkerOptions.reloadOnActivate} is disabled, reload
|
|
5140
|
+
* the page as soon as a new worker takes control. Mirrors the auto-update
|
|
5141
|
+
* behaviour of `vite-plugin-pwa` without depending on it. Default `false`.
|
|
5142
|
+
*/
|
|
5143
|
+
autoUpdate?: boolean;
|
|
5144
|
+
/**
|
|
5145
|
+
* How often, in ms, to call `registration.update()` while `autoUpdate` is
|
|
5146
|
+
* on. Browsers already re-check roughly every 24h; an hourly poll keeps
|
|
5147
|
+
* long-lived sessions current without flooding the network. Default
|
|
5148
|
+
* `3600000` (1 hour).
|
|
5149
|
+
*/
|
|
5150
|
+
updateIntervalMs?: number;
|
|
5151
|
+
/**
|
|
5152
|
+
* When `autoUpdate` is on, reload the page once a new worker takes control
|
|
5153
|
+
* (`controllerchange`), guarded against reload loops. Set to `false` to
|
|
5154
|
+
* keep polling but leave the reload to the host app. Default `true`.
|
|
5155
|
+
*/
|
|
5156
|
+
reloadOnActivate?: boolean;
|
|
4869
5157
|
}
|
|
4870
5158
|
|
|
4871
5159
|
/**
|
|
@@ -5243,6 +5531,33 @@ export declare interface SentryLike {
|
|
|
5243
5531
|
*/
|
|
5244
5532
|
export declare function share(payload: SharePayload): Promise<ShareResult>;
|
|
5245
5533
|
|
|
5534
|
+
/**
|
|
5535
|
+
* Try the Web Share API with the given `Blob` as a file; fall back to a
|
|
5536
|
+
* download anchor when the browser cannot share files (desktop Firefox, older
|
|
5537
|
+
* iOS Safari, etc.).
|
|
5538
|
+
*
|
|
5539
|
+
* A companion to {@link share} for the common "export a generated artifact"
|
|
5540
|
+
* flow: on mobile it opens the native share sheet, and everywhere else it
|
|
5541
|
+
* triggers a plain download. Returns early when the user shares or cancels the
|
|
5542
|
+
* dialog; otherwise it downloads.
|
|
5543
|
+
*
|
|
5544
|
+
* @param blob - The binary payload to share or download.
|
|
5545
|
+
* @param fileName - The file name presented to the user.
|
|
5546
|
+
* @param options - Optional `title` for the share dialog.
|
|
5547
|
+
* @returns A promise that resolves once the share or download completes.
|
|
5548
|
+
*
|
|
5549
|
+
* @example
|
|
5550
|
+
* const zip = new Blob([bytes], { type: "application/zip" });
|
|
5551
|
+
* await shareOrDownloadBlob(zip, "export.zip");
|
|
5552
|
+
*/
|
|
5553
|
+
export declare function shareOrDownloadBlob(blob: Blob, fileName: string, options?: ShareOrDownloadOptions): Promise<void>;
|
|
5554
|
+
|
|
5555
|
+
/** Options for {@link shareOrDownloadBlob}. */
|
|
5556
|
+
export declare interface ShareOrDownloadOptions {
|
|
5557
|
+
/** Title passed to the Web Share dialog. Defaults to the file name. */
|
|
5558
|
+
title?: string;
|
|
5559
|
+
}
|
|
5560
|
+
|
|
5246
5561
|
export declare interface SharePayload {
|
|
5247
5562
|
title?: string;
|
|
5248
5563
|
text?: string;
|
|
@@ -5574,6 +5889,26 @@ export declare interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputE
|
|
|
5574
5889
|
wrapperClassName?: string;
|
|
5575
5890
|
}
|
|
5576
5891
|
|
|
5892
|
+
/** Outcome of a single {@link OfflineSync.flush} run. */
|
|
5893
|
+
export declare interface SyncRunSummary {
|
|
5894
|
+
/** The trigger passed to `flush`. */
|
|
5895
|
+
trigger: SyncTrigger;
|
|
5896
|
+
/** Entries delivered to the server this run. */
|
|
5897
|
+
succeeded: number;
|
|
5898
|
+
/** Entries that failed and stay queued for the next run. */
|
|
5899
|
+
failed: number;
|
|
5900
|
+
/** Total wall-clock milliseconds the run took. */
|
|
5901
|
+
durationMs: number;
|
|
5902
|
+
/** `true` when the run was skipped because the device was offline. */
|
|
5903
|
+
skipped: boolean;
|
|
5904
|
+
}
|
|
5905
|
+
|
|
5906
|
+
/**
|
|
5907
|
+
* Why a sync run was triggered. The listed values are the common ones; any
|
|
5908
|
+
* string is accepted so apps can add their own telemetry labels.
|
|
5909
|
+
*/
|
|
5910
|
+
export declare type SyncTrigger = "boot" | "online-event" | "after-mutation" | "manual" | "interval" | (string & {});
|
|
5911
|
+
|
|
5577
5912
|
export declare interface TabItem {
|
|
5578
5913
|
id: string;
|
|
5579
5914
|
label: ReactNode;
|
|
@@ -6725,6 +7060,75 @@ export declare function useI18n(): I18nContextValue;
|
|
|
6725
7060
|
*/
|
|
6726
7061
|
export declare function useIdle(timeout?: number): boolean;
|
|
6727
7062
|
|
|
7063
|
+
/**
|
|
7064
|
+
* React hook that resolves how (and whether) to offer PWA installation.
|
|
7065
|
+
*
|
|
7066
|
+
* It caches the `beforeinstallprompt` event, detects iOS/iPadOS, detects
|
|
7067
|
+
* Android Chromium forks that lack the prompt API, detects standalone display
|
|
7068
|
+
* mode, and applies a decline cooldown persisted in `localStorage`. The
|
|
7069
|
+
* resulting `method` tells the UI which install affordance to render.
|
|
7070
|
+
*
|
|
7071
|
+
* The decline persistence is pluggable through
|
|
7072
|
+
* {@link UseInstallPromptOptions.declineStorageKey} and
|
|
7073
|
+
* {@link UseInstallPromptOptions.declineCooldownMs} — no app-specific storage
|
|
7074
|
+
* layer is required, and it is SSR-guarded.
|
|
7075
|
+
*
|
|
7076
|
+
* @param options - Optional storage key, cooldown, and fallback-delay tuning.
|
|
7077
|
+
* @returns The install state plus `install()` and `recordDecline()` actions.
|
|
7078
|
+
*
|
|
7079
|
+
* @example
|
|
7080
|
+
* const { method, install } = useInstallPrompt();
|
|
7081
|
+
* if (method === "native") return <button onClick={install}>Install</button>;
|
|
7082
|
+
*/
|
|
7083
|
+
export declare function useInstallPrompt(options?: UseInstallPromptOptions): UseInstallPromptResult;
|
|
7084
|
+
|
|
7085
|
+
/** Options for {@link useInstallPrompt}. */
|
|
7086
|
+
export declare interface UseInstallPromptOptions {
|
|
7087
|
+
/**
|
|
7088
|
+
* `localStorage` key used to persist the decline timestamp. Defaults to
|
|
7089
|
+
* `"tempest:install-declined-at"`.
|
|
7090
|
+
*/
|
|
7091
|
+
declineStorageKey?: string;
|
|
7092
|
+
/**
|
|
7093
|
+
* How long, in ms, the install CTA stays hidden after the user declines.
|
|
7094
|
+
* Defaults to 7 days.
|
|
7095
|
+
*/
|
|
7096
|
+
declineCooldownMs?: number;
|
|
7097
|
+
/**
|
|
7098
|
+
* How long, in ms, to wait for a `beforeinstallprompt` event before
|
|
7099
|
+
* resolving to the `"manual"` method. Defaults to `3000`.
|
|
7100
|
+
*/
|
|
7101
|
+
manualFallbackDelayMs?: number;
|
|
7102
|
+
}
|
|
7103
|
+
|
|
7104
|
+
/** State returned by {@link useInstallPrompt}. */
|
|
7105
|
+
export declare interface UseInstallPromptResult {
|
|
7106
|
+
/** The cached `beforeinstallprompt` event, or `null` when unavailable. */
|
|
7107
|
+
deferredPrompt: BeforeInstallPromptEvent | null;
|
|
7108
|
+
/** True when the app can be installed through any supported method. */
|
|
7109
|
+
canInstall: boolean;
|
|
7110
|
+
/** True when running on iOS/iPadOS Safari. */
|
|
7111
|
+
isIOS: boolean;
|
|
7112
|
+
/** True when already running as an installed PWA. */
|
|
7113
|
+
isStandalone: boolean;
|
|
7114
|
+
/** True when the browser is an Android Chromium fork with no prompt API. */
|
|
7115
|
+
isManualAndroid: boolean;
|
|
7116
|
+
/** True when no `beforeinstallprompt` arrived within the timeout window. */
|
|
7117
|
+
promptTimedOut: boolean;
|
|
7118
|
+
/** The resolved install strategy the UI should follow. */
|
|
7119
|
+
method: InstallMethod;
|
|
7120
|
+
/** An `intent://` URL to re-open the page in Chrome on Android, else `null`. */
|
|
7121
|
+
openInChromeIntent: string | null;
|
|
7122
|
+
/**
|
|
7123
|
+
* Triggers the native prompt.
|
|
7124
|
+
*
|
|
7125
|
+
* @returns `true` when the user accepted the install, `false` otherwise.
|
|
7126
|
+
*/
|
|
7127
|
+
install: () => Promise<boolean>;
|
|
7128
|
+
/** Records that the user declined the CTA, starting the cooldown window. */
|
|
7129
|
+
recordDecline: () => void;
|
|
7130
|
+
}
|
|
7131
|
+
|
|
6728
7132
|
/**
|
|
6729
7133
|
* Track whether the referenced element intersects the viewport. Useful for
|
|
6730
7134
|
* lazy-loading images, "load more" sentinels, and animation triggers.
|
|
@@ -6819,6 +7223,52 @@ export { useLocation }
|
|
|
6819
7223
|
*/
|
|
6820
7224
|
export declare function useLongPress<T extends HTMLElement>(ref: RefObject<T | null>, fn: () => void, options?: UseLongPressOptions): void;
|
|
6821
7225
|
|
|
7226
|
+
/**
|
|
7227
|
+
* Returns DOM event handlers that detect a long press (touch or mouse hold)
|
|
7228
|
+
* and invoke `onLongPress` once after `delayMs`.
|
|
7229
|
+
*
|
|
7230
|
+
* Cancels on touch movement or pointer release. Also wires `contextmenu` to
|
|
7231
|
+
* fire `onLongPress` immediately so a right-click on desktop opens selection
|
|
7232
|
+
* mode the same way an Android long-press does on mobile.
|
|
7233
|
+
*
|
|
7234
|
+
* The hook does not `preventDefault` on the underlying click — the consumer
|
|
7235
|
+
* decides whether the subsequent click should still fire. Track that with the
|
|
7236
|
+
* returned `wasLongPress()` guard to tell "long-press fired" apart from a
|
|
7237
|
+
* "regular click".
|
|
7238
|
+
*
|
|
7239
|
+
* Unlike {@link useLongPress}, which attaches pointer listeners to a `ref`,
|
|
7240
|
+
* this variant returns handler props you spread directly onto an element and
|
|
7241
|
+
* exposes a `wasLongPress()` guard.
|
|
7242
|
+
*
|
|
7243
|
+
* @param onLongPress - Callback invoked once the hold threshold is reached.
|
|
7244
|
+
* @param options - Optional `delayMs` and `disabled` flags.
|
|
7245
|
+
* @returns The spreadable handlers plus a `wasLongPress()` guard.
|
|
7246
|
+
*
|
|
7247
|
+
* @example
|
|
7248
|
+
* const longPress = useLongPressHandlers(() => enterSelectionMode(), { delayMs: 600 });
|
|
7249
|
+
* <button {...longPress} onClick={() => { if (!longPress.wasLongPress()) navigate(); }}>
|
|
7250
|
+
* Item
|
|
7251
|
+
* </button>
|
|
7252
|
+
*/
|
|
7253
|
+
export declare function useLongPressHandlers(onLongPress: () => void, options?: UseLongPressHandlersOptions): UseLongPressHandlersResult;
|
|
7254
|
+
|
|
7255
|
+
/** Options accepted by {@link useLongPressHandlers}. */
|
|
7256
|
+
export declare interface UseLongPressHandlersOptions {
|
|
7257
|
+
/** Hold duration in ms before `onLongPress` fires. Defaults to `500`. */
|
|
7258
|
+
delayMs?: number;
|
|
7259
|
+
/** When `true`, the hook is inert and every handler is a no-op. */
|
|
7260
|
+
disabled?: boolean;
|
|
7261
|
+
}
|
|
7262
|
+
|
|
7263
|
+
/** Return shape of {@link useLongPressHandlers}. */
|
|
7264
|
+
export declare type UseLongPressHandlersResult = LongPressHandlers & {
|
|
7265
|
+
/**
|
|
7266
|
+
* Reads whether the most recent interaction fired a long-press. Use it in
|
|
7267
|
+
* the element's `onClick` to suppress the click that follows a long-press.
|
|
7268
|
+
*/
|
|
7269
|
+
wasLongPress: () => boolean;
|
|
7270
|
+
};
|
|
7271
|
+
|
|
6822
7272
|
export declare interface UseLongPressOptions {
|
|
6823
7273
|
/** Press duration in ms. Default `500`. */
|
|
6824
7274
|
delay?: number;
|
|
@@ -7719,6 +8169,19 @@ export declare interface VisuallyHiddenProps extends HTMLAttributes<HTMLElement>
|
|
|
7719
8169
|
as?: keyof JSX_2.IntrinsicElements;
|
|
7720
8170
|
}
|
|
7721
8171
|
|
|
8172
|
+
/**
|
|
8173
|
+
* Pluggable persistence for the pull watermark (the "changed since" cursor).
|
|
8174
|
+
* Pass an object with a `storageKey` to use a `localStorage`-backed default.
|
|
8175
|
+
*/
|
|
8176
|
+
export declare interface WatermarkStore {
|
|
8177
|
+
/** Read the current watermark, or `null` when none is stored. */
|
|
8178
|
+
get: () => string | null;
|
|
8179
|
+
/** Persist a new watermark. */
|
|
8180
|
+
set: (value: string) => void;
|
|
8181
|
+
/** Drop the watermark (e.g. on logout / account switch). */
|
|
8182
|
+
clear: () => void;
|
|
8183
|
+
}
|
|
8184
|
+
|
|
7722
8185
|
/**
|
|
7723
8186
|
* Browser-side Web Push helper. Wraps `Notification.requestPermission`,
|
|
7724
8187
|
* `pushManager.subscribe`, and the corresponding teardown. Transport is up to
|
|
@@ -7843,6 +8306,32 @@ export declare type WithSelectors<S> = S extends {
|
|
|
7843
8306
|
*/
|
|
7844
8307
|
export declare function withTimeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>;
|
|
7845
8308
|
|
|
8309
|
+
/**
|
|
8310
|
+
* Write a minimal single-sheet Office Open XML (`.xlsx`) workbook and return
|
|
8311
|
+
* its bytes. No extra dependency beyond `fflate` — the archive is assembled and
|
|
8312
|
+
* deflated in-process.
|
|
8313
|
+
*
|
|
8314
|
+
* The output is UTF-8 throughout, so accents round-trip in
|
|
8315
|
+
* Excel/LibreOffice/Google Sheets without the BOM-detection fragility that
|
|
8316
|
+
* plagues CSV exports. The XML stays compact: inline strings (no shared-string
|
|
8317
|
+
* table), no styles, no merged cells. Numeric cells use the native `"n"` type
|
|
8318
|
+
* so spreadsheets recognise them as numbers; `null` renders as an empty cell.
|
|
8319
|
+
*
|
|
8320
|
+
* @param headers - Column headers written as the first row.
|
|
8321
|
+
* @param rows - Data rows; each value is a string, a number, or `null` (empty).
|
|
8322
|
+
* @returns The `.xlsx` file contents as a `Uint8Array`.
|
|
8323
|
+
*
|
|
8324
|
+
* @example
|
|
8325
|
+
* const bytes = writeXlsx(
|
|
8326
|
+
* ["Name", "Score"],
|
|
8327
|
+
* [["Ada", 99], ["Alan", null]],
|
|
8328
|
+
* );
|
|
8329
|
+
* const blob = new Blob([bytes], {
|
|
8330
|
+
* type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
8331
|
+
* });
|
|
8332
|
+
*/
|
|
8333
|
+
export declare function writeXlsx(headers: readonly string[], rows: readonly (readonly (string | number | null)[])[]): Uint8Array;
|
|
8334
|
+
|
|
7846
8335
|
/**
|
|
7847
8336
|
* Minimal `react-hook-form` resolver built on top of zod. Mirrors the shape
|
|
7848
8337
|
* produced by `@hookform/resolvers/zod` so it can be passed straight to
|