@ozura/elements 0.1.0-beta.1

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 (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +717 -0
  3. package/dist/frame/element-frame.html +22 -0
  4. package/dist/frame/element-frame.js +731 -0
  5. package/dist/frame/element-frame.js.map +1 -0
  6. package/dist/frame/tokenizer-frame.html +11 -0
  7. package/dist/frame/tokenizer-frame.js +328 -0
  8. package/dist/frame/tokenizer-frame.js.map +1 -0
  9. package/dist/oz-elements.esm.js +1190 -0
  10. package/dist/oz-elements.esm.js.map +1 -0
  11. package/dist/oz-elements.umd.js +1202 -0
  12. package/dist/oz-elements.umd.js.map +1 -0
  13. package/dist/react/frame/elementFrame.d.ts +8 -0
  14. package/dist/react/frame/tokenizerFrame.d.ts +13 -0
  15. package/dist/react/index.cjs.js +1407 -0
  16. package/dist/react/index.cjs.js.map +1 -0
  17. package/dist/react/index.esm.js +1400 -0
  18. package/dist/react/index.esm.js.map +1 -0
  19. package/dist/react/react/index.d.ts +214 -0
  20. package/dist/react/sdk/OzElement.d.ts +65 -0
  21. package/dist/react/sdk/OzVault.d.ts +106 -0
  22. package/dist/react/sdk/errors.d.ts +55 -0
  23. package/dist/react/sdk/index.d.ts +5 -0
  24. package/dist/react/server/index.d.ts +140 -0
  25. package/dist/react/types/index.d.ts +432 -0
  26. package/dist/react/utils/appearance.d.ts +13 -0
  27. package/dist/react/utils/billingUtils.d.ts +60 -0
  28. package/dist/react/utils/cardUtils.d.ts +37 -0
  29. package/dist/server/frame/elementFrame.d.ts +8 -0
  30. package/dist/server/frame/tokenizerFrame.d.ts +13 -0
  31. package/dist/server/index.cjs.js +294 -0
  32. package/dist/server/index.cjs.js.map +1 -0
  33. package/dist/server/index.esm.js +290 -0
  34. package/dist/server/index.esm.js.map +1 -0
  35. package/dist/server/sdk/OzElement.d.ts +65 -0
  36. package/dist/server/sdk/OzVault.d.ts +106 -0
  37. package/dist/server/sdk/errors.d.ts +55 -0
  38. package/dist/server/sdk/index.d.ts +5 -0
  39. package/dist/server/server/index.d.ts +140 -0
  40. package/dist/server/types/index.d.ts +432 -0
  41. package/dist/server/utils/appearance.d.ts +13 -0
  42. package/dist/server/utils/billingUtils.d.ts +60 -0
  43. package/dist/server/utils/cardUtils.d.ts +37 -0
  44. package/dist/types/frame/elementFrame.d.ts +8 -0
  45. package/dist/types/frame/tokenizerFrame.d.ts +13 -0
  46. package/dist/types/sdk/OzElement.d.ts +65 -0
  47. package/dist/types/sdk/OzVault.d.ts +106 -0
  48. package/dist/types/sdk/errors.d.ts +55 -0
  49. package/dist/types/sdk/index.d.ts +5 -0
  50. package/dist/types/server/index.d.ts +140 -0
  51. package/dist/types/types/index.d.ts +432 -0
  52. package/dist/types/utils/appearance.d.ts +13 -0
  53. package/dist/types/utils/billingUtils.d.ts +60 -0
  54. package/dist/types/utils/cardUtils.d.ts +37 -0
  55. package/package.json +97 -0
@@ -0,0 +1,432 @@
1
+ export interface ElementStyle {
2
+ color?: string;
3
+ fontSize?: string;
4
+ fontFamily?: string;
5
+ fontWeight?: string;
6
+ fontStyle?: string;
7
+ fontVariant?: string;
8
+ letterSpacing?: string;
9
+ lineHeight?: string;
10
+ textAlign?: string;
11
+ textDecoration?: string;
12
+ textShadow?: string;
13
+ textTransform?: string;
14
+ padding?: string;
15
+ paddingTop?: string;
16
+ paddingRight?: string;
17
+ paddingBottom?: string;
18
+ paddingLeft?: string;
19
+ backgroundColor?: string;
20
+ opacity?: string;
21
+ border?: string;
22
+ borderColor?: string;
23
+ borderWidth?: string;
24
+ borderStyle?: string;
25
+ borderRadius?: string;
26
+ borderTop?: string;
27
+ borderRight?: string;
28
+ borderBottom?: string;
29
+ borderLeft?: string;
30
+ borderTopColor?: string;
31
+ borderRightColor?: string;
32
+ borderBottomColor?: string;
33
+ borderLeftColor?: string;
34
+ borderTopWidth?: string;
35
+ borderRightWidth?: string;
36
+ borderBottomWidth?: string;
37
+ borderLeftWidth?: string;
38
+ borderTopStyle?: string;
39
+ borderRightStyle?: string;
40
+ borderBottomStyle?: string;
41
+ borderLeftStyle?: string;
42
+ borderTopLeftRadius?: string;
43
+ borderTopRightRadius?: string;
44
+ borderBottomLeftRadius?: string;
45
+ borderBottomRightRadius?: string;
46
+ boxShadow?: string;
47
+ outline?: string;
48
+ outlineColor?: string;
49
+ outlineWidth?: string;
50
+ outlineStyle?: string;
51
+ outlineOffset?: string;
52
+ cursor?: string;
53
+ caretColor?: string;
54
+ height?: string;
55
+ minHeight?: string;
56
+ maxHeight?: string;
57
+ transition?: string;
58
+ /** Index signature for forward-compatibility with future CSS properties. */
59
+ [key: string]: string | undefined;
60
+ }
61
+ export interface ElementStyleConfig {
62
+ /** Default styles applied to the input. */
63
+ base?: ElementStyle;
64
+ /** Styles applied when the input is focused. Merges on top of `base`. */
65
+ focus?: ElementStyle;
66
+ /** Styles applied when the input contains an invalid value (on blur). Merges on top of `base`. */
67
+ invalid?: ElementStyle;
68
+ /** Styles applied when the input contains a valid, complete value (on blur). Merges on top of `base`. */
69
+ complete?: ElementStyle;
70
+ /** Styles applied to the input's placeholder text (::placeholder pseudo-element). */
71
+ placeholder?: ElementStyle;
72
+ }
73
+ export interface ElementOptions {
74
+ style?: ElementStyleConfig;
75
+ placeholder?: string;
76
+ disabled?: boolean;
77
+ /** How long to wait (ms) for the iframe to load before emitting `loaderror`. Default: 10 000. */
78
+ loadTimeoutMs?: number;
79
+ }
80
+ export interface ElementChangeEvent {
81
+ empty: boolean;
82
+ complete: boolean;
83
+ valid: boolean;
84
+ /** Card brand — only present on cardNumber elements */
85
+ cardBrand?: string;
86
+ /** Parsed month (01-12) — only present on expirationDate elements */
87
+ month?: string;
88
+ /** Parsed 2-digit year — only present on expirationDate elements */
89
+ year?: string;
90
+ /** Human-readable error when valid is false and the field has been touched */
91
+ error?: string;
92
+ }
93
+ export type ElementType = 'cardNumber' | 'cvv' | 'expirationDate';
94
+ /** Bank account element types. */
95
+ export type BankElementType = 'accountNumber' | 'routingNumber';
96
+ /** Load a font from a CSS stylesheet URL (e.g. Google Fonts). Must be HTTPS. */
97
+ export interface CssFontSource {
98
+ cssSrc: string;
99
+ }
100
+ /** Load a custom font via @font-face. `src` must be a `url(https://...)` value. */
101
+ export interface CustomFontSource {
102
+ family: string;
103
+ src: string;
104
+ weight?: string;
105
+ style?: string;
106
+ display?: string;
107
+ unicodeRange?: string;
108
+ }
109
+ export type FontSource = CssFontSource | CustomFontSource;
110
+ export type OzTheme = 'default' | 'night' | 'flat';
111
+ /**
112
+ * CSS variable-style overrides. Each key maps to a specific style property
113
+ * across all style states, so merchants can theme with a single flat object
114
+ * instead of manually building full `ElementStyleConfig` objects.
115
+ */
116
+ export interface AppearanceVariables {
117
+ /** Input text color. Maps to `base.color`. */
118
+ colorText?: string;
119
+ /** Input background color. Maps to `base.backgroundColor`. */
120
+ colorBackground?: string;
121
+ /** Primary accent color. Maps to `focus.caretColor` and `focus.color`. */
122
+ colorPrimary?: string;
123
+ /** Error/invalid state text color. Maps to `invalid.color`. */
124
+ colorDanger?: string;
125
+ /** Success/complete state text color. Maps to `complete.color`. */
126
+ colorSuccess?: string;
127
+ /** Placeholder text color. Maps to `placeholder.color`. */
128
+ colorPlaceholder?: string;
129
+ /** Font family. Maps to `base.fontFamily`. */
130
+ fontFamily?: string;
131
+ /** Font size. Maps to `base.fontSize`. */
132
+ fontSize?: string;
133
+ /** Font weight. Maps to `base.fontWeight`. */
134
+ fontWeight?: string;
135
+ /** Letter spacing. Maps to `base.letterSpacing`. */
136
+ letterSpacing?: string;
137
+ /** Line height. Maps to `base.lineHeight`. */
138
+ lineHeight?: string;
139
+ /** Inner padding. Maps to `base.padding`. */
140
+ padding?: string;
141
+ }
142
+ /**
143
+ * Global appearance configuration. Applied to all elements created by this vault.
144
+ * Per-element `style` overrides take precedence over appearance settings.
145
+ */
146
+ export interface Appearance {
147
+ /** Preset theme. Applies a complete set of default styles. */
148
+ theme?: OzTheme;
149
+ /** Variable overrides. Merged on top of the theme defaults. */
150
+ variables?: AppearanceVariables;
151
+ }
152
+ export interface VaultOptions {
153
+ /** Base URL of the vault API. Defaults to the Ozura production vault. */
154
+ apiUrl?: string;
155
+ /** System pub key required for tokenization. Obtain from Ozura admin.
156
+ * Sent as the `X-Pub-Key` header on tokenize requests. */
157
+ pubKey: string;
158
+ /** Base URL where the Ozura frame HTML/JS assets are served from.
159
+ * Defaults to the production CDN. Override for local development. */
160
+ frameBaseUrl?: string;
161
+ /**
162
+ * Custom fonts to inject into element iframes. Accepts Google Fonts URLs
163
+ * or @font-face declarations. Fonts are loaded inside each iframe so they
164
+ * render in the card input fields.
165
+ *
166
+ * @example
167
+ * // Google Fonts
168
+ * fonts: [{ cssSrc: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap' }]
169
+ *
170
+ * @example
171
+ * // Custom @font-face
172
+ * fonts: [{ family: 'MyFont', src: 'url(https://cdn.example.com/myfont.woff2)', weight: '400' }]
173
+ */
174
+ fonts?: FontSource[];
175
+ /**
176
+ * Called if the tokenizer iframe fails to signal ready within `loadTimeoutMs`.
177
+ * Use this to show a fallback UI (e.g. "Unable to load payment fields").
178
+ */
179
+ onLoadError?: () => void;
180
+ /** How long to wait (ms) for the tokenizer iframe before calling `onLoadError`. Default: 10 000. */
181
+ loadTimeoutMs?: number;
182
+ /**
183
+ * Global appearance configuration. Applies preset themes and/or variable
184
+ * overrides to all elements created by this vault. Per-element `style`
185
+ * overrides take precedence.
186
+ *
187
+ * @example
188
+ * appearance: { theme: 'night' }
189
+ *
190
+ * @example
191
+ * appearance: {
192
+ * theme: 'flat',
193
+ * variables: { colorPrimary: '#6366f1', fontFamily: '"Inter", sans-serif' },
194
+ * }
195
+ */
196
+ appearance?: Appearance;
197
+ }
198
+ /** Billing address. All string fields are validated to 1–50 characters. */
199
+ export interface BillingAddress {
200
+ line1: string;
201
+ /** Optional. Omitted entirely from cardSale if blank (schema enforces minLength 1 if present). */
202
+ line2?: string;
203
+ city: string;
204
+ /** For US and CA: normalized to the 2-letter abbreviation (e.g. "California" → "CA"). */
205
+ state: string;
206
+ zip: string;
207
+ /** ISO 3166-1 alpha-2, e.g. "US", "CA", "GB". */
208
+ country: string;
209
+ }
210
+ /**
211
+ * Cardholder billing details validated against the Ozura cardSale API schema.
212
+ * Mirrors the `billing_details` object in Stripe's createPaymentMethod API.
213
+ *
214
+ * Pass to `vault.createToken({ billing })` — the SDK validates all fields and
215
+ * returns normalized values in `TokenResponse.billing` ready for the cardSale call.
216
+ */
217
+ export interface BillingDetails {
218
+ /** 1–50 characters. Required for cardSale. */
219
+ firstName: string;
220
+ /** 1–50 characters. Required for cardSale. Must be non-empty. */
221
+ lastName: string;
222
+ /** Valid email address, max 50 characters. */
223
+ email?: string;
224
+ /** E.164 format, e.g. "+15551234567". Max 50 characters. */
225
+ phone?: string;
226
+ address?: BillingAddress;
227
+ }
228
+ export interface TokenizeOptions {
229
+ /**
230
+ * Billing details — validated, normalized, and returned in TokenResponse.billing
231
+ * ready to be passed directly to the cardSale API.
232
+ *
233
+ * If provided, firstName and lastName inside billing take precedence over
234
+ * the top-level firstName/lastName params below.
235
+ */
236
+ billing?: BillingDetails;
237
+ /** @deprecated Pass firstName inside `billing` instead. */
238
+ firstName?: string;
239
+ /** @deprecated Pass lastName inside `billing` instead. */
240
+ lastName?: string;
241
+ }
242
+ /** Options for `vault.createBankToken()`. */
243
+ export interface BankTokenizeOptions {
244
+ /** Account holder first name. Required. */
245
+ firstName: string;
246
+ /** Account holder last name. Required. */
247
+ lastName: string;
248
+ }
249
+ /** Non-sensitive bank account metadata returned alongside the token. */
250
+ export interface BankAccountMetadata {
251
+ /** Last 4 digits of the account number. */
252
+ last4: string;
253
+ /** US routing number (9 digits). */
254
+ routingNumber: string;
255
+ }
256
+ /** Non-sensitive card metadata returned alongside the token. */
257
+ export interface CardMetadata {
258
+ /** Last 4 digits of the card number. */
259
+ last4: string;
260
+ /** Detected card brand (e.g. "visa", "mastercard", "amex"). */
261
+ brand: string;
262
+ /** 2-digit expiry month (e.g. "09"). */
263
+ expMonth: string;
264
+ /** 4-digit expiry year (e.g. "2027"). */
265
+ expYear: string;
266
+ }
267
+ export interface TokenResponse {
268
+ token: string;
269
+ cvcSession?: string;
270
+ /** Non-sensitive card metadata — available immediately without a cardSale call. */
271
+ card?: CardMetadata;
272
+ /**
273
+ * Validated, normalized billing details — ready to spread into a cardSale request.
274
+ * Only present when billing was passed to createToken().
275
+ */
276
+ billing?: BillingDetails;
277
+ }
278
+ /**
279
+ * Returned by `vault.createBankToken()` after successful ACH tokenization.
280
+ * The token can be passed to any ACH-capable payment processor.
281
+ * Note: OzuraPay does not currently support bank account payments.
282
+ */
283
+ export interface BankTokenResponse {
284
+ /** Vault token representing the bank account. Use with your ACH processor. */
285
+ token: string;
286
+ /** Non-sensitive bank account metadata. */
287
+ bank?: BankAccountMetadata;
288
+ }
289
+ /**
290
+ * Full request body for the Ozura Pay API cardSale endpoint.
291
+ * All string fields are 1–50 characters. billingAddress2 is optional (omit if blank).
292
+ *
293
+ * Headers required:
294
+ * x-api-key: <merchantApiKey>
295
+ * vault-api-key: <vaultApiKey> (same key passed to OzVault)
296
+ */
297
+ export interface CardSaleRequest {
298
+ /** Processor to use. If omitted, the Pay API auto-selects (Elavon → Nuvei → Worldpay). */
299
+ processor?: 'elavon' | 'nuvei' | 'worldpay';
300
+ merchantId: string;
301
+ /** Decimal string, e.g. "49.00". */
302
+ amount: string;
303
+ /** ISO 4217, e.g. "USD". */
304
+ currency: string;
305
+ /** From TokenResponse.token */
306
+ ozuraCardToken: string;
307
+ /** From TokenResponse.cvcSession */
308
+ ozuraCvcSession: string;
309
+ billingFirstName: string;
310
+ billingLastName: string;
311
+ billingEmail: string;
312
+ /** E.164 format, max 50 chars. */
313
+ billingPhone: string;
314
+ billingAddress1: string;
315
+ /** Omit entirely if blank — schema enforces minLength 1 if present. */
316
+ billingAddress2?: string;
317
+ billingCity: string;
318
+ /** 2-letter state/province code. */
319
+ billingState: string;
320
+ billingZipcode: string;
321
+ /** ISO 3166-1 alpha-2. */
322
+ billingCountry: string;
323
+ /** Fetch from your server — use an internal route, not api.ipify.org (ad-blockers block it). */
324
+ clientIpAddress: string;
325
+ salesTaxExempt: boolean;
326
+ /** Defaults to "0.00". Range 0–3. */
327
+ surchargePercent?: string;
328
+ /** Defaults to "0.00". */
329
+ tipAmount?: string;
330
+ }
331
+ /**
332
+ * The `data` object inside a successful cardSale API response.
333
+ *
334
+ * Store `transactionId` in your database immediately after receiving this —
335
+ * it is required for refunds and idempotency checks.
336
+ */
337
+ export interface CardSaleResponseData {
338
+ /** Unique transaction reference — store this in your database. */
339
+ transactionId: string;
340
+ /** Amount charged, decimal string, e.g. "49.00". */
341
+ amount: string;
342
+ /** ISO 4217 currency code, e.g. "USD". */
343
+ currency: string;
344
+ /** Surcharge amount applied, e.g. "0.00". */
345
+ surchargeAmount: string;
346
+ /** Sales tax calculated by the Pay API based on billing address. */
347
+ salesTaxAmount?: string;
348
+ /** Tip amount applied, e.g. "0.00". */
349
+ tipAmount: string;
350
+ /** Last four digits of the card number. */
351
+ cardLastFour: string;
352
+ /** First six digits of the card number (BIN). */
353
+ cardBin?: string;
354
+ /** Expiry month as 2-digit string, e.g. "09". */
355
+ cardExpMonth: string;
356
+ /** Expiry year as 4-digit string, e.g. "2027". */
357
+ cardExpYear: string;
358
+ /** Card brand returned by processor, e.g. "visa", "mastercard", "amex". */
359
+ cardBrand: string;
360
+ /** Whether the card is a credit card (vs debit). */
361
+ isCreditCard?: boolean;
362
+ /** ISO 8601 transaction timestamp. */
363
+ transDate: string;
364
+ /** Merchant ID echoed back from the request. */
365
+ ozuraMerchantId: string;
366
+ /** Client IP address echoed back. */
367
+ clientIpAddress?: string;
368
+ /** Billing fields echoed back — useful for receipts. */
369
+ billingFirstName: string;
370
+ billingLastName: string;
371
+ billingEmail: string;
372
+ billingPhone: string;
373
+ billingAddress1: string;
374
+ billingAddress2?: string;
375
+ billingCity: string;
376
+ billingState: string;
377
+ billingZipcode: string;
378
+ billingCountry: string;
379
+ }
380
+ /**
381
+ * Full response envelope from the Ozura Pay API cardSale endpoint.
382
+ *
383
+ * On success: `{ success: true, data: CardSaleResponseData }`
384
+ * On failure: HTTP 4xx/5xx with `{ error: string }` — pass `error` to
385
+ * `normalizeCardSaleError()` to get a user-facing message.
386
+ */
387
+ export interface CardSaleApiResponse {
388
+ success: boolean;
389
+ data: CardSaleResponseData;
390
+ }
391
+ /** Query params for GET /api/v1/transQuery. */
392
+ export interface TransactionQueryParams {
393
+ merchantId: string;
394
+ /** Fetch a specific transaction. */
395
+ transactionId?: string;
396
+ /** Date range start, format "YYYY-MM-DD HH:MM:SS". */
397
+ dateFrom?: string;
398
+ /** Date range end, format "YYYY-MM-DD HH:MM:SS". */
399
+ dateTo?: string;
400
+ /** Filter by type, e.g. "sale", "refund". */
401
+ transactionType?: string;
402
+ /** 1-based page number. Default: 1. */
403
+ page?: number;
404
+ /** Results per page. Default: 50, max: 100. */
405
+ limit?: number;
406
+ /** Comma-separated field names to return. */
407
+ fields?: string;
408
+ sortBy?: string;
409
+ sortOrder?: 'asc' | 'desc';
410
+ }
411
+ export interface TransactionQueryPagination {
412
+ currentPage: number;
413
+ totalPages: number;
414
+ totalCount: number;
415
+ limit: number;
416
+ hasNextPage: boolean;
417
+ hasPrevPage: boolean;
418
+ nextPage: number | null;
419
+ prevPage: number | null;
420
+ }
421
+ export interface TransactionQueryResponse {
422
+ success: boolean;
423
+ data: CardSaleResponseData[];
424
+ pagination: TransactionQueryPagination;
425
+ }
426
+ export type OzMessageType = 'OZ_FRAME_READY' | 'OZ_INIT' | 'OZ_UPDATE' | 'OZ_CLEAR' | 'OZ_CHANGE' | 'OZ_FOCUS' | 'OZ_BLUR' | 'OZ_RESIZE' | 'OZ_SET_TOKENIZER_NAME' | 'OZ_BEGIN_COLLECT' | 'OZ_FIELD_VALUE' | 'OZ_TOKENIZE' | 'OZ_TOKEN_RESULT' | 'OZ_TOKEN_ERROR' | 'OZ_FOCUS_REQUEST' | 'OZ_BLUR_REQUEST' | 'OZ_SET_CVV_LENGTH' | 'OZ_BANK_TOKENIZE' | 'OZ_BANK_TOKEN_RESULT';
427
+ export interface OzMessage {
428
+ __oz: true;
429
+ vaultId: string;
430
+ type: OzMessageType;
431
+ [key: string]: unknown;
432
+ }
@@ -0,0 +1,13 @@
1
+ import type { Appearance, ElementStyleConfig } from '../types';
2
+ /**
3
+ * Resolves an `Appearance` config into a flat `ElementStyleConfig`.
4
+ * Resolution order: theme defaults → variable overrides.
5
+ * The returned config is then used as the "base appearance" that
6
+ * per-element `style` overrides merge on top of.
7
+ */
8
+ export declare function resolveAppearance(appearance?: Appearance): ElementStyleConfig | undefined;
9
+ /**
10
+ * Merges a resolved appearance with per-element style overrides.
11
+ * Element styles always win over appearance styles.
12
+ */
13
+ export declare function mergeAppearanceWithElementStyle(appearance: ElementStyleConfig | undefined, elementStyle: ElementStyleConfig | undefined): ElementStyleConfig | undefined;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * billingUtils.ts — billing detail validation and normalization.
3
+ *
4
+ * Mirrors the validation in checkout/page.tsx (pre-flight checks before cardSale)
5
+ * so that billing data passed to createToken() is guaranteed schema-compliant and
6
+ * ready to forward directly to the Ozura Pay API cardSale endpoint.
7
+ *
8
+ * All string fields enforced to 1–50 characters (cardSale schema constraint).
9
+ * State is normalized to 2-letter abbreviation for US and CA.
10
+ * Phone must be E.164 format (matches checkout's formatPhoneForAPI output).
11
+ */
12
+ import { BillingDetails } from '../types';
13
+ /** Returns true when the email is syntactically valid and ≤50 characters. */
14
+ export declare function validateEmail(email: string): boolean;
15
+ /**
16
+ * Validates E.164 phone format: starts with +, 1–3 digit country code,
17
+ * followed by 7–12 digits, total ≤50 characters.
18
+ *
19
+ * Matches the output of checkout's formatPhoneForAPI() function.
20
+ * Examples: "+15551234567", "+447911123456", "+61412345678"
21
+ */
22
+ export declare function validateE164Phone(phone: string): boolean;
23
+ /** Returns true when the string is non-empty and ≤50 characters (cardSale schema). */
24
+ export declare function isValidBillingField(value: string): boolean;
25
+ /**
26
+ * Converts a full US state or Canadian province name to its 2-letter abbreviation.
27
+ * If already a valid abbreviation (case-insensitive), returns it uppercased.
28
+ * For non-US/CA countries, returns the input uppercased unchanged.
29
+ *
30
+ * Matches checkout's convertStateToAbbreviation() behaviour exactly.
31
+ */
32
+ export declare function normalizeState(state: string, country: string): string;
33
+ /**
34
+ * Validates a postal/ZIP code against country-specific format rules.
35
+ * For countries without a specific pattern, falls back to generic 1–50 char check.
36
+ */
37
+ export declare function validatePostalCode(zip: string, country: string): {
38
+ valid: boolean;
39
+ error?: string;
40
+ };
41
+ export interface BillingValidationResult {
42
+ valid: boolean;
43
+ /** One entry per failing field, each suitable for display in a thrown OzError message. */
44
+ errors: string[];
45
+ /** Trimmed and normalized billing details — state converted, address2 omitted if blank. */
46
+ normalized: BillingDetails;
47
+ }
48
+ /**
49
+ * Validates and normalizes billing details against the Ozura cardSale API schema.
50
+ *
51
+ * Rules applied (same as checkout's pre-flight validation in page.tsx):
52
+ * - firstName, lastName: required, 1–50 chars
53
+ * - email: optional; if provided, must be valid format and ≤50 chars
54
+ * - phone: optional; if provided, must be E.164 and ≤50 chars
55
+ * - address fields: if address is provided, line1/city/state/zip/country are
56
+ * required (1–50 chars each); line2 is optional and omitted from normalized
57
+ * output if blank (cardSale schema: minLength 1 if present)
58
+ * - state: normalized to 2-letter abbreviation for US and CA
59
+ */
60
+ export declare function validateBilling(billing: BillingDetails): BillingValidationResult;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * cardUtils.ts — pure card validation and formatting helpers.
3
+ *
4
+ * These functions contain no DOM or browser dependencies and are shared
5
+ * between the element frame runtime and the test suite.
6
+ */
7
+ /** Returns true when the digit string passes the Luhn checksum. */
8
+ export declare function luhn(digits: string): boolean;
9
+ export type CardBrand = 'visa' | 'mastercard' | 'amex' | 'dinersclub' | 'discover' | 'jcb' | 'unknown';
10
+ /** Detects the card brand from the leading digits. Returns 'unknown' for no match. */
11
+ export declare function detectBrand(num: string): CardBrand;
12
+ /** Maximum digit length allowed for a given brand. */
13
+ export declare function getCardMaxLength(brand: CardBrand | string): number;
14
+ /**
15
+ * Formats raw card digits into the display string for the given brand.
16
+ * Amex: 4-6-5 grouping. All others: groups of 4.
17
+ */
18
+ export declare function formatCard(digits: string, brand: CardBrand | string): string;
19
+ export interface CardValidationResult {
20
+ complete: boolean;
21
+ valid: boolean;
22
+ error?: string;
23
+ }
24
+ export declare function validateCardNumber(digits: string, brand: CardBrand | string): CardValidationResult;
25
+ export interface ExpiryValidationResult {
26
+ complete: boolean;
27
+ valid: boolean;
28
+ month?: string;
29
+ year?: string;
30
+ error?: string;
31
+ }
32
+ /**
33
+ * Validates a raw 4-digit MMYY string (as stored by the element frame).
34
+ * Month is clamped to 01–12 at input time, so only past-date and
35
+ * incomplete checks are needed here.
36
+ */
37
+ export declare function validateExpiry(rawMMYY: string): ExpiryValidationResult;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * elementFrame.ts — runs inside an <iframe> served from Ozura's domain.
3
+ *
4
+ * Renders a single card or bank input, manages formatting/validation, and
5
+ * communicates with the host SDK via postMessage. Raw values NEVER leave this
6
+ * file except when sent directly to the tokenizer frame (same-origin).
7
+ */
8
+ export {};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * tokenizerFrame.ts — runs inside a hidden <iframe> served from Ozura's domain.
3
+ *
4
+ * Collects raw card field values sent by element frames (same-origin),
5
+ * assembles the vault tokenization payload, and POSTs it directly to the
6
+ * vault API. The merchant page never sees raw card data.
7
+ */
8
+ /**
9
+ * Returns true when the given URL's origin is in the compile-time allowlist.
10
+ * For localhost entries, any port is accepted (dev-server port varies).
11
+ * Exported for unit testing only — not part of the public SDK API.
12
+ */
13
+ export declare function isAllowedVaultOrigin(apiUrl: string): boolean;
@@ -0,0 +1,65 @@
1
+ import { ElementType, BankElementType, ElementOptions, ElementStyleConfig, FontSource, OzMessage } from '../types';
2
+ type AnyElementType = ElementType | BankElementType;
3
+ type ElementEvent = 'ready' | 'change' | 'focus' | 'blur' | 'loaderror';
4
+ type ElementCallback = (payload?: unknown) => void;
5
+ /**
6
+ * A proxy for one Ozura iframe element. Merchants interact with this object;
7
+ * it never holds raw card data — all sensitive values live in the iframe.
8
+ */
9
+ export declare class OzElement {
10
+ private elementType;
11
+ private options;
12
+ private vaultId;
13
+ readonly frameId: string;
14
+ private frameBaseUrl;
15
+ private frameOrigin;
16
+ private fonts;
17
+ private appearanceStyle;
18
+ private iframe;
19
+ private _frameWindow;
20
+ private _ready;
21
+ private _destroyed;
22
+ private _loadTimer;
23
+ private pendingMessages;
24
+ private handlers;
25
+ constructor(elementType: AnyElementType, options: ElementOptions, vaultId: string, frameBaseUrl: string, fonts?: FontSource[], appearanceStyle?: ElementStyleConfig);
26
+ /** The element type this proxy represents. */
27
+ get type(): AnyElementType;
28
+ /** True once the element iframe has loaded and signalled ready. */
29
+ get isReady(): boolean;
30
+ /**
31
+ * Mounts the element iframe into a container.
32
+ * Accepts either a CSS selector string or a direct HTMLElement reference
33
+ * (useful when integrating with React refs).
34
+ */
35
+ mount(target: string | HTMLElement): void;
36
+ on(event: ElementEvent, callback: ElementCallback): this;
37
+ off(event: ElementEvent, callback: ElementCallback): this;
38
+ once(event: ElementEvent, callback: ElementCallback): this;
39
+ update(options: Partial<ElementOptions>): void;
40
+ clear(): void;
41
+ /**
42
+ * Removes the iframe from the DOM and resets internal state.
43
+ * Called automatically by `OzVault.destroy()`. Safe to call manually
44
+ * for partial teardown (e.g. swapping payment method in a SPA).
45
+ */
46
+ unmount(): void;
47
+ /** Programmatically focus this element's input. Used internally for auto-advance. */
48
+ focus(): void;
49
+ /** Programmatically blur this element's input. */
50
+ blur(): void;
51
+ /**
52
+ * Permanently destroys this element: unmounts it, clears all event handlers,
53
+ * and prevents future use. Distinct from `unmount()` which allows re-mounting.
54
+ */
55
+ destroy(): void;
56
+ setTokenizerName(tokenizerName: string): void;
57
+ beginCollect(requestId: string): void;
58
+ /** Tell a CVV element how many digits to expect. Called automatically when card brand changes. */
59
+ setCvvLength(length: number): void;
60
+ handleMessage(msg: OzMessage): void;
61
+ private emit;
62
+ private post;
63
+ private send;
64
+ }
65
+ export {};