@doswiftly/storefront-sdk 20.2.0 → 21.0.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/CHANGELOG.md +38 -0
- package/README.md +776 -529
- package/dist/core/auth/handlers.d.ts +10 -9
- package/dist/core/auth/handlers.d.ts.map +1 -1
- package/dist/core/auth/handlers.js +10 -9
- package/dist/core/auth/session-events.d.ts +2 -2
- package/dist/core/auth/session-events.js +2 -2
- package/dist/core/cart/cart-client.d.ts +23 -24
- package/dist/core/cart/cart-client.d.ts.map +1 -1
- package/dist/core/cart/cart-client.js +24 -25
- package/dist/core/generated/operation-types.d.ts +102 -108
- package/dist/core/generated/operation-types.d.ts.map +1 -1
- package/dist/core/middleware/session-retry.d.ts +5 -6
- package/dist/core/middleware/session-retry.d.ts.map +1 -1
- package/dist/core/middleware/session-retry.js +7 -8
- package/dist/core/operations/auth.d.ts.map +1 -1
- package/dist/core/operations/auth.js +4 -0
- package/dist/core/operations/cart.d.ts +11 -10
- package/dist/core/operations/cart.d.ts.map +1 -1
- package/dist/core/operations/cart.js +14 -11
- package/dist/react/components/PaymentInstrumentSection.d.ts +24 -24
- package/dist/react/components/PaymentInstrumentSection.d.ts.map +1 -1
- package/dist/react/components/PaymentInstrumentSection.js +15 -15
- package/dist/react/components/PaymentInstrumentTile.d.ts +19 -20
- package/dist/react/components/PaymentInstrumentTile.d.ts.map +1 -1
- package/dist/react/components/PaymentInstrumentTile.js +15 -16
- package/dist/react/helpers/browser-data.d.ts +30 -33
- package/dist/react/helpers/browser-data.d.ts.map +1 -1
- package/dist/react/helpers/browser-data.js +26 -29
- package/dist/react/hooks/use-cart-manager.d.ts +1 -1
- package/dist/react/hooks/use-cart-manager.js +1 -1
- package/dist/react/hooks/use-cart.d.ts +2 -2
- package/dist/react/hooks/use-cart.js +3 -3
- package/dist/react/hooks/use-session-expired.d.ts +6 -5
- package/dist/react/hooks/use-session-expired.d.ts.map +1 -1
- package/dist/react/hooks/use-session-expired.js +6 -5
- package/dist/react/stores/auth.store.d.ts.map +1 -1
- package/dist/react/stores/auth.store.js +13 -10
- package/dist/react/stores/cart.store.d.ts +1 -1
- package/dist/react/stores/cart.store.js +1 -1
- package/package.json +1 -1
|
@@ -4,15 +4,14 @@
|
|
|
4
4
|
* When a request fails with HTTP 401 (the access token lapsed between the
|
|
5
5
|
* proactive refresh and this call):
|
|
6
6
|
*
|
|
7
|
-
* - **Read query** — refresh the session once and replay the request
|
|
7
|
+
* - **Read query** — refresh the session once and replay the request.
|
|
8
8
|
* Because this middleware is the outermost one, the retry re-runs the auth
|
|
9
9
|
* middleware, which re-reads the freshly-stored token. Concurrent 401s share
|
|
10
|
-
* a single renewal because the injected `refresh` dedupes in-flight calls
|
|
11
|
-
*
|
|
12
|
-
* (R2.4).
|
|
10
|
+
* a single renewal because the injected `refresh` dedupes in-flight calls.
|
|
11
|
+
* If the refresh also fails, the session is gone — signal and bail.
|
|
13
12
|
*
|
|
14
13
|
* - **Mutation** — never auto-retry (mutations are sacred; client-side
|
|
15
|
-
* idempotency is not guaranteed). Bail and signal the session loss
|
|
14
|
+
* idempotency is not guaranteed). Bail and signal the session loss.
|
|
16
15
|
*
|
|
17
16
|
* Auth operations (login / signup / refresh / logout) are exempt: they own
|
|
18
17
|
* their own error handling, and retrying the refresh op itself would recurse.
|
|
@@ -35,7 +34,7 @@ export interface SessionRetryOptions {
|
|
|
35
34
|
/**
|
|
36
35
|
* Renew the session (refresh token → cookie sync → store update). Resolves
|
|
37
36
|
* `true` on success. MUST dedupe concurrent calls so simultaneous 401s share
|
|
38
|
-
* a single renewal
|
|
37
|
+
* a single renewal.
|
|
39
38
|
*/
|
|
40
39
|
refresh: () => Promise<boolean>;
|
|
41
40
|
/** Notify that the session is gone (a mutation 401, or a query whose refresh-retry failed). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-retry.d.ts","sourceRoot":"","sources":["../../../src/core/middleware/session-retry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"session-retry.d.ts","sourceRoot":"","sources":["../../../src/core/middleware/session-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAQlE,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,+FAA+F;IAC/F,gBAAgB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACvD,+EAA+E;IAC/E,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAMD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,mBAAmB,GAAG,UAAU,CAgC/E"}
|
|
@@ -4,15 +4,14 @@
|
|
|
4
4
|
* When a request fails with HTTP 401 (the access token lapsed between the
|
|
5
5
|
* proactive refresh and this call):
|
|
6
6
|
*
|
|
7
|
-
* - **Read query** — refresh the session once and replay the request
|
|
7
|
+
* - **Read query** — refresh the session once and replay the request.
|
|
8
8
|
* Because this middleware is the outermost one, the retry re-runs the auth
|
|
9
9
|
* middleware, which re-reads the freshly-stored token. Concurrent 401s share
|
|
10
|
-
* a single renewal because the injected `refresh` dedupes in-flight calls
|
|
11
|
-
*
|
|
12
|
-
* (R2.4).
|
|
10
|
+
* a single renewal because the injected `refresh` dedupes in-flight calls.
|
|
11
|
+
* If the refresh also fails, the session is gone — signal and bail.
|
|
13
12
|
*
|
|
14
13
|
* - **Mutation** — never auto-retry (mutations are sacred; client-side
|
|
15
|
-
* idempotency is not guaranteed). Bail and signal the session loss
|
|
14
|
+
* idempotency is not guaranteed). Bail and signal the session loss.
|
|
16
15
|
*
|
|
17
16
|
* Auth operations (login / signup / refresh / logout) are exempt: they own
|
|
18
17
|
* their own error handling, and retrying the refresh op itself would recurse.
|
|
@@ -52,14 +51,14 @@ export function sessionRetryMiddleware(options) {
|
|
|
52
51
|
if (!isUnauthorized(err))
|
|
53
52
|
throw err;
|
|
54
53
|
if (request.isMutation) {
|
|
55
|
-
//
|
|
54
|
+
// Mutations are sacred: bail, never auto-retry.
|
|
56
55
|
onSessionExpired({ reason: 'mutation-unauthorized', cause: err });
|
|
57
56
|
throw err;
|
|
58
57
|
}
|
|
59
|
-
//
|
|
58
|
+
// Read query: refresh once (deduped) and replay.
|
|
60
59
|
const renewed = await refresh();
|
|
61
60
|
if (!renewed) {
|
|
62
|
-
//
|
|
61
|
+
// The refresh also failed; the session is gone.
|
|
63
62
|
onSessionExpired({ reason: 'reactive-refresh-failed', cause: err });
|
|
64
63
|
throw err;
|
|
65
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/core/operations/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/core/operations/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA0HH,eAAO,MAAM,cAAc,QASzB,CAAC;AAEH,eAAO,MAAM,eAAe,QAS1B,CAAC;AAEH,eAAO,MAAM,sBAAsB,QASjC,CAAC;AAEH,eAAO,MAAM,eAAe,QAW1B,CAAC;AAMH,eAAO,MAAM,cAAc,QAOzB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,QAYnC,CAAC"}
|
|
@@ -53,6 +53,8 @@ const MAILING_ADDRESS_FRAGMENT_AUTH = `
|
|
|
53
53
|
company
|
|
54
54
|
streetLine1
|
|
55
55
|
streetLine2
|
|
56
|
+
buildingNumber
|
|
57
|
+
flatNumber
|
|
56
58
|
city
|
|
57
59
|
state
|
|
58
60
|
stateCode
|
|
@@ -90,6 +92,8 @@ const CUSTOMER_FRAGMENT = `
|
|
|
90
92
|
id
|
|
91
93
|
streetLine1
|
|
92
94
|
streetLine2
|
|
95
|
+
buildingNumber
|
|
96
|
+
flatNumber
|
|
93
97
|
city
|
|
94
98
|
company
|
|
95
99
|
country
|
|
@@ -85,7 +85,7 @@ export declare const CART_UPDATE_GIFT_CARD_RECIPIENT: string;
|
|
|
85
85
|
* flow decisions). The cart itself is NOT returned — after completion it is
|
|
86
86
|
* CONVERTED/locked, so the storefront drops its local cart and works with the
|
|
87
87
|
* Order. `order` is non-null on success. `paymentUrl` is intentionally NOT in
|
|
88
|
-
* the payload
|
|
88
|
+
* the payload — the payment session is created by a separate `paymentCreate`
|
|
89
89
|
* mutation after checking `order.canCreatePayment`.
|
|
90
90
|
*/
|
|
91
91
|
export declare const CART_COMPLETE: string;
|
|
@@ -97,19 +97,20 @@ export declare const CART_COMPLETE: string;
|
|
|
97
97
|
*/
|
|
98
98
|
export declare const PAYMENT_CREATE: string;
|
|
99
99
|
/**
|
|
100
|
-
* cartClearPaymentSelection Mutation
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
100
|
+
* cartClearPaymentSelection Mutation — explicit deselect for "back to payment
|
|
101
|
+
* method selection" storefront accordion UI. Atomically NULLs all 4 payment
|
|
102
|
+
* selection fields, idempotent. The cart MUST be ACTIVE (CONVERTED carts are
|
|
103
|
+
* rejected with `ALREADY_COMPLETED`).
|
|
104
104
|
*/
|
|
105
105
|
export declare const CART_CLEAR_PAYMENT_SELECTION: string;
|
|
106
106
|
/**
|
|
107
|
-
* cartValidateDiscountCode Query — read-only preview discount applicability
|
|
108
|
-
*
|
|
109
|
-
*
|
|
107
|
+
* cartValidateDiscountCode Query — read-only preview of discount applicability;
|
|
108
|
+
* validation must not mutate cart state. No cart side effects; storefront UI
|
|
109
|
+
* uses it for inline feedback while the customer types a code (before calling
|
|
110
|
+
* cartDiscountCodesUpdate).
|
|
110
111
|
*
|
|
111
|
-
* Caching guidance: `fetchPolicy: 'network-only'`
|
|
112
|
-
* `cart.subtotal` (discount eligibility
|
|
112
|
+
* Caching guidance: `fetchPolicy: 'network-only'` or a key that includes
|
|
113
|
+
* `cart.subtotal` (discount eligibility may depend on a minimum order amount).
|
|
113
114
|
*/
|
|
114
115
|
export declare const CART_VALIDATE_DISCOUNT_CODE: string;
|
|
115
116
|
//# sourceMappingURL=cart.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cart.d.ts","sourceRoot":"","sources":["../../../src/core/operations/cart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"cart.d.ts","sourceRoot":"","sources":["../../../src/core/operations/cart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAwbH,eAAO,MAAM,UAAU,QAOrB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,qCAAqC,QAehD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,QAO1C,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,QAO/B,CAAC;AAMH,eAAO,MAAM,WAAW,QAYtB,CAAC;AAEH,eAAO,MAAM,cAAc,QAWzB,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAW5B,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAW5B,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAEH,eAAO,MAAM,gBAAgB,QAW3B,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,QAWjC,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAMH;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAWrB,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,QAWnC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,QAY/B,CAAC;AAMH,eAAO,MAAM,yBAAyB,QAWpC,CAAC;AAEH,eAAO,MAAM,wBAAwB,QAWnC,CAAC;AAEH,eAAO,MAAM,2BAA2B,QAWtC,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAEH,eAAO,MAAM,oBAAoB,QAW/B,CAAC;AAEH,eAAO,MAAM,qBAAqB,QAWhC,CAAC;AAEH,eAAO,MAAM,+BAA+B,QAW1C,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,QAWxB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QAWzB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAWvC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,QAoBtC,CAAC"}
|
|
@@ -162,6 +162,8 @@ const MAILING_ADDRESS_FRAGMENT = `
|
|
|
162
162
|
company
|
|
163
163
|
streetLine1
|
|
164
164
|
streetLine2
|
|
165
|
+
buildingNumber
|
|
166
|
+
flatNumber
|
|
165
167
|
city
|
|
166
168
|
state
|
|
167
169
|
stateCode
|
|
@@ -640,7 +642,7 @@ export const CART_RECOVERY_REDEEM = composeOperation(`
|
|
|
640
642
|
${CART_WARNING_FRAGMENT}
|
|
641
643
|
`);
|
|
642
644
|
// ---------------------------------------------------------------------------
|
|
643
|
-
//
|
|
645
|
+
// Cart completion lifecycle mutations
|
|
644
646
|
// ---------------------------------------------------------------------------
|
|
645
647
|
export const CART_SET_SHIPPING_ADDRESS = composeOperation(`
|
|
646
648
|
mutation CartSetShippingAddress($input: CartSetShippingAddressInput!) {
|
|
@@ -732,7 +734,7 @@ export const CART_UPDATE_GIFT_CARD_RECIPIENT = composeOperation(`
|
|
|
732
734
|
* flow decisions). The cart itself is NOT returned — after completion it is
|
|
733
735
|
* CONVERTED/locked, so the storefront drops its local cart and works with the
|
|
734
736
|
* Order. `order` is non-null on success. `paymentUrl` is intentionally NOT in
|
|
735
|
-
* the payload
|
|
737
|
+
* the payload — the payment session is created by a separate `paymentCreate`
|
|
736
738
|
* mutation after checking `order.canCreatePayment`.
|
|
737
739
|
*/
|
|
738
740
|
export const CART_COMPLETE = composeOperation(`
|
|
@@ -766,10 +768,10 @@ export const PAYMENT_CREATE = composeOperation(`
|
|
|
766
768
|
${PAYMENT_WARNING_FRAGMENT}
|
|
767
769
|
`);
|
|
768
770
|
/**
|
|
769
|
-
* cartClearPaymentSelection Mutation
|
|
770
|
-
*
|
|
771
|
-
*
|
|
772
|
-
*
|
|
771
|
+
* cartClearPaymentSelection Mutation — explicit deselect for "back to payment
|
|
772
|
+
* method selection" storefront accordion UI. Atomically NULLs all 4 payment
|
|
773
|
+
* selection fields, idempotent. The cart MUST be ACTIVE (CONVERTED carts are
|
|
774
|
+
* rejected with `ALREADY_COMPLETED`).
|
|
773
775
|
*/
|
|
774
776
|
export const CART_CLEAR_PAYMENT_SELECTION = composeOperation(`
|
|
775
777
|
mutation CartClearPaymentSelection($input: CartClearPaymentSelectionInput!) {
|
|
@@ -784,12 +786,13 @@ export const CART_CLEAR_PAYMENT_SELECTION = composeOperation(`
|
|
|
784
786
|
${CART_WARNING_FRAGMENT}
|
|
785
787
|
`);
|
|
786
788
|
/**
|
|
787
|
-
* cartValidateDiscountCode Query — read-only preview discount applicability
|
|
788
|
-
*
|
|
789
|
-
*
|
|
789
|
+
* cartValidateDiscountCode Query — read-only preview of discount applicability;
|
|
790
|
+
* validation must not mutate cart state. No cart side effects; storefront UI
|
|
791
|
+
* uses it for inline feedback while the customer types a code (before calling
|
|
792
|
+
* cartDiscountCodesUpdate).
|
|
790
793
|
*
|
|
791
|
-
* Caching guidance: `fetchPolicy: 'network-only'`
|
|
792
|
-
* `cart.subtotal` (discount eligibility
|
|
794
|
+
* Caching guidance: `fetchPolicy: 'network-only'` or a key that includes
|
|
795
|
+
* `cart.subtotal` (discount eligibility may depend on a minimum order amount).
|
|
793
796
|
*/
|
|
794
797
|
export const CART_VALIDATE_DISCOUNT_CODE = composeOperation(`
|
|
795
798
|
query CartValidateDiscountCode($cartId: ID!, $discountCode: String!) {
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `<PaymentInstrumentSection>` — radio-group container
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* per item
|
|
2
|
+
* `<PaymentInstrumentSection>` — radio-group container for the payment
|
|
3
|
+
* instruments within a single method (e.g. a bank list + BLIK code entry in a
|
|
4
|
+
* BLIK method, wallets + card brands in a CARD method). Renders one
|
|
5
|
+
* `<PaymentInstrumentTile>` per item with keyboard nav (Arrow Up/Down,
|
|
6
|
+
* Home/End) + ARIA `role="radiogroup"`.
|
|
6
7
|
*
|
|
7
|
-
* Headless — section + tiles
|
|
8
|
-
*
|
|
9
|
-
* `iconClassName`/`labelClassName`
|
|
8
|
+
* Headless — section + tiles ship without any styling. Pass `sectionClassName`
|
|
9
|
+
* for the layout (grid/flex), `tileClassName` for per-tile styling, optional
|
|
10
|
+
* `iconClassName`/`labelClassName` for the tile's inner structure.
|
|
10
11
|
*
|
|
11
|
-
* Auto-
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Auto-grouping is **not** implemented — the backend already returns
|
|
13
|
+
* instruments sorted (BLIK + wallets first → banks alphabetically → others)
|
|
14
|
+
* in `availablePaymentMethods.methods[].instruments[]`. The component renders
|
|
15
|
+
* them in the order received, with no re-sorting logic of its own.
|
|
15
16
|
*
|
|
16
17
|
* @example
|
|
17
18
|
* ```tsx
|
|
@@ -24,32 +25,31 @@
|
|
|
24
25
|
* tileClassName="rounded border p-3 data-[selected=true]:border-blue-500"
|
|
25
26
|
* />
|
|
26
27
|
* ```
|
|
27
|
-
*
|
|
28
|
-
* Added by payment-instrument-preselection-advanced sub-sprint Adv-2 Req 9.
|
|
29
28
|
*/
|
|
30
29
|
import type { PaymentMethod } from '../../core/generated/operation-types';
|
|
31
30
|
/**
|
|
32
|
-
*
|
|
33
|
-
* `instruments[]
|
|
34
|
-
* query — extra
|
|
31
|
+
* Minimal projection of `PaymentMethod` used by the section — only
|
|
32
|
+
* `instruments[]` is required. The caller may pass a full `PaymentMethod` from
|
|
33
|
+
* the `availablePaymentMethods` query — extra fields (id, name,
|
|
34
|
+
* providersAvailable, etc.) are ignored.
|
|
35
35
|
*/
|
|
36
36
|
export type PaymentInstrumentSectionMethod = Pick<PaymentMethod, 'instruments'>;
|
|
37
37
|
export interface PaymentInstrumentSectionProps {
|
|
38
|
-
/** Payment method
|
|
38
|
+
/** Payment method with an `instruments[]` list (null/empty → the component returns null). */
|
|
39
39
|
method: PaymentInstrumentSectionMethod;
|
|
40
|
-
/** Currently selected instrument code — controlled by parent. Undefined
|
|
40
|
+
/** Currently selected instrument code — controlled by parent. Undefined when the buyer has not picked one yet. */
|
|
41
41
|
selectedInstrumentCode?: string;
|
|
42
|
-
/** Callback
|
|
42
|
+
/** Callback fired when the buyer selects an instrument. The parent persists the state + calls `cartSelectPaymentMethod`. */
|
|
43
43
|
onSelectInstrument: (instrumentCode: string) => void;
|
|
44
|
-
/** Optional class
|
|
44
|
+
/** Optional class for the outer section element — typically grid/flex layout. */
|
|
45
45
|
sectionClassName?: string;
|
|
46
|
-
/** Optional class
|
|
46
|
+
/** Optional class for each `<PaymentInstrumentTile>` — passed as `className`. */
|
|
47
47
|
tileClassName?: string;
|
|
48
|
-
/** Optional class
|
|
48
|
+
/** Optional class for the brand image inside tiles — passed as `iconClassName`. */
|
|
49
49
|
iconClassName?: string;
|
|
50
|
-
/** Optional class
|
|
50
|
+
/** Optional class for the label span inside tiles — passed as `labelClassName`. */
|
|
51
51
|
labelClassName?: string;
|
|
52
|
-
/** Optional ARIA label
|
|
52
|
+
/** Optional ARIA label for the radiogroup. Defaults to nothing (caller's responsibility — the section is typically nested in a wider label structure). */
|
|
53
53
|
ariaLabel?: string;
|
|
54
54
|
}
|
|
55
55
|
export declare function PaymentInstrumentSection({ method, selectedInstrumentCode, onSelectInstrument, sectionClassName, tileClassName, iconClassName, labelClassName, ariaLabel, }: PaymentInstrumentSectionProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentInstrumentSection.d.ts","sourceRoot":"","sources":["../../../src/react/components/PaymentInstrumentSection.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"PaymentInstrumentSection.d.ts","sourceRoot":"","sources":["../../../src/react/components/PaymentInstrumentSection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAqB,MAAM,sCAAsC,CAAC;AAG7F;;;;;GAKG;AACH,MAAM,MAAM,8BAA8B,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AAEhF,MAAM,WAAW,6BAA6B;IAC5C,6FAA6F;IAC7F,MAAM,EAAE,8BAA8B,CAAC;IACvC,kHAAkH;IAClH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,4HAA4H;IAC5H,kBAAkB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0JAA0J;IAC1J,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,wBAAwB,CAAC,EACvC,MAAM,EACN,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACd,SAAS,GACV,EAAE,6BAA6B,kDAoF/B"}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `<PaymentInstrumentSection>` — radio-group container
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* per item
|
|
2
|
+
* `<PaymentInstrumentSection>` — radio-group container for the payment
|
|
3
|
+
* instruments within a single method (e.g. a bank list + BLIK code entry in a
|
|
4
|
+
* BLIK method, wallets + card brands in a CARD method). Renders one
|
|
5
|
+
* `<PaymentInstrumentTile>` per item with keyboard nav (Arrow Up/Down,
|
|
6
|
+
* Home/End) + ARIA `role="radiogroup"`.
|
|
6
7
|
*
|
|
7
|
-
* Headless — section + tiles
|
|
8
|
-
*
|
|
9
|
-
* `iconClassName`/`labelClassName`
|
|
8
|
+
* Headless — section + tiles ship without any styling. Pass `sectionClassName`
|
|
9
|
+
* for the layout (grid/flex), `tileClassName` for per-tile styling, optional
|
|
10
|
+
* `iconClassName`/`labelClassName` for the tile's inner structure.
|
|
10
11
|
*
|
|
11
|
-
* Auto-
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Auto-grouping is **not** implemented — the backend already returns
|
|
13
|
+
* instruments sorted (BLIK + wallets first → banks alphabetically → others)
|
|
14
|
+
* in `availablePaymentMethods.methods[].instruments[]`. The component renders
|
|
15
|
+
* them in the order received, with no re-sorting logic of its own.
|
|
15
16
|
*
|
|
16
17
|
* @example
|
|
17
18
|
* ```tsx
|
|
@@ -24,8 +25,6 @@
|
|
|
24
25
|
* tileClassName="rounded border p-3 data-[selected=true]:border-blue-500"
|
|
25
26
|
* />
|
|
26
27
|
* ```
|
|
27
|
-
*
|
|
28
|
-
* Added by payment-instrument-preselection-advanced sub-sprint Adv-2 Req 9.
|
|
29
28
|
*/
|
|
30
29
|
'use client';
|
|
31
30
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -75,8 +74,9 @@ export function PaymentInstrumentSection({ method, selectedInstrumentCode, onSel
|
|
|
75
74
|
return null;
|
|
76
75
|
}
|
|
77
76
|
return (_jsx("div", { ref: sectionRef, role: "radiogroup", "aria-label": ariaLabel, onKeyDown: handleKeyDown, className: sectionClassName, children: instruments.map((instrument) => {
|
|
78
|
-
// Cast to tile-projection shape — instruments[]
|
|
79
|
-
//
|
|
77
|
+
// Cast to the tile-projection shape — instruments[] from the generated
|
|
78
|
+
// types carries more fields than the tile needs (provider, type); the
|
|
79
|
+
// tile picks its subset explicitly.
|
|
80
80
|
const tileInstrument = {
|
|
81
81
|
code: instrument.code,
|
|
82
82
|
displayName: instrument.displayName,
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `<PaymentInstrumentTile>` — single payment instrument tile (BLIK code,
|
|
3
|
-
* bank logo, wallet button, card brand). Headless — buyer-facing button
|
|
4
|
-
*
|
|
5
|
-
* `data-instrument-code`, `data-display-hint`). Pass className per part
|
|
6
|
-
* (button, icon, label)
|
|
7
|
-
* styled-components —
|
|
3
|
+
* bank logo, wallet button, card brand). Headless — a buyer-facing button
|
|
4
|
+
* with accessibility built in (`role="radio"`, `aria-checked`, `aria-label`,
|
|
5
|
+
* `data-instrument-code`, `data-display-hint`). Pass a className per part
|
|
6
|
+
* (button, icon, label) to integrate with Tailwind / CSS Modules /
|
|
7
|
+
* styled-components — the component has no styling of its own.
|
|
8
8
|
*
|
|
9
|
-
* `displayHint` dispatch — backend hint
|
|
10
|
-
* instrument.
|
|
11
|
-
* `<button>`
|
|
9
|
+
* `displayHint` dispatch — a backend hint describing how the storefront should
|
|
10
|
+
* render the instrument. The component emits the hint as a `data-display-hint`
|
|
11
|
+
* attribute on the `<button>` so the caller can style it through CSS attribute
|
|
12
|
+
* selectors:
|
|
12
13
|
*
|
|
13
|
-
* - `BRANDED_TILE` — bank logo / wallet icon
|
|
14
|
-
* - `PROMINENT_BUTTON` —
|
|
15
|
-
* - `RADIO_OPTION` — radio-list look, image (
|
|
16
|
-
* - `DROPDOWN_OPTION` — text-only
|
|
14
|
+
* - `BRANDED_TILE` — bank logo / wallet icon dominates, label as a caption.
|
|
15
|
+
* - `PROMINENT_BUTTON` — large CTA (BLIK code entry), brand image omitted.
|
|
16
|
+
* - `RADIO_OPTION` — radio-list look, image (when present) + label inline.
|
|
17
|
+
* - `DROPDOWN_OPTION` — text-only for dropdown integration (caller wraps it).
|
|
17
18
|
*
|
|
18
|
-
* Headless = no opinion. CSS styling
|
|
19
|
+
* Headless = no opinion. CSS styling decides, the component only hints.
|
|
19
20
|
*
|
|
20
21
|
* @example
|
|
21
22
|
* ```tsx
|
|
@@ -27,21 +28,19 @@
|
|
|
27
28
|
* labelClassName="font-semibold"
|
|
28
29
|
* />
|
|
29
30
|
* ```
|
|
30
|
-
*
|
|
31
|
-
* Added by payment-instrument-preselection-advanced sub-sprint Adv-2 Req 9.
|
|
32
31
|
*/
|
|
33
32
|
import type { PaymentInstrument } from '../../core/generated/operation-types';
|
|
34
33
|
/**
|
|
35
|
-
*
|
|
36
|
-
* pass
|
|
37
|
-
* (provider, type)
|
|
38
|
-
* provider — gateway-agnostic, code + displayHint
|
|
34
|
+
* Minimal projection of `PaymentInstrument` used by the tile. The caller may
|
|
35
|
+
* pass a full instrument from the `availablePaymentMethods` query — extra
|
|
36
|
+
* fields (provider, type) are ignored by the component (the UI never branches
|
|
37
|
+
* on the provider — gateway-agnostic, code + displayHint are enough).
|
|
39
38
|
*/
|
|
40
39
|
export type PaymentInstrumentTileInstrument = Pick<PaymentInstrument, 'code' | 'displayName' | 'displayHint' | 'enabled'> & Partial<Pick<PaymentInstrument, 'brandImage'>>;
|
|
41
40
|
export interface PaymentInstrumentTileProps {
|
|
42
41
|
/** Instrument projection — gateway code, label, display hint, enabled state. */
|
|
43
42
|
instrument: PaymentInstrumentTileInstrument;
|
|
44
|
-
/** True
|
|
43
|
+
/** True when this tile is currently selected in the parent section. Controls `aria-checked` + `data-selected`. */
|
|
45
44
|
selected: boolean;
|
|
46
45
|
/** Click handler — caller updates selected state external (controlled component). */
|
|
47
46
|
onSelect: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentInstrumentTile.d.ts","sourceRoot":"","sources":["../../../src/react/components/PaymentInstrumentTile.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"PaymentInstrumentTile.d.ts","sourceRoot":"","sources":["../../../src/react/components/PaymentInstrumentTile.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAE9E;;;;;GAKG;AACH,MAAM,MAAM,+BAA+B,GAAG,IAAI,CAChD,iBAAiB,EACjB,MAAM,GAAG,aAAa,GAAG,aAAa,GAAG,SAAS,CACnD,GACC,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC,CAAC;AAEjD,MAAM,WAAW,0BAA0B;IACzC,gFAAgF;IAChF,UAAU,EAAE,+BAA+B,CAAC;IAC5C,kHAAkH;IAClH,QAAQ,EAAE,OAAO,CAAC;IAClB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2GAA2G;IAC3G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,aAAa,EACb,cAAc,GACf,EAAE,0BAA0B,2CAuB5B"}
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `<PaymentInstrumentTile>` — single payment instrument tile (BLIK code,
|
|
3
|
-
* bank logo, wallet button, card brand). Headless — buyer-facing button
|
|
4
|
-
*
|
|
5
|
-
* `data-instrument-code`, `data-display-hint`). Pass className per part
|
|
6
|
-
* (button, icon, label)
|
|
7
|
-
* styled-components —
|
|
3
|
+
* bank logo, wallet button, card brand). Headless — a buyer-facing button
|
|
4
|
+
* with accessibility built in (`role="radio"`, `aria-checked`, `aria-label`,
|
|
5
|
+
* `data-instrument-code`, `data-display-hint`). Pass a className per part
|
|
6
|
+
* (button, icon, label) to integrate with Tailwind / CSS Modules /
|
|
7
|
+
* styled-components — the component has no styling of its own.
|
|
8
8
|
*
|
|
9
|
-
* `displayHint` dispatch — backend hint
|
|
10
|
-
* instrument.
|
|
11
|
-
* `<button>`
|
|
9
|
+
* `displayHint` dispatch — a backend hint describing how the storefront should
|
|
10
|
+
* render the instrument. The component emits the hint as a `data-display-hint`
|
|
11
|
+
* attribute on the `<button>` so the caller can style it through CSS attribute
|
|
12
|
+
* selectors:
|
|
12
13
|
*
|
|
13
|
-
* - `BRANDED_TILE` — bank logo / wallet icon
|
|
14
|
-
* - `PROMINENT_BUTTON` —
|
|
15
|
-
* - `RADIO_OPTION` — radio-list look, image (
|
|
16
|
-
* - `DROPDOWN_OPTION` — text-only
|
|
14
|
+
* - `BRANDED_TILE` — bank logo / wallet icon dominates, label as a caption.
|
|
15
|
+
* - `PROMINENT_BUTTON` — large CTA (BLIK code entry), brand image omitted.
|
|
16
|
+
* - `RADIO_OPTION` — radio-list look, image (when present) + label inline.
|
|
17
|
+
* - `DROPDOWN_OPTION` — text-only for dropdown integration (caller wraps it).
|
|
17
18
|
*
|
|
18
|
-
* Headless = no opinion. CSS styling
|
|
19
|
+
* Headless = no opinion. CSS styling decides, the component only hints.
|
|
19
20
|
*
|
|
20
21
|
* @example
|
|
21
22
|
* ```tsx
|
|
@@ -27,15 +28,13 @@
|
|
|
27
28
|
* labelClassName="font-semibold"
|
|
28
29
|
* />
|
|
29
30
|
* ```
|
|
30
|
-
*
|
|
31
|
-
* Added by payment-instrument-preselection-advanced sub-sprint Adv-2 Req 9.
|
|
32
31
|
*/
|
|
33
32
|
'use client';
|
|
34
33
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
35
34
|
export function PaymentInstrumentTile({ instrument, selected, onSelect, className, iconClassName, labelClassName, }) {
|
|
36
35
|
const { code, displayName, displayHint, brandImage, enabled } = instrument;
|
|
37
36
|
const brandImageUrl = brandImage?.url;
|
|
38
|
-
// PROMINENT_BUTTON hides brand image — instrument
|
|
37
|
+
// PROMINENT_BUTTON hides the brand image — the instrument is a text-only CTA (BLIK code entry).
|
|
39
38
|
const showImage = displayHint !== 'PROMINENT_BUTTON' && brandImageUrl;
|
|
40
39
|
return (_jsxs("button", { type: "button", role: "radio", "aria-checked": selected, "aria-label": displayName, "data-instrument-code": code, "data-display-hint": displayHint, "data-selected": selected, disabled: !enabled, onClick: onSelect, className: className, children: [showImage && _jsx("img", { src: brandImageUrl, alt: brandImage?.altText ?? '', className: iconClassName }), _jsx("span", { className: labelClassName, children: displayName })] }));
|
|
41
40
|
}
|
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `getBrowserDataForPayment()` — collects browser context required by PSD2/3DS2
|
|
3
|
-
* authentication flows (card-on-file
|
|
4
|
-
* Apple/Google Pay
|
|
3
|
+
* authentication flows (card-on-file with a 3DS challenge, BLIK confirmation,
|
|
4
|
+
* Apple/Google Pay with risk scoring).
|
|
5
5
|
*
|
|
6
|
-
* **Browser-only** — throws
|
|
7
|
-
* rendering).
|
|
8
|
-
* code path. NEVER call this
|
|
6
|
+
* **Browser-only** — throws when `typeof window === 'undefined'` (server-side
|
|
7
|
+
* rendering). Callers MUST gate the call inside a useEffect / event handler /
|
|
8
|
+
* browser-only code path. NEVER call this in a Server Component or Route Handler.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* Values come from standard Web APIs:
|
|
11
11
|
* - `userAgent` — `navigator.userAgent`.
|
|
12
12
|
* - `language` — `navigator.language` (BCP 47, fallback `en-US`).
|
|
13
13
|
* - `screen{Width,Height}` — `window.screen.{width,height}`.
|
|
14
14
|
* - `colorDepth` — `window.screen.colorDepth`.
|
|
15
15
|
* - `timezoneOffset` — `new Date().getTimezoneOffset()` (signed integer, minutes,
|
|
16
|
-
* reverse signed per ECMA:
|
|
17
|
-
* - `javaEnabled` — `navigator.javaEnabled?.()` (deprecated
|
|
18
|
-
* specification;
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
16
|
+
* reverse signed per ECMA: positive = behind UTC, negative = ahead of UTC).
|
|
17
|
+
* - `javaEnabled` — `navigator.javaEnabled?.()` (deprecated but required by the
|
|
18
|
+
* PSD2/EMV specification; falls back to `false` when the browser does not
|
|
19
|
+
* expose it).
|
|
20
|
+
* - `acceptHeader` — NOT available client-side (`navigator` does not expose
|
|
21
|
+
* request headers). Callers pass it from server context or omit it
|
|
22
|
+
* (gateway-dependent requirement). The helper returns undefined.
|
|
22
23
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* Mollie `cardToken` z 3DS lookup).
|
|
24
|
+
* The shape matches the PSD2/3DS2 BrowserData specification (EMVCo), so it can
|
|
25
|
+
* be merged into gateway-specific request bodies (gateway-specific field names
|
|
26
|
+
* vary).
|
|
27
27
|
*
|
|
28
28
|
* @example
|
|
29
29
|
* ```tsx
|
|
30
|
-
* //
|
|
30
|
+
* // In an event handler (browser-only):
|
|
31
31
|
* function handleCheckoutSubmit() {
|
|
32
32
|
* const browserData = getBrowserDataForPayment();
|
|
33
|
-
*
|
|
33
|
+
* // pass to your payment integration where required
|
|
34
34
|
* }
|
|
35
35
|
*
|
|
36
36
|
* // SSR-safe wrap:
|
|
@@ -39,21 +39,18 @@
|
|
|
39
39
|
* ...
|
|
40
40
|
* }
|
|
41
41
|
* ```
|
|
42
|
-
*
|
|
43
|
-
* Added by payment-instrument-preselection-advanced sub-sprint Adv-2 Req 9.5
|
|
44
|
-
* (carry-over z Adv-1 plan — moved here as standalone utility, no backend
|
|
45
|
-
* mutation impact yet — Adv-3 będzie consumer'em w `paymentCreate` input).
|
|
46
42
|
*/
|
|
47
43
|
/**
|
|
48
|
-
* PSD2/3DS2 browser context shape. All fields optional
|
|
49
|
-
* standard API — gateway-specific requirements
|
|
44
|
+
* PSD2/3DS2 browser context shape. All fields are optional except the ones
|
|
45
|
+
* backed by a standard API — gateway-specific requirements decide which fields
|
|
46
|
+
* are mandatory.
|
|
50
47
|
*/
|
|
51
48
|
export interface PaymentBrowserData {
|
|
52
49
|
/** Accept HTTP header value — NOT available client-side (caller passes from server context or omits). */
|
|
53
50
|
acceptHeader?: string;
|
|
54
51
|
/** Full user-agent string (`navigator.userAgent`). */
|
|
55
52
|
userAgent: string;
|
|
56
|
-
/** BCP 47 language tag (`navigator.language`).
|
|
53
|
+
/** BCP 47 language tag (`navigator.language`). Falls back to `'en-US'` when missing. */
|
|
57
54
|
language: string;
|
|
58
55
|
/** Screen width in pixels (`window.screen.width`). */
|
|
59
56
|
screenWidth: number;
|
|
@@ -62,25 +59,25 @@ export interface PaymentBrowserData {
|
|
|
62
59
|
/** Color depth bits-per-pixel (`window.screen.colorDepth`). Typically `24` or `32`. */
|
|
63
60
|
colorDepth: number;
|
|
64
61
|
/**
|
|
65
|
-
* Local timezone offset
|
|
66
|
-
*
|
|
62
|
+
* Local timezone offset in minutes (ECMA signed convention — positive = behind UTC,
|
|
63
|
+
* negative = ahead of UTC). For example, CET in winter = `-60`, PST in winter = `480`.
|
|
67
64
|
*/
|
|
68
65
|
timezoneOffset: number;
|
|
69
66
|
/**
|
|
70
|
-
* Java support (`navigator.javaEnabled?.()`). Deprecated API
|
|
71
|
-
* specification;
|
|
67
|
+
* Java support (`navigator.javaEnabled?.()`). Deprecated API but required by the
|
|
68
|
+
* PSD2/EMV specification; falls back to `false` when the browser does not expose it.
|
|
72
69
|
*/
|
|
73
70
|
javaEnabled: boolean;
|
|
74
71
|
/**
|
|
75
72
|
* IANA timezone name (`Intl.DateTimeFormat().resolvedOptions().timeZone`).
|
|
76
|
-
* Optional —
|
|
73
|
+
* Optional — some gateways use it instead of the numeric offset for risk scoring.
|
|
77
74
|
*/
|
|
78
75
|
timezone?: string;
|
|
79
76
|
}
|
|
80
77
|
/**
|
|
81
|
-
*
|
|
82
|
-
* Node
|
|
83
|
-
*
|
|
78
|
+
* Thrown when the helper is called in an SSR context (Server Component, Route
|
|
79
|
+
* Handler, Node without JSDOM). Callers MUST guard with a `typeof window` check
|
|
80
|
+
* or call it only inside an event handler / `useEffect`.
|
|
84
81
|
*/
|
|
85
82
|
export declare class BrowserDataNotAvailableError extends Error {
|
|
86
83
|
constructor();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-data.d.ts","sourceRoot":"","sources":["../../../src/react/helpers/browser-data.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"browser-data.d.ts","sourceRoot":"","sources":["../../../src/react/helpers/browser-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,yGAAyG;IACzG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,wFAAwF;IACxF,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;;CAKtD;AAED,wBAAgB,wBAAwB,IAAI,kBAAkB,CA8B7D"}
|