@sparkvault/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +720 -0
  2. package/dist/auto-init.d.ts +51 -0
  3. package/dist/config.d.ts +25 -0
  4. package/dist/errors.d.ts +30 -0
  5. package/dist/http.d.ts +48 -0
  6. package/dist/identity/api.d.ts +101 -0
  7. package/dist/identity/container.d.ts +49 -0
  8. package/dist/identity/handlers/index.d.ts +9 -0
  9. package/dist/identity/handlers/passkey-handler.d.ts +52 -0
  10. package/dist/identity/handlers/sparklink-handler.d.ts +43 -0
  11. package/dist/identity/handlers/totp-handler.d.ts +52 -0
  12. package/dist/identity/index.d.ts +69 -0
  13. package/dist/identity/inline-container.d.ts +60 -0
  14. package/dist/identity/methods.d.ts +23 -0
  15. package/dist/identity/modal.d.ts +74 -0
  16. package/dist/identity/renderer.d.ts +97 -0
  17. package/dist/identity/state.d.ts +95 -0
  18. package/dist/identity/styles.d.ts +22 -0
  19. package/dist/identity/types.d.ts +183 -0
  20. package/dist/identity/utils/cooldown-timer.d.ts +73 -0
  21. package/dist/identity/utils/index.d.ts +5 -0
  22. package/dist/identity/utils.d.ts +27 -0
  23. package/dist/identity/views/base.d.ts +62 -0
  24. package/dist/identity/views/error.d.ts +25 -0
  25. package/dist/identity/views/icons.d.ts +34 -0
  26. package/dist/identity/views/identity-input.d.ts +48 -0
  27. package/dist/identity/views/index.d.ts +14 -0
  28. package/dist/identity/views/loading.d.ts +15 -0
  29. package/dist/identity/views/method-select.d.ts +29 -0
  30. package/dist/identity/views/passkey-prompt.d.ts +22 -0
  31. package/dist/identity/views/passkey.d.ts +38 -0
  32. package/dist/identity/views/sparklink-waiting.d.ts +33 -0
  33. package/dist/identity/views/totp-verify.d.ts +58 -0
  34. package/dist/index.d.ts +658 -0
  35. package/dist/logger.d.ts +45 -0
  36. package/dist/rng/index.d.ts +54 -0
  37. package/dist/rng/types.d.ts +26 -0
  38. package/dist/sparks/index.d.ts +37 -0
  39. package/dist/sparks/types.d.ts +56 -0
  40. package/dist/sparkvault.cjs.js +6152 -0
  41. package/dist/sparkvault.cjs.js.map +1 -0
  42. package/dist/sparkvault.esm.js +6137 -0
  43. package/dist/sparkvault.esm.js.map +1 -0
  44. package/dist/sparkvault.js +2 -0
  45. package/dist/sparkvault.js.map +1 -0
  46. package/dist/utils/base64url.d.ts +49 -0
  47. package/dist/utils/retry.d.ts +32 -0
  48. package/dist/vaults/index.d.ts +83 -0
  49. package/dist/vaults/types.d.ts +120 -0
  50. package/package.json +64 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Identity Modal Container
