@inttegro/react 0.4.0 → 0.5.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/README.md +3 -3
- package/dist/index.cjs +9 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -17,9 +17,9 @@ export function Payment({ orderId }: { orderId: string }) {
|
|
|
17
17
|
}
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Pass `purchaseIntentId` instead of `orderId`
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
Pass `purchaseIntentId` instead of `orderId` for a Buy link. Fixed pricing
|
|
21
|
+
continues directly to payment; customer-selected pricing renders the amount
|
|
22
|
+
picker first:
|
|
23
23
|
|
|
24
24
|
```tsx
|
|
25
25
|
<Checkout purchaseIntentId={purchaseIntentId} presentation="modal" />
|
package/dist/index.cjs
CHANGED
|
@@ -36,6 +36,7 @@ var Checkout = (0, import_react.forwardRef)(
|
|
|
36
36
|
locale,
|
|
37
37
|
onCanceled,
|
|
38
38
|
onCompleted,
|
|
39
|
+
onFailed,
|
|
39
40
|
onError,
|
|
40
41
|
onEvent,
|
|
41
42
|
onReady,
|
|
@@ -51,6 +52,7 @@ var Checkout = (0, import_react.forwardRef)(
|
|
|
51
52
|
const callbacksRef = (0, import_react.useRef)({
|
|
52
53
|
onCanceled,
|
|
53
54
|
onCompleted,
|
|
55
|
+
onFailed,
|
|
54
56
|
onError,
|
|
55
57
|
onEvent,
|
|
56
58
|
onReady
|
|
@@ -64,6 +66,7 @@ var Checkout = (0, import_react.forwardRef)(
|
|
|
64
66
|
callbacksRef.current = {
|
|
65
67
|
onCanceled,
|
|
66
68
|
onCompleted,
|
|
69
|
+
onFailed,
|
|
67
70
|
onError,
|
|
68
71
|
onEvent,
|
|
69
72
|
onReady
|
|
@@ -83,6 +86,7 @@ var Checkout = (0, import_react.forwardRef)(
|
|
|
83
86
|
if (presentation === "embedded" && !target) return;
|
|
84
87
|
let active = true;
|
|
85
88
|
let canceled = false;
|
|
89
|
+
let failed = false;
|
|
86
90
|
let checkout;
|
|
87
91
|
let unsubscribe;
|
|
88
92
|
void (0, import_js.loadInttegro)().then(async (inttegro) => {
|
|
@@ -117,12 +121,15 @@ var Checkout = (0, import_react.forwardRef)(
|
|
|
117
121
|
if (event.type === "ready") callbacksRef.current.onReady?.(event);
|
|
118
122
|
if (event.type === "completed")
|
|
119
123
|
callbacksRef.current.onCompleted?.(event);
|
|
120
|
-
if (event.type === "
|
|
124
|
+
if (event.type === "failed") {
|
|
125
|
+
failed = true;
|
|
126
|
+
callbacksRef.current.onFailed?.(event);
|
|
127
|
+
}
|
|
121
128
|
});
|
|
122
129
|
if (presentation === "modal") await instance.present();
|
|
123
130
|
else await instance.mount(target);
|
|
124
131
|
}).catch((error) => {
|
|
125
|
-
if (active && !canceled)
|
|
132
|
+
if (active && !canceled && !failed)
|
|
126
133
|
callbacksRef.current.onError?.(asError(error));
|
|
127
134
|
});
|
|
128
135
|
return () => {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/Checkout.tsx"],"sourcesContent":["/**\n * React component adapter for Inttegro-hosted Checkout.\n *\n * @module @inttegro/react\n */\nexport { Checkout, type CheckoutHandle, type CheckoutProps } from './Checkout'\nexport type {\n CheckoutAppearance,\n CheckoutErrorEvent,\n CheckoutEvent,\n CheckoutFeatures,\n CheckoutPresentation,\n CheckoutTheme,\n} from '@inttegro/js'\n","import {\n loadInttegro,\n type CheckoutController,\n type CheckoutErrorEvent,\n type CheckoutEvent,\n type CheckoutOptions,\n type CheckoutPresentation,\n} from '@inttegro/js'\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n type CSSProperties,\n} from 'react'\n\n/**\n * Props for {@link Checkout}.\n *\n * `features`, the Checkout reference, `presentation`, `timeout`, and `title`\n * identify the experience. Changing one replaces the underlying controller.\n * `appearance` and `locale` update the existing controller without discarding\n * payer progress.\n *\n * @category React\n */\nexport type CheckoutProps = CheckoutOptions & {\n /** CSS class applied to the outer container owned by your React application. */\n className?: string\n /** Inline styles applied to the outer container, never to controls inside Checkout. */\n style?: CSSProperties\n /** Displays Checkout inline by default or in an Inttegro-managed modal. */\n presentation?: CheckoutPresentation\n /** Called when a payer dismisses managed modal Checkout before completion. */\n onCanceled?: (event: Extract<CheckoutEvent, { type: 'canceled' }>) => void\n /**\n * Called after Checkout reports its successful terminal state.\n * Use this to navigate or refresh server-owned Order state, not as the sole\n * signal for fulfillment.\n */\n onCompleted?: (event: Extract<CheckoutEvent, { type: 'completed' }>) => void\n /**\n * Called for loader/mount errors and sanitized hosted errors.\n * Use `error instanceof InttegroCheckoutError` or check for an event `type`\n * before reading framework-independent details.\n */\n onError?: (event: CheckoutErrorEvent | Error) => void\n /** Called for every sanitized lifecycle event, including events above. */\n onEvent?: (event: CheckoutEvent) => void\n /** Called once the iframe is interactive and its mount promise has resolved. */\n onReady?: (event: Extract<CheckoutEvent, { type: 'ready' }>) => void\n}\n\n/**\n * Imperative operations exposed by {@link Checkout} through a React ref.\n *\n * Prefer props for normal updates. Use the handle for focus management in\n * dialogs or for updates driven by imperative host integrations.\n *\n * @category React\n */\nexport interface CheckoutHandle {\n /** Closes managed modal Checkout when it is open. */\n dismiss(): void\n /** Moves focus into Checkout when its controller is ready; otherwise does nothing. */\n focus(): void\n /** Applies a new locale or theme when the controller exists. */\n update(options: Parameters<CheckoutController['update']>[0]): void\n}\n\n/**\n * Displays Inttegro-hosted Checkout in a React application.\n *\n * The component renders an empty `div`, loads the executable runtime from\n * Inttegro's fixed origin after mount, creates a controller for an `orderId` or\n * `purchaseIntentId`, and destroys it during cleanup. Server rendering is safe\n * because no runtime is loaded until the effect runs in a browser.\n *\n * Changing `features`, the Checkout reference, `presentation`, `timeout`, or\n * `title` starts a fresh hosted experience. Changing `appearance` or `locale`\n * updates the active experience in place. Keep the component mounted while a\n * payment is pending or confirmation is in progress.\n *\n * @example Present Checkout without building a dialog\n * ```tsx\n * import { Checkout } from '@inttegro/react'\n *\n * function Payment({ orderId }: { orderId: string }) {\n * return (\n * <Checkout\n * orderId={orderId}\n * presentation=\"modal\"\n * appearance={{ theme: 'system' }}\n * onCompleted={() => location.assign(`/orders/${orderId}/complete`)}\n * onError={(error) => reportCheckoutError(error)}\n * />\n * )\n * }\n * ```\n *\n * @category React\n */\nexport const Checkout = forwardRef<CheckoutHandle, CheckoutProps>(\n function Checkout(\n {\n appearance,\n className,\n features,\n locale,\n onCanceled,\n onCompleted,\n onError,\n onEvent,\n onReady,\n orderId,\n purchaseIntentId,\n presentation = 'embedded',\n style,\n timeout,\n title,\n },\n forwardedRef,\n ) {\n const containerRef = useRef<HTMLDivElement>(null)\n const checkoutRef = useRef<CheckoutController | null>(null)\n const callbacksRef = useRef({\n onCanceled,\n onCompleted,\n onError,\n onEvent,\n onReady,\n })\n const updateOptionsRef = useRef({ appearance, locale })\n const hasFeatureOverrides = features !== undefined\n const showLineItems = features?.showLineItems\n const showInvoiceDownload = features?.showInvoiceDownload\n const showReceiptDownload = features?.showReceiptDownload\n const allowPaymentMethodChange = features?.allowPaymentMethodChange\n callbacksRef.current = {\n onCanceled,\n onCompleted,\n onError,\n onEvent,\n onReady,\n }\n updateOptionsRef.current = { appearance, locale }\n\n useImperativeHandle(\n forwardedRef,\n () => ({\n dismiss: () => checkoutRef.current?.dismiss(),\n focus: () => checkoutRef.current?.focus(),\n update: (options) => checkoutRef.current?.update(options),\n }),\n [],\n )\n\n useEffect(() => {\n const target = containerRef.current\n if (presentation === 'embedded' && !target) return\n\n let active = true\n let canceled = false\n let checkout: CheckoutController | undefined\n let unsubscribe: (() => void) | undefined\n\n void loadInttegro()\n .then(async (inttegro) => {\n if (!active || !inttegro) return\n const instance = inttegro.createCheckout(\n definedOptions({\n ...updateOptionsRef.current,\n features: hasFeatureOverrides\n ? definedOptions({\n allowPaymentMethodChange,\n showInvoiceDownload,\n showLineItems,\n showReceiptDownload,\n })\n : undefined,\n orderId,\n purchaseIntentId,\n timeout,\n title,\n }) as CheckoutOptions,\n )\n if (!active) {\n instance.destroy()\n return\n }\n checkout = instance\n checkoutRef.current = instance\n unsubscribe = instance.onEvent((event) => {\n callbacksRef.current.onEvent?.(event)\n if (event.type === 'canceled') {\n canceled = true\n callbacksRef.current.onCanceled?.(event)\n }\n if (event.type === 'ready') callbacksRef.current.onReady?.(event)\n if (event.type === 'completed')\n callbacksRef.current.onCompleted?.(event)\n if (event.type === 'error') callbacksRef.current.onError?.(event)\n })\n if (presentation === 'modal') await instance.present()\n else await instance.mount(target!)\n })\n .catch((error: unknown) => {\n if (active && !canceled)\n callbacksRef.current.onError?.(asError(error))\n })\n\n return () => {\n active = false\n unsubscribe?.()\n checkout?.destroy()\n if (checkoutRef.current === checkout) checkoutRef.current = null\n }\n }, [\n allowPaymentMethodChange,\n hasFeatureOverrides,\n orderId,\n purchaseIntentId,\n presentation,\n showInvoiceDownload,\n showLineItems,\n showReceiptDownload,\n timeout,\n title,\n ])\n\n useEffect(() => {\n checkoutRef.current?.update(definedOptions({ appearance, locale }))\n }, [appearance, locale])\n\n return <div className={className} ref={containerRef} style={style} />\n },\n)\n\nfunction definedOptions<Value extends object>(options: Value): Value {\n return Object.fromEntries(\n Object.entries(options).filter(([, value]) => value !== undefined),\n ) as Value\n}\n\nfunction asError(error: unknown): Error {\n return error instanceof Error ? error : new Error('Checkout failed to load.')\n}\n"],"mappings":"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","names":["Checkout"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Checkout.tsx"],"sourcesContent":["/**\n * React component adapter for Inttegro-hosted Checkout.\n *\n * @module @inttegro/react\n */\nexport { Checkout, type CheckoutHandle, type CheckoutProps } from './Checkout'\nexport type {\n CheckoutAppearance,\n CheckoutEvent,\n CheckoutFailedEvent,\n CheckoutOrder,\n CheckoutFeatures,\n CheckoutPresentation,\n CheckoutTheme,\n} from '@inttegro/js'\n","import {\n loadInttegro,\n type CheckoutController,\n type CheckoutEvent,\n type CheckoutOptions,\n type CheckoutPresentation,\n} from '@inttegro/js'\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n type CSSProperties,\n} from 'react'\n\n/**\n * Props for {@link Checkout}.\n *\n * `features`, the Checkout reference, `presentation`, `timeout`, and `title`\n * identify the experience. Changing one replaces the underlying controller.\n * `appearance` and `locale` update the existing controller without discarding\n * payer progress.\n *\n * @category React\n */\nexport type CheckoutProps = CheckoutOptions & {\n /** CSS class applied to the outer container owned by your React application. */\n className?: string\n /** Inline styles applied to the outer container, never to controls inside Checkout. */\n style?: CSSProperties\n /** Displays Checkout inline by default or in an Inttegro-managed modal. */\n presentation?: CheckoutPresentation\n /** Called when a payer dismisses managed modal Checkout before completion. */\n onCanceled?: (event: Extract<CheckoutEvent, { type: 'canceled' }>) => void\n /**\n * Called after Checkout reports its successful terminal state.\n * Use this to navigate or refresh server-owned Order state, not as the sole\n * signal for fulfillment.\n */\n onCompleted?: (event: Extract<CheckoutEvent, { type: 'completed' }>) => void\n /** Called when Checkout reaches a terminal failure state. */\n onFailed?: (event: Extract<CheckoutEvent, { type: 'failed' }>) => void\n /** Called for loader or mount errors. */\n onError?: (error: Error) => void\n /** Called for every sanitized lifecycle event, including events above. */\n onEvent?: (event: CheckoutEvent) => void\n /** Called once the iframe is interactive and its mount promise has resolved. */\n onReady?: (event: Extract<CheckoutEvent, { type: 'ready' }>) => void\n}\n\n/**\n * Imperative operations exposed by {@link Checkout} through a React ref.\n *\n * Prefer props for normal updates. Use the handle for focus management in\n * dialogs or for updates driven by imperative host integrations.\n *\n * @category React\n */\nexport interface CheckoutHandle {\n /** Closes managed modal Checkout when it is open. */\n dismiss(): void\n /** Moves focus into Checkout when its controller is ready; otherwise does nothing. */\n focus(): void\n /** Applies a new locale or theme when the controller exists. */\n update(options: Parameters<CheckoutController['update']>[0]): void\n}\n\n/**\n * Displays Inttegro-hosted Checkout in a React application.\n *\n * The component renders an empty `div`, loads the executable runtime from\n * Inttegro's fixed origin after mount, creates a controller for an `orderId` or\n * `purchaseIntentId`, and destroys it during cleanup. Server rendering is safe\n * because no runtime is loaded until the effect runs in a browser.\n *\n * Changing `features`, the Checkout reference, `presentation`, `timeout`, or\n * `title` starts a fresh hosted experience. Changing `appearance` or `locale`\n * updates the active experience in place. Keep the component mounted while a\n * payment is pending or confirmation is in progress.\n *\n * @example Present Checkout without building a dialog\n * ```tsx\n * import { Checkout } from '@inttegro/react'\n *\n * function Payment({ orderId }: { orderId: string }) {\n * return (\n * <Checkout\n * orderId={orderId}\n * presentation=\"modal\"\n * appearance={{ theme: 'system' }}\n * onCompleted={() => location.assign(`/orders/${orderId}/complete`)}\n * onError={(error) => reportCheckoutError(error)}\n * />\n * )\n * }\n * ```\n *\n * @category React\n */\nexport const Checkout = forwardRef<CheckoutHandle, CheckoutProps>(\n function Checkout(\n {\n appearance,\n className,\n features,\n locale,\n onCanceled,\n onCompleted,\n onFailed,\n onError,\n onEvent,\n onReady,\n orderId,\n purchaseIntentId,\n presentation = 'embedded',\n style,\n timeout,\n title,\n },\n forwardedRef,\n ) {\n const containerRef = useRef<HTMLDivElement>(null)\n const checkoutRef = useRef<CheckoutController | null>(null)\n const callbacksRef = useRef({\n onCanceled,\n onCompleted,\n onFailed,\n onError,\n onEvent,\n onReady,\n })\n const updateOptionsRef = useRef({ appearance, locale })\n const hasFeatureOverrides = features !== undefined\n const showLineItems = features?.showLineItems\n const showInvoiceDownload = features?.showInvoiceDownload\n const showReceiptDownload = features?.showReceiptDownload\n const allowPaymentMethodChange = features?.allowPaymentMethodChange\n callbacksRef.current = {\n onCanceled,\n onCompleted,\n onFailed,\n onError,\n onEvent,\n onReady,\n }\n updateOptionsRef.current = { appearance, locale }\n\n useImperativeHandle(\n forwardedRef,\n () => ({\n dismiss: () => checkoutRef.current?.dismiss(),\n focus: () => checkoutRef.current?.focus(),\n update: (options) => checkoutRef.current?.update(options),\n }),\n [],\n )\n\n useEffect(() => {\n const target = containerRef.current\n if (presentation === 'embedded' && !target) return\n\n let active = true\n let canceled = false\n let failed = false\n let checkout: CheckoutController | undefined\n let unsubscribe: (() => void) | undefined\n\n void loadInttegro()\n .then(async (inttegro) => {\n if (!active || !inttegro) return\n const instance = inttegro.createCheckout(\n definedOptions({\n ...updateOptionsRef.current,\n features: hasFeatureOverrides\n ? definedOptions({\n allowPaymentMethodChange,\n showInvoiceDownload,\n showLineItems,\n showReceiptDownload,\n })\n : undefined,\n orderId,\n purchaseIntentId,\n timeout,\n title,\n }) as CheckoutOptions,\n )\n if (!active) {\n instance.destroy()\n return\n }\n checkout = instance\n checkoutRef.current = instance\n unsubscribe = instance.onEvent((event) => {\n callbacksRef.current.onEvent?.(event)\n if (event.type === 'canceled') {\n canceled = true\n callbacksRef.current.onCanceled?.(event)\n }\n if (event.type === 'ready') callbacksRef.current.onReady?.(event)\n if (event.type === 'completed')\n callbacksRef.current.onCompleted?.(event)\n if (event.type === 'failed') {\n failed = true\n callbacksRef.current.onFailed?.(event)\n }\n })\n if (presentation === 'modal') await instance.present()\n else await instance.mount(target!)\n })\n .catch((error: unknown) => {\n if (active && !canceled && !failed)\n callbacksRef.current.onError?.(asError(error))\n })\n\n return () => {\n active = false\n unsubscribe?.()\n checkout?.destroy()\n if (checkoutRef.current === checkout) checkoutRef.current = null\n }\n }, [\n allowPaymentMethodChange,\n hasFeatureOverrides,\n orderId,\n purchaseIntentId,\n presentation,\n showInvoiceDownload,\n showLineItems,\n showReceiptDownload,\n timeout,\n title,\n ])\n\n useEffect(() => {\n checkoutRef.current?.update(definedOptions({ appearance, locale }))\n }, [appearance, locale])\n\n return <div className={className} ref={containerRef} style={style} />\n },\n)\n\nfunction definedOptions<Value extends object>(options: Value): Value {\n return Object.fromEntries(\n Object.entries(options).filter(([, value]) => value !== undefined),\n ) as Value\n}\n\nfunction asError(error: unknown): Error {\n return error instanceof Error ? error : new Error('Checkout failed to load.')\n}\n"],"mappings":"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","names":["Checkout"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { CSSProperties } from 'react';
|
|
3
|
-
import { CheckoutOptions, CheckoutPresentation, CheckoutEvent,
|
|
4
|
-
export { CheckoutAppearance,
|
|
3
|
+
import { CheckoutOptions, CheckoutPresentation, CheckoutEvent, CheckoutController } from '@inttegro/js';
|
|
4
|
+
export { CheckoutAppearance, CheckoutEvent, CheckoutFailedEvent, CheckoutFeatures, CheckoutOrder, CheckoutPresentation, CheckoutTheme } from '@inttegro/js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Props for {@link Checkout}.
|
|
@@ -32,12 +32,12 @@ type CheckoutProps = CheckoutOptions & {
|
|
|
32
32
|
onCompleted?: (event: Extract<CheckoutEvent, {
|
|
33
33
|
type: 'completed';
|
|
34
34
|
}>) => void;
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
onError?: (
|
|
35
|
+
/** Called when Checkout reaches a terminal failure state. */
|
|
36
|
+
onFailed?: (event: Extract<CheckoutEvent, {
|
|
37
|
+
type: 'failed';
|
|
38
|
+
}>) => void;
|
|
39
|
+
/** Called for loader or mount errors. */
|
|
40
|
+
onError?: (error: Error) => void;
|
|
41
41
|
/** Called for every sanitized lifecycle event, including events above. */
|
|
42
42
|
onEvent?: (event: CheckoutEvent) => void;
|
|
43
43
|
/** Called once the iframe is interactive and its mount promise has resolved. */
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { CSSProperties } from 'react';
|
|
3
|
-
import { CheckoutOptions, CheckoutPresentation, CheckoutEvent,
|
|
4
|
-
export { CheckoutAppearance,
|
|
3
|
+
import { CheckoutOptions, CheckoutPresentation, CheckoutEvent, CheckoutController } from '@inttegro/js';
|
|
4
|
+
export { CheckoutAppearance, CheckoutEvent, CheckoutFailedEvent, CheckoutFeatures, CheckoutOrder, CheckoutPresentation, CheckoutTheme } from '@inttegro/js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Props for {@link Checkout}.
|
|
@@ -32,12 +32,12 @@ type CheckoutProps = CheckoutOptions & {
|
|
|
32
32
|
onCompleted?: (event: Extract<CheckoutEvent, {
|
|
33
33
|
type: 'completed';
|
|
34
34
|
}>) => void;
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
onError?: (
|
|
35
|
+
/** Called when Checkout reaches a terminal failure state. */
|
|
36
|
+
onFailed?: (event: Extract<CheckoutEvent, {
|
|
37
|
+
type: 'failed';
|
|
38
|
+
}>) => void;
|
|
39
|
+
/** Called for loader or mount errors. */
|
|
40
|
+
onError?: (error: Error) => void;
|
|
41
41
|
/** Called for every sanitized lifecycle event, including events above. */
|
|
42
42
|
onEvent?: (event: CheckoutEvent) => void;
|
|
43
43
|
/** Called once the iframe is interactive and its mount promise has resolved. */
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ var Checkout = forwardRef(
|
|
|
17
17
|
locale,
|
|
18
18
|
onCanceled,
|
|
19
19
|
onCompleted,
|
|
20
|
+
onFailed,
|
|
20
21
|
onError,
|
|
21
22
|
onEvent,
|
|
22
23
|
onReady,
|
|
@@ -32,6 +33,7 @@ var Checkout = forwardRef(
|
|
|
32
33
|
const callbacksRef = useRef({
|
|
33
34
|
onCanceled,
|
|
34
35
|
onCompleted,
|
|
36
|
+
onFailed,
|
|
35
37
|
onError,
|
|
36
38
|
onEvent,
|
|
37
39
|
onReady
|
|
@@ -45,6 +47,7 @@ var Checkout = forwardRef(
|
|
|
45
47
|
callbacksRef.current = {
|
|
46
48
|
onCanceled,
|
|
47
49
|
onCompleted,
|
|
50
|
+
onFailed,
|
|
48
51
|
onError,
|
|
49
52
|
onEvent,
|
|
50
53
|
onReady
|
|
@@ -64,6 +67,7 @@ var Checkout = forwardRef(
|
|
|
64
67
|
if (presentation === "embedded" && !target) return;
|
|
65
68
|
let active = true;
|
|
66
69
|
let canceled = false;
|
|
70
|
+
let failed = false;
|
|
67
71
|
let checkout;
|
|
68
72
|
let unsubscribe;
|
|
69
73
|
void loadInttegro().then(async (inttegro) => {
|
|
@@ -98,12 +102,15 @@ var Checkout = forwardRef(
|
|
|
98
102
|
if (event.type === "ready") callbacksRef.current.onReady?.(event);
|
|
99
103
|
if (event.type === "completed")
|
|
100
104
|
callbacksRef.current.onCompleted?.(event);
|
|
101
|
-
if (event.type === "
|
|
105
|
+
if (event.type === "failed") {
|
|
106
|
+
failed = true;
|
|
107
|
+
callbacksRef.current.onFailed?.(event);
|
|
108
|
+
}
|
|
102
109
|
});
|
|
103
110
|
if (presentation === "modal") await instance.present();
|
|
104
111
|
else await instance.mount(target);
|
|
105
112
|
}).catch((error) => {
|
|
106
|
-
if (active && !canceled)
|
|
113
|
+
if (active && !canceled && !failed)
|
|
107
114
|
callbacksRef.current.onError?.(asError(error));
|
|
108
115
|
});
|
|
109
116
|
return () => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Checkout.tsx"],"sourcesContent":["import {\n loadInttegro,\n type CheckoutController,\n type CheckoutErrorEvent,\n type CheckoutEvent,\n type CheckoutOptions,\n type CheckoutPresentation,\n} from '@inttegro/js'\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n type CSSProperties,\n} from 'react'\n\n/**\n * Props for {@link Checkout}.\n *\n * `features`, the Checkout reference, `presentation`, `timeout`, and `title`\n * identify the experience. Changing one replaces the underlying controller.\n * `appearance` and `locale` update the existing controller without discarding\n * payer progress.\n *\n * @category React\n */\nexport type CheckoutProps = CheckoutOptions & {\n /** CSS class applied to the outer container owned by your React application. */\n className?: string\n /** Inline styles applied to the outer container, never to controls inside Checkout. */\n style?: CSSProperties\n /** Displays Checkout inline by default or in an Inttegro-managed modal. */\n presentation?: CheckoutPresentation\n /** Called when a payer dismisses managed modal Checkout before completion. */\n onCanceled?: (event: Extract<CheckoutEvent, { type: 'canceled' }>) => void\n /**\n * Called after Checkout reports its successful terminal state.\n * Use this to navigate or refresh server-owned Order state, not as the sole\n * signal for fulfillment.\n */\n onCompleted?: (event: Extract<CheckoutEvent, { type: 'completed' }>) => void\n /**\n * Called for loader/mount errors and sanitized hosted errors.\n * Use `error instanceof InttegroCheckoutError` or check for an event `type`\n * before reading framework-independent details.\n */\n onError?: (event: CheckoutErrorEvent | Error) => void\n /** Called for every sanitized lifecycle event, including events above. */\n onEvent?: (event: CheckoutEvent) => void\n /** Called once the iframe is interactive and its mount promise has resolved. */\n onReady?: (event: Extract<CheckoutEvent, { type: 'ready' }>) => void\n}\n\n/**\n * Imperative operations exposed by {@link Checkout} through a React ref.\n *\n * Prefer props for normal updates. Use the handle for focus management in\n * dialogs or for updates driven by imperative host integrations.\n *\n * @category React\n */\nexport interface CheckoutHandle {\n /** Closes managed modal Checkout when it is open. */\n dismiss(): void\n /** Moves focus into Checkout when its controller is ready; otherwise does nothing. */\n focus(): void\n /** Applies a new locale or theme when the controller exists. */\n update(options: Parameters<CheckoutController['update']>[0]): void\n}\n\n/**\n * Displays Inttegro-hosted Checkout in a React application.\n *\n * The component renders an empty `div`, loads the executable runtime from\n * Inttegro's fixed origin after mount, creates a controller for an `orderId` or\n * `purchaseIntentId`, and destroys it during cleanup. Server rendering is safe\n * because no runtime is loaded until the effect runs in a browser.\n *\n * Changing `features`, the Checkout reference, `presentation`, `timeout`, or\n * `title` starts a fresh hosted experience. Changing `appearance` or `locale`\n * updates the active experience in place. Keep the component mounted while a\n * payment is pending or confirmation is in progress.\n *\n * @example Present Checkout without building a dialog\n * ```tsx\n * import { Checkout } from '@inttegro/react'\n *\n * function Payment({ orderId }: { orderId: string }) {\n * return (\n * <Checkout\n * orderId={orderId}\n * presentation=\"modal\"\n * appearance={{ theme: 'system' }}\n * onCompleted={() => location.assign(`/orders/${orderId}/complete`)}\n * onError={(error) => reportCheckoutError(error)}\n * />\n * )\n * }\n * ```\n *\n * @category React\n */\nexport const Checkout = forwardRef<CheckoutHandle, CheckoutProps>(\n function Checkout(\n {\n appearance,\n className,\n features,\n locale,\n onCanceled,\n onCompleted,\n onError,\n onEvent,\n onReady,\n orderId,\n purchaseIntentId,\n presentation = 'embedded',\n style,\n timeout,\n title,\n },\n forwardedRef,\n ) {\n const containerRef = useRef<HTMLDivElement>(null)\n const checkoutRef = useRef<CheckoutController | null>(null)\n const callbacksRef = useRef({\n onCanceled,\n onCompleted,\n onError,\n onEvent,\n onReady,\n })\n const updateOptionsRef = useRef({ appearance, locale })\n const hasFeatureOverrides = features !== undefined\n const showLineItems = features?.showLineItems\n const showInvoiceDownload = features?.showInvoiceDownload\n const showReceiptDownload = features?.showReceiptDownload\n const allowPaymentMethodChange = features?.allowPaymentMethodChange\n callbacksRef.current = {\n onCanceled,\n onCompleted,\n onError,\n onEvent,\n onReady,\n }\n updateOptionsRef.current = { appearance, locale }\n\n useImperativeHandle(\n forwardedRef,\n () => ({\n dismiss: () => checkoutRef.current?.dismiss(),\n focus: () => checkoutRef.current?.focus(),\n update: (options) => checkoutRef.current?.update(options),\n }),\n [],\n )\n\n useEffect(() => {\n const target = containerRef.current\n if (presentation === 'embedded' && !target) return\n\n let active = true\n let canceled = false\n let checkout: CheckoutController | undefined\n let unsubscribe: (() => void) | undefined\n\n void loadInttegro()\n .then(async (inttegro) => {\n if (!active || !inttegro) return\n const instance = inttegro.createCheckout(\n definedOptions({\n ...updateOptionsRef.current,\n features: hasFeatureOverrides\n ? definedOptions({\n allowPaymentMethodChange,\n showInvoiceDownload,\n showLineItems,\n showReceiptDownload,\n })\n : undefined,\n orderId,\n purchaseIntentId,\n timeout,\n title,\n }) as CheckoutOptions,\n )\n if (!active) {\n instance.destroy()\n return\n }\n checkout = instance\n checkoutRef.current = instance\n unsubscribe = instance.onEvent((event) => {\n callbacksRef.current.onEvent?.(event)\n if (event.type === 'canceled') {\n canceled = true\n callbacksRef.current.onCanceled?.(event)\n }\n if (event.type === 'ready') callbacksRef.current.onReady?.(event)\n if (event.type === 'completed')\n callbacksRef.current.onCompleted?.(event)\n if (event.type === 'error') callbacksRef.current.onError?.(event)\n })\n if (presentation === 'modal') await instance.present()\n else await instance.mount(target!)\n })\n .catch((error: unknown) => {\n if (active && !canceled)\n callbacksRef.current.onError?.(asError(error))\n })\n\n return () => {\n active = false\n unsubscribe?.()\n checkout?.destroy()\n if (checkoutRef.current === checkout) checkoutRef.current = null\n }\n }, [\n allowPaymentMethodChange,\n hasFeatureOverrides,\n orderId,\n purchaseIntentId,\n presentation,\n showInvoiceDownload,\n showLineItems,\n showReceiptDownload,\n timeout,\n title,\n ])\n\n useEffect(() => {\n checkoutRef.current?.update(definedOptions({ appearance, locale }))\n }, [appearance, locale])\n\n return <div className={className} ref={containerRef} style={style} />\n },\n)\n\nfunction definedOptions<Value extends object>(options: Value): Value {\n return Object.fromEntries(\n Object.entries(options).filter(([, value]) => value !== undefined),\n ) as Value\n}\n\nfunction asError(error: unknown): Error {\n return error instanceof Error ? error : new Error('Checkout failed to load.')\n}\n"],"mappings":"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","names":["Checkout"]}
|
|
1
|
+
{"version":3,"sources":["../src/Checkout.tsx"],"sourcesContent":["import {\n loadInttegro,\n type CheckoutController,\n type CheckoutEvent,\n type CheckoutOptions,\n type CheckoutPresentation,\n} from '@inttegro/js'\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n type CSSProperties,\n} from 'react'\n\n/**\n * Props for {@link Checkout}.\n *\n * `features`, the Checkout reference, `presentation`, `timeout`, and `title`\n * identify the experience. Changing one replaces the underlying controller.\n * `appearance` and `locale` update the existing controller without discarding\n * payer progress.\n *\n * @category React\n */\nexport type CheckoutProps = CheckoutOptions & {\n /** CSS class applied to the outer container owned by your React application. */\n className?: string\n /** Inline styles applied to the outer container, never to controls inside Checkout. */\n style?: CSSProperties\n /** Displays Checkout inline by default or in an Inttegro-managed modal. */\n presentation?: CheckoutPresentation\n /** Called when a payer dismisses managed modal Checkout before completion. */\n onCanceled?: (event: Extract<CheckoutEvent, { type: 'canceled' }>) => void\n /**\n * Called after Checkout reports its successful terminal state.\n * Use this to navigate or refresh server-owned Order state, not as the sole\n * signal for fulfillment.\n */\n onCompleted?: (event: Extract<CheckoutEvent, { type: 'completed' }>) => void\n /** Called when Checkout reaches a terminal failure state. */\n onFailed?: (event: Extract<CheckoutEvent, { type: 'failed' }>) => void\n /** Called for loader or mount errors. */\n onError?: (error: Error) => void\n /** Called for every sanitized lifecycle event, including events above. */\n onEvent?: (event: CheckoutEvent) => void\n /** Called once the iframe is interactive and its mount promise has resolved. */\n onReady?: (event: Extract<CheckoutEvent, { type: 'ready' }>) => void\n}\n\n/**\n * Imperative operations exposed by {@link Checkout} through a React ref.\n *\n * Prefer props for normal updates. Use the handle for focus management in\n * dialogs or for updates driven by imperative host integrations.\n *\n * @category React\n */\nexport interface CheckoutHandle {\n /** Closes managed modal Checkout when it is open. */\n dismiss(): void\n /** Moves focus into Checkout when its controller is ready; otherwise does nothing. */\n focus(): void\n /** Applies a new locale or theme when the controller exists. */\n update(options: Parameters<CheckoutController['update']>[0]): void\n}\n\n/**\n * Displays Inttegro-hosted Checkout in a React application.\n *\n * The component renders an empty `div`, loads the executable runtime from\n * Inttegro's fixed origin after mount, creates a controller for an `orderId` or\n * `purchaseIntentId`, and destroys it during cleanup. Server rendering is safe\n * because no runtime is loaded until the effect runs in a browser.\n *\n * Changing `features`, the Checkout reference, `presentation`, `timeout`, or\n * `title` starts a fresh hosted experience. Changing `appearance` or `locale`\n * updates the active experience in place. Keep the component mounted while a\n * payment is pending or confirmation is in progress.\n *\n * @example Present Checkout without building a dialog\n * ```tsx\n * import { Checkout } from '@inttegro/react'\n *\n * function Payment({ orderId }: { orderId: string }) {\n * return (\n * <Checkout\n * orderId={orderId}\n * presentation=\"modal\"\n * appearance={{ theme: 'system' }}\n * onCompleted={() => location.assign(`/orders/${orderId}/complete`)}\n * onError={(error) => reportCheckoutError(error)}\n * />\n * )\n * }\n * ```\n *\n * @category React\n */\nexport const Checkout = forwardRef<CheckoutHandle, CheckoutProps>(\n function Checkout(\n {\n appearance,\n className,\n features,\n locale,\n onCanceled,\n onCompleted,\n onFailed,\n onError,\n onEvent,\n onReady,\n orderId,\n purchaseIntentId,\n presentation = 'embedded',\n style,\n timeout,\n title,\n },\n forwardedRef,\n ) {\n const containerRef = useRef<HTMLDivElement>(null)\n const checkoutRef = useRef<CheckoutController | null>(null)\n const callbacksRef = useRef({\n onCanceled,\n onCompleted,\n onFailed,\n onError,\n onEvent,\n onReady,\n })\n const updateOptionsRef = useRef({ appearance, locale })\n const hasFeatureOverrides = features !== undefined\n const showLineItems = features?.showLineItems\n const showInvoiceDownload = features?.showInvoiceDownload\n const showReceiptDownload = features?.showReceiptDownload\n const allowPaymentMethodChange = features?.allowPaymentMethodChange\n callbacksRef.current = {\n onCanceled,\n onCompleted,\n onFailed,\n onError,\n onEvent,\n onReady,\n }\n updateOptionsRef.current = { appearance, locale }\n\n useImperativeHandle(\n forwardedRef,\n () => ({\n dismiss: () => checkoutRef.current?.dismiss(),\n focus: () => checkoutRef.current?.focus(),\n update: (options) => checkoutRef.current?.update(options),\n }),\n [],\n )\n\n useEffect(() => {\n const target = containerRef.current\n if (presentation === 'embedded' && !target) return\n\n let active = true\n let canceled = false\n let failed = false\n let checkout: CheckoutController | undefined\n let unsubscribe: (() => void) | undefined\n\n void loadInttegro()\n .then(async (inttegro) => {\n if (!active || !inttegro) return\n const instance = inttegro.createCheckout(\n definedOptions({\n ...updateOptionsRef.current,\n features: hasFeatureOverrides\n ? definedOptions({\n allowPaymentMethodChange,\n showInvoiceDownload,\n showLineItems,\n showReceiptDownload,\n })\n : undefined,\n orderId,\n purchaseIntentId,\n timeout,\n title,\n }) as CheckoutOptions,\n )\n if (!active) {\n instance.destroy()\n return\n }\n checkout = instance\n checkoutRef.current = instance\n unsubscribe = instance.onEvent((event) => {\n callbacksRef.current.onEvent?.(event)\n if (event.type === 'canceled') {\n canceled = true\n callbacksRef.current.onCanceled?.(event)\n }\n if (event.type === 'ready') callbacksRef.current.onReady?.(event)\n if (event.type === 'completed')\n callbacksRef.current.onCompleted?.(event)\n if (event.type === 'failed') {\n failed = true\n callbacksRef.current.onFailed?.(event)\n }\n })\n if (presentation === 'modal') await instance.present()\n else await instance.mount(target!)\n })\n .catch((error: unknown) => {\n if (active && !canceled && !failed)\n callbacksRef.current.onError?.(asError(error))\n })\n\n return () => {\n active = false\n unsubscribe?.()\n checkout?.destroy()\n if (checkoutRef.current === checkout) checkoutRef.current = null\n }\n }, [\n allowPaymentMethodChange,\n hasFeatureOverrides,\n orderId,\n purchaseIntentId,\n presentation,\n showInvoiceDownload,\n showLineItems,\n showReceiptDownload,\n timeout,\n title,\n ])\n\n useEffect(() => {\n checkoutRef.current?.update(definedOptions({ appearance, locale }))\n }, [appearance, locale])\n\n return <div className={className} ref={containerRef} style={style} />\n },\n)\n\nfunction definedOptions<Value extends object>(options: Value): Value {\n return Object.fromEntries(\n Object.entries(options).filter(([, value]) => value !== undefined),\n ) as Value\n}\n\nfunction asError(error: unknown): Error {\n return error instanceof Error ? error : new Error('Checkout failed to load.')\n}\n"],"mappings":"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","names":["Checkout"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inttegro/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "React components for Inttegro hosted workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"typecheck": "tsc --noEmit"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@inttegro/js": "0.
|
|
35
|
+
"@inttegro/js": "0.5.2"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"react": ">=18"
|