tempest-react-sdk 0.21.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 +289 -0
- package/dist/tempest-react-sdk.js +3362 -3198
- 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.
|
|
@@ -3406,6 +3436,17 @@ export declare interface InstallButtonProps extends Omit<ButtonProps, "onClick"
|
|
|
3406
3436
|
onResult?: (outcome: InstallOutcome) => void;
|
|
3407
3437
|
}
|
|
3408
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
|
+
|
|
3409
3450
|
/**
|
|
3410
3451
|
* Install a `notificationclick` handler that focuses an existing client when
|
|
3411
3452
|
* possible and falls back to opening a new window.
|
|
@@ -3485,6 +3526,22 @@ export declare function installSkipWaitingListener(): void;
|
|
|
3485
3526
|
|
|
3486
3527
|
export declare type InterpolationValues = Record<string, string | number>;
|
|
3487
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
|
+
|
|
3488
3545
|
/**
|
|
3489
3546
|
* Type guard for the {@link ApiError} shape. Matches both {@link TempestApiError}
|
|
3490
3547
|
* instances and plain objects carrying `status` + `detail`.
|
|
@@ -3539,6 +3596,14 @@ export declare function isDefined<T>(value: T | null | undefined): value is T;
|
|
|
3539
3596
|
*/
|
|
3540
3597
|
export declare function isEmpty(value: unknown): boolean;
|
|
3541
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
|
+
|
|
3542
3607
|
/**
|
|
3543
3608
|
* Return true when the JWT's `exp` claim is in the past (or missing).
|
|
3544
3609
|
*
|
|
@@ -3588,6 +3653,15 @@ export declare function isPushSupported(): boolean;
|
|
|
3588
3653
|
/** True when the Web Share API is available in this environment. */
|
|
3589
3654
|
export declare function isShareSupported(): boolean;
|
|
3590
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
|
+
|
|
3591
3665
|
/**
|
|
3592
3666
|
* Type guard asserting a value is a string primitive.
|
|
3593
3667
|
*
|
|
@@ -3799,6 +3873,27 @@ export declare interface LoggerSink {
|
|
|
3799
3873
|
|
|
3800
3874
|
export declare type LogLevel = "debug" | "info" | "warn" | "error";
|
|
3801
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
|
+
|
|
3802
3897
|
/**
|
|
3803
3898
|
* Memoize only the most recent call of `fn`, keyed by shallow-equal arguments.
|
|
3804
3899
|
*
|
|
@@ -5014,6 +5109,11 @@ export declare interface RefreshIndicatorProps {
|
|
|
5014
5109
|
* app keeps full control over the SW file — this helper only handles the
|
|
5015
5110
|
* boilerplate around `register()` and `updatefound`.
|
|
5016
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
|
+
*
|
|
5017
5117
|
* @returns The registration when it succeeds, or `null` when unsupported.
|
|
5018
5118
|
*/
|
|
5019
5119
|
export declare function registerServiceWorker(options: RegisterServiceWorkerOptions): Promise<ServiceWorkerRegistration | null>;
|
|
@@ -5033,6 +5133,27 @@ export declare interface RegisterServiceWorkerOptions {
|
|
|
5033
5133
|
onUpdate?: (waiting: ServiceWorker, registration: ServiceWorkerRegistration) => void;
|
|
5034
5134
|
/** Called on registration failure. */
|
|
5035
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;
|
|
5036
5157
|
}
|
|
5037
5158
|
|
|
5038
5159
|
/**
|
|
@@ -5410,6 +5531,33 @@ export declare interface SentryLike {
|
|
|
5410
5531
|
*/
|
|
5411
5532
|
export declare function share(payload: SharePayload): Promise<ShareResult>;
|
|
5412
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
|
+
|
|
5413
5561
|
export declare interface SharePayload {
|
|
5414
5562
|
title?: string;
|
|
5415
5563
|
text?: string;
|
|
@@ -6912,6 +7060,75 @@ export declare function useI18n(): I18nContextValue;
|
|
|
6912
7060
|
*/
|
|
6913
7061
|
export declare function useIdle(timeout?: number): boolean;
|
|
6914
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
|
+
|
|
6915
7132
|
/**
|
|
6916
7133
|
* Track whether the referenced element intersects the viewport. Useful for
|
|
6917
7134
|
* lazy-loading images, "load more" sentinels, and animation triggers.
|
|
@@ -7006,6 +7223,52 @@ export { useLocation }
|
|
|
7006
7223
|
*/
|
|
7007
7224
|
export declare function useLongPress<T extends HTMLElement>(ref: RefObject<T | null>, fn: () => void, options?: UseLongPressOptions): void;
|
|
7008
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
|
+
|
|
7009
7272
|
export declare interface UseLongPressOptions {
|
|
7010
7273
|
/** Press duration in ms. Default `500`. */
|
|
7011
7274
|
delay?: number;
|
|
@@ -8043,6 +8306,32 @@ export declare type WithSelectors<S> = S extends {
|
|
|
8043
8306
|
*/
|
|
8044
8307
|
export declare function withTimeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>;
|
|
8045
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
|
+
|
|
8046
8335
|
/**
|
|
8047
8336
|
* Minimal `react-hook-form` resolver built on top of zod. Mirrors the shape
|
|
8048
8337
|
* produced by `@hookform/resolvers/zod` so it can be passed straight to
|