@movmo_app/payments 0.1.0 → 0.2.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.
package/dist/index.d.ts CHANGED
@@ -7,6 +7,23 @@ export declare interface CardFieldError {
7
7
  message: string;
8
8
  }
9
9
 
10
+ /**
11
+ * Focus state of each Spreedly-hosted iframe. The browser's `focus-within`
12
+ * CSS pseudo-class can't see across iframe boundaries, so the consumer needs
13
+ * an explicit signal to render the "active border" on the iframe shell.
14
+ */
15
+ declare interface CardFieldFocus {
16
+ number: boolean;
17
+ cvv: boolean;
18
+ }
19
+
20
+ declare interface CardFieldValidity {
21
+ /** True only when the card-number field has a complete, length-valid value. */
22
+ number: boolean;
23
+ /** True only when the CVV field has a complete value (3 or 4 digits). */
24
+ cvv: boolean;
25
+ }
26
+
10
27
  export declare type CardFormStatus = 'idle' | 'loading' | 'ready' | 'tokenizing' | 'saving' | 'error';
11
28
 
12
29
  export declare interface CardholderTokenizeData {
@@ -25,7 +42,7 @@ export declare const getPaymentsConfig: () => InternalPaymentsConfig;
25
42
  /* Excluded from this release type: InternalPaymentsConfig */
26
43
 
27
44
  export declare const MovmoCardForm: {
28
- ({ userId, onSuccess, onError, isDefault, className, defaultCardholderFirstName, defaultCardholderLastName, }: MovmoCardFormProps): JSX_2.Element;
45
+ ({ userId, onSuccess, onError, isDefault, className, defaultCardholderName, defaultCardholderFirstName, defaultCardholderLastName, autoSave, formId, hideInternalSaveButton, onCanSubmitChange, onSavingChange, autoFocus, }: MovmoCardFormProps): JSX_2.Element;
29
46
  displayName: string;
30
47
  };
31
48
 
@@ -36,13 +53,151 @@ export declare interface MovmoCardFormProps {
36
53
  isDefault?: boolean;
37
54
  className?: string;
38
55
  /**
39
- * Pre-fills the cardholder first-name input. Cardholders aren't always the
56
+ * Pre-fills the cardholder name input. Cardholders aren't always the
40
57
  * logged-in user (spouse card, corporate card), so the field remains
41
- * editable — pass `user.firstName` as a sensible default.
58
+ * editable — pass `user.fullName` as a sensible default.
59
+ */
60
+ defaultCardholderName?: string;
61
+ /**
62
+ * @deprecated Prefer `defaultCardholderName`. Concatenated with
63
+ * `defaultCardholderLastName` to seed the single cardholder name field.
42
64
  */
43
65
  defaultCardholderFirstName?: string;
44
- /** Pre-fills the cardholder last-name input. See `defaultCardholderFirstName`. */
66
+ /** @deprecated See `defaultCardholderFirstName`. */
45
67
  defaultCardholderLastName?: string;
68
+ /**
69
+ * When true, the form submits automatically the moment all fields are valid —
70
+ * no Save button is rendered. Matches the flights-ui "first card" auto-save UX.
71
+ * Defaults to `false`.
72
+ */
73
+ autoSave?: boolean;
74
+ /**
75
+ * HTML `id` for the underlying `<form>` element. Lets a parent (e.g. modal
76
+ * footer) wire its own submit button via `<button type="submit" form="...">`
77
+ * — useful when `hideInternalSaveButton` is true. Defaults to `movmo-card-form`.
78
+ */
79
+ formId?: string;
80
+ /**
81
+ * When true, the form omits its internal Save button. Use together with
82
+ * `formId` to drive submit from a parent (e.g. a modal footer's Save button).
83
+ */
84
+ hideInternalSaveButton?: boolean;
85
+ /**
86
+ * Fires whenever the "ready to submit" state changes (all fields valid +
87
+ * not in flight). Use to enable / disable an external Save button.
88
+ */
89
+ onCanSubmitChange?: (canSubmit: boolean) => void;
90
+ /**
91
+ * Fires whenever the form transitions in / out of the "saving" state
92
+ * (tokenize call or save POST in flight). A parent rendering its own
93
+ * Save button (e.g. a modal footer) uses this to swap the button label
94
+ * for a spinner. The hook's loading state is internal and not surfaced
95
+ * directly — this callback is the single source of truth.
96
+ */
97
+ onSavingChange?: (isSaving: boolean) => void;
98
+ /**
99
+ * When set, the named Spreedly hosted-fields iframe receives keyboard
100
+ * focus the moment the field becomes ready. Use `"number"` for the
101
+ * accounts-ui add-card modal so the user can start typing immediately.
102
+ */
103
+ autoFocus?: 'number' | 'cvv';
104
+ }
105
+
106
+ /**
107
+ * Compact preview of a single saved card: brand icon + label. Used by
108
+ * consumers (e.g. flights-ui's collapsed checkout drawer) to show the
109
+ * currently-selected card outside the full `<PaymentMethodsManager />`
110
+ * list view. Keeps the brand-icon styling consistent with the expanded list.
111
+ *
112
+ * Brand icon is sized to match flights-ui main's `w-[34px]` collapsed view.
113
+ * No vertical padding — the parent controls spacing.
114
+ */
115
+ export declare const PaymentMethodPreview: ({ method, trailing, onClick, cardLabelFormat, className, }: PaymentMethodPreviewProps) => JSX_2.Element;
116
+
117
+ export declare interface PaymentMethodPreviewProps {
118
+ /**
119
+ * The card to render. Consumers typically derive this from
120
+ * `useUserPaymentMethods(userId)` — e.g. the selected card in a checkout
121
+ * drawer, or the default card on a summary line.
122
+ */
123
+ method: PaymentMethodSummary;
124
+ /** Trailing slot — flights-ui drops an expand-chevron button here. */
125
+ trailing?: React.ReactNode;
126
+ /** Whole-row click handler — typically toggles the drawer open. */
127
+ onClick?: () => void;
128
+ /**
129
+ * Controls how the card label is rendered.
130
+ * - `'branded'` (default): "Visa 4242" — brand name + last4
131
+ * - `'masked'`: "•••• 4242" — masked bullets + last4 (flights-ui collapsed-drawer style)
132
+ */
133
+ cardLabelFormat?: 'masked' | 'branded';
134
+ className?: string;
135
+ }
136
+
137
+ export declare const PaymentMethodsManager: {
138
+ ({ userId, defaultCardholderName, defaultCardholderFirstName, defaultCardholderLastName, selectedId, onSelect, onChange, paymentTypeSelector, autoSaveFirstCard, selectionSetsDefault, showDefaultBadge, collapsible, cardLabelFormat, className, }: PaymentMethodsManagerProps): JSX_2.Element;
139
+ displayName: string;
140
+ };
141
+
142
+ export declare interface PaymentMethodsManagerProps {
143
+ userId: string;
144
+ /**
145
+ * Pre-fill the single cardholder-name input in the add-card form.
146
+ * Falls back to `defaultCardholderFirstName + " " + defaultCardholderLastName`
147
+ * for backward compatibility with the legacy MovmoCardForm props.
148
+ */
149
+ defaultCardholderName?: string;
150
+ /** @deprecated Use `defaultCardholderName`. */
151
+ defaultCardholderFirstName?: string;
152
+ /** @deprecated Use `defaultCardholderName`. */
153
+ defaultCardholderLastName?: string;
154
+ /** Selection (opt-in). When `onSelect` is provided, each row renders a radio. */
155
+ selectedId?: string;
156
+ onSelect?: (method: PaymentMethodSummary) => void;
157
+ /** Fires when the list state changes (add, delete, set-default). */
158
+ onChange?: (items: PaymentMethodSummary[]) => void;
159
+ /**
160
+ * Show the Credit card / PayPal / GooglePay / Klarna / ACH radios above
161
+ * the card-capture form. Only Credit card is functional today; the others
162
+ * render as "Coming soon" to match the existing flights-ui design without
163
+ * dropping the visual cues. Defaults to `true`. accounts-ui can opt out
164
+ * by passing `false`.
165
+ */
166
+ paymentTypeSelector?: boolean;
167
+ /**
168
+ * When `true` AND the user has zero saved cards, the card form auto-submits
169
+ * the moment all fields are valid. Matches the flights-ui first-card UX.
170
+ * Defaults to `true`.
171
+ */
172
+ autoSaveFirstCard?: boolean;
173
+ /**
174
+ * When `true`, clicking a row both fires `onSelect` AND sets that method
175
+ * as the default (the flights-ui checkout model: "selected = default").
176
+ * Also hides the "Set as default" menu item since the row click already
177
+ * does it. Requires `onSelect` to be useful. Defaults to `false`.
178
+ */
179
+ selectionSetsDefault?: boolean;
180
+ /**
181
+ * Render the green "Default" pill on the default row. accounts-ui keeps
182
+ * this on; flights-ui passes `false` (the thick selected-border alone
183
+ * communicates default since `selectionSetsDefault` couples the two).
184
+ * Defaults to `true`.
185
+ */
186
+ showDefaultBadge?: boolean;
187
+ /**
188
+ * When `true` AND the user has at least one saved card, the list collapses
189
+ * into a compact preview row with a chevron-down toggle. Expanding shows the
190
+ * full list + Add button. Defaults to `false` (accounts-ui behaviour).
191
+ * flights-ui passes `true`.
192
+ */
193
+ collapsible?: boolean;
194
+ /**
195
+ * Controls the card label format inside rows.
196
+ * - `'branded'` (default): "Visa 4242" — brand name + last4
197
+ * - `'masked'`: "•••• 4242" — masked bullets + last4 (flights-ui style)
198
+ */
199
+ cardLabelFormat?: 'masked' | 'branded';
200
+ className?: string;
46
201
  }
47
202
 
48
203
  export declare interface PaymentMethodSummary {
@@ -56,10 +211,42 @@ export declare interface PaymentMethodSummary {
56
211
 
57
212
  export declare interface PaymentsConfig {
58
213
  baseUrl: string;
214
+ /**
215
+ * Base URL for Movmo's payment-icon assets (Visa / MC / Amex / Discover SVGs
216
+ * + PayPal / GooglePay / Klarna PNGs). Defaults to the e2e CDN; prod
217
+ * consumers should override at boot once a prod CDN is set up.
218
+ */
219
+ iconCdnBaseUrl?: string;
220
+ /**
221
+ * Custom `fetch` impl used by every API call in this package. Defaults to
222
+ * `globalThis.fetch`. Consumers that need auth-token refresh, CSRF-token
223
+ * injection, or any other request-shaping logic should provide their own
224
+ * wrapper here (e.g. one that retries on 401/403 after refreshing the
225
+ * session cookie). The package never adds business headers — that's the
226
+ * consumer's responsibility.
227
+ */
228
+ fetch?: typeof fetch;
59
229
  }
60
230
 
61
231
  export declare const setPaymentsConfig: (config: Partial<PaymentsConfig>) => void;
62
232
 
233
+ /**
234
+ * Calls `DELETE /v1/users/:userId/payment-methods/:methodId`.
235
+ *
236
+ * The hook owns the network call + status; consumers own list state so they
237
+ * can apply optimistic updates / rollback at their layer. The returned promise
238
+ * resolves on success and rejects on failure so callers can roll back.
239
+ */
240
+ export declare const useDeletePaymentMethod: (userId: string) => UseDeletePaymentMethodResult;
241
+
242
+ export declare interface UseDeletePaymentMethodResult {
243
+ deletePaymentMethod: (methodId: string) => Promise<void>;
244
+ status: UseDeletePaymentMethodStatus;
245
+ error: string | null;
246
+ }
247
+
248
+ export declare type UseDeletePaymentMethodStatus = 'idle' | 'pending' | 'error';
249
+
63
250
  /**
64
251
  * Mounts PCI-safe card-capture fields into the DOM containers identified by
65
252
  * `numberEl` and `cvvEl`, fetches a signed tokenization session from
@@ -79,12 +266,76 @@ export declare interface UseMovmoCardFieldsOptions {
79
266
  cvvEl?: string;
80
267
  onCardTokenized?: (token: string) => void;
81
268
  onFieldErrors?: (errors: CardFieldError[]) => void;
269
+ /**
270
+ * Fires whenever per-field validity changes (number length valid, CVV length valid).
271
+ * Use to gate the save button at the form layer.
272
+ */
273
+ onValidityChange?: (validity: CardFieldValidity) => void;
274
+ /**
275
+ * Fires whenever the detected card brand changes (visa/master/american_express/discover/etc).
276
+ * Use to render the brand icon inline with the card-number field.
277
+ */
278
+ onBrandChange?: (brand: string | null) => void;
82
279
  }
83
280
 
84
281
  export declare interface UseMovmoCardFieldsResult {
85
282
  status: 'idle' | 'loading' | 'ready' | 'error';
86
283
  error: string | null;
87
284
  tokenize: (data: CardholderTokenizeData) => void;
285
+ /** Latest validity snapshot — also pushed via `onValidityChange`. */
286
+ validity: CardFieldValidity;
287
+ /** Latest detected brand (or null if unknown). */
288
+ brand: string | null;
289
+ /**
290
+ * Live focus state for each iframe. True while the user is editing that
291
+ * field. Consumers use this to apply an "active" border on the iframe shell
292
+ * (the browser's `:focus-within` CSS doesn't propagate across iframes).
293
+ */
294
+ focused: CardFieldFocus;
295
+ /**
296
+ * Programmatically move keyboard focus into one of the Spreedly iframes.
297
+ * No-op when the hook is not in the `'ready'` state. Used to auto-advance
298
+ * focus from an outer form input (e.g. expiry) into a hosted field (CVV).
299
+ */
300
+ focusField: (field: 'number' | 'cvv') => void;
301
+ }
302
+
303
+ /**
304
+ * Calls `PUT /v1/users/:userId/payment-methods/:methodId` with
305
+ * `{ isDefault: true }`. Server clears the previous default automatically.
306
+ *
307
+ * The hook owns the network call + status; consumers own list state so they
308
+ * can apply optimistic updates / rollback at their layer. The returned promise
309
+ * resolves on success and rejects on failure so callers can roll back.
310
+ */
311
+ export declare const useSetDefaultPaymentMethod: (userId: string) => UseSetDefaultPaymentMethodResult;
312
+
313
+ export declare interface UseSetDefaultPaymentMethodResult {
314
+ setDefault: (methodId: string) => Promise<void>;
315
+ status: UseSetDefaultPaymentMethodStatus;
316
+ error: string | null;
88
317
  }
89
318
 
319
+ export declare type UseSetDefaultPaymentMethodStatus = 'idle' | 'pending' | 'error';
320
+
321
+ /**
322
+ * Fetches a user's saved payment methods from monolith-api.
323
+ *
324
+ * Auto-runs on mount and whenever `userId` changes. Cancels the in-flight
325
+ * request on unmount or refetch so consumers don't see stale results land
326
+ * after a navigation. Status mirrors `useMovmoCardFields`:
327
+ * `idle` → `loading` → `ready | error`.
328
+ */
329
+ export declare const useUserPaymentMethods: (userId: string) => UseUserPaymentMethodsResult;
330
+
331
+ export declare interface UseUserPaymentMethodsResult {
332
+ items: PaymentMethodSummary[];
333
+ status: UseUserPaymentMethodsStatus;
334
+ error: string | null;
335
+ /** Re-issues the GET request. Cancels any in-flight request first. */
336
+ refetch: () => void;
337
+ }
338
+
339
+ export declare type UseUserPaymentMethodsStatus = 'idle' | 'loading' | 'ready' | 'error';
340
+
90
341
  export { }