3
+ *
4
+ * Single responsibility: DOM modal container lifecycle.
5
+ * Creates, shows, hides, and destroys the modal overlay and container.
6
+ * Does NOT handle content rendering - that's the Renderer's job.
7
+ */
8
+ import type { SdkConfigBranding } from './types';
9
+ import type { Container } from './container';
10
+ export interface ModalOptions {
11
+ branding: SdkConfigBranding;
12
+ /** Enable backdrop blur (default: true) */
13
+ backdropBlur?: boolean;
14
+ }
15
+ export interface ModalContainerElements {
16
+ overlay: HTMLDivElement;
17
+ modal: HTMLDivElement;
18
+ header: HTMLDivElement;
19
+ body: HTMLDivElement;
20
+ footer: HTMLDivElement;
21
+ }
22
+ export declare class ModalContainer implements Container {
23
+ private elements;
24
+ private onCloseCallback;
25
+ private keydownHandler;
26
+ private overlayClickHandler;
27
+ private closeBtnClickHandler;
28
+ private closeBtn;
29
+ private backdropBlur;
30
+ private effectiveTheme;
31
+ private headerElement;
32
+ /**
33
+ * Create and show the modal immediately with loading state.
34
+ * Uses default branding until real config is loaded.
35
+ * This provides instant visual feedback to the user.
36
+ */
37
+ createLoading(options: {
38
+ backdropBlur?: boolean;
39
+ }, onClose: () => void): ModalContainerElements;
40
+ /**
41
+ * Update the modal header and styles with real branding.
42
+ * Called after SDK config loads.
43
+ */
44
+ updateBranding(branding: SdkConfigBranding): void;
45
+ /**
46
+ * Update the backdrop blur setting.
47
+ * Called after SDK config loads with resolved value (client override > server config > default).
48
+ */
49
+ updateBackdropBlur(enabled: boolean): void;
50
+ /**
51
+ * Create and show the modal container.
52
+ * Returns the container elements for the renderer to populate.
53
+ */
54
+ create(options: ModalOptions, onClose: () => void): ModalContainerElements;
55
+ private createHeader;
56
+ private handleClose;
57
+ /**
58
+ * Get the modal body element for content rendering.
59
+ */
60
+ getBody(): HTMLDivElement | null;
61
+ /**
62
+ * Check if the modal is currently open.
63
+ */
64
+ isOpen(): boolean;
65
+ /**
66
+ * Destroy the modal and clean up all event listeners.
67
+ */
68
+ destroy(): void;
69
+ }
70
+ /**
71
+ * Escape HTML to prevent XSS.
72
+ * Used for any user-provided content rendered in the modal.
73
+ */
74
+ export declare function escapeHtml(str: string): string;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Identity View Renderer
3
+ *
4
+ * Orchestrates view state and rendering for identity verification flows.
5
+ * Uses extracted handlers for TOTP and Passkey operations.
6
+ */
7
+ import type { VerifyOptions, VerifyResult } from './types';
8
+ import { IdentityApi } from './api';
9
+ import type { Container } from './container';
10
+ interface RendererCallbacks {
11
+ onSuccess: (result: VerifyResult) => void;
12
+ onError: (error: Error) => void;
13
+ onCancel: () => void;
14
+ }
15
+ export declare class IdentityRenderer {
16
+ private readonly api;
17
+ private readonly container;
18
+ private readonly options;
19
+ private readonly callbacks;
20
+ private readonly verificationState;
21
+ private readonly passkeyHandler;
22
+ private readonly totpHandler;
23
+ private readonly sparkLinkHandler;
24
+ private currentView;
25
+ private focusTimeoutId;
26
+ private pollingInterval;
27
+ constructor(container: Container, api: IdentityApi, options: VerifyOptions, callbacks: RendererCallbacks);
28
+ private get recipient();
29
+ private get identityType();
30
+ private get sdkConfig();
31
+ /**
32
+ * Start the identity verification flow.
33
+ * If config was preloaded, opens modal and proceeds immediately.
34
+ * Otherwise shows loading state while fetching config.
35
+ */
36
+ start(): Promise<void>;
37
+ /**
38
+ * Close the modal and clean up.
39
+ */
40
+ close(): void;
41
+ private handleClose;
42
+ private get viewState();
43
+ private setState;
44
+ private render;
45
+ private destroyCurrentView;
46
+ private createViewForState;
47
+ private showIdentityInput;
48
+ private showMethodSelect;
49
+ private handleIdentitySubmit;
50
+ private getAllowedIdentityTypes;
51
+ private handleMethodSelect;
52
+ private handleTotpSubmit;
53
+ private handleTotpResend;
54
+ private handlePasskeyStart;
55
+ /**
56
+ * Handle fallback from passkey to email/SMS code.
57
+ * User clicked "Having trouble? Use email code instead".
58
+ */
59
+ private handlePasskeyFallback;
60
+ /**
61
+ * Handle skipping passkey registration when coming from passkey prompt.
62
+ * User clicked "Back" or cancelled registration after being prompted.
63
+ */
64
+ private handlePasskeyRegistrationSkip;
65
+ private handleSocialLogin;
66
+ private normalizeError;
67
+ /**
68
+ * Check if we should show the passkey registration prompt after PIN verification.
69
+ */
70
+ private shouldShowPasskeyPrompt;
71
+ /**
72
+ * Handle user clicking "Add Passkey" in the prompt.
73
+ * Directly triggers browser passkey creation without intermediate screen.
74
+ */
75
+ private handlePasskeyPromptAdd;
76
+ /**
77
+ * Handle user clicking "Not now" / "Skip" in the prompt.
78
+ */
79
+ private handlePasskeyPromptSkip;
80
+ /**
81
+ * Start polling for SparkLink verification status.
82
+ */
83
+ private startSparkLinkPolling;
84
+ /**
85
+ * Stop SparkLink polling.
86
+ */
87
+ private stopSparkLinkPolling;
88
+ /**
89
+ * Handle resending SparkLink.
90
+ */
91
+ private handleSparkLinkResend;
92
+ /**
93
+ * Handle fallback from SparkLink to TOTP verification code.
94
+ */
95
+ private handleSparkLinkFallback;
96
+ }
97
+ export {};
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Verification State Manager
3
+ *
4
+ * Single source of truth for all verification flow state.
5
+ * Centralizes scattered state from IdentityRenderer for:
6
+ * - Predictable state transitions
7
+ * - Easier debugging and testing
8
+ * - Clear data ownership
9
+ */
10
+ import type { SdkConfig, VerifyResult, IdentityViewState, MethodMetadata } from './types';
11
+ import type { IdentityType } from './views';
12
+ /**
13
+ * Passkey-specific state
14
+ */
15
+ interface PasskeyState {
16
+ /** Whether user has registered passkeys (null = unknown) */
17
+ hasPasskey: boolean | null;
18
+ /** Whether user fell back from passkey to another method */
19
+ isFallbackMode: boolean;
20
+ /** Pending result when prompting for passkey registration after TOTP */
21
+ pendingResult: VerifyResult | null;
22
+ }
23
+ /**
24
+ * TOTP-specific state
25
+ */
26
+ interface TotpState {
27
+ /** Current kindling token for TOTP verification */
28
+ kindling: string;
29
+ /** Current TOTP method (email or sms) */
30
+ method: 'email' | 'sms' | null;
31
+ }
32
+ /**
33
+ * Centralized verification state
34
+ */
35
+ export declare class VerificationState {
36
+ private _sdkConfig;
37
+ private _viewState;
38
+ private _recipient;
39
+ private _identityType;
40
+ private readonly _passkey;
41
+ private readonly _totp;
42
+ private readonly listeners;
43
+ /**
44
+ * Subscribe to state changes
45
+ * @param listener - Callback invoked on state change
46
+ * @returns Unsubscribe function
47
+ */
48
+ subscribe(listener: (state: IdentityViewState) => void): () => void;
49
+ /**
50
+ * Notify all listeners of state change
51
+ */
52
+ private notify;
53
+ get sdkConfig(): SdkConfig | null;
54
+ setConfig(config: SdkConfig): void;
55
+ get accountId(): string;
56
+ /**
57
+ * Get enriched methods filtered by identity type
58
+ */
59
+ getAvailableMethods(): MethodMetadata[];
60
+ /**
61
+ * Check if passkey method is enabled in config
62
+ */
63
+ isPasskeyEnabled(): boolean;
64
+ get viewState(): IdentityViewState;
65
+ setViewState(state: IdentityViewState): void;
66
+ get recipient(): string;
67
+ get identityType(): IdentityType;
68
+ setIdentity(recipient: string, type: IdentityType): void;
69
+ getAllowedIdentityTypes(): IdentityType[];
70
+ get passkey(): Readonly<PasskeyState>;
71
+ setPasskeyStatus(hasPasskey: boolean | null): void;
72
+ enablePasskeyFallback(): void;
73
+ setPendingResult(result: VerifyResult | null): void;
74
+ /**
75
+ * Check if we should show passkey registration prompt
76
+ * Based on: passkey enabled, user doesn't have one, not dismissed
77
+ */
78
+ shouldShowPasskeyPrompt(): boolean;
79
+ /**
80
+ * Check if passkey prompt was dismissed (30-day cookie)
81
+ */
82
+ private isPasskeyPromptDismissed;
83
+ /**
84
+ * Dismiss passkey prompt for 30 days
85
+ */
86
+ dismissPasskeyPrompt(): void;
87
+ get totp(): Readonly<TotpState>;
88
+ setKindling(kindling: string): void;
89
+ setTotpMethod(method: 'email' | 'sms'): void;
90
+ /**
91
+ * Reset state for new verification attempt
92
+ */
93
+ reset(): void;
94
+ }
95
+ export {};
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Identity Modal Styles
3
+ *
4
+ * Enterprise-grade styling following Stripe/Adobe design principles:
5
+ * - Clean, minimal aesthetic with purposeful whitespace
6
+ * - 4px base spacing unit for consistency
7
+ * - Subtle depth through shadows and borders (not gradients)
8
+ * - Professional typography with clear hierarchy
9
+ * - Refined color palette with single accent
10
+ */
11
+ import type { SdkConfigBranding } from './types';
12
+ export interface StyleOptions {
13
+ branding: SdkConfigBranding;
14
+ backdropBlur?: boolean;
15
+ }
16
+ /**
17
+ * Inject modal styles into the document head.
18
+ */
19
+ export declare function injectStyles(options: StyleOptions): void;
20
+ export declare function updateThemeVariables(_branding: SdkConfigBranding | undefined | null): void;
21
+ export declare function removeStyles(): void;
22
+ export declare function resolveTheme(branding: SdkConfigBranding | undefined | null): 'light' | 'dark';
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Identity Module Types
3
+ */
4
+ export type AuthMethod = 'passkey' | 'totp_email' | 'totp_sms' | 'totp_voice' | 'magic_link' | 'sparklink' | 'google' | 'apple' | 'microsoft' | 'github' | 'facebook' | 'linkedin' | 'social_google' | 'social_apple' | 'social_microsoft' | 'social_github' | 'social_facebook' | 'social_linkedin';
5
+ export type Theme = 'light' | 'dark';
6
+ export interface VerifyOptions {
7
+ /** Pre-fill email address (mutually exclusive with phone) */
8
+ email?: string;
9
+ /** Pre-fill phone number in E.164 format, e.g. "+14155551234" (mutually exclusive with email) */
10
+ phone?: string;
11
+ /** Override backdrop blur setting from app config */
12
+ backdropBlur?: boolean;
13
+ /** Called when user cancels */
14
+ onCancel?: () => void;
15
+ /** Called when verification completes (before promise resolves) */
16
+ onSuccess?: (result: VerifyResult) => void;
17
+ /** Called on error (before promise rejects) */
18
+ onError?: (error: Error) => void;
19
+ }
20
+ export interface RenderOptions extends VerifyOptions {
21
+ /** Target element to render inline UI into (required) */
22
+ target: HTMLElement;
23
+ /** Show header with branding and close button (default: true) */
24
+ showHeader?: boolean;
25
+ /** Show close button in header (default: true, requires showHeader) */
26
+ showCloseButton?: boolean;
27
+ /** Show footer with SparkVault branding (default: true) */
28
+ showFooter?: boolean;
29
+ }
30
+ export interface VerifyResult {
31
+ /** Signed JWT token */
32
+ token: string;
33
+ /** Verified identity (email or phone) */
34
+ identity: string;
35
+ /** Type of identity verified */
36
+ identityType: 'email' | 'phone';
37
+ }
38
+ export interface TokenClaims {
39
+ /** Issuer */
40
+ iss: string;
41
+ /** Subject (hashed identity) */
42
+ sub: string;
43
+ /** Audience (account ID for simple tokens, client ID for OIDC) */
44
+ aud: string;
45
+ /** Expiry (Unix seconds) */
46
+ exp: number;
47
+ /** Issued at (Unix seconds) */
48
+ iat: number;
49
+ /** Unique token ID for replay protection */
50
+ jti?: string;
51
+ /** Verified identity (email or phone) */
52
+ identity: string;
53
+ /** Identity type */
54
+ identity_type: 'email' | 'phone';
55
+ /** Verification timestamp (Unix seconds) */
56
+ verified_at: number;
57
+ /** Authentication method used */
58
+ method: string;
59
+ }
60
+ export interface EmbedMessage {
61
+ type: 'sparkvault:identity:result' | 'sparkvault:identity:cancel' | 'sparkvault:identity:error' | 'sparkvault:identity:ready';
62
+ payload?: VerifyResult | {
63
+ error: string;
64
+ code: string;
65
+ };
66
+ }
67
+ export interface SdkConfigBranding {
68
+ companyName: string;
69
+ logoLight: string | null;
70
+ logoDark: string | null;
71
+ /** Backdrop blur setting (default: true) */
72
+ backdrop_blur?: boolean;
73
+ /** Theme mode from server config */
74
+ themeMode?: 'light' | 'dark';
75
+ }
76
+ /** Method ID returned by config endpoint */
77
+ export type MethodId = 'totp_email' | 'totp_sms' | 'totp_voice' | 'passkey' | 'sparklink' | 'social_google' | 'social_apple' | 'social_microsoft' | 'social_github' | 'social_facebook' | 'social_linkedin' | 'enterprise_okta' | 'enterprise_entra' | 'enterprise_onelogin' | 'enterprise_ping' | 'enterprise_jumpcloud' | 'hris_bamboohr' | 'hris_workday' | 'hris_adp' | 'hris_gusto' | 'hris_rippling';
78
+ export interface SdkConfig {
79
+ accountId: string;
80
+ /** Branding configuration (optional in v1 - uses defaults if not provided) */
81
+ branding?: SdkConfigBranding;
82
+ /** Allowed identity types: 'email', 'phone', or both */
83
+ allowedIdentityTypes?: ('email' | 'phone')[];
84
+ /** Enabled method IDs */
85
+ methods: MethodId[];
86
+ }
87
+ /** Method metadata for SDK rendering (static lookup) */
88
+ export interface MethodMetadata {
89
+ id: MethodId;
90
+ type: 'totp' | 'passkey' | 'magic_link' | 'social' | 'enterprise' | 'hris';
91
+ /** Which identity type this method requires */
92
+ identityType: 'email' | 'phone';
93
+ name: string;
94
+ description: string;
95
+ icon: string;
96
+ /** Provider name for social/enterprise/hris methods */
97
+ provider?: string;
98
+ }
99
+ export interface TotpSendResponse {
100
+ success: boolean;
101
+ kindling: string;
102
+ expires_at: number;
103
+ method: string;
104
+ }
105
+ export interface TotpVerifyResponse {
106
+ verified: boolean;
107
+ token?: string;
108
+ /** Identity (email or phone) - returned on success */
109
+ identity?: string;
110
+ /** Identity type - 'email' or 'phone' */
111
+ identity_type?: 'email' | 'phone';
112
+ /** Returned on failure - new kindling for next attempt */
113
+ kindling?: string;
114
+ /** Returned on failure - seconds until next attempt allowed */
115
+ retry_after?: number;
116
+ /** Returned on failure - when the backoff expires */
117
+ expires_at?: number;
118
+ }
119
+ export interface PasskeyChallengeResponse {
120
+ challenge: string;
121
+ rpId: string;
122
+ rpName: string;
123
+ userId?: string;
124
+ userName?: string;
125
+ allowCredentials?: Array<{
126
+ id: string;
127
+ type: 'public-key';
128
+ }>;
129
+ timeout: number;
130
+ }
131
+ export interface PasskeyVerifyResponse {
132
+ token: string;
133
+ identity: string;
134
+ identity_type: 'email' | 'phone';
135
+ }
136
+ export interface SparkLinkSendResponse {
137
+ sparkId: string;
138
+ expiresAt: number;
139
+ }
140
+ export interface SparkLinkStatusResponse {
141
+ verified: boolean;
142
+ token?: string;
143
+ identity?: string;
144
+ identityType?: string;
145
+ }
146
+ export type IdentityViewState = {
147
+ view: 'loading';
148
+ } | {
149
+ view: 'identity-input';
150
+ error?: string;
151
+ } | {
152
+ view: 'method-select';
153
+ email: string;
154
+ methods: MethodMetadata[];
155
+ } | {
156
+ view: 'totp-verify';
157
+ email: string;
158
+ method: 'email' | 'sms';
159
+ kindling: string;
160
+ error?: string;
161
+ backoffExpires?: number;
162
+ } | {
163
+ view: 'passkey';
164
+ email: string;
165
+ mode: 'register' | 'verify';
166
+ error?: string;
167
+ } | {
168
+ view: 'passkey-prompt';
169
+ email: string;
170
+ pendingResult: VerifyResult;
171
+ } | {
172
+ view: 'sparklink-waiting';
173
+ email: string;
174
+ sparkId: string;
175
+ expiresAt: number;
176
+ } | {
177
+ view: 'oauth-pending';
178
+ provider: string;
179
+ } | {
180
+ view: 'error';
181
+ message: string;
182
+ code: string;
183
+ };
@@ -0,0 +1,73 @@
1
+ /**
2
+ * CooldownTimer - Reusable countdown utility for resend buttons and rate limiting
3
+ *
4
+ * Manages interval-based countdowns with callbacks for tick and completion events.
5
+ * Properly cleans up intervals to prevent memory leaks.
6
+ */
7
+ export interface CooldownTimerConfig {
8
+ /** Duration in seconds */
9
+ duration: number;
10
+ /** Called every second with remaining seconds */
11
+ onTick: (secondsRemaining: number) => void;
12
+ /** Called when countdown reaches zero */
13
+ onComplete: () => void;
14
+ }
15
+ export declare class CooldownTimer {
16
+ private intervalId;
17
+ private secondsRemaining;
18
+ private readonly onTick;
19
+ private readonly onComplete;
20
+ constructor(config: CooldownTimerConfig);
21
+ /**
22
+ * Start the countdown timer
23
+ * Immediately calls onTick with initial value, then updates every second
24
+ */
25
+ start(): void;
26
+ /**
27
+ * Stop and clean up the timer
28
+ */
29
+ stop(): void;
30
+ /**
31
+ * Check if timer is currently running
32
+ */
33
+ isRunning(): boolean;
34
+ /**
35
+ * Get current remaining seconds
36
+ */
37
+ getRemainingSeconds(): number;
38
+ }
39
+ /**
40
+ * ExpirationTimer - Countdown based on an absolute expiration timestamp
41
+ *
42
+ * Unlike CooldownTimer which counts down from a fixed duration,
43
+ * this calculates remaining time from a UTC timestamp, making it
44
+ * accurate even if the page was loaded after the timer started.
45
+ */
46
+ export interface ExpirationTimerConfig {
47
+ /** UTC timestamp (seconds) when the countdown expires */
48
+ expiresAt: number;
49
+ /** Called every second with remaining seconds */
50
+ onTick: (secondsRemaining: number) => void;
51
+ /** Called when countdown reaches zero */
52
+ onExpired: () => void;
53
+ }
54
+ export declare class ExpirationTimer {
55
+ private intervalId;
56
+ private readonly expiresAt;
57
+ private readonly onTick;
58
+ private readonly onExpired;
59
+ constructor(config: ExpirationTimerConfig);
60
+ private calculateRemaining;
61
+ /**
62
+ * Start the countdown timer
63
+ */
64
+ start(): void;
65
+ /**
66
+ * Stop and clean up the timer
67
+ */
68
+ stop(): void;
69
+ /**
70
+ * Check if timer is currently running
71
+ */
72
+ isRunning(): boolean;
73
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * SDK Identity Utilities
3
+ */
4
+ export { CooldownTimer, ExpirationTimer } from './cooldown-timer';
5
+ export type { CooldownTimerConfig, ExpirationTimerConfig } from './cooldown-timer';
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Identity Module Utilities
3
+ *
4
+ * Shared utility functions for encoding, validation, and cookie management.
5
+ * Consolidates duplicated logic from renderer, api, and index.
6
+ */
7
+ export { CooldownTimer, ExpirationTimer } from './utils/cooldown-timer';
8
+ export type { CooldownTimerConfig, ExpirationTimerConfig } from './utils/cooldown-timer';
9
+ export { arrayBufferToBase64url, base64urlToArrayBuffer, base64urlToString, } from '../utils/base64url';
10
+ /**
11
+ * Get cookie value by name
12
+ * @param name - Cookie name
13
+ * @returns Cookie value or null if not found
14
+ */
15
+ export declare function getCookie(name: string): string | null;
16
+ /**
17
+ * Set cookie with expiration
18
+ * @param name - Cookie name
19
+ * @param value - Cookie value
20
+ * @param days - Days until expiration
21
+ */
22
+ export declare function setCookie(name: string, value: string, days: number): void;
23
+ /**
24
+ * Generate cryptographically secure random state string
25
+ * Used for OAuth CSRF protection
26
+ */
27
+ export declare function generateState(): string;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Base View Types and Utilities
3
+ *
4
+ * Shared interfaces and helpers for all view components.
5
+ */
6
+ import { escapeHtml } from '../modal';
7
+ /**
8
+ * Base interface for all view components.
9
+ * Each view must implement render() to return its DOM element.
10
+ */
11
+ export interface View {
12
+ render(): HTMLElement;
13
+ destroy?(): void;
14
+ }
15
+ /**
16
+ * Create an element with optional attributes and children.
17
+ * Type-safe DOM element creation utility.
18
+ */
19
+ export declare function createElement<K extends keyof HTMLElementTagNameMap>(tag: K, attrs?: Partial<HTMLElementTagNameMap[K]> & {
20
+ className?: string;
21
+ }, children?: (HTMLElement | string | null | undefined)[]): HTMLElementTagNameMap[K];
22
+ /**
23
+ * Create a container div with optional class and children.
24
+ */
25
+ export declare function div(className?: string, children?: (HTMLElement | string | null | undefined)[]): HTMLDivElement;
26
+ /**
27
+ * Clear all children from an element safely.
28
+ * Preferred over innerHTML = '' for security and performance.
29
+ */
30
+ export declare function clearChildren(element: HTMLElement): void;
31
+ /**
32
+ * Create an error message element.
33
+ */
34
+ export declare function errorMessage(message: string): HTMLDivElement;
35
+ /**
36
+ * Validate email format.
37
+ * Returns sanitized email or null if invalid.
38
+ */
39
+ export declare function validateEmail(email: string): string | null;
40
+ /**
41
+ * Validate phone number format.
42
+ * Accepts various formats, returns E.164 format (+1XXXXXXXXXX) or null if invalid.
43
+ */
44
+ export declare function validatePhone(phone: string): string | null;
45
+ /**
46
+ * Format phone number for display as user types.
47
+ * Formats US numbers as (XXX) XXX-XXXX.
48
+ */
49
+ export declare function formatPhoneDisplay(phone: string): string;
50
+ /**
51
+ * Detect if input looks like a phone number (starts with digit or +).
52
+ */
53
+ export declare function looksLikePhone(input: string): boolean;
54
+ /**
55
+ * Validate TOTP code format.
56
+ * Returns sanitized code or null if invalid.
57
+ */
58
+ export declare function validateTotpCode(code: string): string | null;
59
+ /**
60
+ * Re-export escapeHtml for convenience.
61
+ */
62
+ export { escapeHtml };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Error View
3
+ *
4
+ * Professional enterprise-quality error display with clear visual hierarchy.
5
+ */
6
+ import type { View } from './base';
7
+ export interface ErrorViewProps {
8
+ message: string;
9
+ code: string;
10
+ onRetry: () => void;
11
+ onClose: () => void;
12
+ }
13
+ export declare class ErrorView implements View {
14
+ private readonly props;
15
+ private retryButton;
16
+ private closeButton;
17
+ private readonly boundHandleRetry;
18
+ private readonly boundHandleClose;
19
+ constructor(props: ErrorViewProps);
20
+ render(): HTMLElement;
21
+ /**
22
+ * Clean up event listeners to prevent memory leaks.
23
+ */
24
+ destroy(): void;
25
+ }