@heyama/pay-react-native 1.0.1 → 1.0.2
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/checkout-core/hooks/use-checkout-controller.js +20 -20
- package/dist/checkout-core/hooks/use-checkout-timers.d.ts +6 -3
- package/dist/checkout-core/hooks/use-checkout-timers.js +6 -6
- package/dist/checkout-core/models/checkout.enum.d.ts +6 -0
- package/dist/checkout-core/models/checkout.enum.js +7 -0
- package/dist/checkout-core/models/checkout.interface.d.ts +9 -2
- package/dist/components/SheetCodeField.js +1 -1
- package/dist/components/SheetContent.js +1 -1
- package/dist/components/SheetFailed.js +2 -2
- package/dist/components/SheetIcon.js +9 -2
- package/dist/components/SheetMessage.js +1 -1
- package/dist/components/SheetPhoneField.js +1 -1
- package/dist/components/SheetSimulator.js +1 -1
- package/dist/components/SheetSuccess.js +1 -1
- package/dist/components/SheetText.d.ts +2 -2
- package/dist/components/SheetText.js +4 -2
- package/dist/components/SheetToast.d.ts +6 -2
- package/dist/components/SheetToast.js +58 -11
- package/dist/components/SheetWaiting.js +1 -1
- package/dist/models/sheet.constants.d.ts +2 -0
- package/dist/models/sheet.constants.js +2 -0
- package/dist/models/sheet.interface.d.ts +4 -2
- package/package.json +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { useFormatter, useTranslations } from 'use-intl';
|
|
3
3
|
import { COPIED_MS, FLOW_TRAITS, OTP_MAX_LENGTH, OTP_PATTERN, } from "../models/checkout.constants.js";
|
|
4
|
-
import { CardFieldsMessageEnum, CheckoutScreenEnum, CheckoutTabEnum, MethodFlowEnum, MethodStateEnum, PayRefusalEnum, } from "../models/checkout.enum.js";
|
|
4
|
+
import { CardFieldsMessageEnum, CheckoutScreenEnum, CheckoutTabEnum, CheckoutToastToneEnum, MethodFlowEnum, MethodStateEnum, PayRefusalEnum, } from "../models/checkout.enum.js";
|
|
5
5
|
import { CountryEnum } from "../models/domain.enum.js";
|
|
6
6
|
import { cardLabel } from "../models/checkout.card.utils.js";
|
|
7
7
|
import { formatMoney } from "../models/checkout.money.utils.js";
|
|
8
8
|
import { maskE164 } from "../models/checkout.phone.utils.js";
|
|
9
|
-
import { countriesOf, deriveCheckout, initialUi, screenOf, waitLeftOf, } from "../models/checkout.view.utils.js";
|
|
9
|
+
import { countriesOf, deriveCheckout, initialUi, logoOf, screenOf, waitLeftOf, } from "../models/checkout.view.utils.js";
|
|
10
10
|
import { useNow, useReturnCountdown, useToast } from "./use-checkout-timers.js";
|
|
11
11
|
import { usePhoneNumber } from "./use-phone-number.js";
|
|
12
12
|
/** Before the payment has loaded, or for a link that matches none. */
|
|
@@ -84,7 +84,7 @@ export function useCheckoutController(view, { clues, mutations, platform }) {
|
|
|
84
84
|
if (!waiting || waitLeft > 0)
|
|
85
85
|
return;
|
|
86
86
|
update({ dismissed: attemptReference });
|
|
87
|
-
showToast(noAnswer);
|
|
87
|
+
showToast(noAnswer, CheckoutToastToneEnum.WARNING);
|
|
88
88
|
}, [waiting, waitLeft, attemptReference, noAnswer, showToast, update]);
|
|
89
89
|
const paymentId = view?.id;
|
|
90
90
|
// A payer opened the link, said once per page (the dashboard's preview has no mutations).
|
|
@@ -131,7 +131,7 @@ export function useCheckoutController(view, { clues, mutations, platform }) {
|
|
|
131
131
|
break;
|
|
132
132
|
case CardFieldsMessageEnum.REFUSED:
|
|
133
133
|
update({ cardPaying: false });
|
|
134
|
-
showToast(message.reason ? refusals(message.reason) : failedToast);
|
|
134
|
+
showToast(message.reason ? refusals(message.reason) : failedToast, CheckoutToastToneEnum.WARNING);
|
|
135
135
|
break;
|
|
136
136
|
}
|
|
137
137
|
};
|
|
@@ -139,7 +139,7 @@ export function useCheckoutController(view, { clues, mutations, platform }) {
|
|
|
139
139
|
}, [update, showToast, refusals, failedToast, platform]);
|
|
140
140
|
/* ---------------------------------------------------------- helpers */
|
|
141
141
|
const reference = attempt?.reference ?? view?.id ?? '';
|
|
142
|
-
const comingSoon = (name) => toast.show(t('toast.soon', { method: name }));
|
|
142
|
+
const comingSoon = (name) => toast.show(t('toast.soon', { method: name }), CheckoutToastToneEnum.INFO);
|
|
143
143
|
/**
|
|
144
144
|
* Starts an attempt with the number, and the payment code of an OTP
|
|
145
145
|
* method; a second tap while one is on its way does nothing.
|
|
@@ -155,9 +155,9 @@ export function useCheckoutController(view, { clues, mutations, platform }) {
|
|
|
155
155
|
: mutations.payWithCode({ ...args, otp }))
|
|
156
156
|
.then((result) => {
|
|
157
157
|
if (!result.ok)
|
|
158
|
-
toast.show(t(`refusals.${result.reason}`));
|
|
158
|
+
toast.show(t(`refusals.${result.reason}`), CheckoutToastToneEnum.WARNING);
|
|
159
159
|
})
|
|
160
|
-
.catch(() => toast.show(t('toast.failed')))
|
|
160
|
+
.catch(() => toast.show(t('toast.failed'), CheckoutToastToneEnum.WARNING))
|
|
161
161
|
.finally(() => {
|
|
162
162
|
paying.current = false;
|
|
163
163
|
update({ submitting: false });
|
|
@@ -188,7 +188,7 @@ export function useCheckoutController(view, { clues, mutations, platform }) {
|
|
|
188
188
|
comingSoon(method.name);
|
|
189
189
|
}
|
|
190
190
|
else if (method.state === MethodStateEnum.MAINTENANCE) {
|
|
191
|
-
toast.show(method.note ?? t('toast.unavailable', { method: method.name }));
|
|
191
|
+
toast.show(method.note ?? t('toast.unavailable', { method: method.name }), CheckoutToastToneEnum.WARNING, logoOf(method));
|
|
192
192
|
}
|
|
193
193
|
else {
|
|
194
194
|
update({
|
|
@@ -205,7 +205,7 @@ export function useCheckoutController(view, { clues, mutations, platform }) {
|
|
|
205
205
|
switchToDetected: () => {
|
|
206
206
|
const detected = derived.mismatch;
|
|
207
207
|
update({ method: detected.id });
|
|
208
|
-
toast.show(t('toast.switched', { method: detected.name }));
|
|
208
|
+
toast.show(t('toast.switched', { method: detected.name }), CheckoutToastToneEnum.SUCCESS, logoOf(detected));
|
|
209
209
|
},
|
|
210
210
|
pay: () => {
|
|
211
211
|
const { selected } = derived;
|
|
@@ -225,11 +225,11 @@ export function useCheckoutController(view, { clues, mutations, platform }) {
|
|
|
225
225
|
}
|
|
226
226
|
const otp = selected.flow === MethodFlowEnum.OTP;
|
|
227
227
|
if (otp && !OTP_PATTERN.test(ui.code)) {
|
|
228
|
-
toast.show(t(`refusals.${PayRefusalEnum.CODE}`));
|
|
228
|
+
toast.show(t(`refusals.${PayRefusalEnum.CODE}`), CheckoutToastToneEnum.WARNING);
|
|
229
229
|
return;
|
|
230
230
|
}
|
|
231
231
|
if (!mutations) {
|
|
232
|
-
toast.show(t('toast.preview'));
|
|
232
|
+
toast.show(t('toast.preview'), CheckoutToastToneEnum.INFO);
|
|
233
233
|
return;
|
|
234
234
|
}
|
|
235
235
|
submit(selected.id, {
|
|
@@ -240,7 +240,7 @@ export function useCheckoutController(view, { clues, mutations, platform }) {
|
|
|
240
240
|
// Only offered while an OTP method, which always has its code, is picked.
|
|
241
241
|
cannotDial: () => {
|
|
242
242
|
const method = derived.selected;
|
|
243
|
-
toast.show(t('toast.dial', { code: method.otpCode, method: method.name }));
|
|
243
|
+
toast.show(t('toast.dial', { code: method.otpCode, method: method.name }), CheckoutToastToneEnum.INFO, logoOf(method));
|
|
244
244
|
},
|
|
245
245
|
// Only on the failure screen, which the preview never shows.
|
|
246
246
|
retry: () => {
|
|
@@ -273,15 +273,15 @@ export function useCheckoutController(view, { clues, mutations, platform }) {
|
|
|
273
273
|
resend: () => {
|
|
274
274
|
void mutations
|
|
275
275
|
.resend({ paymentId: view.id })
|
|
276
|
-
.then((result) =>
|
|
277
|
-
? t('toast.resent', { phone: maskE164(attempt.phone) })
|
|
278
|
-
: t('toast.resend_wait')))
|
|
279
|
-
.catch(() => toast.show(t('toast.failed')));
|
|
276
|
+
.then((result) => result.ok
|
|
277
|
+
? toast.show(t('toast.resent', { phone: maskE164(attempt.phone) }), CheckoutToastToneEnum.SUCCESS)
|
|
278
|
+
: toast.show(t('toast.resend_wait'), CheckoutToastToneEnum.INFO))
|
|
279
|
+
.catch(() => toast.show(t('toast.failed'), CheckoutToastToneEnum.WARNING));
|
|
280
280
|
},
|
|
281
281
|
cancel: () => {
|
|
282
282
|
void mutations
|
|
283
283
|
.cancel({ paymentId: view.id })
|
|
284
|
-
.catch(() => toast.show(t('toast.failed')));
|
|
284
|
+
.catch(() => toast.show(t('toast.failed'), CheckoutToastToneEnum.WARNING));
|
|
285
285
|
},
|
|
286
286
|
returnNow: goBack,
|
|
287
287
|
stayHere: countdown.stop,
|
|
@@ -292,11 +292,11 @@ export function useCheckoutController(view, { clues, mutations, platform }) {
|
|
|
292
292
|
clearTimeout(copiedTimer.current);
|
|
293
293
|
setCopied(true);
|
|
294
294
|
copiedTimer.current = setTimeout(() => setCopied(false), COPIED_MS);
|
|
295
|
-
toast.show(t('toast.copied'));
|
|
295
|
+
toast.show(t('toast.copied'), CheckoutToastToneEnum.SUCCESS);
|
|
296
296
|
},
|
|
297
297
|
downloadReceipt: () => {
|
|
298
298
|
platform.saveReceipt(`receipt-${reference}.txt`, receiptText(view));
|
|
299
|
-
toast.show(t('toast.downloaded'));
|
|
299
|
+
toast.show(t('toast.downloaded'), CheckoutToastToneEnum.SUCCESS);
|
|
300
300
|
},
|
|
301
301
|
simulate: (outcome) => {
|
|
302
302
|
void mutations.simulate({ paymentId: view.id, outcome });
|
|
@@ -310,7 +310,7 @@ export function useCheckoutController(view, { clues, mutations, platform }) {
|
|
|
310
310
|
waitLeft,
|
|
311
311
|
returnLeft: countdown.left,
|
|
312
312
|
helpOpen,
|
|
313
|
-
|
|
313
|
+
toast: toast.toast,
|
|
314
314
|
copied,
|
|
315
315
|
preview: !mutations,
|
|
316
316
|
cardHeight,
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { CheckoutToastToneEnum } from '../models/checkout.enum.js';
|
|
2
|
+
import type { ProviderLogoEnum } from '../models/domain.enum.js';
|
|
3
|
+
import type { CheckoutToast } from '../models/checkout.interface.js';
|
|
1
4
|
/** The time now, moving once a second while `running`: the waiting screen's clock. */
|
|
2
5
|
export declare function useNow(running: boolean): number;
|
|
3
6
|
/**
|
|
@@ -8,8 +11,8 @@ export declare function useReturnCountdown(running: boolean, onDone: () => void)
|
|
|
8
11
|
left: number | null;
|
|
9
12
|
stop: () => void;
|
|
10
13
|
};
|
|
11
|
-
/** One short message at a time at the top of the page. */
|
|
14
|
+
/** One short message at a time at the top of the page, with its tone and the method it is about. */
|
|
12
15
|
export declare function useToast(): {
|
|
13
|
-
|
|
14
|
-
show: (
|
|
16
|
+
toast: CheckoutToast | null;
|
|
17
|
+
show: (message: string, tone: CheckoutToastToneEnum, logo?: ProviderLogoEnum | null) => void;
|
|
15
18
|
};
|
|
@@ -30,15 +30,15 @@ export function useReturnCountdown(running, onDone) {
|
|
|
30
30
|
}, [running, left, onDone]);
|
|
31
31
|
return { left, stop: () => setLeft(null) };
|
|
32
32
|
}
|
|
33
|
-
/** One short message at a time at the top of the page. */
|
|
33
|
+
/** One short message at a time at the top of the page, with its tone and the method it is about. */
|
|
34
34
|
export function useToast() {
|
|
35
|
-
const [
|
|
35
|
+
const [toast, setToast] = useState(null);
|
|
36
36
|
const timer = useRef(undefined);
|
|
37
37
|
useEffect(() => () => clearTimeout(timer.current), []);
|
|
38
|
-
const show = useCallback((
|
|
38
|
+
const show = useCallback((message, tone, logo = null) => {
|
|
39
39
|
clearTimeout(timer.current);
|
|
40
|
-
|
|
41
|
-
timer.current = setTimeout(() =>
|
|
40
|
+
setToast({ message, tone, logo });
|
|
41
|
+
timer.current = setTimeout(() => setToast(null), TOAST_MS);
|
|
42
42
|
}, []);
|
|
43
|
-
return {
|
|
43
|
+
return { toast, show };
|
|
44
44
|
}
|
|
@@ -131,3 +131,9 @@ export declare enum CheckoutThemeEnum {
|
|
|
131
131
|
LIGHT = "light",
|
|
132
132
|
DARK = "dark"
|
|
133
133
|
}
|
|
134
|
+
/** What a toast says: done, a problem, or just good to know. Sets its icon. */
|
|
135
|
+
export declare enum CheckoutToastToneEnum {
|
|
136
|
+
SUCCESS = "success",
|
|
137
|
+
WARNING = "warning",
|
|
138
|
+
INFO = "info"
|
|
139
|
+
}
|
|
@@ -148,3 +148,10 @@ export var CheckoutThemeEnum;
|
|
|
148
148
|
CheckoutThemeEnum["LIGHT"] = "light";
|
|
149
149
|
CheckoutThemeEnum["DARK"] = "dark";
|
|
150
150
|
})(CheckoutThemeEnum || (CheckoutThemeEnum = {}));
|
|
151
|
+
/** What a toast says: done, a problem, or just good to know. Sets its icon. */
|
|
152
|
+
export var CheckoutToastToneEnum;
|
|
153
|
+
(function (CheckoutToastToneEnum) {
|
|
154
|
+
CheckoutToastToneEnum["SUCCESS"] = "success";
|
|
155
|
+
CheckoutToastToneEnum["WARNING"] = "warning";
|
|
156
|
+
CheckoutToastToneEnum["INFO"] = "info";
|
|
157
|
+
})(CheckoutToastToneEnum || (CheckoutToastToneEnum = {}));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CardFieldsMessageEnum, CheckoutPaymentStatusEnum, CheckoutScreenEnum, CheckoutTabEnum, CheckoutThemeEnum, MethodBrandEnum, MethodFlowEnum, MethodKindEnum, MethodStateEnum, PayRefusalEnum, PhoneErrorEnum, SimulatorOutcomeEnum, SupportChannelEnum } from './checkout.enum.js';
|
|
1
|
+
import type { CardFieldsMessageEnum, CheckoutPaymentStatusEnum, CheckoutToastToneEnum, CheckoutScreenEnum, CheckoutTabEnum, CheckoutThemeEnum, MethodBrandEnum, MethodFlowEnum, MethodKindEnum, MethodStateEnum, PayRefusalEnum, PhoneErrorEnum, SimulatorOutcomeEnum, SupportChannelEnum } from './checkout.enum.js';
|
|
2
2
|
import type { AttemptStatusEnum, CountryEnum, CurrencyEnum, FailureReasonEnum, LangEnum, ProviderLogoEnum } from './domain.enum.js';
|
|
3
3
|
export interface CheckoutApp {
|
|
4
4
|
name: string;
|
|
@@ -231,6 +231,13 @@ export interface CheckoutCoreActions {
|
|
|
231
231
|
simulate: (outcome: SimulatorOutcomeEnum) => void;
|
|
232
232
|
}
|
|
233
233
|
/** The checkout's state and actions, the same on the web page and in the payment sheet. */
|
|
234
|
+
/** One short message over the page. */
|
|
235
|
+
export interface CheckoutToast {
|
|
236
|
+
message: string;
|
|
237
|
+
tone: CheckoutToastToneEnum;
|
|
238
|
+
/** The method it is about, shown in place of the tone's icon. */
|
|
239
|
+
logo: ProviderLogoEnum | null;
|
|
240
|
+
}
|
|
234
241
|
export interface CheckoutCore {
|
|
235
242
|
/** Null for a link that matches no payment. */
|
|
236
243
|
view: CheckoutView | null;
|
|
@@ -242,7 +249,7 @@ export interface CheckoutCore {
|
|
|
242
249
|
/** Seconds before the success screen sends the payer back, null once stopped. */
|
|
243
250
|
returnLeft: number | null;
|
|
244
251
|
helpOpen: boolean;
|
|
245
|
-
|
|
252
|
+
toast: CheckoutToast | null;
|
|
246
253
|
copied: boolean;
|
|
247
254
|
/** The Branding tab's preview: nothing can be paid. */
|
|
248
255
|
preview: boolean;
|
|
@@ -49,7 +49,7 @@ export function SheetCodeField({ core }) {
|
|
|
49
49
|
};
|
|
50
50
|
return (_jsxs(View, { style: styles.section, children: [_jsx(SheetText, { weight: FigtreeEnum.BOLD, style: styles.label, children: t('otp_label') }), _jsx(SheetInput, { ref: field, accessibilityLabel: t('otp_label'), keyboardType: "number-pad", textContentType: "oneTimeCode", autoComplete: "sms-otp",
|
|
51
51
|
// iOS's number keypads have no Go key: asking for one adds a bar above them.
|
|
52
|
-
returnKeyType: Platform.OS === 'android' ? 'go' : undefined, maxLength: OTP_MAX_LENGTH, value: ui.code, onChangeText: actions.setCode, onFocus: () => setFocused(true), onBlur: () => setFocused(false), onSubmitEditing: actions.pay, editable: !ui.submitting, style: [styles.input, { borderColor: focused ? brand : colors.line3 }] }), _jsxs(View, { style: [styles.help, { backgroundColor: colors.fill2 }], children: [_jsx(SheetText, { size: 13, color: colors.ink2, style: styles.grow, children: t('otp_help', { method: method.name }) }), _jsxs(TouchableOpacity, { onPress: dial, activeOpacity: 0.7, accessibilityRole: "button", accessibilityLabel: t('sheet.dial', { code }), style: [
|
|
52
|
+
returnKeyType: Platform.OS === 'android' ? 'go' : undefined, maxLength: OTP_MAX_LENGTH, value: ui.code, onChangeText: actions.setCode, onFocus: () => setFocused(true), onBlur: () => setFocused(false), onSubmitEditing: actions.pay, editable: !ui.submitting, style: [styles.input, { borderColor: focused ? brand : colors.line3 }] }), _jsxs(View, { style: [styles.help, { backgroundColor: colors.fill2 }], children: [_jsx(SheetText, { paragraph: true, size: 13, color: colors.ink2, style: styles.grow, children: t('otp_help', { method: method.name }) }), _jsxs(TouchableOpacity, { onPress: dial, activeOpacity: 0.7, accessibilityRole: "button", accessibilityLabel: t('sheet.dial', { code }), style: [
|
|
53
53
|
styles.dial,
|
|
54
54
|
{ borderColor: colors.line3, backgroundColor: colors.surface },
|
|
55
55
|
], children: [_jsx(View, { style: [styles.phone, { borderColor: colors.ink }], children: _jsx(View, { style: [styles.speaker, { backgroundColor: colors.ink }] }) }), _jsx(SheetText, { weight: FigtreeEnum.BOLD, size: 14, children: code })] })] })] }));
|
|
@@ -93,7 +93,7 @@ export function SheetContent({ calls, watched, fontsReady, deviceLocale, onClose
|
|
|
93
93
|
currency: CURRENCY_LABEL[view.currency],
|
|
94
94
|
}), busy: busy, inactive: !canPay, onPress: actions.pay }), children: [_jsx(SheetSummary, { view: view }), _jsx(SheetForm, { core: core, phoneRef: phoneRef, cardFields: cardFields })] }));
|
|
95
95
|
}
|
|
96
|
-
return (_jsxs(View, { testID: "payment-sheet", accessibilityViewIsModal: true, onAccessibilityEscape: onClose, style: [styles.sheet, { backgroundColor: colors.surface }], children: [_jsx(SheetHeader, { view: view, loading: loading, onClose: onClose, dragHandlers: dragHandlers }), body, _jsx(SheetToast, {
|
|
96
|
+
return (_jsxs(View, { testID: "payment-sheet", accessibilityViewIsModal: true, onAccessibilityEscape: onClose, style: [styles.sheet, { backgroundColor: colors.surface }], children: [_jsx(SheetHeader, { view: view, loading: loading, onClose: onClose, dragHandlers: dragHandlers }), body, _jsx(SheetToast, { toast: core.toast })] }));
|
|
97
97
|
}
|
|
98
98
|
const styles = StyleSheet.create({
|
|
99
99
|
// As tall as its screen; past the room it has, the screen scrolls.
|
|
@@ -29,10 +29,10 @@ export function SheetFailed({ core }) {
|
|
|
29
29
|
? t('retry_code')
|
|
30
30
|
: t('retry'), busy: ui.submitting, onPress: actions.retry }), _jsx(SheetButton, { variant: CheckoutButtonVariantEnum.SECONDARY, label: suggestion
|
|
31
31
|
? t('try_with', { method: suggestion.name })
|
|
32
|
-
: t('use_another'), onPress: actions.useAnother })] }), children: _jsxs(View, { style: styles.failed, children: [_jsx(SheetIcon, { kind: SheetIconEnum.CROSS, color: colors.danger, background: colors.dangerSoft }), _jsx(SheetText, { weight: FigtreeEnum.BOLD, size: 22, accessibilityRole: "header", style: styles.title, children: t(`failure.${reason}.title`, values) }), _jsx(SheetText, { size: 15, color: colors.inkStrong, children: t(`failure.${reason}.body`, values) }), _jsx(SheetText, { color: colors.ink2, style: styles.next, children: t(`failure.${reason}.next`, values) }), _jsxs(View, { style: [styles.rows, { borderColor: colors.line }], children: [_jsx(SheetRow, { label: t('amount'), children: formatMoney(view.amount, view.currency) }), _jsxs(SheetRow, { label: t('method'), children: [_jsx(SheetLogo, { logo: logoOf(attempt) }), _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, children: attempt.methodName })] }), _jsx(SheetRow, { label: t('tries_left'), children: t('tries_value', {
|
|
32
|
+
: t('use_another'), onPress: actions.useAnother })] }), children: _jsxs(View, { style: styles.failed, children: [_jsx(SheetIcon, { kind: SheetIconEnum.CROSS, color: colors.danger, background: colors.dangerSoft }), _jsx(SheetText, { weight: FigtreeEnum.BOLD, size: 22, accessibilityRole: "header", style: styles.title, children: t(`failure.${reason}.title`, values) }), _jsx(SheetText, { paragraph: true, size: 15, color: colors.inkStrong, children: t(`failure.${reason}.body`, values) }), _jsx(SheetText, { paragraph: true, color: colors.ink2, style: styles.next, children: t(`failure.${reason}.next`, values) }), _jsxs(View, { style: [styles.rows, { borderColor: colors.line }], children: [_jsx(SheetRow, { label: t('amount'), children: formatMoney(view.amount, view.currency) }), _jsxs(SheetRow, { label: t('method'), children: [_jsx(SheetLogo, { logo: logoOf(attempt) }), _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, children: attempt.methodName })] }), _jsx(SheetRow, { label: t('tries_left'), children: t('tries_value', {
|
|
33
33
|
left: view.attemptsLeft,
|
|
34
34
|
max: view.maxAttempts,
|
|
35
|
-
}) })] }), reason !== FailureReasonEnum.MISMATCH && (_jsx(SheetText, { size: 13, color: colors.muted, style: styles.note, children: t('not_charged') }))] }) }));
|
|
35
|
+
}) })] }), reason !== FailureReasonEnum.MISMATCH && (_jsx(SheetText, { paragraph: true, size: 13, color: colors.muted, style: styles.note, children: t('not_charged') }))] }) }));
|
|
36
36
|
}
|
|
37
37
|
const styles = StyleSheet.create({
|
|
38
38
|
failed: { paddingHorizontal: 18, paddingTop: 28 },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
3
|
import { SheetIconEnum } from "../models/sheet.enum.js";
|
|
4
4
|
/** A sign in a disc, drawn with views: the sheet ships no icon font or SVG. */
|
|
@@ -12,7 +12,8 @@ export function SheetIcon({ kind, color, background, size = 48, }) {
|
|
|
12
12
|
sign = _jsx(View, { style: [styles.check, line] });
|
|
13
13
|
break;
|
|
14
14
|
case SheetIconEnum.CROSS:
|
|
15
|
-
|
|
15
|
+
// Crossed in a box of their own length: centred in the disc.
|
|
16
|
+
sign = (_jsxs(View, { style: styles.cross, children: [_jsx(View, { style: [styles.bar, styles.up, ink] }), _jsx(View, { style: [styles.bar, styles.down, ink] })] }));
|
|
16
17
|
break;
|
|
17
18
|
case SheetIconEnum.CLOCK:
|
|
18
19
|
sign = (_jsxs(View, { style: [styles.ring, line], children: [_jsx(View, { style: [styles.hour, ink] }), _jsx(View, { style: [styles.minute, ink] })] }));
|
|
@@ -43,6 +44,12 @@ const styles = StyleSheet.create({
|
|
|
43
44
|
borderBottomWidth: 3,
|
|
44
45
|
transform: [{ rotate: '45deg' }],
|
|
45
46
|
},
|
|
47
|
+
cross: {
|
|
48
|
+
width: 18,
|
|
49
|
+
height: 18,
|
|
50
|
+
alignItems: 'center',
|
|
51
|
+
justifyContent: 'center',
|
|
52
|
+
},
|
|
46
53
|
bar: { position: 'absolute', width: 18, height: 2.6, borderRadius: 1.3 },
|
|
47
54
|
up: { transform: [{ rotate: '45deg' }] },
|
|
48
55
|
down: { transform: [{ rotate: '-45deg' }] },
|
|
@@ -7,7 +7,7 @@ import { SheetText } from "./SheetText.js";
|
|
|
7
7
|
/** A dead end the payer cannot fix here: its sign, what happened and why. */
|
|
8
8
|
export function SheetMessage({ title, body, icon = SheetIconEnum.BAN, danger = false, }) {
|
|
9
9
|
const { colors } = useSheetTheme();
|
|
10
|
-
return (_jsxs(View, { style: styles.message, children: [_jsx(SheetIcon, { kind: icon, color: danger ? colors.danger : colors.ink2, background: danger ? colors.dangerSoft : colors.fill2 }), _jsx(SheetText, { weight: FigtreeEnum.BOLD, size: 22, accessibilityRole: "header", style: styles.title, children: title }), _jsx(SheetText, { size: 15, color: colors.inkStrong, children: body })] }));
|
|
10
|
+
return (_jsxs(View, { style: styles.message, children: [_jsx(SheetIcon, { kind: icon, color: danger ? colors.danger : colors.ink2, background: danger ? colors.dangerSoft : colors.fill2 }), _jsx(SheetText, { weight: FigtreeEnum.BOLD, size: 22, accessibilityRole: "header", style: styles.title, children: title }), _jsx(SheetText, { paragraph: true, size: 15, color: colors.inkStrong, children: body })] }));
|
|
11
11
|
}
|
|
12
12
|
const styles = StyleSheet.create({
|
|
13
13
|
message: { paddingHorizontal: 18, paddingTop: 28 },
|
|
@@ -24,7 +24,7 @@ export function SheetPhoneField({ core, phoneRef }) {
|
|
|
24
24
|
},
|
|
25
25
|
], children: [_jsxs(View, { style: [styles.dial, { borderColor: colors.line2 }], children: [_jsx(SheetText, { size: 16, children: flagOf(ui.country) }), _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, size: 16, children: `+${phone.dial}` })] }), _jsx(SheetInput, { ref: phoneRef, accessibilityLabel: t('phone_label'), keyboardType: "phone-pad", textContentType: "telephoneNumber", autoComplete: "tel",
|
|
26
26
|
// iOS's number keypads have no Go key: asking for one adds a bar above them.
|
|
27
|
-
returnKeyType: Platform.OS === 'android' ? 'go' : undefined, placeholder: phone.placeholder, value: phone.value, onChangeText: (text) => void phone.type(text, text.length), onFocus: phone.onFocus, onBlur: phone.onBlur, onSubmitEditing: actions.pay, editable: !ui.submitting, style: styles.input })] }), _jsx(View, { accessibilityLiveRegion: "polite", style: styles.message, children: error ? (_jsx(SheetText, { weight: FigtreeEnum.MEDIUM, size: 13, color: colors.danger, children: t(`phone_errors.${error}`) })) : mismatch ? (_jsxs(View, { style: styles.mismatch, children: [_jsx(SheetLogo, { logo: mismatch.logos[0] }), _jsx(SheetText, { size: 13, color: colors.ink2, style: styles.grow, children: t('mismatch', { method: mismatch.name }) }), _jsx(Pressable, { onPress: actions.switchToDetected, accessibilityRole: "button", hitSlop: 6, style: [styles.switch, { borderColor: colors.line3 }], children: _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, size: 13, children: t('switch_to') }) })] })) : (selected && (_jsx(SheetText, { size: 13, color: colors.muted, children: t('helper', { method: selected.name }) }))) })] }));
|
|
27
|
+
returnKeyType: Platform.OS === 'android' ? 'go' : undefined, placeholder: phone.placeholder, value: phone.value, onChangeText: (text) => void phone.type(text, text.length), onFocus: phone.onFocus, onBlur: phone.onBlur, onSubmitEditing: actions.pay, editable: !ui.submitting, style: styles.input })] }), _jsx(View, { accessibilityLiveRegion: "polite", style: styles.message, children: error ? (_jsx(SheetText, { paragraph: true, weight: FigtreeEnum.MEDIUM, size: 13, color: colors.danger, children: t(`phone_errors.${error}`) })) : mismatch ? (_jsxs(View, { style: styles.mismatch, children: [_jsx(SheetLogo, { logo: mismatch.logos[0] }), _jsx(SheetText, { paragraph: true, size: 13, color: colors.ink2, style: styles.grow, children: t('mismatch', { method: mismatch.name }) }), _jsx(Pressable, { onPress: actions.switchToDetected, accessibilityRole: "button", hitSlop: 6, style: [styles.switch, { borderColor: colors.line3 }], children: _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, size: 13, children: t('switch_to') }) })] })) : (selected && (_jsx(SheetText, { paragraph: true, size: 13, color: colors.muted, children: t('helper', { method: selected.name }) }))) })] }));
|
|
28
28
|
}
|
|
29
29
|
const styles = StyleSheet.create({
|
|
30
30
|
section: { marginTop: 18 },
|
|
@@ -18,7 +18,7 @@ export function SheetSimulator({ core }) {
|
|
|
18
18
|
return (_jsxs(View, { accessibilityLabel: t('simulator.title'), style: [
|
|
19
19
|
styles.panel,
|
|
20
20
|
{ backgroundColor: colors.warnSoft, borderColor: colors.warnLine },
|
|
21
|
-
], children: [_jsx(SheetText, { weight: FigtreeEnum.EXTRA_BOLD, size: 12, color: colors.warnInk2, style: styles.title, children: t('simulator.title') }), _jsxs(SheetText, { size: 13, color: colors.warnInk2, style: styles.body, children: [t('simulator.body'), traits.prompt &&
|
|
21
|
+
], children: [_jsx(SheetText, { weight: FigtreeEnum.EXTRA_BOLD, size: 12, color: colors.warnInk2, style: styles.title, children: t('simulator.title') }), _jsxs(SheetText, { paragraph: true, size: 13, color: colors.warnInk2, style: styles.body, children: [t('simulator.body'), traits.prompt &&
|
|
22
22
|
` ${t('simulator.no_answer', { suffix: SIMULATOR_NO_ANSWER_SUFFIX })}`] }), _jsx(View, { style: styles.outcomes, children: outcomes.map((outcome) => (_jsx(TouchableOpacity, { onPress: () => core.actions.simulate(outcome), activeOpacity: 0.7, accessibilityRole: "button", style: [
|
|
23
23
|
styles.outcome,
|
|
24
24
|
{ backgroundColor: colors.surface, borderColor: colors.warnLine },
|
|
@@ -26,7 +26,7 @@ export function SheetSuccess({ core, onClose }) {
|
|
|
26
26
|
// Nothing stops the countdown in the sheet: it always runs here.
|
|
27
27
|
, {
|
|
28
28
|
// Nothing stops the countdown in the sheet: it always runs here.
|
|
29
|
-
label: t('sheet.done_in', { seconds: returnLeft }), onPress: onClose }), children: _jsxs(View, { style: styles.success, children: [_jsx(View, { style: styles.icon, children: _jsx(SheetIcon, { kind: SheetIconEnum.CHECK, color: colors.surface, background: colors.successInk, size: 64 }) }), _jsx(SheetText, { weight: FigtreeEnum.EXTRA_BOLD, size: 22, accessibilityRole: "header", style: [styles.center, styles.title], children: t('success_title') }), _jsxs(View, { style: styles.amountRow, children: [_jsx(SheetText, { weight: FigtreeEnum.EXTRA_BOLD, size: 34, style: styles.amount, children: formatAmount(view.amount, view.currency) }), _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, size: 16, color: colors.ink2, children: CURRENCY_LABEL[view.currency] })] }), _jsx(SheetText, { color: colors.muted, style: styles.center, children: t('paid_to', { app: view.app.name }) }), _jsxs(View, { style: [styles.rows, { borderColor: colors.line }], children: [_jsxs(SheetRow, { label: t('method'), children: [_jsx(SheetLogo, { logo: logoOf(attempt) }), _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, children: attempt.methodName })] }), attempt.phone && (_jsx(SheetRow, { label: t('number'), children: maskE164(attempt.phone) })), attempt.card && (_jsx(SheetRow, { label: t('card'), children: cardLabel(attempt.card) })), _jsx(SheetRow, { label: t('date'), children: format.dateTime(view.paidAt, {
|
|
29
|
+
label: t('sheet.done_in', { seconds: returnLeft }), onPress: onClose }), children: _jsxs(View, { style: styles.success, children: [_jsx(View, { style: styles.icon, children: _jsx(SheetIcon, { kind: SheetIconEnum.CHECK, color: colors.surface, background: colors.successInk, size: 64 }) }), _jsx(SheetText, { weight: FigtreeEnum.EXTRA_BOLD, size: 22, accessibilityRole: "header", style: [styles.center, styles.title], children: t('success_title') }), _jsxs(View, { style: styles.amountRow, children: [_jsx(SheetText, { weight: FigtreeEnum.EXTRA_BOLD, size: 34, style: styles.amount, children: formatAmount(view.amount, view.currency) }), _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, size: 16, color: colors.ink2, children: CURRENCY_LABEL[view.currency] })] }), _jsx(SheetText, { paragraph: true, color: colors.muted, style: styles.center, children: t('paid_to', { app: view.app.name }) }), _jsxs(View, { style: [styles.rows, { borderColor: colors.line }], children: [_jsxs(SheetRow, { label: t('method'), children: [_jsx(SheetLogo, { logo: logoOf(attempt) }), _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, children: attempt.methodName })] }), attempt.phone && (_jsx(SheetRow, { label: t('number'), children: maskE164(attempt.phone) })), attempt.card && (_jsx(SheetRow, { label: t('card'), children: cardLabel(attempt.card) })), _jsx(SheetRow, { label: t('date'), children: format.dateTime(view.paidAt, {
|
|
30
30
|
day: 'numeric',
|
|
31
31
|
month: 'short',
|
|
32
32
|
year: 'numeric',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SheetInputProps, SheetTextProps } from '../models/sheet.interface.js';
|
|
2
|
-
/** Every text of the sheet: Figtree, in the sheet's ink unless told otherwise. */
|
|
3
|
-
export declare function SheetText({ weight, size, color, style, ...props }: SheetTextProps): import("react").JSX.Element;
|
|
2
|
+
/** Every text of the sheet: Figtree, in the sheet's ink unless told otherwise; a paragraph's lines spaced as on the web. */
|
|
3
|
+
export declare function SheetText({ weight, size, color, paragraph, style, ...props }: SheetTextProps): import("react").JSX.Element;
|
|
4
4
|
/** Every field of the sheet: Figtree at 16, so iOS never zooms, in the sheet's ink. */
|
|
5
5
|
export declare function SheetInput({ style, ...props }: SheetInputProps): import("react").JSX.Element;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Text, TextInput } from 'react-native';
|
|
3
3
|
import { useSheetTheme } from "../hooks/use-sheet-theme.js";
|
|
4
|
+
import { PARAGRAPH_LINE_HEIGHT } from "../models/sheet.constants.js";
|
|
4
5
|
import { FigtreeEnum } from "../models/sheet.enum.js";
|
|
5
|
-
/** Every text of the sheet: Figtree, in the sheet's ink unless told otherwise. */
|
|
6
|
-
export function SheetText({ weight = FigtreeEnum.REGULAR, size = 14, color, style, ...props }) {
|
|
6
|
+
/** Every text of the sheet: Figtree, in the sheet's ink unless told otherwise; a paragraph's lines spaced as on the web. */
|
|
7
|
+
export function SheetText({ weight = FigtreeEnum.REGULAR, size = 14, color, paragraph = false, style, ...props }) {
|
|
7
8
|
const { colors } = useSheetTheme();
|
|
8
9
|
return (_jsx(Text, { ...props, style: [
|
|
9
10
|
{ fontFamily: weight, fontSize: size, color: color ?? colors.ink },
|
|
11
|
+
paragraph && { lineHeight: Math.round(size * PARAGRAPH_LINE_HEIGHT) },
|
|
10
12
|
style,
|
|
11
13
|
] }));
|
|
12
14
|
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import type { SheetToastProps } from '../models/sheet.interface.js';
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* One short message at a time, in a small card at the top of the sheet:
|
|
4
|
+
* the method's logo, else the tone's disc (a check when done, "!" for a
|
|
5
|
+
* problem, "i" to know). As on the web checkout.
|
|
6
|
+
*/
|
|
7
|
+
export declare function SheetToast({ toast }: SheetToastProps): import("react").JSX.Element | null;
|
|
@@ -1,24 +1,71 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
|
+
import { CheckoutToastToneEnum } from "../checkout-core/models/checkout.enum.js";
|
|
3
4
|
import { useSheetTheme } from "../hooks/use-sheet-theme.js";
|
|
4
5
|
import { FigtreeEnum } from "../models/sheet.enum.js";
|
|
6
|
+
import { SheetLogo } from "./SheetLogo.js";
|
|
5
7
|
import { SheetText } from "./SheetText.js";
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* One short message at a time, in a small card at the top of the sheet:
|
|
10
|
+
* the method's logo, else the tone's disc (a check when done, "!" for a
|
|
11
|
+
* problem, "i" to know). As on the web checkout.
|
|
12
|
+
*/
|
|
13
|
+
export function SheetToast({ toast }) {
|
|
14
|
+
const { colors, dark } = useSheetTheme();
|
|
15
|
+
if (!toast)
|
|
10
16
|
return null;
|
|
11
|
-
|
|
17
|
+
const disc = {
|
|
18
|
+
[CheckoutToastToneEnum.SUCCESS]: colors.successInk,
|
|
19
|
+
[CheckoutToastToneEnum.WARNING]: colors.warnInk,
|
|
20
|
+
[CheckoutToastToneEnum.INFO]: colors.muted,
|
|
21
|
+
}[toast.tone];
|
|
22
|
+
return (_jsx(View, { pointerEvents: "none", style: styles.place, children: _jsxs(View, { testID: "sheet-toast", accessibilityLiveRegion: "polite", accessibilityRole: "alert", style: [
|
|
23
|
+
styles.toast,
|
|
24
|
+
{
|
|
25
|
+
backgroundColor: dark ? colors.fill3 : colors.surface,
|
|
26
|
+
borderColor: colors.line3,
|
|
27
|
+
},
|
|
28
|
+
], children: [toast.logo ? (_jsx(SheetLogo, { logo: toast.logo })) : (_jsx(View, { testID: `toast-${toast.tone}`, style: [styles.disc, { backgroundColor: disc }], children: toast.tone === CheckoutToastToneEnum.SUCCESS ? (_jsx(View, { style: styles.check })) : (_jsx(SheetText, { weight: FigtreeEnum.BOLD, size: 12, color: "white", style: styles.glyph, children: toast.tone === CheckoutToastToneEnum.WARNING ? '!' : 'i' })) })), _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, size: 13.5, style: styles.text, children: toast.message })] }) }));
|
|
12
29
|
}
|
|
13
30
|
const styles = StyleSheet.create({
|
|
14
|
-
|
|
31
|
+
place: {
|
|
15
32
|
position: 'absolute',
|
|
16
|
-
top:
|
|
33
|
+
top: 12,
|
|
17
34
|
left: 18,
|
|
18
35
|
right: 18,
|
|
36
|
+
alignItems: 'center',
|
|
37
|
+
},
|
|
38
|
+
toast: {
|
|
39
|
+
flexDirection: 'row',
|
|
40
|
+
alignItems: 'center',
|
|
41
|
+
gap: 10,
|
|
42
|
+
borderWidth: 1,
|
|
19
43
|
borderRadius: 12,
|
|
20
|
-
|
|
21
|
-
|
|
44
|
+
paddingVertical: 10,
|
|
45
|
+
paddingLeft: 12,
|
|
46
|
+
paddingRight: 16,
|
|
47
|
+
shadowColor: 'black',
|
|
48
|
+
shadowOpacity: 0.18,
|
|
49
|
+
shadowRadius: 16,
|
|
50
|
+
shadowOffset: { width: 0, height: 8 },
|
|
51
|
+
elevation: 6,
|
|
52
|
+
},
|
|
53
|
+
disc: {
|
|
54
|
+
width: 20,
|
|
55
|
+
height: 20,
|
|
56
|
+
borderRadius: 10,
|
|
57
|
+
alignItems: 'center',
|
|
58
|
+
justifyContent: 'center',
|
|
59
|
+
},
|
|
60
|
+
check: {
|
|
61
|
+
width: 5,
|
|
62
|
+
height: 9,
|
|
63
|
+
marginTop: -2,
|
|
64
|
+
borderColor: 'white',
|
|
65
|
+
borderRightWidth: 2,
|
|
66
|
+
borderBottomWidth: 2,
|
|
67
|
+
transform: [{ rotate: '45deg' }],
|
|
22
68
|
},
|
|
23
|
-
|
|
69
|
+
glyph: { lineHeight: 14, textAlign: 'center' },
|
|
70
|
+
text: { flexShrink: 1 },
|
|
24
71
|
});
|
|
@@ -39,7 +39,7 @@ export function SheetWaiting({ core }) {
|
|
|
39
39
|
: t('resend'), disabled: resendLeft > 0, onPress: () => {
|
|
40
40
|
setSentAt(WAIT_SECONDS - waitLeft);
|
|
41
41
|
actions.resend();
|
|
42
|
-
} })), _jsx(Pressable, { onPress: actions.useAnother, accessibilityRole: "button", style: styles.link, children: _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, style: styles.center, children: t('use_another') }) })] }), children: _jsxs(View, { style: styles.waiting, children: [_jsxs(View, { style: styles.pulse, children: [_jsx(View, { style: [styles.halo, styles.outer, { backgroundColor: brand }] }), _jsx(View, { style: [styles.halo, styles.inner, { backgroundColor: brand }] }), _jsx(View, { testID: "icon-phone", style: [styles.phone, { borderColor: brand }], children: _jsx(View, { style: [styles.speaker, { backgroundColor: brand }] }) })] }), _jsx(SheetText, { weight: FigtreeEnum.EXTRA_BOLD, size: 21, accessibilityRole: "header", style: [styles.center, styles.title], children: prompt ? t('sheet.approve_title') : t('checking_title') }), _jsx(SheetText, { size: 14, color: colors.muted, style: styles.center, children: attempt.phone
|
|
42
|
+
} })), _jsx(Pressable, { onPress: actions.useAnother, accessibilityRole: "button", style: styles.link, children: _jsx(SheetText, { weight: FigtreeEnum.SEMI_BOLD, style: styles.center, children: t('use_another') }) })] }), children: _jsxs(View, { style: styles.waiting, children: [_jsxs(View, { style: styles.pulse, children: [_jsx(View, { style: [styles.halo, styles.outer, { backgroundColor: brand }] }), _jsx(View, { style: [styles.halo, styles.inner, { backgroundColor: brand }] }), _jsx(View, { testID: "icon-phone", style: [styles.phone, { borderColor: brand }], children: _jsx(View, { style: [styles.speaker, { backgroundColor: brand }] }) })] }), _jsx(SheetText, { weight: FigtreeEnum.EXTRA_BOLD, size: 21, accessibilityRole: "header", style: [styles.center, styles.title], children: prompt ? t('sheet.approve_title') : t('checking_title') }), _jsx(SheetText, { paragraph: true, size: 14, color: colors.muted, style: styles.center, children: attempt.phone
|
|
43
43
|
? prompt
|
|
44
44
|
? t('sheet.approve_body', {
|
|
45
45
|
method: attempt.methodName,
|
|
@@ -37,3 +37,5 @@ export declare const SHEET_SWIPE_DISTANCE = 120;
|
|
|
37
37
|
export declare const SHEET_FLICK_SPEED = 0.8;
|
|
38
38
|
/** How the sheet's height eases from one screen to the next. */
|
|
39
39
|
export declare const SHEET_RESIZE: LayoutAnimationConfig;
|
|
40
|
+
/** A paragraph's line height, as a share of its size: the web checkout's 1.5, a touch tighter for Figtree on phones. */
|
|
41
|
+
export declare const PARAGRAPH_LINE_HEIGHT = 1.45;
|
|
@@ -76,3 +76,5 @@ export const SHEET_RESIZE = {
|
|
|
76
76
|
duration: 220,
|
|
77
77
|
update: { type: LayoutAnimation.Types.easeInEaseOut },
|
|
78
78
|
};
|
|
79
|
+
/** A paragraph's line height, as a share of its size: the web checkout's 1.5, a touch tighter for Figtree on phones. */
|
|
80
|
+
export const PARAGRAPH_LINE_HEIGHT = 1.45;
|
|
@@ -3,7 +3,7 @@ import type { Animated, DimensionValue, GestureResponderHandlers, StyleProp, Tex
|
|
|
3
3
|
import type { WebView } from 'react-native-webview';
|
|
4
4
|
import type { CheckoutButtonVariantEnum, TerminalKindEnum } from '../checkout-core/models/checkout.enum.js';
|
|
5
5
|
import type { LangEnum, ProviderLogoEnum } from '../checkout-core/models/domain.enum.js';
|
|
6
|
-
import type { CardFieldsMessage, CheckoutColors, CheckoutCore, CheckoutMutations, CheckoutPlatform, CheckoutView } from '../checkout-core/models/checkout.interface.js';
|
|
6
|
+
import type { CardFieldsMessage, CheckoutColors, CheckoutCore, CheckoutToast, CheckoutMutations, CheckoutPlatform, CheckoutView } from '../checkout-core/models/checkout.interface.js';
|
|
7
7
|
import type { FigtreeEnum, SheetIconEnum } from './sheet.enum.js';
|
|
8
8
|
/**
|
|
9
9
|
* How the sheet ended. `closed`: the payer closed it with the payment still
|
|
@@ -88,6 +88,8 @@ export interface SheetTextProps extends TextProps {
|
|
|
88
88
|
weight?: FigtreeEnum;
|
|
89
89
|
size?: number;
|
|
90
90
|
color?: string;
|
|
91
|
+
/** Text that may wrap: lines spaced as on the web checkout. */
|
|
92
|
+
paragraph?: boolean;
|
|
91
93
|
style?: StyleProp<TextStyle>;
|
|
92
94
|
}
|
|
93
95
|
export interface SheetHeaderProps {
|
|
@@ -209,7 +211,7 @@ export interface SheetRowProps {
|
|
|
209
211
|
urgent?: boolean;
|
|
210
212
|
}
|
|
211
213
|
export interface SheetToastProps {
|
|
212
|
-
|
|
214
|
+
toast: CheckoutToast | null;
|
|
213
215
|
}
|
|
214
216
|
export interface BoneProps {
|
|
215
217
|
/** Points, or a share of the row (`100%`). */
|