bitsnap-react 1.18.1 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/AGENTS.md +21 -0
  2. package/README.md +45 -0
  3. package/dist/BitsnapCart-LHJ6KOTV.css +2 -0
  4. package/dist/BitsnapCart-LHJ6KOTV.css.map +1 -0
  5. package/dist/BitsnapCart-V4S4EXYV.js +2 -0
  6. package/dist/BitsnapCart-V4S4EXYV.js.map +1 -0
  7. package/dist/BitsnapCart-Z6JFYNH2.mjs +2 -0
  8. package/dist/CartProvider-5NP4WACK.js +2 -0
  9. package/dist/CartProvider-5NP4WACK.js.map +1 -0
  10. package/dist/CartProvider-G7FQUPXL.mjs +2 -0
  11. package/dist/PanelModelFiles-EKQRLF46.js.map +1 -1
  12. package/dist/analytics.js +1 -1
  13. package/dist/analytics.js.map +1 -1
  14. package/dist/analytics.mjs +1 -1
  15. package/dist/catalog.js +1 -1
  16. package/dist/catalog.js.map +1 -1
  17. package/dist/catalog.mjs +1 -1
  18. package/dist/chat.css +2 -0
  19. package/dist/chat.css.map +1 -0
  20. package/dist/chat.d.mts +173 -0
  21. package/dist/chat.d.ts +173 -0
  22. package/dist/chat.js +2 -0
  23. package/dist/chat.js.map +1 -0
  24. package/dist/chat.mjs +2 -0
  25. package/dist/chat.mjs.map +1 -0
  26. package/dist/chunk-2G46TAUX.mjs +2 -0
  27. package/dist/chunk-2G46TAUX.mjs.map +1 -0
  28. package/dist/{chunk-N3B25GTY.js → chunk-4Y233NII.js} +2 -2
  29. package/dist/chunk-4Y233NII.js.map +1 -0
  30. package/dist/chunk-5M3OUOMU.mjs +5 -0
  31. package/dist/chunk-5M3OUOMU.mjs.map +1 -0
  32. package/dist/chunk-6Q3VGPSF.js.map +1 -1
  33. package/dist/chunk-A2ZDFN3J.mjs +2 -0
  34. package/dist/{chunk-ZM5T4TQW.mjs.map → chunk-A2ZDFN3J.mjs.map} +1 -1
  35. package/dist/{chunk-DR7WYI37.js → chunk-AQYHQY2Y.js} +2 -2
  36. package/dist/chunk-AQYHQY2Y.js.map +1 -0
  37. package/dist/{chunk-62WDFH7K.mjs → chunk-BTERIY6N.mjs} +2 -2
  38. package/dist/chunk-C736F727.js +2 -0
  39. package/dist/chunk-C736F727.js.map +1 -0
  40. package/dist/chunk-EFN4OW2C.js +2 -0
  41. package/dist/chunk-EFN4OW2C.js.map +1 -0
  42. package/dist/chunk-EMR4YXNY.mjs +2 -0
  43. package/dist/chunk-EMR4YXNY.mjs.map +1 -0
  44. package/dist/chunk-GHBRR665.js +2 -0
  45. package/dist/chunk-GHBRR665.js.map +1 -0
  46. package/dist/chunk-HKRH6FI6.mjs +2 -0
  47. package/dist/chunk-HKRH6FI6.mjs.map +1 -0
  48. package/dist/chunk-HP3I6D2R.js +2 -0
  49. package/dist/chunk-HP3I6D2R.js.map +1 -0
  50. package/dist/{chunk-G4SEOVLD.js → chunk-IRZJIPUF.js} +2 -2
  51. package/dist/chunk-IRZJIPUF.js.map +1 -0
  52. package/dist/chunk-IXQCN7MR.mjs +2 -0
  53. package/dist/chunk-IXQCN7MR.mjs.map +1 -0
  54. package/dist/chunk-IXX6SUMB.mjs +2 -0
  55. package/dist/chunk-IXX6SUMB.mjs.map +1 -0
  56. package/dist/chunk-JSDGZ4NY.js.map +1 -1
  57. package/dist/chunk-KDL35KEI.js +2 -0
  58. package/dist/chunk-KDL35KEI.js.map +1 -0
  59. package/dist/chunk-KO7ZERN5.mjs +2 -0
  60. package/dist/chunk-KO7ZERN5.mjs.map +1 -0
  61. package/dist/chunk-KOYBZORL.js.map +1 -1
  62. package/dist/chunk-KZWCVKLU.js +5 -0
  63. package/dist/chunk-KZWCVKLU.js.map +1 -0
  64. package/dist/chunk-LHNTSQYO.mjs +2 -0
  65. package/dist/chunk-LHNTSQYO.mjs.map +1 -0
  66. package/dist/chunk-LHQEM3CU.mjs +2 -0
  67. package/dist/chunk-LHQEM3CU.mjs.map +1 -0
  68. package/dist/chunk-MDAFPGPA.js +2 -0
  69. package/dist/chunk-MDAFPGPA.js.map +1 -0
  70. package/dist/chunk-Q337IQNA.js.map +1 -1
  71. package/dist/chunk-RJPQMDIQ.js +2 -0
  72. package/dist/chunk-RJPQMDIQ.js.map +1 -0
  73. package/dist/{chunk-GKJURMDO.mjs → chunk-TW25G7XX.mjs} +2 -2
  74. package/dist/{chunk-GKJURMDO.mjs.map → chunk-TW25G7XX.mjs.map} +1 -1
  75. package/dist/{chunk-UTUPPMLK.mjs → chunk-URQBHNJK.mjs} +2 -2
  76. package/dist/chunk-W3RGQYPD.js.map +1 -1
  77. package/dist/chunk-XEXPQFKN.mjs +2 -0
  78. package/dist/chunk-XEXPQFKN.mjs.map +1 -0
  79. package/dist/chunk-YPA6MMGJ.js +2 -0
  80. package/dist/chunk-YPA6MMGJ.js.map +1 -0
  81. package/dist/chunk-Z3YOJ6NZ.js +2 -0
  82. package/dist/chunk-Z3YOJ6NZ.js.map +1 -0
  83. package/dist/consent.js.map +1 -1
  84. package/dist/course.d.mts +2 -14
  85. package/dist/course.d.ts +2 -14
  86. package/dist/course.js +1 -1
  87. package/dist/course.js.map +1 -1
  88. package/dist/course.mjs +1 -1
  89. package/dist/course.mjs.map +1 -1
  90. package/dist/embed/analytics.js +1 -1
  91. package/dist/errors.js.map +1 -1
  92. package/dist/index.css +1 -1
  93. package/dist/index.css.map +1 -1
  94. package/dist/index.d.mts +50 -33
  95. package/dist/index.d.ts +50 -33
  96. package/dist/index.js +1 -1
  97. package/dist/index.js.map +1 -1
  98. package/dist/index.mjs +1 -1
  99. package/dist/index.mjs.map +1 -1
  100. package/dist/internal.js.map +1 -1
  101. package/dist/methods-33CWGKNA.mjs +2 -0
  102. package/dist/methods-33CWGKNA.mjs.map +1 -0
  103. package/dist/methods-4GB652MQ.js +2 -0
  104. package/dist/methods-4GB652MQ.js.map +1 -0
  105. package/dist/model-files-client-P4PORZJ6.js.map +1 -1
  106. package/dist/models.js.map +1 -1
  107. package/dist/returns.js +1 -1
  108. package/dist/returns.js.map +1 -1
  109. package/dist/returns.mjs +1 -1
  110. package/dist/texts-9kfgClsA.d.mts +14 -0
  111. package/dist/texts-9kfgClsA.d.ts +14 -0
  112. package/dist/{types-D6LsoycW.d.mts → types-CjWyHunk.d.mts} +9 -1
  113. package/dist/{types-ClFCVzk_.d.ts → types-DfqzDP9k.d.ts} +9 -1
  114. package/dist/viewer3d.js.map +1 -1
  115. package/dist/viewer3d.mjs +2 -2
  116. package/dist/viewer3d.mjs.map +1 -1
  117. package/dist/widgets-Bsojw94g.d.ts +556 -0
  118. package/dist/widgets-u7xMJbsY.d.mts +556 -0
  119. package/package.json +16 -2
  120. package/dist/CartProvider-CC6YIZVS.js +0 -2
  121. package/dist/CartProvider-CC6YIZVS.js.map +0 -1
  122. package/dist/CartProvider-ZL65WZN6.mjs +0 -2
  123. package/dist/chunk-2XSLIZ27.js +0 -2
  124. package/dist/chunk-2XSLIZ27.js.map +0 -1
  125. package/dist/chunk-5OCGXVLC.js +0 -2
  126. package/dist/chunk-5OCGXVLC.js.map +0 -1
  127. package/dist/chunk-5YN752OV.mjs +0 -2
  128. package/dist/chunk-5YN752OV.mjs.map +0 -1
  129. package/dist/chunk-7BG22YBF.js +0 -5
  130. package/dist/chunk-7BG22YBF.js.map +0 -1
  131. package/dist/chunk-AHISXVEE.js +0 -2
  132. package/dist/chunk-AHISXVEE.js.map +0 -1
  133. package/dist/chunk-DR7WYI37.js.map +0 -1
  134. package/dist/chunk-EOFJAQPT.js +0 -2
  135. package/dist/chunk-EOFJAQPT.js.map +0 -1
  136. package/dist/chunk-G4SEOVLD.js.map +0 -1
  137. package/dist/chunk-IGQZP4YR.mjs +0 -2
  138. package/dist/chunk-IGQZP4YR.mjs.map +0 -1
  139. package/dist/chunk-N3B25GTY.js.map +0 -1
  140. package/dist/chunk-VWA3ZCNI.mjs +0 -2
  141. package/dist/chunk-VWA3ZCNI.mjs.map +0 -1
  142. package/dist/chunk-YGE2223J.mjs +0 -5
  143. package/dist/chunk-YGE2223J.mjs.map +0 -1
  144. package/dist/chunk-ZKT4N553.mjs +0 -2
  145. package/dist/chunk-ZKT4N553.mjs.map +0 -1
  146. package/dist/chunk-ZM5T4TQW.mjs +0 -2
  147. package/dist/methods-7DWKFCPK.js +0 -2
  148. package/dist/methods-7DWKFCPK.js.map +0 -1
  149. package/dist/methods-DQTADIN4.mjs +0 -2
  150. /package/dist/{CartProvider-ZL65WZN6.mjs.map → BitsnapCart-Z6JFYNH2.mjs.map} +0 -0
  151. /package/dist/{methods-DQTADIN4.mjs.map → CartProvider-G7FQUPXL.mjs.map} +0 -0
  152. /package/dist/{chunk-62WDFH7K.mjs.map → chunk-BTERIY6N.mjs.map} +0 -0
  153. /package/dist/{chunk-UTUPPMLK.mjs.map → chunk-URQBHNJK.mjs.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/checkout/BitsnapCart.tsx","../src/components/checkout/CartComponent.tsx","../src/components/checkout/appearance.context.tsx","../src/components/checkout/appearance.ts","../src/components/checkout/CartComponentContent.tsx","../src/components/checkout/CountrySelector.tsx","../src/ui/select.tsx","../src/components/checkout/SingleProduct.tsx","../src/ui/button-group.tsx","../src/components/checkout/ProductPrice.tsx","../src/components/checkout/quantity.ts","../src/components/checkout/Skeleton.tsx","../src/components/checkout/ApplePay.tsx","../src/components/checkout/project-id.ts","../src/components/checkout/GooglePay.tsx","../src/components/express/InPostPayButton.tsx","../src/express/client.ts","../src/express/cart-record.ts","../src/express/cart-session.ts","../src/express/delivery-quote.ts","../src/express/cart-adapter.ts","../src/express/inpost-widget.ts","../src/express/react.ts","../src/express/revolut.ts","../src/components/express/ExpressStatus.tsx","../src/components/express/RevolutPayButton.tsx","../src/express/revolut-sdk.ts","../src/express/return-url.ts","../src/components/notifications/NotificationsComponentPublic.tsx","../src/components/notifications/constants.tsx","../src/components/notifications/NotificationHeader.tsx","../src/ui/switch.tsx","../src/components/notifications/NotificationGroupsList.tsx","../src/ui/popover.tsx","../src/components/notifications/HowOftenComponent.tsx","../src/components/notifications/QRCodeSection.tsx","../src/components/notifications/AddUserToGroups.tsx","../src/components/notifications/FormInput.tsx","../src/components/notifications/ManageMyData.tsx","../src/components/notifications/UnsubscribeDialog.tsx","../src/components/notifications/LoginScreen.tsx","../src/ui/dialog.tsx","../src/components/notifications/login-adapter.ts","../src/components/checkout/PaymentMethodChoice.tsx"],"sourcesContent":["import { useEffect, useId, useRef } from \"react\";\nimport zod from \"zod\";\nimport {\n InstrumentProvider,\n useCartInstrument,\n useInstrument,\n type AnalyticsOption,\n} from \"@/src/analytics/instrument\";\nimport type { CheckoutAppearance } from \"./appearance\";\nimport type { CheckoutTexts } from \"./texts\";\nimport CartComponent from \"./CartComponent\";\nimport { getCheckoutMethods, getProjectID, setProjectID } from \"./CartProvider\";\nimport { sendAnalyticEvent } from \"./frontent.analytics\";\nimport { isErr } from \"./lib/err\";\nimport { useCheckoutStore } from \"./state\";\nimport { getLocale, setLocale } from \"./locale\";\nimport { getCheckoutText, type CheckoutTextKey } from \"./texts\";\n\nenum CartEvent {\n ADD_TO_CART = \"ADD_TO_CART\",\n}\n\nconst cartAddToCartSchema = zod.object({\n id: zod.string(),\n isSubscription: zod.boolean().default(false),\n quantity: zod.number(),\n metadata: zod.record(zod.string(), zod.string().optional()).optional(),\n url: zod.string().optional(),\n});\n\ntype CartAddToCartEvent = zod.infer<typeof cartAddToCartSchema>;\n\nexport type BitsnapCartProps = {\n projectID: string;\n locale?: string;\n children?: React.ReactNode;\n onVisibleChange?: (isVisible: boolean) => void;\n className?: string;\n numberOfProductsInCartOptions?: {\n style?: React.CSSProperties;\n isVisible?: boolean;\n };\n /**\n * Optional checkout appearance. Omitting it (or passing `{}`) keeps the\n * current presentation; every token and element slot is partial.\n */\n appearance?: CheckoutAppearance;\n /**\n * Optional text overrides. Any key given here replaces the built-in string\n * whatever the locale; omitted keys keep the `pl`/`en` defaults.\n */\n texts?: Partial<CheckoutTexts>;\n /**\n * Usage statistics for your Bitsnap dashboard (cart opened, checkout\n * started, add to cart). On by default; `false` turns it off. An object\n * lets you forward every event: `{ onEvent }`. Nothing is stored on the\n * visitor's device.\n */\n analytics?: AnalyticsOption;\n};\n\nconst visuallyHidden: React.CSSProperties = {\n position: \"absolute\",\n width: 1,\n height: 1,\n margin: -1,\n padding: 0,\n overflow: \"hidden\",\n clip: \"rect(0, 0, 0, 0)\",\n whiteSpace: \"nowrap\",\n border: 0,\n};\n\nfunction BitsnapCart({\n projectID,\n locale,\n children,\n onVisibleChange,\n className,\n numberOfProductsInCartOptions,\n appearance,\n texts,\n analytics,\n}: BitsnapCartProps) {\n const instrument = useInstrument(projectID, analytics, \"cart\");\n // Cart changes made outside of components (`Bitsnap.addProductToCart`) are reported here.\n useCartInstrument(instrument);\n const { isCartVisible, showCart, hideCart, numberOfProductsInCart } =\n useCheckoutStore();\n const panelId = `bitsnap-cart-${useId()}`;\n const text = (key: CheckoutTextKey) =>\n getCheckoutText(key, locale ?? getLocale(), texts);\n // The `window.cart` handlers are created once and must read the latest props.\n const textRef = useRef(text);\n textRef.current = text;\n\n /** Shows a message through the error area of the cart drawer. */\n function showCartNotice(key: CheckoutTextKey) {\n useCheckoutStore.getState().setNotice(textRef.current(key));\n showCart();\n }\n\n function sentPostMessageToIframe(msg: unknown) {\n const iframes = document.querySelectorAll(\"iframe\");\n\n iframes.forEach((iframe) => {\n iframe.contentWindow?.postMessage(msg, \"*\");\n });\n }\n\n useEffect(() => {\n onVisibleChange?.(isCartVisible);\n if (isCartVisible) {\n sendAnalyticEvent({\n event: \"viewCart\",\n });\n }\n }, [isCartVisible]);\n\n useEffect(() => {\n setProjectID(projectID);\n }, [projectID]);\n\n useEffect(() => {\n setLocale(locale);\n }, [locale]);\n\n useEffect(() => {\n if (!(\"cart\" in window)) {\n const projectID = getProjectID();\n if (projectID == null) {\n console.warn(\"There is no project ID configured.\");\n return;\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n window[\"cart\"] = {\n buyProduct: async (args: unknown) => {\n try {\n const payload = zod\n .object({\n productID: zod.string(),\n email: zod.string().optional(),\n name: zod.string().optional(),\n country: zod.string().optional(),\n marketingAgreement: zod.boolean().optional(),\n locale: zod.string().optional(),\n })\n .parse(args);\n const methods = getCheckoutMethods(projectID);\n try {\n const products = await methods.getProducts();\n if (isErr(products) == false) {\n sendAnalyticEvent({\n event: \"initiateCheckout\",\n items: products.map((el) => ({\n id: el.productID,\n name: el.details?.name ?? \"\",\n price: el.details?.price ?? 0,\n quantity: el.quantity,\n currency: el.details?.currency ?? \"PLN\",\n })),\n });\n }\n } catch (e) {}\n\n const result = await methods.justRedirectToPayment(payload);\n\n if (isErr(result) == false) {\n window.location.href = result.url;\n } else {\n showCartNotice(\"redirectFailed\");\n }\n } catch (e) {\n console.warn(e);\n }\n },\n };\n }\n }, []);\n\n async function handleAddingToCart(id: string, payload?: unknown) {\n const projectID = getProjectID();\n if (projectID == null) {\n console.warn(\"There is no project ID configured.\");\n return;\n }\n\n try {\n const data = cartAddToCartSchema.parse(payload);\n\n if (data.isSubscription) {\n await handleAddingSubscriptionToCart(projectID, data);\n return;\n }\n\n const methods = getCheckoutMethods(projectID);\n\n await methods.addProduct({\n productID: data.id,\n quantity: data.quantity,\n metadata: data.metadata,\n url: data.url,\n });\n\n sentPostMessageToIframe({\n id: id,\n type: CartEvent.ADD_TO_CART,\n success: true,\n });\n showCart();\n } catch (e) {\n console.warn(\"cannot add item to cart\", e);\n }\n }\n\n async function handleAddingSubscriptionToCart(\n projectID: string,\n event: CartAddToCartEvent,\n ) {\n console.warn(\n \"subscriptions cannot be added to the cart yet\",\n projectID,\n event.id,\n );\n showCartNotice(\"subscriptionUnsupported\");\n }\n\n function setupEventListener() {\n if (\"__cart_is_listening\" in window) {\n return;\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n window[\"__cart_is_listening\"] = true;\n window.addEventListener(\"message\", (event) => {\n if (\n typeof event.data[\"id\"] != \"undefined\" &&\n typeof event.data[\"type\"] != \"undefined\"\n ) {\n const { id, type } = event.data;\n switch (type) {\n case CartEvent.ADD_TO_CART.toString():\n handleAddingToCart(id, event.data[\"payload\"]).then().catch();\n break;\n default:\n break;\n }\n }\n });\n }\n\n useEffect(() => {\n setupEventListener();\n\n if (typeof window !== \"undefined\") {\n try {\n const parsedParams = new URLSearchParams(window.location.search);\n const refLink =\n parsedParams.get(\"ref\") ?? parsedParams.get(\"utm-source\");\n if (\n typeof localStorage != \"undefined\" &&\n refLink &&\n refLink.length > 0\n ) {\n localStorage.setItem(\"bitsnap-ref\", refLink);\n }\n } catch (e) {\n return;\n }\n }\n }, []);\n\n return (\n <>\n <button\n type=\"button\"\n onClick={() => (isCartVisible ? hideCart() : showCart())}\n aria-label={\n children\n ? undefined\n : numberOfProductsInCart > 0\n ? `${text(\"openCart\")}. ${text(\"cartItemsCount\")}: ${numberOfProductsInCart}`\n : text(\"openCart\")\n }\n aria-expanded={isCartVisible}\n aria-haspopup=\"dialog\"\n aria-controls={isCartVisible ? panelId : undefined}\n style={{ position: \"relative\" }}\n className={[\n \"bitsnap-react\",\n className ?? \"rounded-full hover:bg-neutral-300 transition p-1\",\n ].join(\" \")}\n >\n {children ? (\n <>{children}</>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-shopping-cart\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <circle cx=\"8\" cy=\"21\" r=\"1\" />\n <circle cx=\"19\" cy=\"21\" r=\"1\" />\n <path d=\"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12\" />\n </svg>\n )}\n {numberOfProductsInCart > 0 && (\n <span style={visuallyHidden}>\n {text(\"cartItemsCount\")}: {numberOfProductsInCart}\n </span>\n )}\n {numberOfProductsInCartOptions?.isVisible != false &&\n numberOfProductsInCart > 0 && (\n <div\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n bottom: -5,\n right: -5,\n background: \"black\",\n color: \"white\",\n borderRadius: \"50%\",\n width: \"22px\",\n height: \"22px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"13px\",\n fontWeight: 600,\n boxShadow: \"0 2px 8px rgba(0, 0, 0, 0.25)\",\n ...numberOfProductsInCartOptions?.style,\n }}\n >\n {numberOfProductsInCart}\n </div>\n )}\n </button>\n <InstrumentProvider value={instrument}>\n <CartComponent\n isVisible={isCartVisible}\n locale={locale}\n appearance={appearance}\n texts={texts}\n panelId={panelId}\n shouldHide={() => {\n hideCart();\n }}\n />\n </InstrumentProvider>\n </>\n );\n}\n\nexport default BitsnapCart;\n","import { useAutoAnimate } from \"@formkit/auto-animate/react\";\nimport * as Dialog from \"@radix-ui/react-dialog\";\nimport { useCallback, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"@/src/lib/utils\";\nimport {\n CheckoutAppearanceProvider,\n useCheckoutAppearance,\n useCheckoutSlot,\n} from \"./appearance.context\";\nimport type { CheckoutAppearance } from \"./appearance\";\nimport CartComponentContent from \"./CartComponentContent\";\nimport CartProvider from \"./CartProvider\";\nimport { CheckoutTextsProvider, useCheckoutText } from \"./texts.context\";\nimport type { CheckoutTexts } from \"./texts\";\n\ninterface Props {\n isVisible: boolean;\n shouldHide: () => void;\n locale?: string;\n appearance?: CheckoutAppearance;\n texts?: Partial<CheckoutTexts>;\n /** DOM id of the panel, for `aria-controls` of the button that opens it. */\n panelId?: string;\n}\n\nfunction CartComponent({ isVisible, shouldHide, panelId, locale }: Props) {\n const [parent] = useAutoAnimate(/* optional config */);\n // The drawer renders inside the checkout root: the stylesheet is scoped to `.bitsnap-react`.\n const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null);\n const rootRef = useCallback(\n (element: HTMLDivElement | null) => {\n parent(element);\n setRootElement(element);\n },\n [parent],\n );\n // The trigger lives outside of the dialog, so Radix does not know which element to give the focus back to.\n const returnFocusTo = useRef<HTMLElement | null>(null);\n const { boundaryClassName, boundaryStyle } = useCheckoutAppearance();\n const root = useCheckoutSlot(\"root\");\n const overlay = useCheckoutSlot(\"overlay\");\n const panel = useCheckoutSlot(\"panel\");\n const header = useCheckoutSlot(\"header\");\n const title = useCheckoutSlot(\"title\");\n const closeButton = useCheckoutSlot(\"closeButton\");\n const cartText = useCheckoutText(\"cart\");\n const closeText = useCheckoutText(\"close\");\n\n return (\n <div\n ref={rootRef}\n data-bitsnap-checkout=\"root\"\n data-bitsnap-checkout-slot=\"root\"\n className={cn(\"bitsnap-react\", boundaryClassName, root.className)}\n style={{ zIndex: 999999, ...boundaryStyle, ...root.style }}\n >\n {rootElement != null && (\n <Dialog.Root\n open={isVisible}\n onOpenChange={(open) => {\n if (!open) {\n shouldHide();\n }\n }}\n >\n <Dialog.Portal container={rootElement}>\n <Dialog.Overlay\n data-bitsnap-checkout-slot=\"overlay\"\n aria-hidden=\"true\"\n className={cn(\n \"fixed top-0 right-0 left-0 bottom-0 cursor-pointer z-10\",\n overlay.className,\n )}\n style={overlay.style}\n onClick={shouldHide}\n />\n <Dialog.Content\n id={panelId}\n data-bitsnap-checkout-slot=\"panel\"\n aria-modal=\"true\"\n aria-describedby={undefined}\n onOpenAutoFocus={() => {\n const active = document.activeElement;\n returnFocusTo.current = active instanceof HTMLElement ? active : null;\n }}\n onCloseAutoFocus={(event) => {\n event.preventDefault();\n returnFocusTo.current?.focus();\n returnFocusTo.current = null;\n }}\n className={cn(\n // Scrolls when the summary and the payment choice do not fit (small phones).\n \"fixed z-20 top-0 right-0 bottom-0 w-full md:w-[350px] xl:w-[420px] flex flex-col overflow-y-auto\",\n panel.className,\n )}\n style={panel.style}\n // The overlay closes the drawer on click; a close on pointer down would let the click through.\n onPointerDownOutside={(event) => event.preventDefault()}\n >\n <div\n data-bitsnap-checkout-slot=\"header\"\n className={cn(\n \"mx-3 mt-7 flex justify-between items-center\",\n header.className,\n )}\n style={header.style}\n >\n <Dialog.Title asChild>\n <h1\n data-bitsnap-checkout-slot=\"title\"\n className={cn(\"text-2xl font-medium\", title.className)}\n style={title.style}\n >\n {cartText}\n </h1>\n </Dialog.Title>\n <button\n type=\"button\"\n data-bitsnap-checkout-slot=\"closeButton\"\n className={cn(\n \"rounded-xl p-2 transition\",\n closeButton.className,\n )}\n style={closeButton.style}\n aria-label={closeText}\n onClick={shouldHide}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"lucide lucide-x\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n\n <CartComponentContent className={\"grow\"} locale={locale} />\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n )}\n </div>\n );\n}\n\nconst WrapperCartComponent = (props: Props) => {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n return createPortal(\n <CheckoutAppearanceProvider appearance={props.appearance}>\n <CheckoutTextsProvider texts={props.texts} locale={props.locale}>\n <CartProvider locale={props.locale}>\n <CartComponent {...props} />\n </CartProvider>\n </CheckoutTextsProvider>\n </CheckoutAppearanceProvider>,\n document.body,\n );\n};\n\nexport default WrapperCartComponent;\n","import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport {\n getCheckoutSlotAppearance,\n resolveCheckoutAppearance,\n type CheckoutAppearance,\n type CheckoutSlotAppearance,\n type CheckoutSlotName,\n type ResolvedCheckoutAppearance,\n} from \"./appearance\";\n\nconst CheckoutAppearanceContext = createContext<ResolvedCheckoutAppearance>(\n resolveCheckoutAppearance(),\n);\n\n/**\n * Checkout scoped appearance provider. It only wraps the checkout drawer, so\n * the configuration never leaks into the panel, the notifications or any\n * global state.\n */\nexport function CheckoutAppearanceProvider({\n appearance,\n children,\n}: {\n appearance?: CheckoutAppearance;\n children: ReactNode;\n}) {\n const resolved = useMemo(\n () => resolveCheckoutAppearance(appearance),\n [appearance],\n );\n\n return (\n <CheckoutAppearanceContext.Provider value={resolved}>\n {children}\n </CheckoutAppearanceContext.Provider>\n );\n}\n\nexport function useCheckoutAppearance(): ResolvedCheckoutAppearance {\n return useContext(CheckoutAppearanceContext);\n}\n\n/**\n * Returns the caller overrides for a slot. The values are meant to be merged\n * with the built-in presentation:\n *\n * ```tsx\n * const slot = useCheckoutSlot(\"title\");\n *\n * return <h1 className={cn(\"text-2xl font-medium\", slot.className)} style={slot.style} />;\n * ```\n */\nexport function useCheckoutSlot(\n slot: CheckoutSlotName,\n): CheckoutSlotAppearance {\n const resolved = useCheckoutAppearance();\n\n return getCheckoutSlotAppearance(resolved, slot) ?? {};\n}\n","import type { CSSProperties } from \"react\";\nimport {\n getSlotAppearance,\n resolveAppearanceCore,\n type AppearanceElements,\n type ShadcnVariableMapping,\n type SlotAppearance,\n} from \"@/src/lib/appearance-core\";\n\n/**\n * Checkout appearance API.\n *\n * `CheckoutAppearance` is resolved once per render into plain data: a theme\n * name, the tokens that are actually in effect, the per-slot overrides and the\n * inline style that both theme boundaries (the drawer root and the portalled\n * country dropdown) have to receive. Everything here is pure so it can be\n * tested without a DOM.\n *\n * Backward compatibility: the resolver never invents values. A token is only\n * present in the resolved output when the caller provided it or when the\n * caller explicitly selected a theme preset, so every unset token keeps falling\n * back to the value the checkout renders today (see `checkout.css`).\n */\n\nexport type CheckoutTheme = \"dark\" | \"light\";\n\nexport type CheckoutAppearanceTokens = {\n /** Checkout wide font family. The library never loads fonts. */\n fontFamily?: string;\n /** Base font size of the checkout. */\n fontSize?: string;\n /** Panel background. */\n background?: string;\n /** Raised surfaces: country dropdown, search bar, loading skeletons. */\n surface?: string;\n /** Main text color. */\n foreground?: string;\n /** Secondary text: empty cart, delivery info, country label, search input. */\n mutedForeground?: string;\n /** Borders: country trigger, dropdown, product separators. */\n border?: string;\n /** Checkout button background. */\n buttonBackground?: string;\n /** Checkout button text. */\n buttonForeground?: string;\n /** Checkout button background on hover. */\n buttonHoverBackground?: string;\n /** Hover and selected surfaces: close button, country options. */\n hoverSurface?: string;\n /** Focus ring color. Also applied to shared UI primitives through `--ring`. */\n focusRing?: string;\n /** Error and unavailable state color. */\n error?: string;\n /** Drawer backdrop color. */\n overlay?: string;\n /** Corner radius, applied through `--radius`. */\n radius?: string;\n};\n\n/**\n * Stable slot names. They are exposed as `data-bitsnap-checkout-slot`\n * attributes so they can also be targeted from plain CSS.\n */\nexport const CHECKOUT_SLOT_NAMES = [\n \"root\",\n \"overlay\",\n \"panel\",\n \"header\",\n \"title\",\n \"closeButton\",\n \"productList\",\n \"product\",\n \"productImage\",\n \"productName\",\n \"productPrice\",\n \"quantityControl\",\n \"quantityInput\",\n \"quantityButton\",\n \"removeButton\",\n \"summary\",\n \"totalLabel\",\n \"totalValue\",\n \"deliveryText\",\n \"summaryNote\",\n \"countryLabel\",\n \"countryTrigger\",\n \"countryDropdown\",\n \"countrySearch\",\n \"countryOption\",\n \"paymentButtons\",\n \"paymentMethods\",\n \"paymentMethodOption\",\n \"checkoutButton\",\n \"emptyState\",\n \"error\",\n \"skeleton\",\n] as const;\n\nexport type CheckoutSlotName = (typeof CHECKOUT_SLOT_NAMES)[number];\n\nexport type CheckoutSlotAppearance = SlotAppearance;\n\nexport type CheckoutAppearanceElements = AppearanceElements<CheckoutSlotName>;\n\nexport type CheckoutAppearance = {\n /**\n * `\"dark\"` keeps the current presentation, `\"light\"` applies the light preset.\n * Omitted means `\"dark\"`.\n */\n theme?: CheckoutTheme;\n /** Partial overrides. Anything omitted keeps today's value. */\n tokens?: CheckoutAppearanceTokens;\n /** Per element `className`/`style` overrides. */\n elements?: CheckoutAppearanceElements;\n};\n\nexport type ResolvedCheckoutAppearance = {\n theme: CheckoutTheme;\n /**\n * `true` as soon as the caller passed anything through `appearance`. The\n * country dropdown is portalled outside of the checkout root, so it only\n * receives the checkout boundary when the caller opted in - an omitted or\n * empty `appearance` keeps the previous (unthemed) dropdown untouched.\n */\n isCustomized: boolean;\n /** Tokens that are in effect. Empty entries were dropped. */\n tokens: CheckoutAppearanceTokens;\n elements: CheckoutAppearanceElements;\n /** Theme marker class for the theme boundaries. */\n boundaryClassName: string;\n /** Inline custom properties applied to the drawer root. */\n boundaryStyle: CSSProperties;\n /**\n * Extra properties for the portalled country dropdown. The shared select\n * content paints itself with `bg-popover`/`text-popover-foreground`, so those\n * variables have to carry the checkout colors over to the portal. They are\n * resolved eagerly because the dropdown is the only place where the built-in\n * defaults differ from the drawer.\n */\n dropdownStyle: CSSProperties;\n};\n\n/** CSS custom property used for each token. */\nexport const CHECKOUT_TOKEN_VARIABLES = {\n fontFamily: \"--bitsnap-checkout-font-family\",\n fontSize: \"--bitsnap-checkout-font-size\",\n background: \"--bitsnap-checkout-background\",\n surface: \"--bitsnap-checkout-surface\",\n foreground: \"--bitsnap-checkout-foreground\",\n mutedForeground: \"--bitsnap-checkout-muted-foreground\",\n border: \"--bitsnap-checkout-border\",\n buttonBackground: \"--bitsnap-checkout-button-background\",\n buttonForeground: \"--bitsnap-checkout-button-foreground\",\n buttonHoverBackground: \"--bitsnap-checkout-button-hover-background\",\n hoverSurface: \"--bitsnap-checkout-hover-surface\",\n focusRing: \"--bitsnap-checkout-focus-ring\",\n error: \"--bitsnap-checkout-error\",\n overlay: \"--bitsnap-checkout-overlay\",\n radius: \"--bitsnap-checkout-radius\",\n} as const;\n\nexport type CheckoutTokenName = keyof typeof CHECKOUT_TOKEN_VARIABLES;\n\n/**\n * Theme presets are intentionally partial. `\"dark\"` is empty because every\n * default already renders the current dark presentation; `\"light\"` only carries\n * the colors that have to change for a light checkout, so typography is never\n * reset implicitly.\n */\nexport const CHECKOUT_THEME_PRESETS: Record<\n CheckoutTheme,\n CheckoutAppearanceTokens\n> = {\n dark: {},\n light: {\n background: \"#ffffff\",\n surface: \"#f9fafb\",\n foreground: \"#18181b\",\n mutedForeground: \"#71717a\",\n border: \"#e4e4e7\",\n buttonBackground: \"#18181b\",\n buttonForeground: \"#fafafa\",\n buttonHoverBackground: \"#000000\",\n hoverSurface: \"#e4e4e7\",\n focusRing: \"#71717a\",\n error: \"#dc2626\",\n overlay: \"rgb(0 0 0 / 0.35)\",\n },\n};\n\n/**\n * Some shared UI primitives (`Button`, `SelectTrigger`, ...) read the shadcn\n * theme variables instead of checkout tokens. Those are remapped so a themed\n * dropdown and themed primitives stay consistent. They are only written when\n * the matching token is in effect, so untouched tokens change nothing.\n */\nconst CHECKOUT_SHADCN_VARIABLES: ShadcnVariableMapping<CheckoutTokenName> = [\n { token: \"background\", variable: \"--background\" },\n { token: \"foreground\", variable: \"--foreground\" },\n { token: \"surface\", variable: \"--card\" },\n { token: \"surface\", variable: \"--popover\" },\n { token: \"foreground\", variable: \"--popover-foreground\" },\n { token: \"mutedForeground\", variable: \"--muted-foreground\" },\n { token: \"border\", variable: \"--border\" },\n { token: \"border\", variable: \"--input\" },\n { token: \"focusRing\", variable: \"--ring\" },\n { token: \"error\", variable: \"--destructive\" },\n { token: \"radius\", variable: \"--radius\" },\n];\n\n/**\n * The portalled dropdown renders `bg-popover`/`text-popover-foreground` from the\n * shared primitives, so those two variables are resolved eagerly: without a\n * token they fall back to the dark values the checkout has always used.\n */\nfunction resolveDropdownStyle(tokens: CheckoutAppearanceTokens): CSSProperties {\n return {\n \"--popover\": tokens.surface ?? \"var(--color-neutral-800)\",\n \"--popover-foreground\": tokens.foreground ?? \"var(--color-neutral-200)\",\n } as CSSProperties;\n}\n\nexport function resolveCheckoutAppearance(\n appearance?: CheckoutAppearance,\n): ResolvedCheckoutAppearance {\n const resolved = resolveAppearanceCore<\n CheckoutTokenName,\n CheckoutTheme,\n CheckoutSlotName\n >(appearance, {\n defaultTheme: \"dark\",\n presets: CHECKOUT_THEME_PRESETS,\n variables: CHECKOUT_TOKEN_VARIABLES,\n shadcnVariables: CHECKOUT_SHADCN_VARIABLES,\n });\n\n return {\n theme: resolved.theme,\n isCustomized: resolved.isCustomized,\n tokens: resolved.tokens,\n elements: resolved.elements,\n boundaryClassName: resolved.theme,\n boundaryStyle: resolved.boundaryStyle,\n dropdownStyle: resolveDropdownStyle(resolved.tokens),\n };\n}\n\n/** Caller overrides for a single slot, if any were provided. */\nexport function getCheckoutSlotAppearance(\n resolved: ResolvedCheckoutAppearance,\n slot: CheckoutSlotName,\n): CheckoutSlotAppearance | undefined {\n return getSlotAppearance(resolved.elements, slot);\n}\n","import { useAutoAnimate } from \"@formkit/auto-animate/react\";\nimport React from \"react\";\nimport { useInstrumentContext } from \"@/src/analytics/instrument\";\nimport { getCartLines, getProjectID, useCartProvider } from \"./CartProvider\";\nimport CountrySelector from \"./CountrySelector\";\nimport { isErr } from \"./lib/err\";\nimport { formatCurrency } from \"./lib/round.number\";\nimport LoadingIndicator from \"./LoadingIndicator\";\nimport SingleProduct from \"./SingleProduct\";\nimport { Skeleton } from \"./Skeleton\";\nimport { ApplePayButton, GooglePayButton } from \"..\";\nimport { Spinner } from \"@/src/ui/spinner\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { cn } from \"@/src/lib/utils\";\nimport { sendAnalyticEvent } from \"./frontent.analytics\";\nimport { getLocale } from \"./locale\";\nimport { buyErrorText } from \"./buy-error\";\nimport { useCheckoutText, useCheckoutTextResolver } from \"./texts.context\";\nimport { useCheckoutSlot } from \"./appearance.context\";\nimport { rememberPendingOrder } from \"./pending-order\";\nimport { useCheckoutStore } from \"./state\";\nimport { PaymentMethodChoice } from \"./PaymentMethodChoice\";\nimport {\n effectivePaymentMethod,\n withoutCod,\n type PaymentMethod,\n type PaymentMethodChoice as Choice,\n} from \"./payment-method\";\nimport { InPostPayButtonInner } from \"../express/InPostPayButton\";\nimport { RevolutPayButtonInner } from \"../express/RevolutPayButton\";\n\nconst CartComponentContent = ({\n className,\n locale,\n}: {\n className: string;\n locale?: string;\n}) => {\n const provider = useCartProvider();\n const instrument = useInstrumentContext();\n const currentLocale = locale ?? getLocale();\n\n const productList = useCheckoutSlot(\"productList\");\n const summary = useCheckoutSlot(\"summary\");\n const totalLabel = useCheckoutSlot(\"totalLabel\");\n const totalValue = useCheckoutSlot(\"totalValue\");\n const deliveryText = useCheckoutSlot(\"deliveryText\");\n const summaryNote = useCheckoutSlot(\"summaryNote\");\n const countryLabel = useCheckoutSlot(\"countryLabel\");\n const paymentButtons = useCheckoutSlot(\"paymentButtons\");\n const checkoutButton = useCheckoutSlot(\"checkoutButton\");\n const emptyState = useCheckoutSlot(\"emptyState\");\n const error = useCheckoutSlot(\"error\");\n const skeleton = useCheckoutSlot(\"skeleton\");\n\n const unavailableProductsText = useCheckoutText(\"unavailableProducts\");\n const resolveCheckoutText = useCheckoutTextResolver();\n const emptyCartText = useCheckoutText(\"emptyCart\");\n const totalText = useCheckoutText(\"total\");\n const deliveryCopy = useCheckoutText(\"delivery\");\n const chooseCountryText = useCheckoutText(\"chooseCountry\");\n const nextStepText = useCheckoutText(\"nextStep\");\n const loadFailedText = useCheckoutText(\"loadFailed\");\n const retryText = useCheckoutText(\"retry\");\n const countryRequiredText = useCheckoutText(\"countryRequired\");\n const extrasCalculatedNextText = useCheckoutText(\"extrasCalculatedNext\");\n const countrySelectorId = React.useId();\n const countryHintId = React.useId();\n\n const { mutateAsync: removeProduct } = useMutation({\n mutationFn: provider.removeProductFromCart,\n });\n const { mutateAsync: updateQuantity } = useMutation({\n mutationFn: provider.updateQuantity,\n });\n const { mutateAsync: setCountryAsync } = useMutation({\n mutationFn: provider.setCountry,\n });\n const { mutateAsync: clearCart } = useMutation({\n mutationFn: provider.clearCart,\n });\n\n const [errMsg, setErrMsg] = React.useState(\"\");\n // Raised outside of the drawer (for example a failed redirect of `window.cart.buyProduct`).\n const notice = useCheckoutStore((state) => state.notice);\n React.useEffect(\n () => () => useCheckoutStore.getState().setNotice(undefined),\n [],\n );\n const shownError = errMsg.length > 0 ? errMsg : (notice ?? \"\");\n const [missingItemIds, setMissingItemIds] = React.useState<string[]>([]);\n\n const [isCountryOpen, setIsCountryOpen] = React.useState(false);\n\n const {\n mutateAsync: continueToCheckoutAsync,\n isPending: isContinueToCheckoutLoading,\n } = useMutation({\n mutationFn: provider.redirectToNextStep,\n });\n\n const { data: availableCountries } = useQuery({\n queryKey: [\"cart-available-countries\"],\n queryFn: provider.getAvailableCountries,\n });\n const { data: isApplePayAvailable } = useQuery({\n queryKey: [\"cart-one-click-payment\"],\n queryFn: provider.checkIfApplePayIsAvailable,\n });\n const { data, isLoading, isError, refetch } = useQuery({\n queryKey: [\"cart\", currentLocale],\n queryFn: provider.getProducts,\n });\n const { data: countryData, refetch: refetchCountry } = useQuery({\n queryKey: [\"cart-country\"],\n queryFn: provider.getCountry,\n });\n\n const [productsParent] = useAutoAnimate(/* optional config */);\n\n const products = isErr(data) ? undefined : data;\n\n const selectedCountry =\n countryData != null && !isErr(countryData) && countryData != \"\"\n ? countryData\n : undefined;\n\n // Whether the shop lets the buyer pay by hand (transfer / BLIK to a phone)\n // or on delivery for this cart. Asked once per cart content and country\n // (cash on delivery is for Poland only); any failure means \"no choice\".\n // Without a country \"Next step\" is disabled, so there is nothing to ask yet.\n // Until a new country or cart is answered, the last choice stays on screen\n // without cash on delivery, which the new answer may not offer.\n const queryClient = useQueryClient();\n const cartSignature =\n products == null || products.length === 0 || selectedCountry == null\n ? undefined\n : products\n .map((el) => `${el.productID}:${el.quantity}`)\n .sort()\n .join(\",\");\n const paymentMethodsQuery = {\n queryKey: [\n \"cart-payment-methods\",\n getProjectID(),\n currentLocale,\n selectedCountry,\n cartSignature,\n ],\n queryFn: async (): Promise<Choice | null> =>\n provider.getPaymentMethodChoice().catch(() => null),\n staleTime: 60_000,\n retry: false,\n } as const;\n const {\n data: paymentMethodChoiceData,\n isPlaceholderData: isPaymentMethodChoicePlaceholder,\n } = useQuery({\n ...paymentMethodsQuery,\n enabled: cartSignature != null,\n placeholderData: (previous: Choice | null | undefined) =>\n previous === undefined ? undefined : withoutCod(previous),\n });\n const paymentMethodChoice =\n cartSignature != null ? (paymentMethodChoiceData ?? null) : null;\n const [selectedPaymentMethod, setSelectedPaymentMethod] = React.useState<\n PaymentMethod | undefined\n >(undefined);\n const [isWaitingForChoice, setIsWaitingForChoice] = React.useState(false);\n const paymentMethodsRef = React.useRef<HTMLDivElement>(null);\n const hasLoadFailed = !isLoading && (isError || isErr(data));\n\n const countries = isErr(availableCountries) ? [] : availableCountries;\n\n const sumOfProducts =\n products?.reduce((prev, curr) => {\n if (curr.details == null) {\n return prev;\n }\n return prev + (curr.details.pricing?.effectivePrice ?? curr.details.price) * curr.quantity;\n }, 0) ?? 0;\n const currency = products?.[0]?.details?.currency ?? \"PLN\";\n\n const isSomeProductDeliverable =\n products?.some((product) => product.details?.isDeliverable === true) ??\n false;\n\n // The hint waits for the answer: the country is read asynchronously.\n const isCountryMissing = countryData !== undefined && selectedCountry == null;\n\n // A stored country the shop does not ship to (or none at all) would leave the checkout button disabled.\n const autoSelectedCountry = React.useRef(false);\n React.useEffect(() => {\n if (\n autoSelectedCountry.current ||\n countries == null ||\n countries.length === 0 ||\n countryData == null ||\n (selectedCountry != null &&\n countries.some((el) => el.code === selectedCountry))\n ) {\n return;\n }\n autoSelectedCountry.current = true;\n setCountryAsync(countries[0].code)\n .then(() => refetchCountry())\n .catch(() => {});\n }, [countries, countryData, selectedCountry]);\n\n // One `cart_opened` per opening of the drawer, once the cart is loaded.\n const opened = React.useRef(false);\n React.useEffect(() => {\n if (opened.current || isLoading) {\n return;\n }\n opened.current = true;\n instrument.track(\"cart_opened\", {\n item_count: products?.reduce((sum, el) => sum + el.quantity, 0) ?? 0,\n value_minor: sumOfProducts,\n currency,\n });\n }, [isLoading, instrument, products, sumOfProducts, currency]);\n\n const reportedQuantity = React.useRef(new Map<string, number>());\n React.useEffect(() => {\n reportedQuantity.current.clear();\n }, [products]);\n\n /** `add_to_cart` / `remove_from_cart` for a quantity change in the drawer. */\n function trackQuantityChange(id: string, newQuantity: number) {\n const line = products?.find((el) => el.id === id);\n if (line?.details == null) {\n return;\n }\n // Quick clicks arrive before the cart is reloaded: count from the last reported quantity.\n const delta = newQuantity - (reportedQuantity.current.get(id) ?? line.quantity);\n reportedQuantity.current.set(id, newQuantity);\n if (delta === 0) {\n return;\n }\n const price = line.details.pricing?.effectivePrice ?? line.details.price;\n const productID = line.catalogProductID ?? line.productID;\n instrument.track(\n delta > 0 ? \"add_to_cart\" : \"remove_from_cart\",\n {\n qty: Math.abs(delta),\n value_minor: Math.round(price * Math.abs(delta)),\n currency: line.details.currency,\n },\n {\n product_id: productID,\n variant_id: productID !== line.productID ? line.productID : null,\n },\n );\n }\n\n const startedCheckout = React.useRef(false);\n\n /** Rejects when the cart could not be changed; the cart is reloaded either way. */\n async function shouldUpdate(id: string, newQuantity?: number) {\n if (newQuantity == null) {\n return;\n }\n trackQuantityChange(id, Math.max(0, newQuantity));\n try {\n const result =\n newQuantity <= 0\n ? await removeProduct({ id: id })\n : await updateQuantity({ id: id, quantity: newQuantity });\n if (isErr(result)) {\n throw new Error(`cannot change the cart: ${result.error}`);\n }\n } finally {\n await refetch().catch(() => undefined);\n }\n }\n\n async function continueToCheckout() {\n try {\n setErrMsg(\"\");\n setMissingItemIds([]);\n useCheckoutStore.getState().setNotice(undefined);\n\n // A click before the choice arrived waits for it (at most the request\n // timeout); a choice the buyer has not seen yet is shown, not used. The\n // last choice shown in the meantime is used if the new one still offers\n // the selected method.\n let choice = paymentMethodChoice;\n let paymentMethod =\n choice != null\n ? effectivePaymentMethod(choice, selectedPaymentMethod)\n : undefined;\n if (\n cartSignature != null &&\n (paymentMethodChoiceData === undefined || isPaymentMethodChoicePlaceholder)\n ) {\n setIsWaitingForChoice(true);\n try {\n choice = await queryClient\n .fetchQuery(paymentMethodsQuery)\n .catch(() => null);\n } finally {\n setIsWaitingForChoice(false);\n }\n if (choice == null) {\n paymentMethod = undefined;\n } else if (paymentMethod == null || !choice.methods.includes(paymentMethod)) {\n // Let the buyer see the options first; focus moves to the selected one.\n window.setTimeout(() => {\n paymentMethodsRef.current\n ?.querySelector<HTMLInputElement>(\"input:checked\")\n ?.focus();\n }, 0);\n return;\n }\n }\n\n if (products != null) {\n if (!startedCheckout.current && products.length > 0) {\n startedCheckout.current = true;\n instrument.track(\"checkout_started\", {\n item_count: products.reduce((sum, el) => sum + el.quantity, 0),\n checkout_type: \"cart\",\n value_minor: sumOfProducts,\n currency,\n });\n }\n try {\n sendAnalyticEvent({\n event: \"initiateCheckout\",\n items: products?.map((el) => ({\n id: el.productID,\n name: el.details?.name ?? \"\",\n price: el.details?.price ?? 0,\n quantity: el.quantity,\n currency: el.details?.currency ?? \"PLN\",\n })),\n });\n } catch (e) {}\n }\n\n // What this order is made of; only these lines go once it is paid.\n const cartLinesBeforeBuy = getCartLines();\n const response = await continueToCheckoutAsync(\n paymentMethod != null ? { paymentMethod } : undefined,\n );\n\n if (isErr(response)) {\n // The seller may have changed the payment methods in the meantime.\n void queryClient.invalidateQueries({ queryKey: [\"cart-payment-methods\"] });\n if (response.error == \"item-ids-not-found\") {\n setErrMsg(unavailableProductsText);\n if (\"data\" in response && Array.isArray(response.data)) {\n setMissingItemIds(response.data as string[]);\n }\n } else if (\n paymentMethod === \"cod\" &&\n response.error == \"gateway-not-configured\"\n ) {\n // The shop turned cash on delivery off, or this cart does not qualify.\n setErrMsg(resolveCheckoutText(\"paymentMethodCodUnavailable\"));\n } else {\n setErrMsg(buyErrorText(response, resolveCheckoutText));\n }\n return;\n }\n\n // The cart stays until the order is paid (or placed, for cash on\n // delivery); without an order to ask about it is cleared now.\n if (\n !rememberPendingOrder(response, {\n cartProjectId: getProjectID(),\n lines: cartLinesBeforeBuy,\n })\n ) {\n await clearCart();\n }\n window.location.href = response.url;\n } catch (e: unknown) {\n console.warn(\"checkout failed\", e);\n setErrMsg(resolveCheckoutText(\"checkoutFailed\"));\n }\n }\n\n return (\n <div className={`${className} flex flex-col`} ref={productsParent}>\n {isLoading && (\n <div className={\"relative flex w-full justify-center flex-col gap-4\"}>\n <Skeleton\n data-bitsnap-checkout-slot=\"skeleton\"\n className={cn(\"w-full h-32\", skeleton.className)}\n style={skeleton.style}\n />\n <Skeleton\n data-bitsnap-checkout-slot=\"skeleton\"\n className={cn(\"w-full h-32\", skeleton.className)}\n style={skeleton.style}\n />\n </div>\n )}\n\n {hasLoadFailed && (\n <div className={\"flex flex-col items-start gap-3 p-4\"}>\n <p\n role=\"alert\"\n data-bitsnap-checkout-slot=\"error\"\n className={cn(error.className)}\n style={error.style}\n >\n {loadFailedText}\n </p>\n {notice != null && notice.length > 0 && (\n <p\n role=\"alert\"\n data-bitsnap-checkout-slot=\"error\"\n className={cn(\"text-sm\", error.className)}\n style={error.style}\n >\n {notice}\n </p>\n )}\n <button\n type=\"button\"\n data-bitsnap-checkout-slot=\"checkoutButton\"\n onClick={() => {\n refetch().then().catch();\n }}\n className={cn(\n \"px-3 py-2 rounded-md transition font-bold\",\n checkoutButton.className,\n )}\n style={checkoutButton.style}\n >\n {retryText}\n </button>\n </div>\n )}\n\n {!isLoading && !hasLoadFailed && (products == null || products.length == 0) && (\n <div className={\"flex flex-col gap-4 p-4\"}>\n <p\n data-bitsnap-checkout-slot=\"emptyState\"\n className={cn(emptyState.className)}\n style={emptyState.style}\n >\n {emptyCartText}\n </p>\n {notice != null && notice.length > 0 && (\n <p\n role=\"alert\"\n data-bitsnap-checkout-slot=\"error\"\n className={cn(\"text-sm\", error.className)}\n style={error.style}\n >\n {notice}\n </p>\n )}\n </div>\n )}\n\n <div\n data-bitsnap-checkout-slot=\"productList\"\n className={cn(\n \"max-h-[70vh] overflow-clip overflow-y-scroll\",\n productList.className,\n )}\n style={productList.style}\n >\n {products != null && products.length > 0 && (\n <ul className={\"mt-5\"}>\n {products.map((product) => (\n <React.Fragment key={product.id}>\n {product.details != null && (\n <li className={\"mb-3\"}>\n <SingleProduct\n isNotAvailable={missingItemIds.includes(\n product.productID,\n )}\n quantity={product.quantity}\n details={product.details}\n url={product.url}\n shouldUpdate={(newQuantity) =>\n shouldUpdate(product.id, newQuantity)\n }\n />\n <hr className=\"h-1\" />\n </li>\n )}\n </React.Fragment>\n ))}\n </ul>\n )}\n </div>\n\n <div className=\"grow\"></div>\n\n {sumOfProducts > 0 && currency != null && (\n <>\n <div\n data-bitsnap-checkout-slot=\"summary\"\n className={cn(\"mx-3 flex flex-col\", summary.className)}\n style={summary.style}\n >\n <div className={\"flex flex-row justify-between text-lg\"}>\n <p\n data-bitsnap-checkout-slot=\"totalLabel\"\n className={cn(\"text-xl\", totalLabel.className)}\n style={totalLabel.style}\n >\n {totalText}\n </p>\n <div className={\"flex flex-col items-end\"}>\n <p\n data-bitsnap-checkout-slot=\"totalValue\"\n className={cn(\"font-medium\", totalValue.className)}\n style={totalValue.style}\n >\n {formatCurrency(sumOfProducts, currency)}\n </p>\n {isSomeProductDeliverable && (\n <p\n data-bitsnap-checkout-slot=\"deliveryText\"\n className={cn(\n \"opacity-70 text-right text-base\",\n deliveryText.className,\n )}\n style={deliveryText.style}\n >\n {deliveryCopy}\n </p>\n )}\n </div>\n </div>\n <p\n data-bitsnap-checkout-slot=\"summaryNote\"\n className={cn(\"opacity-70 text-sm\", summaryNote.className)}\n style={summaryNote.style}\n >\n {extrasCalculatedNextText}\n </p>\n </div>\n\n {countries && countries?.length > 1 && (\n <div>\n <h4\n data-bitsnap-checkout-slot=\"countryLabel\"\n className={cn(\"ml-3 text-sm\", countryLabel.className)}\n style={countryLabel.style}\n >\n {chooseCountryText}\n </h4>\n <CountrySelector\n id={countrySelectorId}\n open={isCountryOpen}\n onToggle={() => {\n setIsCountryOpen(!isCountryOpen);\n }}\n onChange={(newValue) => {\n setCountryAsync(newValue).then(() => {\n refetchCountry().then().catch();\n });\n }}\n selectedValue={selectedCountry ?? \"\"}\n countries={countries}\n />\n </div>\n )}\n\n <div className={\"mb-3 flex flex-col\"}>\n {isApplePayAvailable && products != null && products.length > 0 && (\n <div\n data-bitsnap-checkout-slot=\"paymentButtons\"\n className={cn(\"w-full px-2\", paymentButtons.className)}\n style={paymentButtons.style}\n >\n <ApplePayButton\n colorType=\"white\"\n style={{ width: \"100%\" }}\n items={products?.map((el) => ({\n name: el.details?.name ?? \"\",\n id: el.productID,\n price: el.details?.pricing?.effectivePrice ?? el.details?.price ?? 0,\n currency: el.details?.currency,\n quantity: el.quantity,\n isDeliverable: el.details?.isDeliverable ?? false,\n metadata: el.metadata,\n }))}\n />\n </div>\n )}\n {products != null && products.length > 0 && (\n <div\n data-bitsnap-checkout-slot=\"paymentButtons\"\n className={cn(\"w-full px-2\", paymentButtons.className)}\n style={paymentButtons.style}\n >\n <GooglePayButton\n buttonSizeMode=\"fill\"\n buttonColor=\"white\"\n style={{ width: \"100%\" }}\n items={products?.map((el) => ({\n name: el.details?.name ?? \"\",\n id: el.productID,\n price: el.details?.pricing?.effectivePrice ?? el.details?.price ?? 0,\n quantity: el.quantity,\n isDeliverable: el.details?.isDeliverable ?? false,\n metadata: el.metadata,\n }))}\n />\n </div>\n )}\n {products != null && products.length > 0 && (\n <div\n data-bitsnap-checkout-slot=\"paymentButtons\"\n className={cn(\"w-full px-2\", paymentButtons.className)}\n style={paymentButtons.style}\n >\n <InPostPayButtonInner\n projectID={getProjectID() ?? \"\"}\n locale={currentLocale}\n />\n <RevolutPayButtonInner\n projectID={getProjectID() ?? \"\"}\n locale={currentLocale}\n />\n </div>\n )}\n {paymentMethodChoice != null && (\n <div ref={paymentMethodsRef} className=\"contents\">\n <PaymentMethodChoice\n choice={paymentMethodChoice}\n selected={effectivePaymentMethod(\n paymentMethodChoice,\n selectedPaymentMethod,\n )}\n onChange={setSelectedPaymentMethod}\n disabled={isContinueToCheckoutLoading}\n />\n </div>\n )}\n <button\n data-bitsnap-checkout-slot=\"checkoutButton\"\n onClick={continueToCheckout}\n disabled={\n isLoading ||\n isContinueToCheckoutLoading ||\n isWaitingForChoice ||\n selectedCountry == null\n }\n aria-describedby={isCountryMissing ? countryHintId : undefined}\n className={cn(\n \"px-3 py-2 my-2 mx-2 rounded-md disabled:opacity-40 disabled:cursor-not-allowed transition font-bold\",\n checkoutButton.className,\n )}\n style={checkoutButton.style}\n >\n {isContinueToCheckoutLoading || isWaitingForChoice ? (\n <Spinner />\n ) : (\n nextStepText\n )}\n </button>\n {isCountryMissing && (\n <p\n id={countryHintId}\n className={\"text-sm text-center opacity-70\"}\n >\n {countryRequiredText}\n </p>\n )}\n {shownError.length > 0 && (\n <p\n role=\"alert\"\n data-bitsnap-checkout-slot=\"error\"\n className={cn(\"text-sm text-center\", error.className)}\n style={error.style}\n >\n {shownError}\n </p>\n )}\n </div>\n </>\n )}\n </div>\n );\n};\n\nexport default CartComponentContent;\n","import { useEffect, useState } from \"react\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/src/ui/select\";\nimport { cn } from \"@/src/lib/utils\";\nimport { useCheckoutAppearance, useCheckoutSlot } from \"./appearance.context\";\nimport { useCheckoutText } from \"./texts.context\";\n\nexport interface CountrySelectorProps {\n id: string;\n open: boolean;\n disabled?: boolean;\n onToggle: () => void;\n onChange: (value: string) => void;\n selectedValue: string;\n countries: { name: string; code: string }[];\n}\n\nfunction CountrySelector({\n id,\n open,\n disabled = false,\n onToggle,\n onChange,\n selectedValue,\n countries,\n}: CountrySelectorProps) {\n const [query, setQuery] = useState(\"\");\n\n const {\n isCustomized,\n boundaryClassName,\n boundaryStyle,\n dropdownStyle,\n } = useCheckoutAppearance();\n const countryTrigger = useCheckoutSlot(\"countryTrigger\");\n const countryDropdown = useCheckoutSlot(\"countryDropdown\");\n const countrySearch = useCheckoutSlot(\"countrySearch\");\n const countryOption = useCheckoutSlot(\"countryOption\");\n const searchCountryText = useCheckoutText(\"searchCountry\");\n const noCountriesFoundText = useCheckoutText(\"noCountriesFound\");\n\n useEffect(() => {\n if (selectedValue == null && countries.length > 0) {\n onChange(countries[0].code);\n }\n }, []);\n\n const filteredCountries = countries.filter((country) =>\n country.name.toLowerCase().startsWith(query.toLowerCase()),\n );\n\n const selectedCountry = countries.find((el) => el.code === selectedValue);\n\n return (\n <Select\n value={selectedValue}\n onValueChange={(value) => {\n onChange(value);\n setQuery(\"\");\n }}\n open={open}\n onOpenChange={(isOpen) => {\n if (isOpen !== open) {\n onToggle();\n }\n if (!isOpen) {\n setQuery(\"\");\n }\n }}\n disabled={disabled}\n >\n <SelectTrigger\n data-bitsnap-checkout-slot=\"countryTrigger\"\n theme=\"bare\"\n className={cn(\n disabled\n ? \"bg-neutral-100 dark:bg-neutral-800 dark:border-neutral-700\"\n : \"\",\n \"w-full rounded-md\",\n countryTrigger.className,\n )}\n style={countryTrigger.style}\n >\n <SelectValue>\n {selectedCountry && (\n <span className=\"truncate flex items-center\">\n <img\n alt={selectedValue}\n src={`https://purecatamphetamine.github.io/country-flag-icons/3x2/${selectedValue}.svg`}\n className=\"inline mr-2 h-4 rounded-sm\"\n />\n {selectedCountry.name}\n </span>\n )}\n </SelectValue>\n </SelectTrigger>\n <SelectContent\n data-bitsnap-checkout={isCustomized ? \"dropdown\" : undefined}\n data-bitsnap-checkout-slot={isCustomized ? \"countryDropdown\" : undefined}\n className={cn(\n // The dropdown is portalled outside of the checkout root, so it only\n // joins the checkout theme boundary once the caller opts into an\n // appearance. Without it the content renders exactly as before.\n isCustomized ? \"bitsnap-react\" : \"\",\n boundaryClassName,\n \"w-full max-h-80 max-w-[350px] z-[999999]\",\n countryDropdown.className,\n )}\n style={{\n ...(isCustomized ? { ...boundaryStyle, ...dropdownStyle } : undefined),\n ...countryDropdown.style,\n }}\n position=\"popper\"\n >\n <div\n data-bitsnap-checkout-slot=\"countrySearch\"\n className={cn(\"sticky top-0 z-10 p-1 border-b\", countrySearch.className)}\n style={countrySearch.style}\n >\n <input\n type=\"search\"\n name=\"search\"\n autoComplete=\"off\"\n className=\"block w-full outline-none sm:text-body-regular bg-transparent rounded-md px-2 py-1.5\"\n placeholder={searchCountryText}\n aria-label={searchCountryText}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n />\n </div>\n <div className=\"max-h-64 overflow-y-auto\">\n {filteredCountries.length === 0 ? (\n <div className=\"cursor-default select-none relative py-2 pl-3 pr-9 text-sm\">\n {noCountriesFoundText}\n </div>\n ) : (\n filteredCountries.map((country) => (\n <SelectItem\n key={`${id}-${country.code}`}\n data-bitsnap-checkout-slot=\"countryOption\"\n value={country.code}\n className={cn(\n \"cursor-default select-none relative py-2 pl-3 pr-9 flex items-center transition\",\n countryOption.className,\n )}\n style={countryOption.style}\n >\n <img\n alt={country.code}\n src={`https://purecatamphetamine.github.io/country-flag-icons/3x2/${country.code}.svg`}\n className=\"inline mr-2 h-4 rounded-sm\"\n />\n <span className=\"font-normal truncate\">{country.name}</span>\n </SelectItem>\n ))\n )}\n </div>\n </SelectContent>\n </Select>\n );\n}\n\nexport default CountrySelector;\n","import * as React from \"react\"\nimport * as SelectPrimitive from \"@radix-ui/react-select\"\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\"\n\nimport { cn } from \"@/src/lib/utils\"\n\nfunction Select({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />\n}\n\nfunction SelectGroup({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Group>) {\n return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />\n}\n\nfunction SelectValue({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />\n}\n\n/**\n * Colors owned by the shared shadcn theme. They live in Tailwind's\n * `utilities` layer, so plain CSS can never win against them. Components that\n * theme themselves through their own stylesheet (the checkout and its\n * `appearance` tokens) opt out with `theme=\"bare\"`, which keeps the colors the\n * checkout owns (`background-color`, `border-color`) and leaves the rest alone.\n * The default is unchanged.\n */\nconst selectTriggerThemeClasses =\n \"border-input dark:bg-input/30 dark:hover:bg-input/50 bg-transparent\"\n\nfunction SelectTrigger({\n className,\n size = \"default\",\n theme = \"default\",\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {\n size?: \"sm\" | \"default\"\n theme?: \"default\" | \"bare\"\n}) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n \"data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive flex w-fit items-center justify-between gap-2 rounded-md border px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n theme === \"bare\" ? \"\" : selectTriggerThemeClasses,\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"size-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n}\n\nfunction SelectContent({\n className,\n children,\n position = \"popper\",\n align = \"center\",\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md\",\n position === \"popper\" &&\n \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n className\n )}\n position={position}\n align={align}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n \"p-1\",\n position === \"popper\" &&\n \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1\"\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n )\n}\n\nfunction SelectLabel({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n data-slot=\"select-label\"\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2\",\n className\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n )\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(\"bg-border pointer-events-none -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectScrollUpButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n return (\n <SelectPrimitive.ScrollUpButton\n data-slot=\"select-scroll-up-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronUpIcon className=\"size-4\" />\n </SelectPrimitive.ScrollUpButton>\n )\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n return (\n <SelectPrimitive.ScrollDownButton\n data-slot=\"select-scroll-down-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronDownIcon className=\"size-4\" />\n </SelectPrimitive.ScrollDownButton>\n )\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type { SingleProduct } from \"./product.details.model\";\nimport { Button } from \"@/src/ui/button\";\nimport { MinusIcon, PlusIcon } from \"lucide-react\";\nimport { ButtonGroup } from \"@/src/ui/button-group\";\nimport { cn } from \"@/src/lib/utils\";\nimport { useCheckoutSlot } from \"./appearance.context\";\nimport { ProductPrice } from \"./ProductPrice\";\nimport { useCheckoutText } from \"./texts.context\";\nimport { clampQuantity, quantityFromInput } from \"./quantity\";\n\nconst SingleProduct = ({\n isNotAvailable,\n quantity,\n details,\n url,\n shouldUpdate,\n}: {\n isNotAvailable: boolean;\n quantity: number;\n metadata?: { [key: string]: string | undefined };\n /** Product page; the image and the name link to it. */\n url?: string;\n details: SingleProduct;\n /** Rejects when the cart could not be changed. */\n shouldUpdate: (newQuantity?: number) => Promise<unknown> | void;\n}) => {\n const product = useCheckoutSlot(\"product\");\n const productImage = useCheckoutSlot(\"productImage\");\n const productName = useCheckoutSlot(\"productName\");\n const productPrice = useCheckoutSlot(\"productPrice\");\n const removeButton = useCheckoutSlot(\"removeButton\");\n const removeText = useCheckoutText(\"remove\");\n\n const imageUrl = details.image_url ?? details.images?.[0];\n const [brokenImageUrl, setBrokenImageUrl] = useState<string | undefined>();\n const showImage =\n imageUrl != null && imageUrl.length > 0 && imageUrl !== brokenImageUrl;\n const name = details.baseName ?? details.name;\n\n return (\n <div\n data-bitsnap-checkout-slot=\"product\"\n data-bitsnap-checkout-unavailable={isNotAvailable ? \"\" : undefined}\n className={cn(\n \"flex items-center gap-3 mx-3\",\n isNotAvailable ? \"outline outline-1 rounded-md m-1\" : \"\",\n product.className,\n )}\n style={product.style}\n >\n {showImage && (\n <ProductLink\n url={url}\n // The name links to the same page; one link per item for keyboards.\n tabIndex={-1}\n aria-hidden=\"true\"\n className=\"contents\"\n >\n <img\n data-bitsnap-checkout-slot=\"productImage\"\n className={cn(\n \"aspect-auto max-w-[30%] max-w-32 max-h-32 py-2 overflow-hidden\",\n productImage.className,\n )}\n style={productImage.style}\n src={imageUrl}\n alt=\"\"\n onError={() => setBrokenImageUrl(imageUrl)}\n />\n </ProductLink>\n )}\n\n <div className={\"flex flex-col w-full\"}>\n <p\n data-bitsnap-checkout-slot=\"productName\"\n className={cn(\"font-medium\", productName.className)}\n style={productName.style}\n >\n <ProductLink\n url={url}\n className=\"text-inherit no-underline hover:underline\"\n >\n {name}\n </ProductLink>\n </p>\n {details.variantName != null && details.variantName.length > 0 && (\n <p className=\"text-sm opacity-70\">{details.variantName}</p>\n )}\n <p\n data-bitsnap-checkout-slot=\"productPrice\"\n className={cn(\"text-sm\", productPrice.className)}\n style={productPrice.style}\n suppressHydrationWarning\n >\n <ProductPrice\n price={details.price}\n currency={details.currency}\n pricing={details.pricing}\n quantity={quantity}\n />\n </p>\n <div className={\"flex justify-between\"}>\n <QuantityComponent\n className={\"\"}\n quantity={quantity}\n shouldUpdate={shouldUpdate}\n />\n <Button\n data-bitsnap-checkout-slot=\"removeButton\"\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className={removeButton.className}\n style={removeButton.style}\n aria-label={`${removeText}: ${details.name}`}\n onClick={() => {\n Promise.resolve(shouldUpdate(0)).catch(() => undefined);\n }}\n >\n {removeText}\n </Button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default SingleProduct;\n\n/** The children as a link to the product page, or as they are without one. */\nconst ProductLink = ({\n url,\n children,\n ...props\n}: React.AnchorHTMLAttributes<HTMLAnchorElement> & {\n url?: string;\n children: React.ReactNode;\n}) => {\n if (url == null) {\n return <>{children}</>;\n }\n return (\n <a href={url} {...props}>\n {children}\n </a>\n );\n};\n\nconst QuantityComponent = ({\n quantity,\n shouldUpdate,\n className,\n}: {\n quantity: number;\n shouldUpdate: (newQuantity: number) => Promise<unknown> | void;\n className: string;\n}) => {\n const [quantityString, setQuantityString] = useState(quantity.toString());\n // The last quantity sent, so quick clicks count from it before the cart reloads.\n const sent = useRef(quantity);\n\n const quantityControl = useCheckoutSlot(\"quantityControl\");\n const quantityInput = useCheckoutSlot(\"quantityInput\");\n const quantityButton = useCheckoutSlot(\"quantityButton\");\n const quantityText = useCheckoutText(\"quantity\");\n const increaseText = useCheckoutText(\"increaseQuantity\");\n const decreaseText = useCheckoutText(\"decreaseQuantity\");\n\n const shownQuantity = useRef(quantity);\n shownQuantity.current = quantity;\n\n // The cart is the source of truth once it has reloaded.\n useEffect(() => {\n sent.current = quantity;\n setQuantityString(quantity.toString());\n }, [quantity]);\n\n function commit(newQuantity: number) {\n setQuantityString(newQuantity.toString());\n if (newQuantity !== sent.current) {\n sent.current = newQuantity;\n Promise.resolve(shouldUpdate(newQuantity)).catch(() => {\n // The cart rejected it: show what the cart has.\n if (sent.current === newQuantity) {\n sent.current = shownQuantity.current;\n setQuantityString(shownQuantity.current.toString());\n }\n });\n }\n }\n\n return (\n <div\n data-bitsnap-checkout-slot=\"quantityControl\"\n className={cn(\"flex\", className, quantityControl.className)}\n style={quantityControl.style}\n >\n <ButtonGroup aria-label={quantityText}>\n <Button\n data-bitsnap-checkout-slot=\"quantityButton\"\n type=\"button\"\n className={quantityButton.className}\n style={quantityButton.style}\n aria-label={decreaseText}\n onClick={() => commit(clampQuantity(sent.current - 1))}\n >\n <MinusIcon aria-hidden=\"true\" />\n </Button>\n <input\n data-bitsnap-checkout-slot=\"quantityInput\"\n className={cn(\"w-8 bg-transparent text-center\", quantityInput.className)}\n style={quantityInput.style}\n value={quantityString}\n aria-label={quantityText}\n inputMode=\"numeric\"\n pattern=\"[0-9]*\"\n onChange={(e) => setQuantityString(e.currentTarget.value)}\n onBlur={(e) => commit(quantityFromInput(e.currentTarget.value, sent.current))}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n commit(quantityFromInput(e.currentTarget.value, sent.current));\n }\n }}\n type=\"text\"\n />\n <Button\n data-bitsnap-checkout-slot=\"quantityButton\"\n type=\"button\"\n className={quantityButton.className}\n style={quantityButton.style}\n aria-label={increaseText}\n onClick={() => commit(clampQuantity(sent.current + 1))}\n >\n <PlusIcon aria-hidden=\"true\" />\n </Button>\n </ButtonGroup>\n </div>\n );\n};\n","import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/src/lib/utils\";\nimport { Separator } from \"@/src/ui/separator\";\n\nconst buttonGroupVariants = cva(\n \"flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2\",\n {\n variants: {\n orientation: {\n horizontal:\n \"[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none\",\n vertical:\n \"flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none\",\n },\n },\n defaultVariants: {\n orientation: \"horizontal\",\n },\n }\n);\n\nfunction ButtonGroup({\n className,\n orientation,\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof buttonGroupVariants>) {\n return (\n <div\n role=\"group\"\n data-slot=\"button-group\"\n data-orientation={orientation}\n className={cn(buttonGroupVariants({ orientation }), className)}\n {...props}\n />\n );\n}\n\nfunction ButtonGroupText({\n className,\n asChild = false,\n ...props\n}: React.ComponentProps<\"div\"> & {\n asChild?: boolean;\n}) {\n const Comp = asChild ? Slot : \"div\";\n\n return (\n <Comp\n className={cn(\n \"bg-muted flex items-center gap-2 rounded-md border px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction ButtonGroupSeparator({\n className,\n orientation = \"vertical\",\n ...props\n}: React.ComponentProps<typeof Separator>) {\n return (\n <Separator\n data-slot=\"button-group-separator\"\n orientation={orientation}\n className={cn(\n \"bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport {\n ButtonGroup,\n ButtonGroupSeparator,\n ButtonGroupText,\n buttonGroupVariants,\n};\n","import type { ProductPricing } from \"./product.details.model\";\nimport { formatCurrency } from \"./lib/round.number\";\nimport { useCheckoutText } from \"./texts.context\";\n\nexport function ProductPrice({\n price,\n currency,\n pricing,\n quantity = 1,\n}: {\n price: number;\n currency: string;\n pricing?: ProductPricing;\n quantity?: number;\n}) {\n const lowestPriceText = useCheckoutText(\"lowestPrice30Days\");\n const noPriceHistoryText = useCheckoutText(\"noPriceHistory\");\n const regular = pricing?.regularPrice ?? price;\n const effective = pricing?.effectivePrice ?? price;\n const onSale = pricing?.discount?.status === \"ACTIVE\" && effective < regular;\n\n return (\n <span>\n {onSale ? (\n <>\n <span className=\"mr-2 text-neutral-500 line-through\">\n {formatCurrency(regular * quantity, currency)}\n </span>\n <span className=\"font-semibold text-red-700\">\n {formatCurrency(effective * quantity, currency)}\n </span>\n <span className=\"mt-1 block text-xs text-neutral-600\">\n {pricing?.referencePrice.historyAvailable && pricing.referencePrice.amount != null\n ? `${lowestPriceText} ${formatCurrency(pricing.referencePrice.amount, currency)}`\n : noPriceHistoryText}\n </span>\n </>\n ) : (\n formatCurrency(effective * quantity, currency)\n )}\n </span>\n );\n}\n","export const MIN_QUANTITY = 1;\nexport const MAX_QUANTITY = 99;\n\n/** Keeps a quantity a whole number in 1..99. */\nexport function clampQuantity(value: number): number {\n if (!Number.isFinite(value)) {\n return MIN_QUANTITY;\n }\n return Math.min(MAX_QUANTITY, Math.max(MIN_QUANTITY, Math.trunc(value)));\n}\n\n/**\n * The quantity a typed value stands for. An empty or non-numeric value keeps\n * the `current` one; anything else is clamped to 1..99.\n */\nexport function quantityFromInput(raw: string, current: number): number {\n const parsed = parseInt(raw, 10);\n return Number.isNaN(parsed) ? current : clampQuantity(parsed);\n}\n","function Skeleton({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"skeleton\"\n className={\"bg-neutral-700 animate-pulse rounded-md\" + ' ' + className}\n {...props}\n />\n );\n}\n\nexport { Skeleton };\n","import ApplePayButtonModule from \"apple-pay-button\";\nimport { PublicApiClient } from \"src/public.api.client\";\nimport CartProvider, {\n getCheckoutSelection,\n getProjectID,\n useCartProvider,\n} from \"./CartProvider\";\nimport { HOST } from \"./constants\";\nimport { isErr } from \"./lib/err\";\nimport { currentProjectID } from \"./project-id\";\nimport { round } from \"./lib/round.number\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { sendAnalyticEvent } from \"./frontent.analytics\";\nimport { useCheckoutText } from \"./texts.context\";\nimport {\n InstrumentProvider,\n useInstrument,\n useInstrumentContext,\n type AnalyticsOption,\n} from \"@/src/analytics/instrument\";\n\n// A CommonJS package with a `default` export: bundlers unwrap it, Node's own\n// ESM loader (server rendering of the unbundled library) does not.\nconst ApplePayButton: typeof ApplePayButtonModule =\n (ApplePayButtonModule as unknown as { default?: typeof ApplePayButtonModule })\n .default ?? ApplePayButtonModule;\n\ntype AppleButtonType =\n | \"plain\"\n | \"add-money\"\n | \"book\"\n | \"buy\"\n | \"check-out\"\n | \"continue\"\n | \"contribute\"\n | \"donate\"\n | \"order\"\n | \"pay\"\n | \"reload\"\n | \"rent\"\n | \"set-up\"\n | \"subscribe\"\n | \"support\"\n | \"tip\"\n | \"top-up\";\ntype ColorType = \"black\" | \"white\" | \"white-outline\";\n\nexport type Props = {\n style?: {\n width?: string;\n height?: string;\n borderRadius?: string;\n padding?: string;\n boxSizing?: string;\n };\n buttonType?: AppleButtonType;\n colorType?: ColorType;\n items: {\n name: string;\n id: string;\n price: number;\n /** Currency of `price` (minor units); defaults to PLN. */\n currency?: string;\n quantity: number;\n isDeliverable?: boolean;\n metadata?: { [key: string]: string | undefined };\n }[];\n onClick?: () => Promise<void>;\n /**\n * Usage statistics for your Bitsnap dashboard (Apple Pay clicks and\n * results). On by default; `false` turns it off. Inside `<BitsnapCheckout>`\n * the checkout's setting applies unless this is given.\n */\n analytics?: AnalyticsOption;\n};\n\nfunction ApplePayButtonComponent({\n style,\n buttonType,\n colorType,\n items,\n onClick,\n}: Props) {\n const {\n checkIfApplePayIsAvailable,\n getApplePayPaymentRequest,\n completeApplePayPayment,\n setCountry,\n setCouponCodeIfPossible,\n setDeliveryMethod,\n setEmail,\n setPostalCode,\n clearCart,\n getApplePayPreview,\n } = useCartProvider();\n const instrument = useInstrumentContext();\n const paymentForCartText = useCheckoutText(\"paymentForCart\");\n const { data: isApplePayAvailable } = useQuery({\n queryKey: [\"is-apple-pay-available\"],\n queryFn: checkIfApplePayIsAvailable,\n });\n const itemsKey = items.map((el) => `${el.id}:${el.quantity}`).join(\",\");\n const selection = getCheckoutSelection();\n const { data: preview } = useQuery({\n queryKey: [\n \"apple-pay-preview\",\n itemsKey,\n selection.country ?? \"\",\n selection.couponCode ?? \"\",\n selection.selectedDeliveryMethod ?? \"\",\n selection.postalCode ?? \"\",\n ],\n queryFn: () =>\n getApplePayPreview({\n items: items.map((el) => ({\n productID: el.id,\n quantity: el.quantity,\n metadata: el.metadata,\n })),\n }),\n enabled: isApplePayAvailable === true,\n });\n if (isApplePayAvailable != true) {\n return null;\n }\n // The backend's answer when it is there; else the cart's own currency and\n // total, with no delivery in it (it is added once the buyer picks a method).\n const loadedPreview =\n preview != null && !isErr(preview)\n ? preview\n : {\n countryCode: selection.country || \"PL\",\n currencyCode: items[0]?.currency ?? \"PLN\",\n totalAmount: `${round(\n items.reduce((acc, item) => acc + item.price * item.quantity, 0) /\n 100,\n 2,\n )}`,\n };\n\n const expectedItems = items.map((el) => ({\n productID: el.id,\n quantity: el.quantity,\n metadata: el.metadata,\n }));\n\n async function beginSession() {\n let reported = false;\n const report = (outcome: \"success\" | \"fail\" | \"cancel\") => {\n if (reported) {\n return;\n }\n reported = true;\n instrument.track(\"apple_pay_result\", { outcome });\n };\n instrument.track(\"apple_pay_clicked\", {});\n instrument.track(\"payment_method_selected\", {\n gateway: \"apple_pay\",\n method: \"apple_pay\",\n });\n sendAnalyticEvent({\n event: \"initiateCheckout\",\n items: items.map((el) => ({\n id: el.id,\n name: el.name,\n price: el.price,\n quantity: el.quantity,\n currency: loadedPreview.currencyCode,\n })),\n });\n const requiresShipping =\n items.find((el) => el.isDeliverable === true) != null;\n // The session has to be created inside the click, so country, currency\n // and total come from the backend's answer that was loaded beforehand.\n const session = new ApplePaySession(14, {\n countryCode: loadedPreview.countryCode,\n merchantCapabilities: [\"supports3DS\"],\n supportedNetworks: [\"visa\", \"masterCard\"],\n currencyCode: loadedPreview.currencyCode,\n total: {\n amount: loadedPreview.totalAmount,\n label: paymentForCartText,\n type: \"pending\",\n },\n // Delivery is added once the buyer picks a contact and a method.\n lineItems: items.map(\n (item) =>\n ({\n amount: `${round((item.price * item.quantity) / 100, 2)}`,\n label: item.name,\n type: \"final\",\n } as ApplePayJS.ApplePayLineItem)\n ),\n ...(requiresShipping\n ? {\n shippingMethods: [],\n supportsCouponCode: true,\n requiredBillingContactFields: [\n \"name\",\n \"email\",\n \"postalAddress\",\n \"phone\",\n ],\n requiredShippingContactFields: [\n \"name\",\n \"email\",\n \"postalAddress\",\n \"phone\",\n ],\n }\n : {}),\n });\n await onClick?.();\n const apRequest = await getApplePayPaymentRequest({ expectedItems });\n if (isErr(apRequest)) {\n console.error(\"Error creating ApplePaySession:\", apRequest.error);\n report(\"fail\");\n return;\n }\n\n session.oncancel = (event) => {\n console.log(\"ApplePaySession cancelled\", event);\n report(\"cancel\");\n };\n\n session.onvalidatemerchant = async (event) => {\n try {\n const result = await PublicApiClient.get(HOST).applePayValidateMerchant(\n {\n validationUrl: event.validationURL,\n projectId: getProjectID(),\n }\n );\n console.log(\"merchantSession\", result.merchantSession);\n if (result.merchantSession.length > 0) {\n console.log(\"completing merchant session\");\n session.completeMerchantValidation(\n JSON.parse(result.merchantSession)\n );\n } else {\n session.abort();\n }\n } catch (error) {\n session.abort();\n }\n };\n\n session.onshippingmethodselected = async (event) => {\n console.log(\"shipping method selected\", event);\n instrument.track(\"delivery_method_selected\", {\n method: event.shippingMethod.identifier,\n });\n await setDeliveryMethod(event.shippingMethod.identifier);\n const apRequest = await getApplePayPaymentRequest({ expectedItems });\n console.log(\"apRequest\", apRequest);\n if (isErr(apRequest)) {\n session.abort();\n throw new Error(\"Failed to get Apple Pay payment request\");\n }\n\n session.completeShippingMethodSelection({\n newTotal: apRequest.total,\n newLineItems: apRequest.lineItems,\n newShippingMethods: apRequest.shippingMethods,\n });\n };\n session.onshippingcontactselected = async (event) => {\n try {\n if (event.shippingContact.countryCode != null) {\n await setCountry(event.shippingContact.countryCode);\n }\n if (event.shippingContact.postalCode != null) {\n await setPostalCode(event.shippingContact.postalCode);\n }\n if (event.shippingContact.phoneNumber != null) {\n await setEmail(event.shippingContact.emailAddress);\n }\n const apRequest = await getApplePayPaymentRequest({ expectedItems });\n if (isErr(apRequest)) {\n session.abort();\n throw new Error(\"Failed to get Apple Pay payment request\");\n }\n\n console.log(\"apRequest\", apRequest);\n session.completeShippingContactSelection({\n newLineItems: apRequest.lineItems,\n newTotal: apRequest.total,\n newShippingMethods: apRequest.shippingMethods,\n });\n } catch (error) {\n console.log(\"shipping contact selected error\", error);\n session.abort();\n }\n };\n\n session.oncouponcodechanged = async (event) => {\n try {\n console.log(\"coupon code changed\", event);\n const result = await setCouponCodeIfPossible(event.couponCode);\n const apRequest = await getApplePayPaymentRequest({ expectedItems });\n console.log(\"apRequest\", apRequest);\n if (isErr(apRequest)) {\n session.abort();\n throw new Error(\"Failed to get Apple Pay payment request\");\n }\n\n session.completeCouponCodeChange({\n errors: isErr(result)\n ? [new ApplePayError(\"couponCodeInvalid\")]\n : undefined,\n newTotal: apRequest.total,\n newLineItems: apRequest.lineItems,\n newShippingMethods: apRequest.shippingMethods,\n });\n } catch (error) {\n console.log(\"coupon code changed error\", error);\n session.abort();\n }\n };\n\n session.onpaymentauthorized = async (event) => {\n instrument.track(\"payment_submitted\", {\n gateway: \"apple_pay\",\n method: \"apple_pay\",\n });\n try {\n const result = await completeApplePayPayment({\n token: event.payment.token,\n billingContact: event.payment.billingContact,\n shippingContact: event.payment.shippingContact,\n });\n if (isErr(result)) {\n console.log(\"apple pay error\", result);\n report(\"fail\");\n session.completePayment({\n status: ApplePaySession.STATUS_FAILURE,\n });\n return;\n }\n\n if (result.redirectURL) {\n setTimeout(() => {\n open(result.redirectURL, \"_self\");\n }, 2000);\n }\n report(result.isSuccess ? \"success\" : \"fail\");\n session.completePayment({\n status: result.isSuccess\n ? ApplePaySession.STATUS_SUCCESS\n : ApplePaySession.STATUS_FAILURE,\n });\n\n result.isSuccess && clearCart();\n } catch (e) {\n report(\"fail\");\n session.completePayment({\n status: ApplePaySession.STATUS_FAILURE,\n });\n }\n // event.complete(ApplePaySession.STATUS_SUCCESS);\n };\n\n session.begin();\n }\n\n return (\n <ApplePayButton\n style={style}\n buttonStyle={colorType}\n type={buttonType}\n onClick={beginSession}\n />\n );\n}\n\nfunction Wrapper(props: Props) {\n const instrument = useInstrument(\n currentProjectID(),\n props.analytics,\n \"cart\",\n );\n return (\n <InstrumentProvider value={instrument}>\n <CartProvider>\n <ApplePayButtonComponent {...props} />\n </CartProvider>\n </InstrumentProvider>\n );\n}\nexport default Wrapper;\n","import { getProjectID } from \"./CartProvider\";\n\n/** The page's project ID; `undefined` (instead of a throw) during server rendering. */\nexport function currentProjectID(): string | undefined {\n try {\n return getProjectID();\n } catch {\n return undefined;\n }\n}\n","import GooglePayButton from \"@google-pay/button-react\";\nimport CartProvider, { useCartProvider } from \"./CartProvider\";\nimport { isErr } from \"./lib/err\";\nimport { currentProjectID } from \"./project-id\";\nimport { Spinner } from \"@/src/ui/spinner\";\nimport { useQuery, useMutation } from \"@tanstack/react-query\";\nimport { sendAnalyticEvent } from \"./frontent.analytics\";\nimport {\n InstrumentProvider,\n useInstrument,\n useInstrumentContext,\n type AnalyticsOption,\n} from \"@/src/analytics/instrument\";\n\nexport type Props = {\n test?: boolean;\n buttonSizeMode?: \"static\" | \"fill\";\n buttonColor?: \"white\" | \"black\";\n style?: {\n width?: string;\n };\n items: {\n name: string;\n id: string;\n price: number;\n quantity: number;\n isDeliverable?: boolean;\n metadata?: { [key: string]: string | undefined };\n }[];\n /**\n * Usage statistics for your Bitsnap dashboard. On by default; `false` turns\n * it off. Inside `<BitsnapCheckout>` the checkout's setting applies unless\n * this is given.\n */\n analytics?: AnalyticsOption;\n};\n\nfunction GooglePayButtonComponent({\n items,\n style,\n buttonColor,\n buttonSizeMode,\n test,\n}: Props) {\n const {\n getGooglePayConfiguration,\n completeGooglePayPayment,\n setCountry,\n setCouponCodeIfPossible,\n setDeliveryMethod,\n setEmail,\n setPostalCode,\n clearCart,\n } = useCartProvider();\n\n const instrument = useInstrumentContext();\n const { data: googlePayConfiguration } = useQuery({\n queryKey: [\n \"get-google-pay-configuration\",\n items.map((el) => el.id).join(\",\"),\n ],\n queryFn: () =>\n getGooglePayConfiguration({\n items: items.map((el) => ({\n ...el,\n id: undefined,\n productID: el.id,\n })),\n }),\n });\n\n const { mutateAsync: completeGooglePayPaymentAsync, isPending } = useMutation(\n {\n mutationFn: completeGooglePayPayment,\n }\n );\n if (\n googlePayConfiguration == null ||\n googlePayConfiguration.isAvailable != true\n ) {\n console.log(\n \"google pay configuration is not available\",\n googlePayConfiguration\n );\n return null;\n }\n\n return (\n <>\n <GooglePayButton\n buttonSizeMode={buttonSizeMode}\n buttonColor={buttonColor}\n style={style}\n existingPaymentMethodRequired={true}\n onClick={() =>\n instrument.track(\"payment_method_selected\", {\n gateway: \"google_pay\",\n method: \"google_pay\",\n })\n }\n environment={test === true ? \"TEST\" : \"PRODUCTION\"}\n onPaymentDataChanged={async (paymentData) => {\n sendAnalyticEvent({\n event: \"initiateCheckout\",\n items: items.map((el) => ({\n id: el.id,\n name: el.name,\n price: el.price,\n quantity: el.quantity,\n currency: \"PLN\",\n })),\n });\n console.log(\"payment data changed\", paymentData);\n if (paymentData.shippingAddress?.postalCode != null) {\n await setPostalCode(paymentData.shippingAddress?.postalCode);\n }\n if (paymentData.shippingAddress?.countryCode != null) {\n await setCountry(paymentData.shippingAddress?.countryCode);\n }\n if (paymentData.shippingOptionData?.id != null) {\n await setDeliveryMethod(paymentData.shippingOptionData.id);\n }\n\n const config = await getGooglePayConfiguration({ items: [] });\n console.log(\"PAYMENT DATA CHANGED CONFIG\", config);\n if (config.isAvailable) {\n return {\n error: undefined,\n newShippingOptionParameters:\n config.config.shippingOptionParameters,\n newTransactionInfo: config.config.transactionInfo,\n };\n }\n\n return {\n error: undefined,\n };\n }}\n paymentRequest={googlePayConfiguration.config}\n onLoadPaymentData={async (paymentRequest) => {\n instrument.track(\"payment_submitted\", {\n gateway: \"google_pay\",\n method: \"google_pay\",\n });\n try {\n const result = await completeGooglePayPaymentAsync({\n paymentData: paymentRequest,\n });\n if (isErr(result)) {\n console.log(\"apple pay error\", result);\n return;\n }\n\n result.isSuccess && clearCart();\n if (result.redirectURL) {\n open(result.redirectURL, \"_self\");\n }\n } catch (e) {\n console.warn(\"error completing google pay payment\", e);\n }\n }}\n />\n {isPending ? <Spinner /> : null}\n </>\n );\n}\n\nfunction Wrapper(props: Props) {\n const instrument = useInstrument(\n currentProjectID(),\n props.analytics,\n \"cart\",\n );\n return (\n <InstrumentProvider value={instrument}>\n <CartProvider>\n <GooglePayButtonComponent {...props} />\n </CartProvider>\n </InstrumentProvider>\n );\n}\n\nexport default Wrapper;\n","import {\n createElement,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n} from \"react\";\nimport {\n InstrumentProvider,\n useInstrument,\n useInstrumentContext,\n type AnalyticsOption,\n} from \"@/src/analytics/instrument\";\nimport type { CheckoutAppearance } from \"@/src/components/checkout/appearance\";\nimport {\n CheckoutAppearanceProvider,\n} from \"@/src/components/checkout/appearance.context\";\nimport { Bitsnap } from \"@/src/components/checkout/methods\";\nimport {\n readLocalCartLines,\n setProjectID,\n} from \"@/src/components/checkout/CartProvider\";\nimport { getLocale } from \"@/src/components/checkout/locale\";\nimport { currentProjectID } from \"@/src/components/checkout/project-id\";\nimport type { CheckoutTexts } from \"@/src/components/checkout/texts\";\nimport { CheckoutTextsProvider } from \"@/src/components/checkout/texts.context\";\nimport { createExpressSession, getInpostStatus, startProviderForCart } from \"@/src/express/cart-adapter\";\nimport type { CartSnapshot, ProviderStart } from \"@/src/express/contracts\";\nimport type { FetchLike } from \"@/src/express/client\";\nimport {\n initInpostWidget,\n inpostIziButtonAttributes,\n inpostLanguage,\n loadInpostWidget,\n readInpostPublicConfig,\n INPOST_IZI_BUTTON_TAG,\n INPOST_THANK_YOU_TAG,\n type InPostBindingPlace,\n type InPostPayWidgetInstance,\n type InPostWidgetBasketEvent,\n} from \"@/src/express/inpost-widget\";\nimport {\n expressCartLocal,\n expressCartSignature,\n resolveExpressCart,\n resolveExpressHost,\n useExpressAvailability,\n useLocalCartVersion,\n type ExpressItem,\n} from \"@/src/express/react\";\nimport { pollProviderStatus } from \"@/src/express/revolut\";\nimport { ExpressStatus, type ExpressPhase } from \"./ExpressStatus\";\n\n/**\n * InPost Pay on a product page or in a cart.\n *\n * The button is the official InPost Pay widget: this component renders its\n * documented `<inpost-izi-button>` element, loads the widget lazily in the\n * browser and gives it the documented callbacks. The basket itself is durable\n * on Bitsnap: the first click uploads the cart, binds it through the InPost\n * merchant API (server side) and returns only the basket key the widget needs.\n *\n * Nothing renders unless the backend says the provider is available with a\n * public `merchantClientId`; a 501, an old backend or a missing credential\n * shows no button at all.\n */\n\nexport type InPostPayButtonProps = {\n /**\n * The Bitsnap project of the cart. Optional when the page already called\n * `setProjectID(projectID)`; given here it is configured for the page.\n */\n projectID?: string;\n /** Bitsnap host; defaults to the configured one. */\n host?: string;\n locale?: string;\n /** Text overrides, as on `BitsnapCheckout`. */\n texts?: Partial<CheckoutTexts>;\n /** Checkout appearance tokens and slots for the status line. */\n appearance?: CheckoutAppearance;\n /**\n * Explicit cart lines (a custom cart layout that is not the Bitsnap drawer).\n * The SDK uploads and prices them; it never edits the merchant's own state.\n * Omitted: the Bitsnap cart is the basket.\n */\n items?: ExpressItem[];\n /** Product to add to the basket on click (product page placement). */\n productId?: string;\n /** Quantity of `productId`; default 1. */\n quantity?: number;\n /** Official widget placement; defaults to PRODUCT_CARD with `productId`, else BASKET_SUMMARY. */\n bindingPlace?: InPostBindingPlace;\n /** Official widget `variation` attribute (visual variant). */\n variation?: string;\n className?: string;\n style?: CSSProperties;\n /** Analytics of the buttons; on by default, `false` opts out. */\n analytics?: AnalyticsOption;\n /**\n * Called after the browser's `orderCreated` event when the server status has\n * been checked. The event is only a hint: `status` is `completed` only when\n * the signed server-side order state confirms it.\n */\n onOrderCreated?: (info: {\n providerOrderId?: string;\n status?: \"pending\" | \"completed\" | \"cancelled\" | \"failed\";\n }) => void;\n /** After InPost changed the basket in its app; the canonical snapshot. */\n onBasketChanged?: (snapshot: CartSnapshot) => void;\n /** Test/custom fetch (for example a mocked storefront). */\n fetch?: FetchLike;\n /** Bounds for the server confirmation (tests use a fake sleep). */\n confirmation?: {\n timeoutMs?: number;\n intervalMs?: number;\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n };\n};\n\ntype ProductUnavailable = { undeliverable: true };\n\nfunction isProductUnavailable(error: unknown): error is ProductUnavailable {\n return (\n typeof error === \"object\" &&\n error != null &&\n (error as ProductUnavailable).undeliverable === true\n );\n}\n\nfunction InPostPayButtonInner(props: InPostPayButtonProps & { projectID: string }) {\n const { projectID } = props;\n const host = resolveExpressHost(props.host);\n const locale = props.locale ?? getLocale();\n const instrument = useInstrumentContext();\n const confirmationTimeoutMs = props.confirmation?.timeoutMs;\n const confirmationIntervalMs = props.confirmation?.intervalMs;\n const confirmationSleep = props.confirmation?.sleep;\n const confirmationNow = props.confirmation?.now;\n const cartVersion = useLocalCartVersion();\n const cart = useMemo(\n () =>\n resolveExpressCart({\n ...(props.items != null ? { items: props.items } : {}),\n ...(props.productId != null ? { productId: props.productId } : {}),\n ...(props.quantity != null ? { quantity: props.quantity } : {}),\n }),\n [props.items, props.productId, props.quantity, cartVersion],\n );\n const signature = expressCartSignature(cart);\n const availability = useExpressAvailability({\n provider: \"inpostPay\",\n projectID,\n host,\n locale,\n ...(props.items != null ? { items: props.items } : {}),\n ...(props.productId != null ? { productId: props.productId } : {}),\n ...(props.quantity != null ? { quantity: props.quantity } : {}),\n ...(props.fetch != null ? { fetch: props.fetch } : {}),\n });\n const provider = availability.provider;\n const environment = provider?.environment ?? availability.environment;\n const config =\n provider?.available === true\n ? readInpostPublicConfig(provider.publicConfig, environment)\n : undefined;\n const merchantClientId = config?.merchantClientId;\n const apiBaseUrl = config?.apiBaseUrl;\n\n const session = useMemo(\n () =>\n createExpressSession({\n projectID,\n host,\n ...(cart.source === \"items\"\n ? { local: expressCartLocal(cart, locale, { host, projectID }) }\n : {}),\n ...(props.fetch != null ? { fetch: props.fetch } : {}),\n }),\n [projectID, host, props.fetch, cart, locale],\n );\n\n const [phase, setPhase] = useState<ExpressPhase>(\"idle\");\n const widgetRef = useRef<InPostPayWidgetInstance | undefined>(undefined);\n const pendingStart = useRef<Promise<ProviderStart> | undefined>(undefined);\n const mounted = useRef(true);\n const confirmingOrder = useRef(false);\n const reportedOrder = useRef(false);\n\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n\n // The widget keeps its options for the page's lifetime: callbacks read the\n // latest props and cart through a ref instead of a stale closure.\n const latest = useRef({\n cart,\n locale,\n environment,\n session,\n onOrderCreated: props.onOrderCreated,\n onBasketChanged: props.onBasketChanged,\n });\n latest.current = {\n cart,\n locale,\n environment,\n session,\n onOrderCreated: props.onOrderCreated,\n onBasketChanged: props.onBasketChanged,\n };\n\n const startBinding = useCallback(async (): Promise<ProviderStart> => {\n if (pendingStart.current != null) {\n return pendingStart.current;\n }\n const start = startProviderForCart(\n {\n projectID,\n host,\n locale: latest.current.locale,\n ...(latest.current.environment != null\n ? { environment: latest.current.environment }\n : {}),\n ...(typeof window !== \"undefined\"\n ? {\n returnUrl: window.location.href,\n cancelUrl: window.location.href,\n embedOrigin: window.location.origin,\n }\n : {}),\n ...(props.fetch != null ? { fetch: props.fetch } : {}),\n },\n \"inpostPay\",\n latest.current.session,\n )\n .then((result) => {\n if (!result.ok) {\n setPhase(\n result.code === \"revision-conflict\"\n ? \"cart-conflict\"\n : \"cart-unavailable\",\n );\n throw new Error(`inpost-start-${result.code}`);\n }\n instrument.track(\"payment_submitted\", {\n gateway: \"inpost_pay\",\n method: \"inpost_pay\",\n });\n return result.value.start;\n })\n .finally(() => {\n pendingStart.current = undefined;\n });\n pendingStart.current = start;\n return start;\n }, [projectID, host, instrument, props.fetch]);\n\n /** Adds the product to the SDK basket once; a failure is \"undeliverable\". */\n const ensureProduct = useCallback(async (productId: string) => {\n const present = readLocalCartLines().some(\n (line) => line.productID === productId,\n );\n if (present) {\n return;\n }\n if (latest.current.cart.source === \"items\") {\n return;\n }\n const error = await Bitsnap.addProductToCart(\n productId,\n latest.current.cart.productQuantity,\n );\n if (error != null) {\n throw { undeliverable: true } satisfies ProductUnavailable;\n }\n }, []);\n\n const unboundWidgetClicked = useCallback(\n async (productId?: string): Promise<string> => {\n instrument.track(\"payment_method_selected\", {\n gateway: \"inpost_pay\",\n method: \"inpost_pay\",\n });\n try {\n if (productId != null) {\n await ensureProduct(productId);\n }\n const start = await startBinding();\n const basketBindingApiKey = start.publicConfig?.basketBindingApiKey;\n if (basketBindingApiKey == null || basketBindingApiKey.length === 0) {\n throw new Error(\"inpost-start-without-basket-key\");\n }\n latest.current.session.storeInpostBindingApiKey(basketBindingApiKey);\n setPhase(\"idle\");\n return basketBindingApiKey;\n } catch (error) {\n if (isProductUnavailable(error)) {\n setPhase(\"product-unavailable\");\n // The widget's documented sentinel: no error popup for this product.\n throw new Error(\"UNDELIVERABLE_PRODUCT\");\n }\n setPhase(\n error instanceof Error &&\n error.message === \"inpost-start-revision-conflict\"\n ? \"cart-conflict\"\n : \"cart-unavailable\",\n );\n throw error instanceof Error ? error : new Error(\"inpost-pay-failed\");\n }\n },\n [ensureProduct, instrument, startBinding],\n );\n\n const addToBasketClicked = useCallback(\n async (productId?: string): Promise<void> => {\n const id = productId ?? latest.current.cart.productId;\n if (id == null) {\n return;\n }\n try {\n const error = await Bitsnap.addProductToCart(\n id,\n latest.current.cart.productQuantity,\n );\n if (error != null) {\n throw { undeliverable: true } satisfies ProductUnavailable;\n }\n // The durable cart is updated now; the bound InPost basket follows\n // through the server-side outbox, never from the browser.\n await latest.current.session.ensure({\n locale: latest.current.locale,\n ...(latest.current.environment != null\n ? { environment: latest.current.environment }\n : {}),\n });\n } catch (error) {\n setPhase(\"product-unavailable\");\n if (isProductUnavailable(error)) {\n throw new Error(\"UNDELIVERABLE_PRODUCT\");\n }\n throw error instanceof Error ? error : new Error(\"inpost-pay-failed\");\n }\n },\n [],\n );\n\n /**\n * `orderCreated` is only a hint. The cart is cleared only after the server\n * status (signed InPost order events) says the order is paid. A pending or\n * unconfirmed answer keeps the cart and the attempt for the next visit; a\n * failed check keeps everything as it was.\n */\n const confirmInpostOrder = useCallback(async () => {\n if (confirmingOrder.current) {\n return;\n }\n confirmingOrder.current = true;\n try {\n const active = latest.current.session;\n const pending = active.getPendingAttempt();\n if (pending?.provider !== \"inpostPay\") {\n return;\n }\n if (mounted.current) {\n setPhase(\"pending\");\n }\n const status = await pollProviderStatus({\n check: () =>\n getInpostStatus(\n {\n projectID,\n host,\n ...(props.fetch != null ? { fetch: props.fetch } : {}),\n },\n active,\n ),\n timeoutMs: confirmationTimeoutMs ?? 20_000,\n intervalMs: confirmationIntervalMs ?? 1_500,\n ...(confirmationSleep != null ? { sleep: confirmationSleep } : {}),\n ...(confirmationNow != null ? { now: confirmationNow } : {}),\n });\n if (!mounted.current) {\n return;\n }\n const providerOrderId = pending.providerOrderId;\n if (status?.ok === true && status.status === \"completed\") {\n const snapshot = await active.reconcileFromServer();\n const lines = snapshot.ok\n ? snapshot.value.lines.map((line) => ({\n id: line.productId,\n quantity: line.quantity,\n }))\n : pending.lines;\n if (lines.length > 0) {\n active.completePurchase(lines);\n }\n setPhase(\"confirmed\");\n instrument.track(\"payment_returned\", {\n gateway: \"inpost_pay\",\n method: \"inpost_pay\",\n outcome: \"pending\",\n });\n if (!reportedOrder.current) {\n reportedOrder.current = true;\n latest.current.onOrderCreated?.({\n ...(providerOrderId != null ? { providerOrderId } : {}),\n status: \"completed\",\n });\n }\n return;\n }\n if (status?.ok === true && status.status === \"failed\") {\n active.clearPending();\n setPhase(\"failed\");\n if (!reportedOrder.current) {\n reportedOrder.current = true;\n latest.current.onOrderCreated?.({\n ...(providerOrderId != null ? { providerOrderId } : {}),\n status: \"failed\",\n });\n }\n return;\n }\n if (status?.ok === true && status.status === \"cancelled\") {\n active.clearPending();\n setPhase(\"cancelled\");\n if (!reportedOrder.current) {\n reportedOrder.current = true;\n latest.current.onOrderCreated?.({\n ...(providerOrderId != null ? { providerOrderId } : {}),\n status: \"cancelled\",\n });\n }\n return;\n }\n // Still pending, an old backend without the status route, or a failed\n // check: never claim a payment, never clear the cart. The attempt stays\n // stored so a later mount can ask again.\n setPhase(\"pending\");\n if (!reportedOrder.current) {\n reportedOrder.current = true;\n latest.current.onOrderCreated?.({\n ...(providerOrderId != null ? { providerOrderId } : {}),\n status: \"pending\",\n });\n }\n } finally {\n confirmingOrder.current = false;\n }\n }, [\n confirmationIntervalMs,\n confirmationNow,\n confirmationSleep,\n confirmationTimeoutMs,\n host,\n instrument,\n projectID,\n props.fetch,\n ]);\n\n const handleBasketEvent = useCallback(\n async (event: InPostWidgetBasketEvent): Promise<boolean> => {\n if (event === \"basketProductChanged\") {\n // InPost is authoritative for what changed in its app: adopt the\n // canonical snapshot so the page shows the same basket.\n const result = await latest.current.session.reconcileFromServer();\n if (result.ok) {\n latest.current.onBasketChanged?.(result.value);\n }\n return true;\n }\n if (event === \"orderCreated\") {\n // Hint only: ask the server in the background, but keep the widget's\n // callback synchronous enough not to block its own UI.\n void confirmInpostOrder();\n return true;\n }\n // `basketDeleted`: the buyer unbound the basket in the app. The cart\n // stays; a later click binds it again.\n return true;\n },\n [confirmInpostOrder],\n );\n\n // Recover a payment attempt left pending by a reload, a closed tab or a\n // missed browser event: ask the server once per mount. Nothing is cleared\n // unless the server reports `completed`.\n useEffect(() => {\n if (provider?.available !== true) {\n return;\n }\n if (session.getPendingAttempt()?.provider !== \"inpostPay\") {\n return;\n }\n void confirmInpostOrder();\n }, [provider?.available, session, confirmInpostOrder]);\n\n useEffect(() => {\n if (\n provider?.available !== true ||\n merchantClientId == null ||\n merchantClientId.length === 0 ||\n typeof window === \"undefined\"\n ) {\n return;\n }\n let cancelled = false;\n loadInpostWidget()\n .then((namespace) => {\n if (cancelled) {\n return;\n }\n const widget = initInpostWidget({\n namespace,\n owner: { projectID, host, merchantClientId },\n options: {\n merchantClientId,\n basketBindingApiKey: session.getInpostBindingApiKey(),\n unboundWidgetClicked,\n ...(cart.source === \"product\" || props.productId != null\n ? { addToBasketClicked }\n : {}),\n handleBasketEvent,\n ...(apiBaseUrl != null ? { apiBaseUrl } : {}),\n language: inpostLanguage(locale),\n },\n });\n if (widget == null) {\n setPhase(\"cart-unavailable\");\n return;\n }\n widgetRef.current = widget;\n // A remount reuses the page-wide widget; re-render the new element.\n widget.rerender();\n })\n .catch(() => {\n if (!cancelled) {\n setPhase(\"load-failed\");\n }\n });\n return () => {\n cancelled = true;\n widgetRef.current = undefined;\n };\n }, [\n provider?.available,\n merchantClientId,\n apiBaseUrl,\n locale,\n projectID,\n host,\n session,\n unboundWidgetClicked,\n addToBasketClicked,\n handleBasketEvent,\n cart.source,\n props.productId,\n ]);\n\n // Keep the widget's basket count in step with the cart after edits.\n useEffect(() => {\n widgetRef.current?.refresh({\n basketBindingApiKey: session.getInpostBindingApiKey(),\n });\n }, [signature, session]);\n\n if (\n provider?.available !== true ||\n merchantClientId == null ||\n merchantClientId.length === 0\n ) {\n return <ExpressStatus phase={phase === \"idle\" ? \"idle\" : phase} />;\n }\n\n const bindingPlace: InPostBindingPlace =\n props.bindingPlace ??\n (props.productId != null ? \"PRODUCT_CARD\" : \"BASKET_SUMMARY\");\n\n return (\n <div\n data-bitsnap-express=\"inpostPay\"\n aria-busy={phase === \"pending\" ? true : undefined}\n className={props.className}\n style={props.style}\n >\n {bindingPlace === \"THANK_YOU_PAGE\"\n ? createElement(INPOST_THANK_YOU_TAG, {\n ...(props.variation != null ? { variation: props.variation } : {}),\n })\n : createElement(\n INPOST_IZI_BUTTON_TAG,\n inpostIziButtonAttributes({\n bindingPlace,\n ...(props.productId != null ? { productId: props.productId } : {}),\n ...(props.variation != null ? { variation: props.variation } : {}),\n }),\n )}\n <ExpressStatus phase={phase} />\n </div>\n );\n}\n\n/**\n * Standalone InPost Pay button for a product or cart page. Inside\n * `<BitsnapCheckout>` the checkout renders this component itself.\n */\nexport function InPostPayButton(props: InPostPayButtonProps) {\n const projectID = props.projectID ?? currentProjectID();\n const instrument = useInstrument(projectID, props.analytics, \"cart\");\n\n useEffect(() => {\n if (props.projectID != null) {\n setProjectID(props.projectID);\n }\n }, [props.projectID]);\n\n return (\n <InstrumentProvider value={instrument}>\n <CheckoutTextsProvider locale={props.locale} texts={props.texts}>\n <CheckoutAppearanceProvider appearance={props.appearance}>\n {projectID == null ? null : (\n <InPostPayButtonInner {...props} projectID={projectID} />\n )}\n </CheckoutAppearanceProvider>\n </CheckoutTextsProvider>\n </InstrumentProvider>\n );\n}\n\nexport default InPostPayButton;\n\n/** The checkout's own express area uses this variant without wrapping providers. */\nexport { InPostPayButtonInner };\n","import { clientHeaders } from \"@/src/lib/client-header\";\nimport type {\n CartLineConflict,\n CartSnapshot,\n CartWriteFailureCode,\n CartWriteResult,\n ExpressAvailability,\n ExpressCartUpload,\n ExpressPayStatus,\n ExpressProviderName,\n ExpressResult,\n ProviderStart,\n RevolutPayStatus,\n StartFailure,\n StartFailureCode,\n} from \"./contracts\";\n\n/**\n * HTTP client of the cart-aware express API. Every function resolves, never\n * throws: an old backend (404 HTML), a provider that is not implemented (501)\n * or a network error is a typed failure the UI can hide a button for.\n */\n\nexport const CART_TOKEN_HEADER = \"x-bitsnap-cart-token\";\n\nexport type FetchLike = (\n input: string,\n init?: RequestInit,\n) => Promise<Response>;\n\nexport type ExpressClientOptions = {\n projectID: string;\n /** Defaults to the configured Bitsnap host. */\n host: string;\n fetch?: FetchLike;\n signal?: AbortSignal;\n};\n\nconst warned = new Set<string>();\n\nfunction warnOnce(key: string, message: string, detail: unknown) {\n if (warned.has(key)) {\n return;\n }\n warned.add(key);\n console.warn(message, detail);\n}\n\n/** Test seam: forget which warnings were already printed. */\nexport function resetExpressClientWarnings() {\n warned.clear();\n}\n\nexport function expressApiUrl(\n host: string,\n projectID: string,\n path: string,\n): string {\n const base = host.replace(/\\/+$/, \"\");\n return `${base}/api/integrations/${encodeURIComponent(projectID)}/public-commerce/express${path}`;\n}\n\ntype RawResponse = { status: number; json: unknown; text: string };\n\nasync function request(\n options: ExpressClientOptions,\n path: string,\n body: unknown,\n cartToken?: string,\n): Promise<RawResponse | { transportError: unknown }> {\n const fetchImpl: FetchLike =\n options.fetch ??\n ((input, init) => globalThis.fetch(input, init) as Promise<Response>);\n try {\n const response = await fetchImpl(\n expressApiUrl(options.host, options.projectID, path),\n {\n method: \"POST\",\n headers: {\n ...clientHeaders,\n \"Content-Type\": \"application/json\",\n ...(cartToken != null ? { [CART_TOKEN_HEADER]: cartToken } : {}),\n },\n body: JSON.stringify(body),\n cache: \"no-store\",\n signal: options.signal,\n },\n );\n const text = await response.text().catch(() => \"\");\n let json: unknown;\n try {\n json = text.length > 0 ? JSON.parse(text) : undefined;\n } catch {\n json = undefined;\n }\n return { status: response.status, json, text };\n } catch (error) {\n return { transportError: error };\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value != null && !Array.isArray(value);\n}\n\nfunction networkFailure<T>(error: unknown): ExpressResult<T> {\n if (isAbortError(error)) {\n return { ok: false, code: \"network\", message: \"aborted\" };\n }\n return { ok: false, code: \"network\", message: \"The server could not be reached.\" };\n}\n\nfunction isAbortError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error != null &&\n (error as { name?: unknown }).name === \"AbortError\"\n );\n}\n\n/** 404/HTML of an older backend and 5xx are \"not implemented here\". */\nfunction isUnsupportedStatus(status: number): boolean {\n return status === 404 || status === 405 || status === 501 || status === 502;\n}\n\nfunction mapFailureCode(value: unknown, fallback: string): string {\n return typeof value === \"string\" && value.length > 0 ? value : fallback;\n}\n\n/**\n * Cart-aware provider availability. `undefined` when the backend does not\n * implement the express API (old server) or the answer is unusable: callers\n * then render no express button at all.\n */\nexport async function fetchExpressAvailability(\n options: ExpressClientOptions,\n cart: ExpressCartUpload,\n): Promise<ExpressAvailability | undefined> {\n const raw = await request(options, \"/availability\", cart);\n if (\"transportError\" in raw) {\n warnOnce(\n `availability:${options.host}:${options.projectID}`,\n \"Bitsnap express availability is not reachable; express buttons stay hidden.\",\n raw.transportError,\n );\n return undefined;\n }\n if (isUnsupportedStatus(raw.status) || raw.status !== 200) {\n warnOnce(\n `availability-status:${options.host}:${options.projectID}`,\n \"Bitsnap express availability is not available on this backend; express buttons stay hidden.\",\n raw.status,\n );\n return undefined;\n }\n const body = raw.json;\n if (\n !isRecord(body) ||\n body.success !== true ||\n !isRecord(body.providers)\n ) {\n warnOnce(\n `availability-shape:${options.host}:${options.projectID}`,\n \"Bitsnap express availability returned an unknown shape; express buttons stay hidden.\",\n undefined,\n );\n return undefined;\n }\n return body as unknown as ExpressAvailability;\n}\n\n/**\n * Creates or replaces the durable cart. `cartId`/`cartToken`/`expectedRevision`\n * are present on an update only; omitting them creates a cart.\n */\nexport async function writeExpressCart(\n options: ExpressClientOptions,\n cart: ExpressCartUpload,\n current?: { cartId: string; cartToken: string; expectedRevision: number },\n): Promise<CartWriteResult> {\n const raw = await request(\n options,\n \"/cart\",\n {\n ...cart,\n ...(current != null\n ? { cartId: current.cartId, expectedRevision: current.expectedRevision }\n : {}),\n },\n current?.cartToken,\n );\n if (\"transportError\" in raw) {\n return { ok: false, code: \"internal\", message: \"The cart could not be saved.\" };\n }\n const body = raw.json;\n if (!isRecord(body) || typeof body.success !== \"boolean\") {\n return {\n ok: false,\n code: raw.status === 403 ? \"cart-forbidden\" : \"internal\",\n message: \"The cart endpoint returned an unknown answer.\",\n };\n }\n if (body.success === true) {\n const snapshot = body.snapshot as CartSnapshot | undefined;\n if (snapshot == null || typeof snapshot.revision !== \"number\") {\n return {\n ok: false,\n code: \"internal\",\n message: \"The cart endpoint returned no snapshot.\",\n };\n }\n return {\n ok: true,\n ...(typeof body.cartToken === \"string\" ? { cartToken: body.cartToken } : {}),\n snapshot,\n };\n }\n return {\n ok: false,\n code: mapFailureCode(body.code, \"internal\") as CartWriteFailureCode,\n message:\n typeof body.message === \"string\"\n ? body.message\n : \"The cart could not be saved.\",\n ...(typeof body.currentRevision === \"number\"\n ? { currentRevision: body.currentRevision }\n : {}),\n ...(isRecord(body.snapshot) ? { snapshot: body.snapshot as CartSnapshot } : {}),\n ...(Array.isArray(body.conflicts)\n ? { conflicts: body.conflicts as CartLineConflict[] }\n : {}),\n };\n}\n\nfunction mapCartFailure(body: Record<string, unknown>) {\n const code = mapFailureCode(body.code, \"internal\");\n return { code, message: mapFailureCode(body.message, code) };\n}\n\n/** Reads the canonical snapshot of a token holder. */\nexport async function readExpressCart(\n options: ExpressClientOptions,\n cartId: string,\n cartToken: string,\n): Promise<ExpressResult<CartSnapshot>> {\n const raw = await request(options, \"/cart-snapshot\", { cartId }, cartToken);\n if (\"transportError\" in raw) {\n return networkFailure(raw.transportError);\n }\n const body = raw.json;\n if (raw.status === 404) {\n return { ok: false, code: \"cart-not-found\", message: \"cart-not-found\", status: 404 };\n }\n if (raw.status === 403) {\n return { ok: false, code: \"cart-forbidden\", message: \"cart-forbidden\", status: 403 };\n }\n if (!isRecord(body) || body.success !== true || !isRecord(body.snapshot)) {\n return {\n ok: false,\n code: isUnsupportedStatus(raw.status) ? \"not-implemented\" : \"invalid-response\",\n message: \"The cart snapshot is not available.\",\n status: raw.status,\n };\n }\n return { ok: true, value: body.snapshot as unknown as CartSnapshot };\n}\n\n/** Binds the cart to a provider and returns the public browser configuration. */\nexport async function startExpressProvider(\n options: ExpressClientOptions,\n provider: ExpressProviderName,\n args: {\n cartId: string;\n cartToken: string;\n returnUrl?: string;\n cancelUrl?: string;\n embedOrigin?: string;\n },\n): Promise<ExpressResult<ProviderStart>> {\n const path =\n provider === \"inpostPay\"\n ? \"/inpost/start\"\n : provider === \"revolutPay\"\n ? \"/revolut/start\"\n : \"/adyen/start\";\n const raw = await request(\n options,\n path,\n {\n cartId: args.cartId,\n ...(args.returnUrl != null ? { returnUrl: args.returnUrl } : {}),\n ...(args.cancelUrl != null ? { cancelUrl: args.cancelUrl } : {}),\n ...(args.embedOrigin != null ? { embedOrigin: args.embedOrigin } : {}),\n },\n args.cartToken,\n );\n if (\"transportError\" in raw) {\n return networkFailure(raw.transportError);\n }\n const body = raw.json;\n if (!isRecord(body) || typeof body.success !== \"boolean\") {\n return {\n ok: false,\n code: isUnsupportedStatus(raw.status) ? \"not-implemented\" : \"invalid-response\",\n message: \"The provider start is not available.\",\n status: raw.status,\n };\n }\n if (body.success === true) {\n if (\n typeof body.redirectUrl !== \"string\" ||\n typeof body.providerOrderId !== \"string\"\n ) {\n return {\n ok: false,\n code: \"invalid-response\",\n message: \"The provider start returned no redirect.\",\n status: raw.status,\n };\n }\n return {\n ok: true,\n value: {\n ok: true,\n provider,\n redirectUrl: body.redirectUrl,\n providerOrderId: body.providerOrderId,\n ...(isRecord(body.publicConfig)\n ? { publicConfig: body.publicConfig as Record<string, string> }\n : {}),\n cartRevision:\n typeof body.cartRevision === \"number\" ? body.cartRevision : 0,\n },\n };\n }\n const failure = body as unknown as StartFailure;\n return {\n ok: false,\n code: (isUnsupportedStatus(raw.status)\n ? \"not-implemented\"\n : failure.code) as StartFailureCode,\n message:\n typeof failure.message === \"string\"\n ? failure.message\n : \"The provider start failed.\",\n status: raw.status,\n };\n}\n\n/**\n * Revolut Pay status. `pending` is what an old backend or an unanswered webhook\n * looks like; only `completed` may remove purchased lines from the cart.\n */\nexport function fetchRevolutPayStatus(\n options: ExpressClientOptions,\n cartId: string,\n cartToken: string,\n): Promise<RevolutPayStatus> {\n return fetchExpressPayStatus(options, \"/revolut/status\", cartId, cartToken);\n}\n\n/**\n * InPost Pay status. A browser `orderCreated` event is only a hint; this route\n * answers from the server-side order association, so a tampered browser event\n * can never clear a cart.\n */\nexport function fetchInpostPayStatus(\n options: ExpressClientOptions,\n cartId: string,\n cartToken: string,\n): Promise<ExpressPayStatus> {\n return fetchExpressPayStatus(options, \"/inpost/status\", cartId, cartToken);\n}\n\nasync function fetchExpressPayStatus(\n options: ExpressClientOptions,\n path: \"/revolut/status\" | \"/inpost/status\",\n cartId: string,\n cartToken: string,\n): Promise<ExpressPayStatus> {\n const raw = await request(options, path, { cartId }, cartToken);\n if (\"transportError\" in raw) {\n return { ok: false, code: \"network\", message: \"The status is not available.\" };\n }\n const body = raw.json;\n if (raw.status === 401 || raw.status === 403) {\n return { ok: false, code: \"cart-forbidden\", message: \"cart-forbidden\" };\n }\n if (raw.status === 404) {\n return { ok: false, code: \"cart-not-found\", message: \"cart-not-found\" };\n }\n if (!isRecord(body) || typeof body.success !== \"boolean\") {\n return {\n ok: false,\n code: isUnsupportedStatus(raw.status) ? \"not-implemented\" : \"provider-error\",\n message: \"The status is not available.\",\n };\n }\n if (body.success === true) {\n if (\n body.status === \"pending\" ||\n body.status === \"completed\" ||\n body.status === \"failed\" ||\n body.status === \"cancelled\"\n ) {\n return {\n ok: true,\n status: body.status,\n ...(typeof body.orderId === \"string\" ? { orderId: body.orderId } : {}),\n };\n }\n return { ok: false, code: \"provider-error\", message: \"Unknown status.\" };\n }\n return {\n ok: false,\n code: isUnsupportedStatus(raw.status) ? \"not-implemented\" : \"provider-error\",\n message: isRecord(body) ? mapCartFailure(body).message : \"The status failed.\",\n };\n}\n","import type { CartEnvironment } from \"./contracts\";\n\n/**\n * The browser-side record of a durable express cart.\n *\n * It is a capability cache, not the cart itself: the server row is the truth\n * and the SDK cart in `localStorage` stays the buyer's convenient copy. The\n * token is scoped to one project + host (+ environment) so two shops, two\n * Bitsnap hosts or a test and a production cart on one page can never reuse\n * each other's authorization.\n *\n * Nothing here is a merchant secret: the token only opens this one guest cart.\n */\n\nexport const EXPRESS_CART_KEY_PREFIX = \"bitsnap-express-cart\";\n\n/** A payment attempt the buyer may return to (mobile redirect, popup close). */\nexport type PendingExpressAttempt = {\n provider: \"inpostPay\" | \"revolutPay\";\n /** The provider's public order/basket id. */\n providerOrderId?: string;\n /** Lines frozen for this attempt; only these are removed once it completes. */\n lines: { id: string; quantity: number }[];\n /** When the attempt started (ms since epoch). */\n ts: number;\n};\n\nexport type ExpressCartRecord = {\n projectID: string;\n host: string;\n environment: CartEnvironment;\n cartId: string;\n cartToken: string;\n revision: number;\n updatedAt: number;\n /**\n * The lines the server last confirmed. Reconciliation compares the local\n * cart against them, so products added after the last upload are never\n * mistaken for lines removed in the provider's app.\n */\n syncedLines?: { id: string; quantity: number }[];\n /** InPost Pay basket binding key, reused by the widget. */\n inpostBindingApiKey?: string;\n pending?: PendingExpressAttempt;\n};\n\n/**\n * A provider attempt younger than this is still worth reconciling; an older\n * one is left alone instead of asking the backend forever.\n */\nexport const PENDING_EXPRESS_MAX_AGE_MS = 24 * 60 * 60 * 1000;\n\nexport type ExpressStorage = Pick<\n Storage,\n \"getItem\" | \"setItem\" | \"removeItem\"\n>;\n\n/** The pending attempt, unless it is older than `PENDING_EXPRESS_MAX_AGE_MS`. */\nexport function activePendingAttempt(\n record: ExpressCartRecord | undefined,\n now: number = Date.now(),\n): PendingExpressAttempt | undefined {\n const pending = record?.pending;\n if (pending == null) {\n return undefined;\n }\n return now - pending.ts <= PENDING_EXPRESS_MAX_AGE_MS ? pending : undefined;\n}\n\nfunction defaultStorage(): ExpressStorage | undefined {\n try {\n return typeof localStorage === \"undefined\" ? undefined : localStorage;\n } catch {\n return undefined;\n }\n}\n\nexport function expressCartKey(host: string, projectID: string): string {\n return `${EXPRESS_CART_KEY_PREFIX}:${encodeURIComponent(host)}:${encodeURIComponent(projectID)}`;\n}\n\nexport function readExpressCartRecord(args: {\n host: string;\n projectID: string;\n storage?: ExpressStorage;\n}): ExpressCartRecord | undefined {\n const storage = args.storage ?? defaultStorage();\n if (storage == null) {\n return undefined;\n }\n const key = expressCartKey(args.host, args.projectID);\n let value: unknown;\n try {\n const raw = storage.getItem(key);\n if (raw == null) {\n return undefined;\n }\n value = JSON.parse(raw);\n } catch {\n clearExpressCartRecord(args);\n return undefined;\n }\n if (!isRecord(value)) {\n clearExpressCartRecord(args);\n return undefined;\n }\n if (\n value.projectID !== args.projectID ||\n value.host !== args.host ||\n typeof value.cartId !== \"string\" ||\n value.cartId.length === 0 ||\n typeof value.cartToken !== \"string\" ||\n value.cartToken.length === 0 ||\n typeof value.revision !== \"number\" ||\n (value.environment !== \"test\" && value.environment !== \"production\")\n ) {\n // Another project's or an older build's record is not ours to use.\n clearExpressCartRecord(args);\n return undefined;\n }\n return {\n projectID: value.projectID,\n host: value.host,\n environment: value.environment,\n cartId: value.cartId,\n cartToken: value.cartToken,\n revision: value.revision,\n updatedAt: typeof value.updatedAt === \"number\" ? value.updatedAt : 0,\n ...(Array.isArray(value.syncedLines)\n ? {\n syncedLines: value.syncedLines.filter(\n (line): line is { id: string; quantity: number } =>\n isRecord(line) &&\n typeof line.id === \"string\" &&\n typeof line.quantity === \"number\",\n ),\n }\n : {}),\n ...(typeof value.inpostBindingApiKey === \"string\"\n ? { inpostBindingApiKey: value.inpostBindingApiKey }\n : {}),\n ...(isPendingAttempt(value.pending) ? { pending: value.pending } : {}),\n };\n}\n\nexport function writeExpressCartRecord(\n record: ExpressCartRecord,\n storage: ExpressStorage | undefined = defaultStorage(),\n): boolean {\n if (storage == null) {\n return false;\n }\n try {\n storage.setItem(\n expressCartKey(record.host, record.projectID),\n JSON.stringify(record),\n );\n return true;\n } catch {\n return false;\n }\n}\n\nexport function clearExpressCartRecord(args: {\n host: string;\n projectID: string;\n storage?: ExpressStorage;\n}): void {\n const storage = args.storage ?? defaultStorage();\n if (storage == null) {\n return;\n }\n try {\n storage.removeItem(expressCartKey(args.host, args.projectID));\n } catch {\n // storage is unavailable\n }\n}\n\n/** Updates a stored record in place; `undefined` when there is none. */\nexport function updateExpressCartRecord(\n args: { host: string; projectID: string; storage?: ExpressStorage },\n update: (record: ExpressCartRecord) => ExpressCartRecord,\n): ExpressCartRecord | undefined {\n const current = readExpressCartRecord(args);\n if (current == null) {\n return undefined;\n }\n const next = update(current);\n writeExpressCartRecord(next, args.storage);\n return next;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value != null && !Array.isArray(value);\n}\n\nfunction isPendingAttempt(value: unknown): value is PendingExpressAttempt {\n if (!isRecord(value)) {\n return false;\n }\n if (\n value.provider !== \"inpostPay\" &&\n value.provider !== \"revolutPay\"\n ) {\n return false;\n }\n if (typeof value.ts !== \"number\" || !Array.isArray(value.lines)) {\n return false;\n }\n return value.lines.every(\n (line) =>\n isRecord(line) &&\n typeof line.id === \"string\" &&\n typeof line.quantity === \"number\",\n );\n}\n","import {\n clearExpressCartRecord,\n readExpressCartRecord,\n writeExpressCartRecord,\n type ExpressCartRecord,\n type ExpressStorage,\n type PendingExpressAttempt,\n} from \"./cart-record\";\nimport type {\n CartEnvironment,\n CartLineConflict,\n CartSnapshot,\n CartWriteResult,\n ExpressCartUpload,\n ExpressResult,\n ProviderStart,\n RevolutPayStatus,\n} from \"./contracts\";\n\n/**\n * The durable cart of an express payment.\n *\n * Rules encoded here (they match the backend contract):\n * - the local cart is only a cache; the server snapshot is authoritative;\n * - an update always names the revision it saw, so a stale tab is refused\n * instead of overwriting a newer cart;\n * - a rejected revision is reconciled and the *local* content is retried, so a\n * buyer's newer lines are never replaced by an older server snapshot;\n * - the cart is kept on cancel, failure and page reload; only the lines of a\n * server-confirmed purchase are removed, and products added meanwhile stay;\n * - after a purchase the record is dropped, because the paid cart is frozen:\n * the next express attempt starts a new server cart from what is left.\n */\n\nexport type LocalCartLineId = { id: string; quantity: number };\n\n/** The local (browser) cart, injected so this module stays free of React. */\nexport type ExpressCartLocal = {\n /** Current lines; `id` is the same id the cart upload takes. */\n lines(): LocalCartLineId[];\n /** Stable content signature used to notice an edit during a request. */\n signature(): string;\n /** The upload body, or `undefined` when the cart is empty. */\n upload(locale: string): ExpressCartUpload | undefined;\n /** Replaces the local lines with a canonical server snapshot. */\n adoptSnapshot(snapshot: CartSnapshot): void;\n /** Adds quantities to the local cart (lines added during a request). */\n appendLines(lines: LocalCartLineId[]): void;\n /** Removes the purchased quantities only. */\n removeLines(lines: LocalCartLineId[]): void;\n /**\n * Replaces the local lines with a merged set after a revision conflict.\n * Absent when the SDK does not own the cart (explicit `items`): a merge that\n * would change those lines is then reported as a visible conflict instead of\n * being written silently.\n */\n replaceLines?(lines: LocalCartLineId[]): void;\n};\n\nexport type ExpressCartSessionOptions = {\n projectID: string;\n host: string;\n local: ExpressCartLocal;\n storage?: ExpressStorage;\n write: (\n upload: ExpressCartUpload,\n current?: {\n cartId: string;\n cartToken: string;\n expectedRevision: number;\n },\n ) => Promise<CartWriteResult>;\n read: (\n cartId: string,\n cartToken: string,\n ) => Promise<ExpressResult<CartSnapshot>>;\n now?: () => number;\n /** Attempts of one upload before giving up on a moving cart. */\n maxAttempts?: number;\n};\n\nconst CART_ATTEMPTS = 3;\n\ntype EnsuredCart = {\n record: ExpressCartRecord;\n snapshot: CartSnapshot;\n};\n\nexport class ExpressCartSession {\n private readonly options: ExpressCartSessionOptions;\n private running: Promise<unknown> = Promise.resolve();\n\n constructor(options: ExpressCartSessionOptions) {\n this.options = options;\n }\n\n getRecord(): ExpressCartRecord | undefined {\n return readExpressCartRecord(this.options);\n }\n\n /** The InPost basket key the widget should start with, when it is known. */\n getInpostBindingApiKey(): string | undefined {\n return this.getRecord()?.inpostBindingApiKey;\n }\n\n /** The upload the next `ensure` would send, without writing anything. */\n previewUpload(locale: string): ExpressCartUpload | undefined {\n return this.options.local.upload(locale);\n }\n\n getPendingAttempt(): PendingExpressAttempt | undefined {\n return this.getRecord()?.pending;\n }\n\n /**\n * Uploads the current local cart. Creates a cart when there is no usable\n * record; updates it with the stored revision otherwise. Reconciles stale\n * revisions and cart locks instead of losing edits.\n */\n ensure(args: {\n locale: string;\n environment?: CartEnvironment;\n }): Promise<ExpressResult<EnsuredCart>> {\n return this.serialize(() => this.ensureNow(args));\n }\n\n private async ensureNow(args: {\n locale: string;\n environment?: CartEnvironment;\n }): Promise<ExpressResult<EnsuredCart>> {\n let record = this.getRecord();\n if (\n record != null &&\n args.environment != null &&\n record.environment !== args.environment\n ) {\n // A test cart token must not drive a production checkout (or the other\n // way round): start a fresh cart in this environment.\n clearExpressCartRecord(this.options);\n record = undefined;\n }\n\n let lastFailure: Extract<CartWriteResult, { ok: false }> | undefined;\n const attempts = this.options.maxAttempts ?? CART_ATTEMPTS;\n\n for (let attempt = 0; attempt < attempts; attempt++) {\n const upload = this.options.local.upload(args.locale);\n if (upload == null) {\n return {\n ok: false,\n code: \"invalid-cart\",\n message: \"The cart is empty.\",\n };\n }\n const signatureBefore = this.options.local.signature();\n const result = await this.options.write(\n upload,\n record != null\n ? {\n cartId: record.cartId,\n cartToken: record.cartToken,\n expectedRevision: record.revision,\n }\n : undefined,\n );\n\n if (result.ok) {\n const cartToken = result.cartToken ?? record?.cartToken;\n if (cartToken == null) {\n return {\n ok: false,\n code: \"internal\",\n message: \"The created cart has no access token.\",\n };\n }\n const snapshot = result.snapshot;\n record = {\n projectID: this.options.projectID,\n host: this.options.host,\n environment: snapshot.environment,\n cartId: snapshot.cartId,\n cartToken,\n revision: snapshot.revision,\n updatedAt: (this.options.now ?? Date.now)(),\n syncedLines: upload.items.map((item) => ({\n id: item.id,\n quantity: item.quantity,\n })),\n ...(record?.inpostBindingApiKey != null\n ? { inpostBindingApiKey: record.inpostBindingApiKey }\n : {}),\n };\n writeExpressCartRecord(record, this.options.storage);\n const stillCurrent = this.options.local.signature() === signatureBefore;\n if (stillCurrent) {\n return { ok: true, value: { record, snapshot } };\n }\n // The buyer changed the cart while it was being uploaded: retry with\n // the new revision so those lines survive.\n continue;\n }\n\n lastFailure = result;\n switch (result.code) {\n case \"revision-conflict\": {\n const nextRevision =\n result.snapshot?.revision ?? result.currentRevision;\n if (record == null || nextRevision == null) {\n return result;\n }\n // A real three-way merge: the local cart is compared against what the\n // server last confirmed (`syncedLines`). Disjoint edits are combined;\n // a line both sides changed differently is never last-write-wins.\n const merged = mergeRevisionConflict({\n base: record.syncedLines,\n local: this.options.local.lines(),\n server: snapshotLinesToLocal(result.snapshot?.lines),\n });\n if (!merged.ok) {\n return {\n ...result,\n currentRevision: nextRevision,\n snapshot: result.snapshot,\n conflicts: merged.conflicts,\n };\n }\n if (!sameLines(merged.lines, this.options.local.lines())) {\n if (this.options.local.replaceLines == null) {\n // Explicit merchant cart: the SDK cannot adopt server changes, so\n // it asks the buyer instead of overwriting either side.\n return {\n ...result,\n currentRevision: nextRevision,\n snapshot: result.snapshot,\n conflicts: merged.conflicts,\n };\n }\n this.options.local.replaceLines(merged.lines);\n }\n record = { ...record, revision: nextRevision };\n if (result.snapshot?.environment != null) {\n record.environment = result.snapshot.environment;\n }\n if (result.snapshot != null) {\n // Keep the baseline in step with the revision we are about to\n // write; the successful write below replaces it with the upload.\n record.syncedLines = snapshotLinesToLocal(result.snapshot.lines);\n }\n writeExpressCartRecord(record, this.options.storage);\n // Retry with the merged content and the newer revision.\n continue;\n }\n case \"cart-locked\": {\n // The stored cart became an order. What is left in the local cart is\n // a new purchase, so it gets a new cart; nothing is overwritten.\n clearExpressCartRecord(this.options);\n record = undefined;\n continue;\n }\n case \"cart-not-found\":\n case \"cart-forbidden\": {\n clearExpressCartRecord(this.options);\n record = undefined;\n continue;\n }\n case \"invalid-request\":\n case \"product-not-available\":\n case \"currency-unsupported\": {\n return result;\n }\n default: {\n return result;\n }\n }\n }\n\n return (\n lastFailure ?? {\n ok: false,\n code: \"internal\",\n message: \"The cart could not be saved.\",\n }\n );\n }\n\n /**\n * Reads the canonical snapshot and adopts it into the local cart (what the\n * InPost app changed must be what the browser shows). Lines added while the\n * request was in flight are kept and uploaded again.\n */\n reconcileFromServer(): Promise<ExpressResult<CartSnapshot>> {\n return this.serialize(async () => {\n const record = this.getRecord();\n if (record == null) {\n return {\n ok: false,\n code: \"cart-not-found\" as const,\n message: \"There is no cart to read.\",\n };\n }\n const before = countLines(this.options.local.lines());\n const result = await this.options.read(\n record.cartId,\n record.cartToken,\n ); if (!result.ok) {\n if (\n result.code === \"cart-not-found\" ||\n result.code === \"cart-forbidden\"\n ) {\n clearExpressCartRecord(this.options);\n }\n return result;\n }\n const snapshot = result.value;\n const after = countLines(this.options.local.lines());\n // The server last confirmed `syncedLines`; without it (older record) the\n // local cart right before this read was in sync.\n const synced = countLines(record.syncedLines ?? []);\n const baseline = record.syncedLines != null ? synced : before;\n this.options.local.adoptSnapshot(snapshot);\n // Keep what the buyer added after the server last confirmed the cart;\n // everything the provider changed stays as the provider set it.\n const added = additionsBeyond(after, baseline);\n if (added.length > 0) {\n this.options.local.appendLines(added);\n }\n const current = this.getRecord();\n if (current != null && current.cartId === snapshot.cartId) {\n writeExpressCartRecord(\n {\n ...current,\n revision: snapshot.revision,\n environment: snapshot.environment,\n updatedAt: (this.options.now ?? Date.now)(),\n },\n this.options.storage,\n );\n }\n if (added.length > 0) {\n const reuploaded = await this.ensureNow({\n locale: snapshot.locale,\n environment: snapshot.environment,\n });\n if (!reuploaded.ok) {\n return {\n ok: false,\n code: reuploaded.code,\n message: reuploaded.message,\n ...(reuploaded.status != null ? { status: reuploaded.status } : {}),\n ...(reuploaded.currentRevision != null\n ? { currentRevision: reuploaded.currentRevision }\n : {}),\n ...(reuploaded.snapshot != null\n ? { snapshot: reuploaded.snapshot }\n : {}),\n ...(reuploaded.conflicts != null\n ? { conflicts: reuploaded.conflicts }\n : {}),\n };\n }\n }\n return { ok: true, value: snapshot };\n });\n }\n\n /** Binds the cart to a provider. The cart is uploaded and reconciled first. */\n async start(\n provider: \"inpostPay\" | \"revolutPay\",\n args: {\n locale: string;\n environment?: CartEnvironment;\n returnUrl?: string;\n cancelUrl?: string;\n embedOrigin?: string;\n start: (request: {\n cartId: string;\n cartToken: string;\n returnUrl?: string;\n cancelUrl?: string;\n embedOrigin?: string;\n }) => Promise<ExpressResult<ProviderStart>>;\n },\n ): Promise<ExpressResult<{ start: ProviderStart; snapshot: CartSnapshot }>> {\n const ensured = await this.ensure({\n locale: args.locale,\n ...(args.environment != null ? { environment: args.environment } : {}),\n });\n if (!ensured.ok) {\n return ensured;\n }\n const { record, snapshot } = ensured.value;\n const started = await args.start({\n cartId: record.cartId,\n cartToken: record.cartToken,\n ...(args.returnUrl != null ? { returnUrl: args.returnUrl } : {}),\n ...(args.cancelUrl != null ? { cancelUrl: args.cancelUrl } : {}),\n ...(args.embedOrigin != null ? { embedOrigin: args.embedOrigin } : {}),\n });\n if (!started.ok) {\n if (\n started.code === \"cart-locked\" ||\n started.code === \"cart-not-found\" ||\n started.code === \"cart-forbidden\"\n ) {\n // The stored cart belongs to another purchase now.\n clearExpressCartRecord(this.options);\n }\n return started;\n }\n\n const current = this.getRecord();\n if (current != null && current.cartId === record.cartId) {\n writeExpressCartRecord(\n {\n ...current,\n revision: Math.max(current.revision, started.value.cartRevision),\n updatedAt: (this.options.now ?? Date.now)(),\n ...(started.value.publicConfig?.basketBindingApiKey != null\n ? {\n inpostBindingApiKey:\n started.value.publicConfig.basketBindingApiKey,\n }\n : {}),\n pending: {\n provider,\n ...(started.value.providerOrderId.length > 0\n ? { providerOrderId: started.value.providerOrderId }\n : {}),\n lines: snapshot.lines.map((line) => ({\n id: line.productId,\n quantity: line.quantity,\n })),\n ts: (this.options.now ?? Date.now)(),\n },\n },\n this.options.storage,\n );\n }\n return { ok: true, value: { start: started.value, snapshot } };\n }\n\n /** Stores the InPost basket key so a remounted widget starts already bound. */\n storeInpostBindingApiKey(basketBindingApiKey: string): void {\n const record = this.getRecord();\n if (record == null || basketBindingApiKey.length === 0) {\n return;\n }\n writeExpressCartRecord(\n {\n ...record,\n inpostBindingApiKey: basketBindingApiKey,\n updatedAt: (this.options.now ?? Date.now)(),\n },\n this.options.storage,\n );\n }\n\n /**\n * Removes only the purchased lines and forgets the (now frozen) cart record,\n * so a later express attempt starts a new cart from the remaining products.\n */\n completePurchase(lines?: LocalCartLineId[]): void {\n const record = this.getRecord();\n const purchased = lines ?? record?.pending?.lines ?? [];\n if (purchased.length > 0) {\n this.options.local.removeLines(purchased);\n }\n clearExpressCartRecord(this.options);\n }\n\n /** Cancel or failure: the cart and its record stay exactly as they are. */\n keepCart(): void {\n // Intentionally empty: kept for call sites that speak in intentions.\n }\n\n /** Forgets the provider attempt but keeps the cart authorization. */\n clearPending(): void {\n const record = this.getRecord();\n if (record == null || record.pending == null) {\n return;\n }\n const { pending: _pending, ...rest } = record;\n writeExpressCartRecord(rest, this.options.storage);\n }\n\n status(\n fetchStatus: (\n cartId: string,\n cartToken: string,\n ) => Promise<RevolutPayStatus>,\n ): Promise<RevolutPayStatus> {\n const record = this.getRecord();\n if (record == null) {\n return Promise.resolve({\n ok: false,\n code: \"cart-not-found\",\n message: \"There is no cart to check.\",\n });\n }\n return fetchStatus(record.cartId, record.cartToken);\n }\n\n /** Runs cart work one at a time: two clicks never race the same revision. */\n private serialize<T>(task: () => Promise<T>): Promise<T> {\n const next = this.running.then(task, task);\n this.running = next.then(\n () => undefined,\n () => undefined,\n );\n return next;\n }\n}\n\nfunction countLines(lines: LocalCartLineId[]): Map<string, number> {\n const counts = new Map<string, number>();\n for (const line of lines) {\n counts.set(line.id, (counts.get(line.id) ?? 0) + line.quantity);\n }\n return counts;\n}\n\nfunction snapshotLinesToLocal(\n lines: CartSnapshot[\"lines\"] | undefined,\n): LocalCartLineId[] {\n return (lines ?? []).map((line) => ({\n id: line.productId,\n quantity: line.quantity,\n }));\n}\n\nfunction sameLines(a: LocalCartLineId[], b: LocalCartLineId[]): boolean {\n const left = countLines(a);\n const right = countLines(b);\n if (left.size !== right.size) {\n return false;\n }\n for (const [id, quantity] of left) {\n if (right.get(id) !== quantity) {\n return false;\n }\n }\n return true;\n}\n\ntype MergeResult =\n | { ok: true; lines: LocalCartLineId[]; conflicts: CartLineConflict[] }\n | { ok: false; lines: LocalCartLineId[]; conflicts: CartLineConflict[] };\n\n/**\n * Three-way merge of the browser cart against the last server-confirmed lines\n * and the current canonical snapshot.\n *\n * - only the browser changed a line → the browser value;\n * - only the server changed a line → the server value;\n * - both changed it to the same quantity → that quantity;\n * - both changed it to different quantities → a conflict, never a silent\n * last-write-wins;\n * - a line absent on one side is quantity 0, so removals merge like edits.\n *\n * Without `syncedLines` there is no safe baseline (an older record): the caller\n * gets a visible conflict instead of overwriting the newer server cart.\n */\nfunction mergeRevisionConflict(args: {\n base: LocalCartLineId[] | undefined;\n local: LocalCartLineId[];\n server: LocalCartLineId[] | undefined;\n}): MergeResult {\n if (args.base == null || args.server == null) {\n return {\n ok: false,\n lines: args.local,\n conflicts: [],\n };\n }\n const base = countLines(args.base);\n const local = countLines(args.local);\n const server = countLines(args.server);\n const ids = new Set<string>([...base.keys(), ...local.keys(), ...server.keys()]);\n const merged: LocalCartLineId[] = [];\n const conflicts: CartLineConflict[] = [];\n for (const id of ids) {\n const b = base.get(id) ?? 0;\n const l = local.get(id) ?? 0;\n const s = server.get(id) ?? 0;\n const localChanged = l !== b;\n const serverChanged = s !== b;\n let quantity: number;\n if (!localChanged) {\n quantity = s;\n } else if (!serverChanged) {\n quantity = l;\n } else if (l === s) {\n quantity = l;\n } else {\n conflicts.push({ id, base: b, local: l, server: s });\n quantity = l;\n }\n if (quantity > 0 && !conflicts.some((conflict) => conflict.id === id)) {\n merged.push({ id, quantity });\n }\n }\n return { ok: conflicts.length === 0, lines: merged, conflicts };\n}\n\nfunction additionsBeyond(\n after: Map<string, number>,\n baseline: Map<string, number>,\n): LocalCartLineId[] {\n const added: LocalCartLineId[] = [];\n for (const [id, quantity] of after) {\n const extra = quantity - (baseline.get(id) ?? 0);\n if (extra > 0) {\n added.push({ id, quantity: extra });\n }\n }\n return added;\n}\n","import { getCheckoutSelection } from \"@/src/components/checkout/CartProvider\";\nimport { PublicApiClient } from \"@/src/public.api.client\";\nimport type {\n ExpressCartUpload,\n ExpressDeliveryOption,\n} from \"./contracts\";\n\n/**\n * The delivery quote of one express cart.\n *\n * The express upload can carry `delivery` options, but only the Bitsnap public\n * API knows the shop's methods and their prices (`getPreOrderDetails`). Without\n * them the backend prices the cart with zero shipping, which is not a total a\n * buyer may pay. This module resolves the quote once per cart content and\n * remembers it, so availability and provider start send exactly the same\n * delivery input to the backend.\n *\n * A failed quote is a hard stop: the express button stays hidden (or the start\n * fails) instead of mounting a payable total without shipping.\n */\n\nexport type ExpressDeliveryQuote = {\n delivery: ExpressDeliveryOption[];\n /** The method the backend selected/quoted; `undefined` when none applies. */\n deliveryMethod?: string;\n};\n\nconst quotes = new Map<\n string,\n { quote: ExpressDeliveryQuote; at: number }\n>();\n\nconst QUOTE_TTL_MS = 5 * 60 * 1000;\n\n/** Test seam: forget every remembered quote. */\nexport function clearDeliveryQuoteCache(): void {\n quotes.clear();\n}\n\nexport function deliveryQuoteKey(\n host: string,\n projectID: string,\n upload: ExpressCartUpload,\n): string {\n const selection = getCheckoutSelection();\n return [\n host,\n projectID,\n upload.items\n .map((item) => `${item.id}:${item.quantity}`)\n .sort()\n .join(\",\"),\n (upload.countries ?? []).slice().sort().join(\",\"),\n upload.couponCode ?? \"\",\n upload.deliveryMethod ?? \"\",\n selection.postalCode ?? \"\",\n ].join(\"|\");\n}\n\nexport function readDeliveryQuote(\n host: string,\n projectID: string,\n upload: ExpressCartUpload,\n): ExpressDeliveryQuote | undefined {\n const key = deliveryQuoteKey(host, projectID, upload);\n const entry = quotes.get(key);\n if (entry == null) {\n return undefined;\n }\n if (Date.now() - entry.at > QUOTE_TTL_MS) {\n quotes.delete(key);\n return undefined;\n }\n return entry.quote;\n}\n\nexport function rememberDeliveryQuote(\n host: string,\n projectID: string,\n upload: ExpressCartUpload,\n quote: ExpressDeliveryQuote,\n): void {\n quotes.set(deliveryQuoteKey(host, projectID, upload), {\n quote,\n at: Date.now(),\n });\n}\n\n/** Adds the remembered quote to an upload; a caller-supplied one wins. */\nexport function withDeliveryQuote(\n upload: ExpressCartUpload,\n quote: ExpressDeliveryQuote | undefined,\n): ExpressCartUpload {\n if (quote == null || quote.delivery.length === 0) {\n return upload;\n }\n return {\n ...upload,\n delivery:\n upload.delivery != null && upload.delivery.length > 0\n ? upload.delivery\n : quote.delivery,\n ...(upload.deliveryMethod == null && quote.deliveryMethod != null\n ? { deliveryMethod: quote.deliveryMethod }\n : {}),\n };\n}\n\n/**\n * Resolves the delivery methods of a cart through the public API and remembers\n * them. Returns `undefined` when the quote cannot be obtained; callers must not\n * fall back to a shipping-free total.\n */\nexport async function loadDeliveryQuote(args: {\n host: string;\n projectID: string;\n upload: ExpressCartUpload;\n}): Promise<ExpressDeliveryQuote | undefined> {\n if (args.upload.items.length === 0) {\n return { delivery: [] };\n }\n const selection = getCheckoutSelection();\n try {\n const response = await PublicApiClient.get(args.host).getPreOrderDetails({\n projectId: args.projectID,\n items: args.upload.items.map((item) => ({\n id: item.id,\n quantity: item.quantity,\n })),\n ...(args.upload.countries?.[0] != null\n ? { countryCode: args.upload.countries[0] }\n : {}),\n ...(args.upload.couponCode != null\n ? { couponCode: args.upload.couponCode }\n : {}),\n ...(args.upload.deliveryMethod != null\n ? { selectedDeliveryMethod: args.upload.deliveryMethod }\n : selection.selectedDeliveryMethod != null\n ? { selectedDeliveryMethod: selection.selectedDeliveryMethod }\n : {}),\n ...(selection.postalCode != null ? { postCode: selection.postalCode } : {}),\n });\n const delivery = response.methods.map((method) => ({\n name: method.id,\n ...(method.description != null ? { desc: method.description } : {}),\n min: method.minDays ?? 1,\n max: method.maxDays ?? 14,\n // The express contract takes major units; the public API quotes minor.\n price: method.amount / 100,\n }));\n const deliveryMethod =\n response.selectedDeliveryMethod ?? delivery[0]?.name ?? undefined;\n const quote: ExpressDeliveryQuote = {\n delivery,\n ...(deliveryMethod != null ? { deliveryMethod } : {}),\n };\n rememberDeliveryQuote(args.host, args.projectID, args.upload, quote);\n return quote;\n } catch (error) {\n console.warn(\"cannot resolve the express delivery quote\", error);\n return undefined;\n }\n}\n\nexport type PreparedExpressUpload =\n | { ok: true; upload: ExpressCartUpload; quote: ExpressDeliveryQuote }\n | { ok: false; message: string };\n\n/**\n * Ensures the upload has the canonical delivery quote. Used by availability and\n * by provider start, so both send the same priced cart to the backend.\n */\nexport async function prepareExpressCartUpload(args: {\n host: string;\n projectID: string;\n upload: ExpressCartUpload;\n}): Promise<PreparedExpressUpload> {\n if (args.upload.delivery != null && args.upload.delivery.length > 0) {\n return {\n ok: true,\n upload: args.upload,\n quote: {\n delivery: args.upload.delivery,\n ...(args.upload.deliveryMethod != null\n ? { deliveryMethod: args.upload.deliveryMethod }\n : {}),\n },\n };\n }\n const cached = readDeliveryQuote(args.host, args.projectID, args.upload);\n if (cached != null) {\n return {\n ok: true,\n upload: withDeliveryQuote(args.upload, cached),\n quote: cached,\n };\n }\n const quote = await loadDeliveryQuote(args);\n if (quote == null) {\n return {\n ok: false,\n message:\n \"The delivery quote for this cart is not available. Use the regular checkout.\",\n };\n }\n return { ok: true, upload: withDeliveryQuote(args.upload, quote), quote };\n}\n","import {\n appendLocalCartLines,\n buildLocalCartUpload,\n readLocalCartLines,\n readLocalCartSignature,\n removeLocalCartLines,\n replaceLocalCartLines,\n} from \"@/src/components/checkout/CartProvider\";\nimport { HOST } from \"@/src/components/checkout/constants\";\nimport {\n fetchInpostPayStatus,\n fetchRevolutPayStatus,\n readExpressCart,\n startExpressProvider,\n writeExpressCart,\n type FetchLike,\n} from \"./client\";\nimport { ExpressCartSession, type ExpressCartLocal } from \"./cart-session\";\nimport type {\n CartEnvironment,\n ExpressPayStatus,\n RevolutPayStatus,\n} from \"./contracts\";\nimport {\n prepareExpressCartUpload,\n readDeliveryQuote,\n withDeliveryQuote,\n} from \"./delivery-quote\";\nimport type { ExpressStorage } from \"./cart-record\";\n\n/**\n * Wires the express cart session to the SDK's browser cart and to the Bitsnap\n * host. The session is cheap and stateless besides the serialized queue, so a\n * component can create one per mount and drop it on unmount.\n */\n\n/** The SDK cart as the session sees it. */\nexport function sdkLocalCart(options: {\n host: string;\n projectID: string;\n}): ExpressCartLocal {\n return {\n lines: () =>\n readLocalCartLines().map((line) => ({\n id: line.productID,\n quantity: line.quantity,\n })),\n signature: readLocalCartSignature,\n upload: (locale) => {\n const upload = buildLocalCartUpload(locale);\n if (upload == null) {\n return undefined;\n }\n return withDeliveryQuote(\n upload,\n readDeliveryQuote(options.host, options.projectID, upload),\n );\n },\n adoptSnapshot: (snapshot) => {\n replaceLocalCartLines(\n snapshot.lines.map((line) => ({\n productId: line.productId,\n quantity: line.quantity,\n })),\n );\n },\n appendLines: appendLocalCartLines,\n removeLines: removeLocalCartLines,\n replaceLines: (lines) => {\n replaceLocalCartLines(\n lines.map((line) => ({\n productId: line.id,\n quantity: line.quantity,\n })),\n );\n },\n };\n}\n\nexport type ExpressSessionOptions = {\n projectID: string;\n host?: string;\n fetch?: FetchLike;\n storage?: ExpressStorage;\n signal?: AbortSignal;\n now?: () => number;\n /** Overrides the SDK cart (explicit `items` of a custom storefront). */\n local?: ExpressCartLocal;\n};\n\nexport function createExpressSession(\n options: ExpressSessionOptions,\n): ExpressCartSession {\n const host = options.host ?? HOST;\n const clientOptions = {\n projectID: options.projectID,\n host,\n ...(options.fetch != null ? { fetch: options.fetch } : {}),\n ...(options.signal != null ? { signal: options.signal } : {}),\n };\n return new ExpressCartSession({\n projectID: options.projectID,\n host,\n local: options.local ?? sdkLocalCart({ host, projectID: options.projectID }),\n ...(options.storage != null ? { storage: options.storage } : {}),\n ...(options.now != null ? { now: options.now } : {}),\n write: (upload, current) =>\n writeExpressCart(clientOptions, upload, current),\n read: (cartId, cartToken) =>\n readExpressCart(clientOptions, cartId, cartToken),\n });\n}\n\n/** Starts a provider for the current browser cart through a fresh session. */\nexport async function startProviderForCart(\n options: ExpressSessionOptions & {\n locale: string;\n environment?: CartEnvironment;\n returnUrl?: string;\n cancelUrl?: string;\n embedOrigin?: string;\n },\n provider: \"inpostPay\" | \"revolutPay\",\n session: ExpressCartSession = createExpressSession(options),\n) {\n const host = options.host ?? HOST;\n // The provider start uploads the cart again. Resolve the delivery quote now\n // for the content that is about to be sent, so a product added since the\n // last availability call cannot slip through with zero shipping.\n const preview = session.previewUpload(options.locale);\n if (preview != null) {\n const prepared = await prepareExpressCartUpload({\n host,\n projectID: options.projectID,\n upload: preview,\n });\n if (!prepared.ok) {\n return {\n ok: false as const,\n code: \"invalid-cart\" as const,\n message: prepared.message,\n };\n }\n }\n return session.start(provider, {\n locale: options.locale,\n ...(options.environment != null\n ? { environment: options.environment }\n : {}),\n ...(options.returnUrl != null ? { returnUrl: options.returnUrl } : {}),\n ...(options.cancelUrl != null ? { cancelUrl: options.cancelUrl } : {}),\n ...(options.embedOrigin != null ? { embedOrigin: options.embedOrigin } : {}),\n start: (request) =>\n startExpressProvider(\n {\n projectID: options.projectID,\n host,\n ...(options.fetch != null ? { fetch: options.fetch } : {}),\n ...(options.signal != null ? { signal: options.signal } : {}),\n },\n provider,\n request,\n ),\n });\n}\n\nexport function getRevolutStatus(\n options: ExpressSessionOptions,\n session?: ExpressCartSession,\n): Promise<RevolutPayStatus> {\n return getProviderStatus(options, \"revolutPay\", session);\n}\n\n/** InPost Pay status: only the signed server-side order state completes it. */\nexport function getInpostStatus(\n options: ExpressSessionOptions,\n session?: ExpressCartSession,\n): Promise<ExpressPayStatus> {\n return getProviderStatus(options, \"inpostPay\", session);\n}\n\nfunction getProviderStatus(\n options: ExpressSessionOptions,\n provider: \"inpostPay\" | \"revolutPay\",\n session?: ExpressCartSession,\n): Promise<ExpressPayStatus> {\n const host = options.host ?? HOST;\n const active = session ?? createExpressSession(options);\n return active.status((cartId, cartToken) =>\n (provider === \"inpostPay\"\n ? fetchInpostPayStatus\n : fetchRevolutPayStatus)(\n {\n projectID: options.projectID,\n host,\n ...(options.fetch != null ? { fetch: options.fetch } : {}),\n ...(options.signal != null ? { signal: options.signal } : {}),\n },\n cartId,\n cartToken,\n ),\n );\n}\n","/**\n * Loader and host binding of the official InPost Pay widget.\n *\n * The widget renders the real InPost Pay buttons into `<inpost-izi-button>`\n * elements and the thank-you page into `<inpost-thank-you>`; the protocol is\n * documented fields only: `merchantClientId`, `basketBindingApiKey`,\n * `unboundWidgetClicked` (returns the basket key), `addToBasketClicked`,\n * `handleBasketEvent`, `apiBaseUrl`, `language`.\n *\n * The package is imported lazily in the browser only: its bundle touches\n * `self` at evaluation, so importing it during server rendering would throw.\n */\n\nexport type InPostWidgetBasketEvent =\n | \"basketDeleted\"\n | \"basketProductChanged\"\n | \"orderCreated\";\n\nexport type InPostWidgetInitOptions = {\n merchantClientId: string;\n /** `undefined` means \"unbound\"; clicking then has to resolve a key. */\n basketBindingApiKey: string | Promise<string> | undefined;\n unboundWidgetClicked?: (productId?: string) => Promise<string>;\n addToBasketClicked?: (productId?: string) => Promise<void>;\n handleBasketEvent?: (\n event: InPostWidgetBasketEvent,\n ) => boolean | Promise<boolean>;\n apiBaseUrl?: string;\n webView?: boolean;\n language?: string;\n features?: {\n backendDrivenContentEnabled?: boolean;\n isWidgetSplitBoundEnabled?: boolean;\n };\n};\n\nexport type InPostPayWidgetInstance = {\n refresh: (options?: Partial<InPostWidgetInitOptions>) => void;\n rerender: () => void;\n};\n\nexport type InPostWidgetNamespace = {\n init: (options: InPostWidgetInitOptions) => InPostPayWidgetInstance;\n};\n\n/**\n * The widget adds itself to `window`; the official `.d.ts` declares the same\n * fields, so this file reads them through a local shape instead of augmenting\n * `Window` twice.\n */\ntype InpostGlobalWindow = Window & {\n InPostPayWidget?: InPostWidgetNamespace;\n __INPOST_PAY_WIDGET__?: InPostPayWidgetInstance;\n __bitsnapInpostOwner?: {\n projectID: string;\n host: string;\n merchantClientId: string;\n };\n};\n\nfunction inpostWindow(): InpostGlobalWindow | undefined {\n return typeof window === \"undefined\"\n ? undefined\n : (window as InpostGlobalWindow);\n}\n\n/** The official placement attribute of the widget's custom element. */\nexport const INPOST_IZI_BUTTON_TAG = \"inpost-izi-button\";\nexport const INPOST_THANK_YOU_TAG = \"inpost-thank-you\";\n\n/** Official `binding_place` values this SDK exposes. */\nexport const INPOST_BINDING_PLACES = [\n \"PRODUCT_CARD\",\n \"BASKET_SUMMARY\",\n \"MINICART_PAGE\",\n \"CHECKOUT_PAGE\",\n \"ORDER_CREATE\",\n \"THANK_YOU_PAGE\",\n] as const;\nexport type InPostBindingPlace = (typeof INPOST_BINDING_PLACES)[number];\n\nexport function inpostLanguage(locale: string | undefined): \"pl\" | \"en\" {\n return locale != null && /^pl\\b/i.test(locale) ? \"pl\" : \"en\";\n}\n\n/** The InPost Pay API base of a sandbox/test configuration. */\nexport const INPOST_SANDBOX_API_BASE_URL =\n \"https://sandbox-inpostpay-widget-api.inpost.pl\";\n\n/** The production InPost Pay widget API base. */\nexport const INPOST_PRODUCTION_API_BASE_URL =\n \"https://inpostpay-widget-api.inpost.pl\";\n\nexport const INPOST_WIDGET_SCRIPT_URL = {\n test: \"https://sandbox-inpostpay-widget-v2.inpost.pl/inpostpay.widget.v2.js\",\n production: \"https://inpostpay-widget-v2.inpost.pl/inpostpay.widget.v2.js\",\n} as const;\n\nexport const INPOST_WIDGET_API_BASE_URL = {\n test: INPOST_SANDBOX_API_BASE_URL,\n production: INPOST_PRODUCTION_API_BASE_URL,\n} as const;\n\nexport type InPostWidgetEnvironment = \"test\" | \"production\";\n\nexport type InPostPublicConfig = {\n merchantClientId: string;\n environment: InPostWidgetEnvironment;\n /** The widget API base the browser must talk to. */\n apiBaseUrl: string;\n /** The official script URL of this environment (informational). */\n scriptUrl: string;\n basketBindingApiKey?: string;\n basketId?: string;\n};\n\nfunction widgetEnvironment(\n value: string | undefined,\n fallback: InPostWidgetEnvironment | undefined,\n): InPostWidgetEnvironment {\n if (value === \"test\" || value === \"production\") {\n return value;\n }\n if (value === \"prod\" || value === \"live\") {\n return \"production\";\n }\n return fallback ?? \"production\";\n}\n\nfunction isSandboxURL(value: string): boolean {\n return value.includes(\"sandbox\");\n}\n\n/**\n * Reads the backend's public InPost configuration. Canonical names are\n * `merchantClientId`, `widgetApiBaseUrl`, `widgetScriptUrl` and `environment`;\n * the older `apiBaseUrl` alias is still accepted. A test cart can never be\n * pointed at the production widget API, and a production cart can never be\n * pointed at the sandbox one.\n */\nexport function readInpostPublicConfig(\n config: Record<string, string> | undefined,\n fallbackEnvironment?: InPostWidgetEnvironment,\n): InPostPublicConfig | undefined {\n if (config == null) {\n return undefined;\n }\n const merchantClientId = config.merchantClientId;\n if (merchantClientId == null || merchantClientId.length === 0) {\n return undefined;\n }\n const environment =\n fallbackEnvironment ?? widgetEnvironment(config.environment, undefined);\n const requestedApiBaseUrl = config.widgetApiBaseUrl ?? config.apiBaseUrl;\n const requestedScriptUrl = config.widgetScriptUrl;\n const apiBaseUrl =\n environment === \"test\"\n ? requestedApiBaseUrl != null && isSandboxURL(requestedApiBaseUrl)\n ? requestedApiBaseUrl\n : INPOST_WIDGET_API_BASE_URL.test\n : requestedApiBaseUrl != null && !isSandboxURL(requestedApiBaseUrl)\n ? requestedApiBaseUrl\n : INPOST_WIDGET_API_BASE_URL.production;\n const scriptUrl =\n environment === \"test\"\n ? requestedScriptUrl != null && isSandboxURL(requestedScriptUrl)\n ? requestedScriptUrl\n : INPOST_WIDGET_SCRIPT_URL.test\n : requestedScriptUrl != null && !isSandboxURL(requestedScriptUrl)\n ? requestedScriptUrl\n : INPOST_WIDGET_SCRIPT_URL.production;\n return {\n merchantClientId,\n environment,\n apiBaseUrl,\n scriptUrl,\n ...(config.basketBindingApiKey != null &&\n config.basketBindingApiKey.length > 0\n ? { basketBindingApiKey: config.basketBindingApiKey }\n : {}),\n ...(config.basketId != null && config.basketId.length > 0\n ? { basketId: config.basketId }\n : {}),\n };\n}\n\nlet widgetLoader: Promise<InPostWidgetNamespace> | undefined;\n\n/** Test seam: drop the cached loader between cases. */\nexport function resetInpostWidgetLoader(): void {\n widgetLoader = undefined;\n const win = inpostWindow();\n if (win != null) {\n delete win.__bitsnapInpostOwner;\n }\n}\n\n/**\n * Loads the widget once per page. Rejects on the server, where the widget has\n * nothing to render into.\n */\nexport function loadInpostWidget(): Promise<InPostWidgetNamespace> {\n if (typeof window === \"undefined\") {\n return Promise.reject(new Error(\"InPost Pay needs a browser.\"));\n }\n const alreadyLoaded = inpostWindow()?.InPostPayWidget;\n if (alreadyLoaded != null) {\n return Promise.resolve(alreadyLoaded);\n }\n widgetLoader ??= import(\"@inpost-pay/widget\")\n .then((module: unknown) => {\n const record = module as {\n initialiseInpostPayWidget?: unknown;\n default?:\n | { initialiseInpostPayWidget?: unknown }\n | ((options: InPostWidgetInitOptions) => InPostPayWidgetInstance);\n };\n const fromModule =\n typeof record.initialiseInpostPayWidget === \"function\"\n ? (record.initialiseInpostPayWidget as InPostWidgetNamespace[\"init\"])\n : typeof record.default === \"function\"\n ? (record.default as InPostWidgetNamespace[\"init\"])\n : typeof record.default?.initialiseInpostPayWidget === \"function\"\n ? (record.default\n .initialiseInpostPayWidget as InPostWidgetNamespace[\"init\"])\n : undefined;\n const namespace = inpostWindow()?.InPostPayWidget;\n if (namespace != null) {\n return namespace;\n }\n if (fromModule != null) {\n return { init: fromModule };\n }\n throw new Error(\"The InPost Pay widget exposed no init function.\");\n })\n .catch((error: unknown) => {\n widgetLoader = undefined;\n throw error;\n });\n return widgetLoader;\n}\n\n/**\n * Initialises the widget for one project and reuses an existing instance only\n * when it belongs to the same project, host and merchant client id.\n *\n * The official widget is a page-wide singleton: a second merchant client id on\n * the same page cannot be rendered without taking the first one over, so this\n * function refuses instead of leaking another shop's configuration into the\n * button.\n */\nexport function initInpostWidget(args: {\n namespace: InPostWidgetNamespace;\n options: InPostWidgetInitOptions;\n owner: { projectID: string; host: string; merchantClientId: string };\n warn?: (message: string) => void;\n}): InPostPayWidgetInstance | undefined {\n if (typeof window === \"undefined\") {\n return undefined;\n }\n const win = window as InpostGlobalWindow;\n const currentOwner = win.__bitsnapInpostOwner;\n const existing = win.__INPOST_PAY_WIDGET__;\n if (existing != null) {\n const sameOwner =\n currentOwner != null &&\n currentOwner.projectID === args.owner.projectID &&\n currentOwner.host === args.owner.host &&\n currentOwner.merchantClientId === args.owner.merchantClientId;\n if (!sameOwner) {\n // A full unmount leaves no widget element behind. Only then may a\n // different project take the page-wide instance over; while an element\n // is still mounted, refuse instead of leaking another shop's config.\n if (hasInpostElements()) {\n args.warn?.(\n \"InPost Pay already runs for another project on this page; mount one InPost Pay button per page.\",\n );\n return undefined;\n }\n delete win.__INPOST_PAY_WIDGET__;\n delete win.__bitsnapInpostOwner;\n } else {\n // A remount of the same project reuses the singleton, but its callbacks\n // must point at the new component instance (refs and props may differ).\n existing.refresh(args.options);\n return existing;\n }\n }\n const widget = args.namespace.init(args.options);\n win.__INPOST_PAY_WIDGET__ = widget;\n win.__bitsnapInpostOwner = args.owner;\n return widget;\n}\n\nfunction hasInpostElements(): boolean {\n if (typeof document === \"undefined\") {\n return false;\n }\n return (\n document.querySelector(\n `${INPOST_IZI_BUTTON_TAG}, ${INPOST_THANK_YOU_TAG}`,\n ) != null\n );\n}\n\n/** Attributes of the official `<inpost-izi-button>` custom element. */\nexport function inpostIziButtonAttributes(args: {\n bindingPlace: InPostBindingPlace;\n productId?: string;\n variation?: string;\n}): Record<string, string> {\n return {\n binding_place: args.bindingPlace,\n ...(args.productId != null ? { \"data-product-id\": args.productId } : {}),\n ...(args.variation != null ? { variation: args.variation } : {}),\n };\n}\n","import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from \"react\";\nimport {\n buildLocalCartUpload,\n localCartVersionSnapshot,\n readLocalCartLines,\n subscribeToLocalCart,\n} from \"@/src/components/checkout/CartProvider\";\nimport { HOST } from \"@/src/components/checkout/constants\";\nimport {\n createExpressSession,\n sdkLocalCart,\n} from \"./cart-adapter\";\nimport type { ExpressCartLocal } from \"./cart-session\";\nimport type {\n ExpressAvailability,\n ExpressCartUpload,\n ProviderAvailability,\n} from \"./contracts\";\nimport {\n prepareExpressCartUpload,\n readDeliveryQuote,\n withDeliveryQuote,\n} from \"./delivery-quote\";\nimport { fetchExpressAvailability, type FetchLike } from \"./client\";\n\n/**\n * React glue between the express client and the buttons. Everything is\n * browser-only: nothing is requested while rendering on the server, and no\n * state is shared between two projects or two hosts.\n */\n\nexport type ExpressItem = { id: string; quantity: number };\n\nexport type ExpressCartSource = \"items\" | \"cart\" | \"product\";\n\nexport type ResolvedExpressCart = {\n items: ExpressItem[];\n source: ExpressCartSource;\n country?: string;\n couponCode?: string;\n /** The product the widget adds on click, when used on a product page. */\n productId?: string;\n productQuantity: number;\n};\n\nexport function resolveExpressCart(args: {\n items?: ExpressItem[];\n productId?: string;\n quantity?: number;\n country?: string;\n couponCode?: string;\n}): ResolvedExpressCart {\n const productQuantity = Math.max(1, Math.trunc(args.quantity ?? 1));\n const base = {\n ...(args.country != null ? { country: args.country } : {}),\n ...(args.couponCode != null ? { couponCode: args.couponCode } : {}),\n productQuantity,\n };\n if (args.items != null && args.items.length > 0) {\n return {\n ...base,\n items: args.items.map((item) => ({\n id: item.id,\n quantity: Math.max(1, Math.trunc(item.quantity)),\n })),\n source: \"items\",\n };\n }\n const cart = readLocalCartLines().map((line) => ({\n id: line.productID,\n quantity: line.quantity,\n }));\n if (args.productId != null && args.productId.length > 0) {\n const present = cart.some((line) => line.id === args.productId);\n return {\n ...base,\n items: present\n ? cart\n : [...cart, { id: args.productId, quantity: productQuantity }],\n source: \"product\",\n productId: args.productId,\n };\n }\n return { ...base, items: cart, source: \"cart\" };\n}\n\nexport function expressCartSignature(cart: ResolvedExpressCart): string {\n const lines = cart.items\n .map((line) => `${line.id}:${line.quantity}`)\n .sort()\n .join(\",\");\n return [\n cart.source,\n lines,\n cart.country ?? \"\",\n cart.couponCode ?? \"\",\n cart.productId ?? \"\",\n ].join(\"|\");\n}\n\n/**\n * The cart adapter the session writes through. Explicit `items` belong to the\n * merchant's own cart: the SDK uploads them but never edits the merchant's\n * state. Otherwise the SDK cart is the basket, as in the drawer checkout.\n */\nexport function expressCartLocal(\n cart: ResolvedExpressCart,\n locale: string,\n options: { host: string; projectID: string },\n): ExpressCartLocal {\n if (cart.source === \"cart\") {\n return sdkLocalCart(options);\n }\n const upload: ExpressCartUpload = {\n items: cart.items.map((item) => ({ id: item.id, quantity: item.quantity })),\n ...(cart.country != null ? { countries: [cart.country] } : {}),\n ...(cart.couponCode != null ? { couponCode: cart.couponCode } : {}),\n locale,\n };\n return {\n lines: () => cart.items,\n signature: () => expressCartSignature(cart),\n upload: () =>\n withDeliveryQuote(\n upload,\n readDeliveryQuote(options.host, options.projectID, upload),\n ),\n adoptSnapshot: () => {},\n appendLines: () => {},\n removeLines: () => {},\n };\n}\n\nexport type UseExpressAvailabilityArgs = {\n provider: \"inpostPay\" | \"revolutPay\";\n projectID: string | undefined;\n host?: string;\n locale: string;\n items?: ExpressItem[];\n productId?: string;\n quantity?: number;\n country?: string;\n couponCode?: string;\n enabled?: boolean;\n fetch?: FetchLike;\n};\n\nexport type ExpressAvailabilityState = {\n loading: boolean;\n provider: ProviderAvailability | undefined;\n environment: \"test\" | \"production\" | undefined;\n /** True when the backend does not implement the express API or failed. */\n failed: boolean;\n};\n\n/**\n * Re-renders when the local Bitsnap cart changes. Standalone buttons use it so\n * their eligibility follows quantity/remove/country/coupon edits made anywhere\n * on the page, not only a parent re-render.\n */\nexport function useLocalCartVersion(): number {\n return useSyncExternalStore(\n subscribeToLocalCart,\n localCartVersionSnapshot,\n () => 0,\n );\n}\n\n/**\n * Asks for provider availability of the current cart. Re-asks when the cart\n * content, project, host or locale changes; an older answer is discarded.\n */\nexport function useExpressAvailability(\n args: UseExpressAvailabilityArgs,\n): ExpressAvailabilityState {\n const latest = useRef(args);\n latest.current = args;\n const cart = resolveExpressCart(args);\n const signature = expressCartSignature(cart);\n const cartVersion = useLocalCartVersion();\n const [state, setState] = useState<ExpressAvailabilityState>({\n loading: false,\n provider: undefined,\n environment: undefined,\n failed: false,\n });\n\n useEffect(() => {\n const current = latest.current;\n if (\n current.enabled === false ||\n current.projectID == null ||\n current.projectID.length === 0 ||\n typeof window === \"undefined\"\n ) {\n setState({\n loading: false,\n provider: undefined,\n environment: undefined,\n failed: false,\n });\n return;\n }\n const resolved = resolveExpressCart(current);\n if (resolved.items.length === 0) {\n setState({\n loading: false,\n provider: undefined,\n environment: undefined,\n failed: false,\n });\n return;\n }\n const controller = new AbortController();\n let active = true;\n setState((previous) => ({ ...previous, loading: true }));\n getExpressAvailability({\n projectID: current.projectID,\n ...(current.host != null ? { host: current.host } : {}),\n locale: current.locale,\n cart: resolved,\n ...(current.fetch != null ? { fetch: current.fetch } : {}),\n signal: controller.signal,\n })\n .then((availability) => {\n if (!active) {\n return;\n }\n const provider = availability?.providers?.[current.provider];\n setState({\n loading: false,\n provider,\n environment: availability?.environment ?? provider?.environment,\n failed: availability == null,\n });\n })\n .catch(() => {\n if (active) {\n setState({\n loading: false,\n provider: undefined,\n environment: undefined,\n failed: true,\n });\n }\n });\n return () => {\n active = false;\n controller.abort();\n };\n }, [\n signature,\n cartVersion,\n args.projectID,\n args.host,\n args.provider,\n args.locale,\n args.enabled,\n ]);\n\n return state;\n}\n\n/** A session bound to one project + host, recreated when either changes. */\nexport function useExpressSession(args: {\n projectID: string | undefined;\n host?: string;\n fetch?: FetchLike;\n signal?: AbortSignal;\n}) {\n return useMemo(\n () =>\n args.projectID == null\n ? undefined\n : createExpressSession({\n projectID: args.projectID,\n ...(args.host != null ? { host: args.host } : {}),\n ...(args.fetch != null ? { fetch: args.fetch } : {}),\n ...(args.signal != null ? { signal: args.signal } : {}),\n }),\n [args.projectID, args.host, args.fetch, args.signal],\n );\n}\n\nexport function resolveExpressHost(host: string | undefined): string {\n return host ?? HOST;\n}\n\n/** The availability/upload body of a resolved express cart. */\nexport function expressUploadFor(\n cart: ResolvedExpressCart,\n locale: string,\n options?: { host?: string; projectID?: string },\n): ExpressCartUpload | undefined {\n const upload =\n cart.source === \"cart\"\n ? buildLocalCartUpload(locale)\n : cart.items.length === 0\n ? undefined\n : {\n items: cart.items.map((item) => ({\n id: item.id,\n quantity: item.quantity,\n })),\n ...(cart.country != null ? { countries: [cart.country] } : {}),\n ...(cart.couponCode != null ? { couponCode: cart.couponCode } : {}),\n locale,\n };\n if (upload == null) {\n return undefined;\n }\n if (options?.host == null || options.projectID == null) {\n return upload;\n }\n return withDeliveryQuote(\n upload,\n readDeliveryQuote(options.host, options.projectID, upload),\n );\n}\n\n/**\n * Availability of one provider for the current browser cart. Resolves the\n * delivery quote first (and remembers it for the start call); without it no\n * express button renders, because a shipping-free total would be wrong.\n */\nexport async function getExpressAvailability(\n options: {\n projectID: string;\n host?: string;\n locale: string;\n cart: ResolvedExpressCart;\n fetch?: FetchLike;\n signal?: AbortSignal;\n },\n): Promise<ExpressAvailability | undefined> {\n const host = options.host ?? HOST;\n const upload = expressUploadFor(options.cart, options.locale);\n if (upload == null) {\n return undefined;\n }\n const prepared = await prepareExpressCartUpload({\n host,\n projectID: options.projectID,\n upload,\n });\n if (!prepared.ok) {\n return undefined;\n }\n const availability = await fetchExpressAvailability(\n {\n projectID: options.projectID,\n host,\n ...(options.fetch != null ? { fetch: options.fetch } : {}),\n ...(options.signal != null ? { signal: options.signal } : {}),\n },\n prepared.upload,\n );\n if (availability == null) {\n return undefined;\n }\n if (prepared.quote.delivery.length === 0) {\n return availability;\n }\n // Revolut Pay express collects no shipping address (start refuses a\n // deliverable cart), so it must not mount with a total that includes no\n // shipping. InPost Pay carries the quoted delivery in its basket.\n const revolutPay = availability.providers.revolutPay;\n if (revolutPay == null || revolutPay.available !== true) {\n return availability;\n }\n return {\n ...availability,\n providers: {\n ...availability.providers,\n revolutPay: {\n ...revolutPay,\n available: false,\n reasons: [...revolutPay.reasons, \"delivery-unsupported\"],\n },\n },\n };\n}\n","import type { ExpressPayStatus } from \"./contracts\";\n\n/**\n * Provider status is server-authoritative. A browser `success`/`orderCreated`\n * event only means \"the widget finished\"; the SDK asks Bitsnap until the\n * verified callback settles the order (or gives up and leaves the attempt for\n * the next visit). Nothing in this module reads a browser callback as proof of\n * payment.\n */\n\nexport type RevolutPublicConfig = {\n publicKey: string;\n mode: \"sandbox\" | \"prod\";\n /** The public order token of this attempt (start response only). */\n orderToken?: string;\n};\n\n/** Validates the public config of the start/availability answer. */\nexport function readRevolutPublicConfig(\n config: Record<string, string> | undefined,\n): RevolutPublicConfig | undefined {\n if (config == null) {\n return undefined;\n }\n const publicKey = config.publicKey ?? config.publicToken;\n const mode = config.mode;\n if (publicKey == null || publicKey.length === 0) {\n return undefined;\n }\n if (mode !== \"sandbox\" && mode !== \"prod\") {\n return undefined;\n }\n return {\n publicKey,\n mode,\n ...(config.orderToken != null && config.orderToken.length > 0\n ? { orderToken: config.orderToken }\n : {}),\n };\n}\n\n/** `{ publicId: orderToken }` — the documented `createOrder` answer. */\nexport function revolutOrderToken(\n start: { publicConfig?: Record<string, string>; providerOrderId: string },\n): string {\n const fromConfig = start.publicConfig?.orderToken;\n if (fromConfig != null && fromConfig.length > 0) {\n return fromConfig;\n }\n // Older backend builds put the public token in the public order id.\n return start.providerOrderId;\n}\n\nexport function revolutLocale(locale: string | undefined): \"pl\" | \"en\" {\n return locale != null && /^pl\\b/i.test(locale) ? \"pl\" : \"en\";\n}\n\n/** The provider is available only when the SDK can actually be initialised. */\nexport function isRevolutPayable(config: RevolutPublicConfig | undefined): boolean {\n return config != null;\n}\n\nexport type PollOptions = {\n check: () => Promise<ExpressPayStatus>;\n timeoutMs?: number;\n intervalMs?: number;\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n signal?: AbortSignal;\n};\n\nconst DEFAULT_TIMEOUT_MS = 60_000;\nconst DEFAULT_INTERVAL_MS = 2_000;\n\nfunction defaultSleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Asks Bitsnap for a provider status until it leaves `pending`, the timeout\n * elapses, or the caller aborts. Resolves with the last status; a transport\n * failure resolves `undefined`. A timeout keeps the attempt pending so a later\n * visit checks again.\n */\nexport async function pollProviderStatus(\n options: PollOptions,\n): Promise<ExpressPayStatus | undefined> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;\n const sleep = options.sleep ?? defaultSleep;\n const startedAt = (options.now ?? Date.now)();\n // Even with a frozen clock the loop is bounded, so a test or a system whose\n // clock jumps cannot spin forever.\n const maxAttempts = Math.min(\n 10_000,\n Math.max(1, Math.ceil(timeoutMs / Math.max(1, intervalMs)) + 1),\n );\n let attempts = 0;\n let last: ExpressPayStatus | undefined;\n\n for (;;) {\n attempts += 1;\n if (options.signal?.aborted === true) {\n return last;\n }\n try {\n last = await options.check();\n } catch {\n last = undefined;\n }\n if (last?.ok === true && last.status !== \"pending\") {\n return last;\n }\n if (last?.ok === false && last.code === \"not-implemented\") {\n // An old backend cannot confirm; leave the attempt for later instead of\n // spinning.\n return last;\n }\n if (\n attempts >= maxAttempts ||\n (options.now ?? Date.now)() - startedAt >= timeoutMs\n ) {\n return last;\n }\n await sleep(intervalMs);\n }\n}\n\n/** Revolut Pay keeps its historical name at the call sites. */\nexport const pollRevolutStatus = pollProviderStatus;\n","import { cn } from \"@/src/lib/utils\";\nimport { useCheckoutSlot } from \"@/src/components/checkout/appearance.context\";\nimport { useCheckoutTextResolver } from \"@/src/components/checkout/texts.context\";\nimport type { CheckoutTextKey } from \"@/src/components/checkout/texts\";\n\n/** What an express button is doing, for the status line under it. */\nexport type ExpressPhase =\n | \"idle\"\n | \"pending\"\n | \"confirmed\"\n | \"failed\"\n | \"cancelled\"\n | \"load-failed\"\n | \"cart-unavailable\"\n | \"cart-conflict\"\n | \"price-changed\"\n | \"product-unavailable\";\n\nconst PHASE_TEXT: Record<Exclude<ExpressPhase, \"idle\">, CheckoutTextKey> = {\n pending: \"expressPending\",\n confirmed: \"expressConfirmed\",\n failed: \"expressFailed\",\n cancelled: \"expressCancelled\",\n \"load-failed\": \"expressLoadFailed\",\n \"cart-unavailable\": \"expressCartUnavailable\",\n \"cart-conflict\": \"expressCartConflict\",\n \"price-changed\": \"expressPriceChanged\",\n \"product-unavailable\": \"expressProductUnavailable\",\n};\n\nconst ALERT_PHASES: ExpressPhase[] = [\n \"failed\",\n \"cancelled\",\n \"load-failed\",\n \"cart-unavailable\",\n \"cart-conflict\",\n \"price-changed\",\n \"product-unavailable\",\n];\n\n/**\n * The accessible line under an express button. Confirmations and \"confirming\"\n * are polite statuses; failures interrupt (`role=\"alert\"`). The cart is never\n * cleared or claimed paid here.\n */\nexport function ExpressStatus({ phase }: { phase: ExpressPhase }) {\n const resolve = useCheckoutTextResolver();\n const errorSlot = useCheckoutSlot(\"error\");\n if (phase === \"idle\") {\n return null;\n }\n const isAlert = ALERT_PHASES.includes(phase);\n return (\n <p\n role={isAlert ? \"alert\" : \"status\"}\n aria-live={isAlert ? \"assertive\" : \"polite\"}\n data-bitsnap-express-status={phase}\n className={cn(\n \"w-full px-2 text-center text-sm\",\n isAlert && \"opacity-90\",\n errorSlot.className,\n )}\n style={errorSlot.style}\n >\n {resolve(PHASE_TEXT[phase])}\n </p>\n );\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n} from \"react\";\nimport {\n InstrumentProvider,\n useInstrument,\n useInstrumentContext,\n type AnalyticsOption,\n} from \"@/src/analytics/instrument\";\nimport type { CheckoutAppearance } from \"@/src/components/checkout/appearance\";\nimport { CheckoutAppearanceProvider } from \"@/src/components/checkout/appearance.context\";\nimport { setProjectID } from \"@/src/components/checkout/CartProvider\";\nimport { getLocale } from \"@/src/components/checkout/locale\";\nimport { currentProjectID } from \"@/src/components/checkout/project-id\";\nimport type { CheckoutTexts } from \"@/src/components/checkout/texts\";\nimport { CheckoutTextsProvider } from \"@/src/components/checkout/texts.context\";\nimport {\n createExpressSession,\n getRevolutStatus,\n startProviderForCart,\n} from \"@/src/express/cart-adapter\";\nimport { activePendingAttempt } from \"@/src/express/cart-record\";\nimport type { ExpressCartSession } from \"@/src/express/cart-session\";\nimport type { FetchLike } from \"@/src/express/client\";\nimport {\n expressCartLocal,\n resolveExpressCart,\n resolveExpressHost,\n useExpressAvailability,\n useLocalCartVersion,\n type ExpressItem,\n} from \"@/src/express/react\";import {\n pollRevolutStatus,\n readRevolutPublicConfig,\n revolutLocale,\n revolutOrderToken,\n type RevolutPublicConfig,\n} from \"@/src/express/revolut\";\nimport {\n createRevolutPayments,\n loadRevolutCheckout,\n type RevolutPayButtonStyle,\n type RevolutPaymentEvent,\n} from \"@/src/express/revolut-sdk\";\nimport {\n readExpressReturn,\n withExpressReturn,\n withoutExpressReturn,\n} from \"@/src/express/return-url\";\nimport { ExpressStatus, type ExpressPhase } from \"./ExpressStatus\";\n\n/**\n * Revolut Pay, mounted through the official Revolut Checkout embed script.\n *\n * The SDK is lazy: it loads only after Bitsnap says the provider is available\n * with a public `publicKey`, and only in the browser. The order is created by\n * the server (`createOrder` calls Bitsnap), never by the browser's numbers.\n *\n * A widget `success` event is a UX signal only: the button shows \"confirming\"\n * and asks Bitsnap (`revolut/status`) until the verified webhook settles the\n * order. Only then are the purchased lines removed from the cart. Cancel,\n * failure and timeout keep the cart exactly as it was.\n */\n\nexport type RevolutPaymentOutcome =\n | { status: \"completed\"; orderId?: string }\n | { status: \"pending\" }\n | { status: \"failed\" }\n | { status: \"cancelled\" };\n\nexport type RevolutPayButtonProps = {\n /** Bitsnap project; optional when the page called `setProjectID(...)`. */\n projectID?: string;\n host?: string;\n locale?: string;\n texts?: Partial<CheckoutTexts>;\n appearance?: CheckoutAppearance;\n /** Explicit cart lines for a custom cart layout; omitted: the Bitsnap cart. */\n items?: ExpressItem[];\n /** Product page support: uploads this product (with `quantity`) as the cart. */\n productId?: string;\n quantity?: number;\n country?: string;\n couponCode?: string;\n /** Page the buyer returns to; defaults to the current page. */\n returnUrl?: string;\n cancelUrl?: string;\n /** Official Revolut button appearance. */\n buttonStyle?: RevolutPayButtonStyle;\n className?: string;\n style?: CSSProperties;\n analytics?: AnalyticsOption;\n /** Called with the browser-level outcome; `completed` is server-confirmed. */\n onPaymentResult?: (outcome: RevolutPaymentOutcome) => void;\n fetch?: FetchLike;\n /** Polling bounds for the server confirmation (tests use a fake sleep). */\n confirmation?: {\n timeoutMs?: number;\n intervalMs?: number;\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n };\n};\n\nfunction RevolutPayButtonInner(\n props: RevolutPayButtonProps & { projectID: string },\n) {\n const { projectID } = props;\n const host = resolveExpressHost(props.host);\n const locale = props.locale ?? getLocale();\n const instrument = useInstrumentContext();\n const confirmationTimeoutMs = props.confirmation?.timeoutMs;\n const confirmationIntervalMs = props.confirmation?.intervalMs;\n const confirmationSleep = props.confirmation?.sleep;\n const confirmationNow = props.confirmation?.now;\n const buttonStyleKey = JSON.stringify(props.buttonStyle ?? null);\n const cartVersion = useLocalCartVersion();\n const cart = useMemo(\n () =>\n resolveExpressCart({\n ...(props.items != null ? { items: props.items } : {}),\n ...(props.productId != null ? { productId: props.productId } : {}),\n ...(props.quantity != null ? { quantity: props.quantity } : {}),\n ...(props.country != null ? { country: props.country } : {}),\n ...(props.couponCode != null ? { couponCode: props.couponCode } : {}),\n }),\n [\n props.items,\n props.productId,\n props.quantity,\n props.country,\n props.couponCode,\n cartVersion,\n ],\n );\n const signature = [cart.source, cart.items.map((line) => `${line.id}:${line.quantity}`).sort().join(\",\")].join(\"|\");\n const availability = useExpressAvailability({\n provider: \"revolutPay\",\n projectID,\n host,\n locale,\n ...(props.items != null ? { items: props.items } : {}),\n ...(props.productId != null ? { productId: props.productId } : {}),\n ...(props.quantity != null ? { quantity: props.quantity } : {}),\n ...(props.country != null ? { country: props.country } : {}),\n ...(props.couponCode != null ? { couponCode: props.couponCode } : {}),\n ...(props.fetch != null ? { fetch: props.fetch } : {}),\n });\n const config: RevolutPublicConfig | undefined =\n availability.provider?.available === true\n ? readRevolutPublicConfig(availability.provider.publicConfig)\n : undefined;\n const environment =\n availability.provider?.environment ?? availability.environment;\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [phase, setPhase] = useState<ExpressPhase>(\"idle\");\n const [mountNonce, setMountNonce] = useState(0);\n const mounted = useRef(true);\n /** The canonical total the currently mounted button was created with. */\n const mountedAmount = useRef<\n { cartId: string; currency: string; totalMinor: number } | undefined\n >(undefined);\n /** A phase an async failure already surfaced (so the SDK error cannot hide it). */\n const surfacedPhase = useRef<ExpressPhase | undefined>(undefined);\n\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n\n useEffect(() => {\n if (\n config == null ||\n typeof window === \"undefined\" ||\n containerRef.current == null\n ) {\n return;\n }\n const controller = new AbortController();\n let cancelled = false;\n let destroySdk: (() => void) | undefined;\n\n const local = expressCartLocal(cart, locale, { host, projectID });\n const session = createExpressSession({\n projectID,\n host,\n local,\n ...(props.fetch != null ? { fetch: props.fetch } : {}),\n signal: controller.signal,\n });\n\n const returnBase = props.returnUrl ?? window.location.href;\n let confirming = false;\n let settled = false;\n const confirm = async (activeSession: ExpressCartSession) => {\n if (!mounted.current || settled) {\n return;\n }\n setPhase(\"pending\");\n const status = await pollRevolutStatus({\n check: () =>\n getRevolutStatus(\n {\n projectID,\n host,\n ...(props.fetch != null ? { fetch: props.fetch } : {}),\n signal: controller.signal,\n },\n activeSession,\n ),\n signal: controller.signal,\n ...(confirmationTimeoutMs != null\n ? { timeoutMs: confirmationTimeoutMs }\n : {}),\n ...(confirmationIntervalMs != null\n ? { intervalMs: confirmationIntervalMs }\n : {}),\n ...(confirmationSleep != null ? { sleep: confirmationSleep } : {}),\n ...(confirmationNow != null ? { now: confirmationNow } : {}),\n });\n if (cancelled || !mounted.current) {\n return;\n }\n if (status?.ok === true && status.status === \"completed\") {\n settled = true;\n // Purchased lines only; what the buyer added meanwhile stays and a\n // later express attempt uploads it as a new cart.\n activeSession.completePurchase();\n setPhase(\"confirmed\");\n props.onPaymentResult?.({\n status: \"completed\",\n ...(status.orderId != null ? { orderId: status.orderId } : {}),\n });\n return;\n }\n if (status?.ok === true && status.status === \"failed\") {\n settled = true;\n activeSession.clearPending();\n setPhase(\"failed\");\n props.onPaymentResult?.({ status: \"failed\" });\n return;\n }\n if (status?.ok === true && status.status === \"cancelled\") {\n settled = true;\n activeSession.clearPending();\n setPhase(\"cancelled\");\n props.onPaymentResult?.({ status: \"cancelled\" });\n return;\n }\n // Unconfirmed (webhook late, old backend, timeout): keep the attempt for\n // the next visit instead of claiming a payment.\n setPhase(\"pending\");\n props.onPaymentResult?.({ status: \"pending\" });\n };\n\n const confirmOnce = (activeSession: ExpressCartSession) => {\n if (confirming) {\n return;\n }\n confirming = true;\n void confirm(activeSession).finally(() => {\n confirming = false;\n });\n };\n\n const handlePayment = (event: RevolutPaymentEvent) => {\n if (event.type === \"cancel\") {\n instrument.track(\"payment_returned\", {\n gateway: \"revolut_pay\",\n method: \"revolut_pay\",\n outcome: \"cancel\",\n });\n session.clearPending();\n setPhase(\"cancelled\");\n props.onPaymentResult?.({ status: \"cancelled\" });\n return;\n }\n if (event.type === \"error\") {\n instrument.track(\"payment_returned\", {\n gateway: \"revolut_pay\",\n method: \"revolut_pay\",\n outcome: \"fail\",\n });\n session.clearPending();\n const surfaced = surfacedPhase.current;\n surfacedPhase.current = undefined;\n setPhase(surfaced ?? \"failed\");\n if (surfaced == null) {\n props.onPaymentResult?.({ status: \"failed\" });\n }\n return;\n }\n instrument.track(\"payment_returned\", {\n gateway: \"revolut_pay\",\n method: \"revolut_pay\",\n outcome: \"pending\",\n });\n confirmOnce(session);\n };\n\n const mount = async () => {\n const ensured = await session.ensure({\n locale,\n ...(environment != null ? { environment } : {}),\n });\n if (cancelled) {\n return;\n }\n if (!ensured.ok) {\n setPhase(\n ensured.code === \"revision-conflict\"\n ? \"cart-conflict\"\n : \"cart-unavailable\",\n );\n return;\n }\n const snapshot = ensured.value.snapshot;\n mountedAmount.current = {\n cartId: snapshot.cartId,\n currency: snapshot.currency,\n totalMinor: snapshot.totalMinor,\n };\n\n const namespace = await loadRevolutCheckout(config.mode);\n if (cancelled) {\n return;\n }\n const payments = await createRevolutPayments(namespace, {\n publicKey: config.publicKey,\n mode: config.mode,\n locale: revolutLocale(locale),\n });\n if (cancelled) {\n payments.destroy?.();\n return;\n }\n const { revolutPay } = payments;\n\n let orderInFlight: Promise<{ publicId: string }> | undefined;\n const createOrder = async (): Promise<{ publicId: string }> => {\n if (orderInFlight != null) {\n // A double click must not create two provider orders.\n return orderInFlight;\n }\n orderInFlight = (async () => {\n // The button was mounted with a total. Re-read the canonical cart\n // right before paying: if the server total or currency changed, do\n // not open the provider for the stale amount; remount with the new\n // one and ask the buyer to confirm it.\n const current = await session.ensure({\n locale,\n ...(environment != null ? { environment } : {}),\n });\n if (!current.ok) {\n surfacedPhase.current =\n current.code === \"revision-conflict\"\n ? \"cart-conflict\"\n : \"cart-unavailable\";\n throw new Error(`revolut-cart-${current.code}`);\n }\n if (!sameMountedAmount(current.value.snapshot, mountedAmount.current)) {\n mountedAmount.current = {\n cartId: current.value.snapshot.cartId,\n currency: current.value.snapshot.currency,\n totalMinor: current.value.snapshot.totalMinor,\n };\n surfacedPhase.current = \"price-changed\";\n setPhase(\"price-changed\");\n setMountNonce((value) => value + 1);\n throw new Error(\"revolut-amount-changed\");\n }\n\n const result = await startProviderForCart(\n {\n projectID,\n host,\n locale,\n ...(environment != null ? { environment } : {}),\n returnUrl: returnBase,\n cancelUrl: props.cancelUrl ?? returnBase,\n embedOrigin: window.location.origin,\n ...(props.fetch != null ? { fetch: props.fetch } : {}),\n },\n \"revolutPay\",\n session,\n );\n if (!result.ok) {\n surfacedPhase.current =\n result.code === \"revision-conflict\"\n ? \"cart-conflict\"\n : \"cart-unavailable\";\n throw new Error(`revolut-start-${result.code}`);\n }\n if (!sameMountedAmount(result.value.snapshot, mountedAmount.current)) {\n mountedAmount.current = {\n cartId: result.value.snapshot.cartId,\n currency: result.value.snapshot.currency,\n totalMinor: result.value.snapshot.totalMinor,\n };\n surfacedPhase.current = \"price-changed\";\n setPhase(\"price-changed\");\n setMountNonce((value) => value + 1);\n throw new Error(\"revolut-amount-changed\");\n }\n instrument.track(\"payment_submitted\", {\n gateway: \"revolut_pay\",\n method: \"revolut_pay\",\n });\n return { publicId: revolutOrderToken(result.value.start) };\n })().finally(() => {\n orderInFlight = undefined;\n });\n return orderInFlight;\n };\n\n revolutPay.mount(containerRef.current, {\n currency: snapshot.currency,\n totalAmount: snapshot.totalMinor,\n createOrder,\n mobileRedirectUrls: {\n success: withExpressReturn(returnBase, {\n provider: \"revolutPay\",\n cartId: snapshot.cartId,\n result: \"success\",\n }),\n failure: withExpressReturn(returnBase, {\n provider: \"revolutPay\",\n cartId: snapshot.cartId,\n result: \"failure\",\n }),\n cancel: withExpressReturn(returnBase, {\n provider: \"revolutPay\",\n cartId: snapshot.cartId,\n result: \"cancel\",\n }),\n },\n ...(props.buttonStyle != null ? { buttonStyle: props.buttonStyle } : {}),\n });\n revolutPay.on(\"click\", () => {\n instrument.track(\"payment_method_selected\", {\n gateway: \"revolut_pay\",\n method: \"revolut_pay\",\n });\n });\n revolutPay.on(\"payment\", handlePayment);\n if (!cancelled && mounted.current) {\n setPhase((current) =>\n current === \"price-changed\" ||\n current === \"cart-conflict\" ||\n current === \"confirmed\" ||\n current === \"failed\" ||\n current === \"cancelled\"\n ? current\n : \"idle\",\n );\n }\n\n destroySdk = () => {\n try {\n revolutPay.destroy();\n } catch {\n // the script may have removed itself\n }\n try {\n payments.destroy?.();\n } catch {\n // nothing to destroy\n }\n };\n\n // A return from the Revolut app / standalone page, or an attempt left\n // pending by a closed tab: ask the server once, then leave the marker\n // out of the URL.\n const returned = readExpressReturn(window.location.search);\n const pending = activePendingAttempt(session.getRecord());\n const shouldReconcile =\n (pending?.provider === \"revolutPay\" &&\n (returned.cartId == null || returned.cartId === snapshot.cartId)) ||\n (returned.returned && returned.provider === \"revolutPay\");\n if (returned.returned) {\n window.history.replaceState(\n {},\n \"\",\n withoutExpressReturn(window.location.href),\n );\n }\n if (shouldReconcile) {\n await confirm(session);\n }\n };\n\n void mount().catch(() => {\n if (!cancelled && mounted.current) {\n setPhase(\"load-failed\");\n }\n });\n\n return () => {\n cancelled = true;\n controller.abort();\n destroySdk?.();\n };\n }, [\n config?.publicKey,\n config?.mode,\n environment,\n locale,\n signature,\n projectID,\n host,\n props.fetch,\n props.returnUrl,\n props.cancelUrl,\n buttonStyleKey,\n confirmationTimeoutMs,\n confirmationIntervalMs,\n confirmationSleep,\n confirmationNow,\n mountNonce,\n ]);\n\n return (\n <div\n data-bitsnap-express=\"revolutPay\"\n aria-busy={phase === \"pending\" ? true : undefined}\n className={props.className}\n style={props.style}\n >\n <div ref={containerRef} />\n <ExpressStatus phase={phase} />\n </div>\n );\n}\n\nfunction sameMountedAmount(\n snapshot: { cartId: string; currency: string; totalMinor: number },\n mounted: { cartId: string; currency: string; totalMinor: number } | undefined,\n): boolean {\n return (\n mounted != null &&\n snapshot.cartId === mounted.cartId &&\n snapshot.currency === mounted.currency &&\n snapshot.totalMinor === mounted.totalMinor\n );\n}\n\n/** Standalone Revolut Pay button for a product or cart page. */\nexport function RevolutPayButton(props: RevolutPayButtonProps) {\n const projectID = props.projectID ?? currentProjectID();\n const instrument = useInstrument(projectID, props.analytics, \"cart\");\n\n useEffect(() => {\n if (props.projectID != null) {\n setProjectID(props.projectID);\n }\n }, [props.projectID]);\n\n return (\n <InstrumentProvider value={instrument}>\n <CheckoutTextsProvider locale={props.locale} texts={props.texts}>\n <CheckoutAppearanceProvider appearance={props.appearance}>\n {projectID == null ? null : (\n <RevolutPayButtonInner {...props} projectID={projectID} />\n )}\n </CheckoutAppearanceProvider>\n </CheckoutTextsProvider>\n </InstrumentProvider>\n );\n}\n\nexport default RevolutPayButton;\n\n/** The checkout's own express area uses this variant without wrapping providers. */\nexport { RevolutPayButtonInner };\n","/**\n * Loader of the official Revolut Checkout embed script.\n *\n * The script is loaded only in the browser and only when a Revolut Pay button\n * is about to render: it never runs during server rendering and never lands in\n * the initial bundle of a page without the button. One `<script>` per mode is\n * shared by every button on the page, including two shops using different\n * public keys (the SDK is keyed per `payments()` call, not globally).\n */\n\nexport type RevolutMode = \"prod\" | \"sandbox\";\n\nexport type RevolutPaymentEvent =\n | { type: \"success\"; orderId: string }\n | { type: \"error\"; error: { message?: string }; orderId: string }\n | { type: \"cancel\"; dropOffState?: string; orderId?: string };\n\nexport type RevolutPayButtonStyle = {\n height?: string;\n size?: \"large\" | \"small\";\n radius?: \"none\" | \"small\" | \"large\" | \"round\";\n variant?: \"dark\" | \"light\" | \"light-outlined\";\n action?: \"donate\" | \"pay\" | \"subscribe\" | \"buy\";\n};\n\nexport type RevolutPayPaymentOptions = {\n currency: string;\n totalAmount: number;\n createOrder: () => Promise<{ publicId: string }>;\n buttonStyle?: RevolutPayButtonStyle;\n mobileRedirectUrls?: {\n success: string;\n failure: string;\n cancel: string;\n };\n redirectUrls?: {\n success: string;\n failure: string;\n cancel: string;\n };\n validate?: () => Promise<boolean> | boolean;\n};\n\nexport type RevolutPayModule = {\n mount: (\n target: string | HTMLElement | null,\n options: RevolutPayPaymentOptions,\n ) => void;\n on: {\n (event: \"click\", callback: () => void): void;\n (event: \"payment\", callback: (payload: RevolutPaymentEvent) => void): void;\n };\n destroy: () => void;\n};\n\nexport type RevolutPaymentsModule = {\n revolutPay: RevolutPayModule;\n destroy?: () => void;\n};\n\nexport type RevolutCheckoutNamespace = {\n payments: (options: {\n publicToken: string;\n mode?: RevolutMode;\n locale?: string;\n }) => Promise<RevolutPaymentsModule>;\n};\n\ndeclare global {\n interface Window {\n RevolutCheckout?: RevolutCheckoutNamespace;\n }\n}\n\nexport const REVOLUT_SCRIPT_URL: Record<RevolutMode, string> = {\n prod: \"https://merchant.revolut.com/embed.js\",\n sandbox: \"https://sandbox-merchant.revolut.com/embed.js\",\n};\n\nconst SCRIPT_ID: Record<RevolutMode, string> = {\n prod: \"revolut-checkout\",\n sandbox: \"revolut-checkout-sandbox\",\n};\n\nconst loading = new Map<RevolutMode, Promise<RevolutCheckoutNamespace>>();\n\n/** Test seam: drop in-flight loader promises between cases. */\nexport function resetRevolutLoader(): void {\n loading.clear();\n}\n\n/**\n * Resolves when `window.RevolutCheckout` is usable. Rejects on a script error\n * or after `timeoutMs`, so a blocked script hides the button instead of\n * leaving a dead one.\n */\nexport function loadRevolutCheckout(\n mode: RevolutMode,\n options: {\n document?: Document;\n timeoutMs?: number;\n } = {},\n): Promise<RevolutCheckoutNamespace> {\n if (typeof window === \"undefined\") {\n return Promise.reject(new Error(\"Revolut Checkout needs a browser.\"));\n }\n const existing = window.RevolutCheckout;\n if (existing != null) {\n return Promise.resolve(existing);\n }\n const cached = loading.get(mode);\n if (cached != null) {\n return cached;\n }\n\n const doc = options.document ?? document;\n const timeoutMs = options.timeoutMs ?? 15_000;\n const promise = new Promise<RevolutCheckoutNamespace>((resolve, reject) => {\n let settled = false;\n let script = doc.getElementById(SCRIPT_ID[mode]) as HTMLScriptElement | null;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const cleanup = () => {\n if (timer != null) {\n clearTimeout(timer);\n }\n script?.removeEventListener(\"load\", onLoad);\n script?.removeEventListener(\"error\", onError);\n };\n const finish = (callback: () => void) => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup();\n callback();\n };\n const onLoad = () => {\n finish(() => {\n const loaded = window.RevolutCheckout;\n if (loaded != null) {\n resolve(loaded);\n } else {\n reject(new Error(\"Revolut Checkout did not initialise.\"));\n }\n });\n };\n const onError = () => {\n finish(() => reject(new Error(\"Revolut Checkout could not be loaded.\")));\n };\n\n if (script == null) {\n script = doc.createElement(\"script\");\n script.id = SCRIPT_ID[mode];\n script.src = REVOLUT_SCRIPT_URL[mode];\n script.async = true;\n script.addEventListener(\"load\", onLoad);\n script.addEventListener(\"error\", onError);\n doc.head.appendChild(script);\n } else {\n script.addEventListener(\"load\", onLoad);\n script.addEventListener(\"error\", onError);\n }\n\n timer = setTimeout(() => {\n finish(() =>\n reject(new Error(\"Revolut Checkout timed out while loading.\")),\n );\n }, timeoutMs);\n });\n\n loading.set(mode, promise);\n promise.catch(() => loading.delete(mode));\n return promise;\n}\n\n/** Initialises the payments module (official API) for one public key. */\nexport function createRevolutPayments(\n namespace: RevolutCheckoutNamespace,\n options: { publicKey: string; mode: RevolutMode; locale: string },\n): Promise<RevolutPaymentsModule> {\n return namespace.payments({\n publicToken: options.publicKey,\n mode: options.mode,\n locale: options.locale,\n });\n}\n","/**\n * Return markers of the express flows.\n *\n * Revolut appends `_rp_oid` (the public order token) to a redirect URL. The SDK\n * also adds its own marker so a full page return can tell which provider and\n * which durable cart it belongs to. None of these values proves a payment:\n * they only select what to ask the server about.\n */\n\nexport const EXPRESS_RETURN_PARAM = \"bitsnap_express\";\nexport const EXPRESS_CART_PARAM = \"bitsnap_express_cart\";\nexport const EXPRESS_RESULT_PARAM = \"bitsnap_express_result\";\nexport const REVOLUT_ORDER_PARAM = \"_rp_oid\";\n\nexport type ExpressReturn = {\n returned: boolean;\n provider?: \"inpostPay\" | \"revolutPay\";\n cartId?: string;\n orderToken?: string;\n result?: \"success\" | \"failure\" | \"cancel\";\n};\n\nexport function readExpressReturn(search: string): ExpressReturn {\n let params: URLSearchParams;\n try {\n params = new URLSearchParams(search.startsWith(\"?\") ? search : `?${search}`);\n } catch {\n return { returned: false };\n }\n const provider = params.get(EXPRESS_RETURN_PARAM);\n const orderToken = params.get(REVOLUT_ORDER_PARAM) ?? undefined;\n const cartId = params.get(EXPRESS_CART_PARAM) ?? undefined;\n const rawResult = params.get(EXPRESS_RESULT_PARAM);\n const result =\n rawResult === \"success\" || rawResult === \"failure\" || rawResult === \"cancel\"\n ? rawResult\n : undefined;\n const isProvider = provider === \"inpostPay\" || provider === \"revolutPay\";\n return {\n returned: isProvider || orderToken != null,\n ...(isProvider ? { provider } : {}),\n ...(cartId != null ? { cartId } : {}),\n ...(orderToken != null ? { orderToken } : {}),\n ...(result != null ? { result } : {}),\n };\n}\n\n/** The page URL a mobile redirect should come back to, with flow markers. */\nexport function withExpressReturn(\n url: string,\n args: {\n provider: \"inpostPay\" | \"revolutPay\";\n cartId: string;\n result: \"success\" | \"failure\" | \"cancel\";\n },\n): string {\n const base =\n typeof window !== \"undefined\" ? window.location.href : \"https://localhost/\";\n const parsed = new URL(url, base);\n parsed.searchParams.set(EXPRESS_RETURN_PARAM, args.provider);\n parsed.searchParams.set(EXPRESS_CART_PARAM, args.cartId);\n parsed.searchParams.set(EXPRESS_RESULT_PARAM, args.result);\n return parsed.toString();\n}\n\n/** Removes this SDK's markers (and the provider's order token) from the URL. */\nexport function withoutExpressReturn(url: string): string {\n const base =\n typeof window !== \"undefined\" ? window.location.href : \"https://localhost/\";\n const parsed = new URL(url, base);\n parsed.searchParams.delete(EXPRESS_RETURN_PARAM);\n parsed.searchParams.delete(EXPRESS_CART_PARAM);\n parsed.searchParams.delete(EXPRESS_RESULT_PARAM);\n parsed.searchParams.delete(REVOLUT_ORDER_PARAM);\n return parsed.pathname + parsed.search + parsed.hash;\n}\n","import { useReducer, useRef, useEffect, useState } from \"react\";\nimport { cn } from \"@/src/lib/utils\";\nimport {\n rpcProvider,\n RpcProvider,\n useMutation,\n useQuery,\n} from \"src/rpc-provider\";\nimport { useQuery as UQ, useQueryClient } from \"@tanstack/react-query\";\nimport { Settings, X } from \"lucide-react\";\nimport type {\n NotificationsComponentPublicProps,\n NotificationGroup,\n CustomizationTexts,\n ComponentClassNames,\n PublicNotificationGroup,\n} from \"./types\";\nexport type {\n NotificationGroup,\n CustomizationTexts,\n ComponentClassNames,\n} from \"./types\";\nexport type Props = NotificationsComponentPublicProps;\nimport { DEFAULT_TEXTS } from \"./constants\";\nimport { NotificationHeader } from \"./NotificationHeader\";\nimport { NotificationGroupsList } from \"./NotificationGroupsList\";\nimport { QRCodeSection } from \"./QRCodeSection\";\nimport { AddUserToGroups } from \"./AddUserToGroups\";\nimport { ManageMyData } from \"./ManageMyData\";\nimport { LoginScreen } from \"./LoginScreen\";\nimport { useLoginBranding } from \"@/src/ui/email-code-login/LoginBrandLogo\";\nimport { Button } from \"@/src/ui/button\";\nimport { getProjectID } from \"../checkout/CartProvider\";\nimport { currentProjectID } from \"../checkout/project-id\";\nimport { useInstrument } from \"@/src/analytics/instrument\";\nimport { NotificationGroupHowOften } from \"@/src/gen/proto/common/v1/push_notifications_pb\";\nimport { useAutoAnimate } from \"@formkit/auto-animate/react\";\nimport { Spinner } from \"@/src/ui/spinner\";\n\ninterface State {\n isLoading: boolean;\n isUserGroupsUpdated: boolean;\n wasChanged: boolean;\n groupsProvided?: PublicNotificationGroup[];\n groups: NotificationGroup[];\n showSettings: boolean;\n isLoggedIn: boolean;\n userID: string | undefined;\n}\n\ntype Action =\n | { type: \"SET_IS_LOGGED_IN\"; value: boolean }\n | { type: \"SET_USER_ID\"; value: string | undefined }\n | { type: \"SET_LOADING\"; value: boolean }\n | { type: \"TOGGLE_GROUP\"; groupID: string }\n | { type: \"CHECK_ALL_GROUPS\" }\n | { type: \"SET_WAS_CHANGED\"; value: boolean }\n | { type: \"SET_IS_USER_GROUPS_UPDATED\"; value: boolean }\n | { type: \"RESET_UPDATE_STATE\" }\n | { type: \"SHOW_SETTINGS\" }\n | { type: \"SET_GROUPS\"; value: NotificationGroup[] }\n | { type: \"SET_PUBLIC_GROUPS\"; value?: PublicNotificationGroup[] }\n | { type: \"HIDE_SETTINGS\" };\n\nfunction reducer(state: State, action: Action): State {\n switch (action.type) {\n case \"SET_IS_LOGGED_IN\": {\n return {\n ...state,\n isLoggedIn: action.value,\n };\n }\n case \"SET_USER_ID\": {\n return {\n ...state,\n userID: action.value,\n };\n }\n case \"SET_LOADING\": {\n return {\n ...state,\n isLoading: action.value,\n };\n }\n case \"SET_PUBLIC_GROUPS\": {\n return {\n ...state,\n groupsProvided: action.value,\n groups:\n action.value != null && action.value.length > 0\n ? state.groups.filter(\n (group) => action.value?.find((g) => g.id === group.id) != null,\n )\n : state.groups,\n };\n }\n case \"SET_GROUPS\": {\n const isDefaultOn =\n state.isLoggedIn == false || state.groupsProvided != null;\n const newGroupsWithIsOn = action.value.map((group) => {\n if (state.isLoggedIn == true) {\n return group;\n }\n return {\n ...group,\n isOn:\n state.groupsProvided?.find((g) => g.id === group.id)?.isOn ??\n isDefaultOn,\n };\n });\n\n return {\n ...state,\n groups: newGroupsWithIsOn,\n };\n }\n case \"TOGGLE_GROUP\": {\n const updatedGroups = state.groups.map((group) => {\n if (group.id === action.groupID) {\n return {\n ...group,\n isOn: !group.isOn,\n };\n }\n return group;\n });\n return {\n ...state,\n wasChanged: true,\n groups: updatedGroups,\n };\n }\n case \"CHECK_ALL_GROUPS\": {\n const updated = state.groups.map((group) => {\n return {\n ...group,\n isOn: true,\n };\n });\n return {\n ...state,\n groups: updated,\n wasChanged: true,\n };\n }\n case \"SET_WAS_CHANGED\":\n return {\n ...state,\n wasChanged: action.value,\n };\n case \"SET_IS_USER_GROUPS_UPDATED\":\n return {\n ...state,\n isUserGroupsUpdated: action.value,\n };\n case \"RESET_UPDATE_STATE\":\n return {\n ...state,\n wasChanged: false,\n isUserGroupsUpdated: true,\n };\n case \"SHOW_SETTINGS\":\n return {\n ...state,\n showSettings: true,\n };\n case \"HIDE_SETTINGS\":\n return {\n ...state,\n showSettings: false,\n };\n default:\n return state;\n }\n}\n\nfunction NotificationsComponentPublic({\n slug: slugProp,\n userID,\n productID,\n projectID,\n analytics,\n projectName,\n projectLogo,\n projectLogoDark,\n showLoginLogo,\n groups,\n isManaging = false,\n texts,\n showQRCode = false,\n showPhoneInput = false,\n hiddenGroupIds = [],\n className,\n}: NotificationsComponentPublicProps) {\n const [parent] = useAutoAnimate();\n const instrument = useInstrument(\n projectID ?? currentProjectID(),\n analytics,\n );\n let slug =\n slugProp ??\n getProjectID() ??\n (typeof window !== \"undefined\" ? window.location.hostname : \"\");\n\n // The login dialog shows the shop logo: read it now, so it is there when\n // the dialog opens (LoginBrandLogo reuses this query).\n useLoginBranding(\n slug.trim(),\n showLoginLogo !== false &&\n !projectLogo &&\n !projectLogoDark &&\n slug.trim() !== \"\",\n );\n\n const { mutateAsync: updateUserGroups, isPending: isUpdating } = useMutation(\n rpcProvider.notifications.updateUserGroups,\n );\n\n const { data: userInfo, refetch: refetchAccessToken } = UQ({\n queryKey: [\"notifications_accessToken\"],\n queryFn: () => {\n if (typeof window !== \"undefined\") {\n return {\n accessToken:\n localStorage.getItem(\"notifications_accessToken\") ?? undefined,\n userID: localStorage.getItem(\"notifications_userID\") ?? undefined,\n };\n }\n return undefined;\n },\n });\n\n const {\n data: groupsDownloaded,\n isPending: isGroupsDownloading,\n refetch: refetchGroups,\n } = useQuery(rpcProvider.notifications.getUserGroups, {\n slug: slug,\n accessToken: userInfo?.accessToken,\n });\n\n const [state, dispatch] = useReducer(reducer, {\n isLoading: isGroupsDownloading,\n isUserGroupsUpdated: false,\n wasChanged: false,\n groupsProvided: groups,\n groups: [],\n showSettings: userInfo != null && isManaging == true,\n isLoggedIn: userInfo != null,\n userID: undefined,\n });\n\n useEffect(() => {\n dispatch({ type: \"SET_LOADING\", value: isUpdating || isGroupsDownloading });\n }, [isUpdating, isGroupsDownloading]);\n\n useEffect(() => {\n dispatch({\n type: \"SET_IS_LOGGED_IN\",\n value: userInfo?.accessToken != null,\n });\n dispatch({ type: \"SET_USER_ID\", value: userInfo?.userID });\n if (userInfo?.accessToken != null && isManaging == true) {\n dispatch({ type: \"SHOW_SETTINGS\" });\n }\n }, [userInfo, isManaging]);\n\n useEffect(() => {\n if (groupsDownloaded == null) {\n return;\n }\n let newGroups = groupsDownloaded.groups.map((group) => {\n let howOften = \"rarely\";\n switch (group.howOften) {\n case NotificationGroupHowOften.RARELY:\n howOften = \"rarely\";\n break;\n case NotificationGroupHowOften.OFTEN:\n howOften = \"often\";\n break;\n case NotificationGroupHowOften.VERY_OFTEN:\n howOften = \"veryOften\";\n break;\n }\n return {\n id: group.id,\n name: group.name,\n description: group.description,\n howOften: howOften,\n isOn: group.isOn ?? undefined,\n };\n });\n dispatch({ type: \"SET_GROUPS\", value: newGroups });\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [groupsDownloaded, isGroupsDownloading, groups]);\n\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n let preparedGroups = groups?.map((el) => {\n if (el.id.startsWith(\"group_\")) {\n return el;\n }\n el.id = `group_${el.id}`;\n return el;\n });\n\n dispatch({ type: \"SET_PUBLIC_GROUPS\", value: preparedGroups });\n }, [groups]);\n\n const mergedTexts = { ...DEFAULT_TEXTS, ...texts };\n\n async function updateGroups() {\n await updateUserGroups({\n accessToken: userInfo?.accessToken,\n slug: slug,\n userId: userID,\n groupIds: state.groups\n .filter((el) => el.isOn === true)\n .map((el) => el.id),\n });\n dispatch({ type: \"RESET_UPDATE_STATE\" });\n\n // Clear existing timeout if any\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n\n // Set timeout to reset isUserGroupsUpdated after 2 seconds\n timeoutRef.current = setTimeout(() => {\n dispatch({ type: \"SET_IS_USER_GROUPS_UPDATED\", value: false });\n }, 2000);\n }\n\n function toggleGroup(groupID: string) {\n dispatch({ type: \"TOGGLE_GROUP\", groupID });\n }\n\n function checkAllGroups() {\n dispatch({ type: \"CHECK_ALL_GROUPS\" });\n }\n\n function handleSettingsClick() {\n dispatch({ type: \"SHOW_SETTINGS\" });\n }\n\n function handleCloseSettings() {\n dispatch({ type: \"HIDE_SETTINGS\" });\n }\n\n function handleLogout() {\n localStorage.removeItem(\"notifications_accessToken\");\n localStorage.removeItem(\"notifications_userID\");\n refetchAccessToken();\n dispatch({ type: \"SET_USER_ID\", value: undefined });\n dispatch({ type: \"SET_IS_LOGGED_IN\", value: false });\n dispatch({ type: \"HIDE_SETTINGS\" });\n }\n\n async function handleLoginSuccess(\n userID: string | undefined,\n accessToken: string,\n ) {\n if (typeof window !== \"undefined\") {\n localStorage.setItem(\"notifications_accessToken\", accessToken);\n if (userID != null) {\n localStorage.setItem(\"notifications_userID\", userID);\n }\n }\n dispatch({ type: \"SET_USER_ID\", value: userID });\n try {\n await refetchAccessToken();\n refetchGroups()\n .then()\n .catch()\n .finally(() => {\n if (isManaging == true) {\n // Automatically switch to managing view\n dispatch({ type: \"SHOW_SETTINGS\" });\n }\n });\n } catch (e) {\n console.log(`Error: ${e}`);\n }\n }\n\n // Cleanup timeout on unmount\n useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n }, []);\n\n const isManagingEnabled =\n isManaging == true && state.userID != null && userInfo?.accessToken != null;\n\n return (\n <main className={cn(\"bitsnap-react relative\", className?.container)}>\n {mergedTexts.title != null && (\n <h1 className=\"text-2xl font-semibold text-black md:text-3xl lg:text-4xl xl:text-5xl dark:text-neutral-100\">\n {mergedTexts.title}\n </h1>\n )}\n\n {/* Floating Settings Icon */}\n {!state.showSettings && isManaging && (\n <Button\n onClick={handleSettingsClick}\n variant=\"outline\"\n size=\"icon\"\n className=\"absolute bottom-6 right-6 z-50 h-12 w-12 rounded-full shadow-lg hover:shadow-xl md:bottom-8 md:right-8\"\n aria-label=\"Settings\"\n >\n <Settings className=\"h-5 w-5\" />\n </Button>\n )}\n\n <div\n className={cn(\n \"md:pt8 relative z-0 mt-6 overflow-hidden rounded-2xl bg-white px-3 pt-6 pb-3 md:px-5 md:pb-5 dark:bg-neutral-800\",\n className?.header,\n )}\n >\n {state.showSettings ? (\n // Settings View\n <div className=\"space-y-6\">\n {state.isLoggedIn && (\n // Managing Groups View (logged in)\n <div\n className={cn(\n \"grid grid-cols-1 gap-3 lg:gap-6\",\n isManagingEnabled ? \"md:grid-cols-2\" : \"\",\n )}\n >\n <div className={className?.groupsContainer}>\n <NotificationHeader\n projectName={projectName}\n projectLogo={projectLogo}\n projectLogoDark={projectLogoDark}\n description={mergedTexts.managingDescription}\n className={className}\n onLogout={handleLogout}\n />\n {isGroupsDownloading && (\n <div className=\"flex justify-center items-center py-8\">\n <Spinner />\n </div>\n )}\n\n <NotificationGroupsList\n groups={state.groups}\n hiddenGroupIds={hiddenGroupIds}\n isManaging={isManaging}\n onToggle={toggleGroup}\n onCheckAll={checkAllGroups}\n onUpdate={updateGroups}\n isUpdating={isUpdating}\n wasChanged={state.wasChanged}\n isUserGroupsUpdated={state.isUserGroupsUpdated}\n className={className}\n texts={mergedTexts}\n />\n </div>\n {isManagingEnabled && (\n <ManageMyData\n accessToken={userInfo.accessToken ?? \"\"}\n slug={slug}\n userID={state.userID ?? \"\"}\n className={className}\n texts={mergedTexts}\n />\n )}\n\n {showQRCode != false && (\n <QRCodeSection\n showQRCode={showQRCode}\n isManaging={true}\n className={className}\n texts={mergedTexts}\n />\n )}\n </div>\n )}\n </div>\n ) : (\n // Default View (Form only)\n <div className={cn(\"grid grid-cols-1 gap-3 lg:gap-6\")}>\n <AddUserToGroups\n slug={slug}\n onToggle={(id) => {\n dispatch({ type: \"TOGGLE_GROUP\", groupID: id });\n }}\n onCheckAll={() => {\n dispatch({ type: \"CHECK_ALL_GROUPS\" });\n }}\n onSuccess={(userAlreadyExists, userID, accessToken) => {\n instrument.track(\n \"availability_signup\",\n {},\n { product_id: productID ?? null },\n );\n if (accessToken != null) {\n handleLoginSuccess(userID, accessToken);\n }\n if (userAlreadyExists) {\n dispatch({ type: \"SHOW_SETTINGS\" });\n }\n }}\n groups={state.groups}\n showPhoneInput={showPhoneInput}\n agreementText={mergedTexts.agreementText}\n className={className}\n texts={mergedTexts}\n wasChanged={state.wasChanged}\n isUpdating={isUpdating}\n />\n </div>\n )}\n </div>\n <LoginScreen\n isOpen={state.showSettings && !state.isLoggedIn}\n slug={slug}\n onSuccess={handleLoginSuccess}\n texts={mergedTexts}\n onClose={handleCloseSettings}\n projectName={projectName}\n projectLogo={projectLogo}\n projectLogoDark={projectLogoDark}\n showLogo={showLoginLogo}\n />\n </main>\n );\n}\n\nfunction Wrapper({\n slug,\n userID,\n productID,\n projectID,\n analytics,\n projectName,\n projectLogo,\n projectLogoDark,\n showLoginLogo,\n groups,\n isManaging,\n texts,\n showQRCode,\n showPhoneInput,\n hiddenGroupIds,\n className,\n}: Props) {\n return (\n <RpcProvider>\n <NotificationsComponentPublic\n slug={slug}\n userID={userID}\n productID={productID}\n projectID={projectID}\n analytics={analytics}\n projectName={projectName}\n projectLogo={projectLogo}\n projectLogoDark={projectLogoDark}\n showLoginLogo={showLoginLogo}\n groups={groups}\n isManaging={isManaging}\n texts={texts}\n showQRCode={showQRCode}\n showPhoneInput={showPhoneInput}\n hiddenGroupIds={hiddenGroupIds}\n className={className}\n />\n </RpcProvider>\n );\n}\nexport default Wrapper;\n","import { EMAIL_CODE_TEXT_TABLES } from \"@/src/ui/email-code-login/texts\";\nimport type { CustomizationTexts } from \"./types\";\n\nconst LOGIN = EMAIL_CODE_TEXT_TABLES.pl;\n\nexport const DEFAULT_TEXTS: Required<CustomizationTexts> = {\n title: null,\n description: null,\n managingDescription:\n \"Zarządzaj rodzajami powiadomień i sposobem dostarczania.\",\n formTitle: \"Podaj Email aby zapisać się do powiadomień\",\n formEmailLabel: \"Email\",\n formPhoneLabel: \"Numer telefonu\",\n formPhoneOptional: \"(opcjonalnie)\",\n formEmailPlaceholder: \"np. mail@gmail...\",\n formPhonePlaceholder: \"np. 663...\",\n formSubmitButton: \"Zapisz się\",\n formSuccessMessage: \"Zapisałeś się do powiadomień.\",\n agreementText: (\n <>\n <span style={{ color: \"red\" }}>*</span>\n Wyrażam zgodę na przetwarzanie moich danych w celach marketingowych\n zgodnie z{\" \"}\n <a\n href=\"/regulations/polityka-prywatnosci\"\n target=\"_blank\"\n className=\"cursor-alias font-bold hover:font-medium\"\n >\n regulaminem\n </a>{\" \"}\n <span className=\"text-xs font-light\">\n (zgodę można w każdej chwili wycofać)\n </span>\n </>\n ),\n qrCodeTitle: \"lub zainstaluj aplikację mobilną\",\n qrCodeSubtitle: \"Aplikacja mobilna\",\n qrCodeScanText: \"zeskanuj kod QR\",\n groupsNoSelectionWarning:\n \"Jeśli żadna z grup nie jest zaznaczona, nie otrzymasz żadnych powiadomień.\",\n groupsSelectAllButton: \"Zaznacz wszystkie\",\n groupsUpdateButton: \"Aktualizuj\",\n groupsUpdateSuccess: \"Zaktualizowano pomyślnie.\",\n groupsTitle: \"Zarządzaj grupami z których chcesz otrzymywać powiadomienia\",\n manageDataTitle: \"Ustawienia powiadomień\",\n manageDataDescription: \"W jaki sposób chcesz otrzymywać powiadomienia?\",\n manageDataUnsubscribeButton: \"Odsubskrybuj\",\n manageDataUpdatedMessage: \"Zaktualizowano\",\n manageDataUnsubscribeDescription:\n \"Wypisz mnie z wszystkich powiadomień i grup.\",\n loginEmailLabel: \"Email\",\n loginEmailPlaceholder: \"Wprowadź swój email\",\n loginSendCodeButton: \"Wyślij kod weryfikacyjny\",\n loginSendingButton: \"Wysyłanie...\",\n loginCodeLabel: \"Wprowadź kod weryfikacyjny\",\n loginCodeSentMessage: \"Wysłaliśmy kod weryfikacyjny na adres\",\n loginChangeEmailButton: \"Popraw email\",\n loginResendCodeButton: \"Wyślij kod ponownie\",\n loginInvalidEmailError: \"Wprowadź prawidłowy adres email\",\n loginSlugRequiredError: \"Wymagany jest identyfikator projektu\",\n loginInvalidCodeError: \"Nieprawidłowy kod weryfikacyjny\",\n loginVerificationFailedError:\n \"Weryfikacja nie powiodła się. Sprawdź swój kod.\",\n loginSendEmailError: \"Nie udało się wysłać kodu weryfikacyjnego\",\n loginVerifyCodeError: \"Nie udało się zweryfikować kodu\",\n loginResendEmailError: \"Nie udało się ponownie wysłać kodu weryfikacyjnego\",\n loginTitle: \"Wpisz email aby zarządzać powiadomieniami\",\n loginDescription: \"Dostaniesz kod weryfikacyjny na email.\",\n loginIHaveCode: \"Mam już kod\",\n loginVerifyButton: \"Potwierdź\",\n loginResendInText: LOGIN.resendIn,\n loginResentMessage: LOGIN.resent,\n loginExpiredError: LOGIN.expired,\n loginTooManyAttemptsError: LOGIN.tooManyAttempts,\n loginRateLimitedError: LOGIN.rateLimited,\n loginNetworkError: LOGIN.network,\n loginSpamHint: LOGIN.spamHint,\n loginValidityHint: LOGIN.validity,\n loginVerifyingButton: LOGIN.verifying,\n loginStepEmailHint: LOGIN.stepEmail,\n loginStepCodeHint: LOGIN.stepCode,\n loginAlreadySentMessage: LOGIN.alreadySent,\n loginEmailNotFoundError: LOGIN.emailNotFound,\n loginDeliveryUnavailableError: LOGIN.deliveryUnavailable,\n loginResendNewCodeButton: LOGIN.resendNew,\n loginNoCodeButton: LOGIN.noCode,\n loginCodeIncompleteError: LOGIN.codeIncomplete,\n};\n","import { cn } from \"@/src/lib/utils\";\nimport type { ComponentClassNames } from \"./types\";\nimport { Button } from \"@/src/ui/button\";\nimport { LogOutIcon } from \"lucide-react\";\n\ninterface NotificationHeaderProps {\n projectName?: string;\n projectLogo?: string;\n projectLogoDark?: string;\n description: string | null;\n className?: ComponentClassNames;\n onLogout?: () => void;\n}\n\nexport function NotificationHeader({\n projectName,\n projectLogo,\n projectLogoDark,\n description,\n className,\n onLogout,\n}: NotificationHeaderProps) {\n return (\n <>\n {projectLogo != null ||\n (projectName != null && (\n <h2\n className={cn(\n \"flex max-w-44 items-center gap-3 text-lg font-medium text-black sm:max-w-none md:text-xl lg:text-2xl xl:text-3xl dark:text-neutral-100\",\n className?.headerTitle\n )}\n >\n {projectLogo != null && (\n <>\n <img\n src={projectLogo}\n alt=\"\"\n className={cn(\n \"h-12 w-auto dark:hidden\",\n className?.headerLogo\n )}\n />\n <img\n src={projectLogoDark ?? projectLogo}\n alt=\"\"\n className={cn(\n \"hidden h-12 w-auto dark:inline\",\n className?.headerLogo\n )}\n />\n </>\n )}\n <span>{projectName}</span>\n </h2>\n ))}\n <div className=\"flex items-center gap-2\">\n {description && (\n <p\n className={cn(\n \"mt-4 font-medium text-left\",\n className?.headerDescription\n )}\n >\n {description}\n </p>\n )}\n <div className=\"grow\"></div>\n {onLogout && (\n <Button variant=\"ghost\" size=\"icon-sm\" onClick={onLogout}>\n <LogOutIcon className=\"h-5 w-5\" />\n </Button>\n )}\n </div>\n </>\n );\n}\n","import * as React from \"react\"\nimport * as SwitchPrimitive from \"@radix-ui/react-switch\"\n\nimport { cn } from \"@/src/lib/utils\"\n\nfunction Switch({\n className,\n ...props\n}: React.ComponentProps<typeof SwitchPrimitive.Root>) {\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n className={cn(\n \"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n \"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0\"\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\n","import { Switch } from \"@/src/ui/switch\";\nimport { cn } from \"@/src/lib/utils\";\nimport { useAutoAnimate } from \"@formkit/auto-animate/react\";\nimport { CheckCircleIcon, TriangleAlertIcon } from \"lucide-react\";\nimport { Button } from \"@/src/ui/button\";\nimport { Spinner } from \"@/src/ui/spinner\";\nimport type {\n NotificationGroup,\n ComponentClassNames,\n CustomizationTexts,\n} from \"./types\";\nimport { DEFAULT_TEXTS } from \"./constants\";\nimport { HowOftenComponent } from \"./HowOftenComponent\";\nimport { rpcProvider, useQuery } from \"@/src/rpc-provider\";\nimport { NotificationGroupHowOften } from \"@/src/gen/proto/common/v1/push_notifications_pb\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/src/ui/card\";\n\ninterface NotificationGroupsListProps {\n groups: NotificationGroup[];\n hiddenGroupIds?: string[];\n isManaging?: boolean;\n onToggle: (groupID: string) => void;\n onCheckAll: () => void;\n onUpdate?: () => void;\n isUpdating?: boolean;\n wasChanged?: boolean;\n isUserGroupsUpdated?: boolean;\n className?: ComponentClassNames;\n texts?: CustomizationTexts;\n}\n\nexport function NotificationGroupsList({\n groups = [],\n isManaging,\n onToggle,\n onCheckAll,\n onUpdate,\n isUpdating,\n wasChanged,\n isUserGroupsUpdated,\n className,\n texts,\n}: NotificationGroupsListProps) {\n const [groupsParent] = useAutoAnimate();\n const [updateGroupsParent] = useAutoAnimate();\n\n const hasNoSelection =\n groups.filter((group) => group.isOn === false).length > 0;\n const hasUnchecked =\n groups.filter((group) => group.isOn === false).length > 0;\n\n if (groups.length <= 1 && isManaging != true) {\n return null;\n }\n\n const content = (\n <div\n ref={groupsParent}\n className={cn(\"my-5 flex flex-col gap-3\", className?.groupsList)}\n >\n {groups.map((group) => (\n <div\n id={group.id}\n role=\"button\"\n key={group.id}\n className={cn(\n group.isOn\n ? \"bg-neutral-50 hover:bg-transparent shadow-sm border-transparent dark:bg-neutral-800\"\n : \"border-neutral-200 hover:bg-neutral-50 dark:hover:border-neutral-800 shadow-sm dark:border-neutral-800\",\n \"active:bg-beige-300 flex w-full cursor-pointer items-center gap-3 rounded-xl border px-3 py-2 transition active:dark:bg-neutral-900\",\n className?.groupItem\n )}\n onClick={(e) => {\n if (e.target instanceof HTMLButtonElement) {\n return;\n }\n onToggle(group.id);\n }}\n >\n <Switch\n checked={group.isOn}\n className=\"data-[state=checked]:bg-blue-500 dark:data-[state=unchecked]:bg-neutral-700\"\n onCheckedChange={() => {\n onToggle(group.id);\n }}\n />\n <div className=\"flex flex-col items-start justify-start\">\n <p className=\"font-medium text-sm\">{group.name}</p>\n {group.description && (\n <p className=\"text-xs font-light\">{group.description}</p>\n )}\n </div>\n <div className=\"grow\"></div>\n {group.howOften && <HowOftenComponent regularity={group.howOften} />}\n </div>\n ))}\n <div className=\"flex gap-2\">\n {isManaging === true && (\n <>\n <div\n ref={updateGroupsParent}\n className=\"flex flex-col items-start justify-start\"\n >\n {wasChanged && (\n <Button\n variant=\"default\"\n size=\"sm\"\n className=\"relative\"\n disabled={isUpdating}\n onClick={onUpdate}\n >\n {texts?.groupsUpdateButton ??\n DEFAULT_TEXTS.groupsUpdateButton}\n {isUpdating && (\n <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2\">\n <Spinner />\n </div>\n )}\n </Button>\n )}\n {isUserGroupsUpdated && (\n <p className=\"mt-3 flex items-center gap-2 text-sm text-green-500\">\n <CheckCircleIcon color=\"var(--color-green-500\" size={16} />{\" \"}\n {texts?.groupsUpdateSuccess ??\n DEFAULT_TEXTS.groupsUpdateSuccess}\n </p>\n )}\n </div>\n <div className=\"grow\"></div>\n </>\n )}\n {hasUnchecked && (\n <div className=\"flex justify-start\">\n <Button\n className=\"cursor-pointer dark:bg-neutral-700\"\n onClick={onCheckAll}\n size=\"sm\"\n variant=\"secondary\"\n type=\"button\"\n >\n {texts?.groupsSelectAllButton ??\n DEFAULT_TEXTS.groupsSelectAllButton}\n </Button>\n </div>\n )}\n </div>\n {hasNoSelection && (\n <div className=\"flex text-left gap-2 text-xs text-yellow-500\">\n <TriangleAlertIcon color=\"orange\" size={16} />\n {texts?.groupsNoSelectionWarning ??\n DEFAULT_TEXTS.groupsNoSelectionWarning}\n </div>\n )}\n </div>\n );\n\n if (isManaging == true) {\n return (\n <Card className=\"mt-5 text-left\">\n <CardHeader>\n <CardTitle>\n {texts?.groupsTitle ?? DEFAULT_TEXTS.groupsTitle}\n </CardTitle>\n </CardHeader>\n <CardContent>{content}</CardContent>\n </Card>\n );\n }\n\n return content;\n}\n","import * as React from \"react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\n\nimport { cn } from \"@/src/lib/utils\"\n\nfunction Popover({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\n}\n\nfunction PopoverTrigger({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />\n}\n\nfunction PopoverContent({\n className,\n align = \"center\",\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Content>) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n )\n}\n\nfunction PopoverAnchor({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />\n}\n\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }\n","import { Popover, PopoverContent, PopoverTrigger } from \"@/src/ui/popover\";\nimport { ClockIcon } from \"lucide-react\";\n\nexport function HowOftenComponent({ regularity }: { regularity: string }) {\n let text = \"\";\n switch (regularity) {\n case \"rarely\":\n text = \"rzadko\";\n break;\n case \"often\":\n text = \"często\";\n break;\n case \"very_often\":\n text = \"codzienne\";\n break;\n }\n\n return (\n <Popover>\n <PopoverTrigger\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n <button\n type=\"button\"\n className=\"flex w-[30%] cursor-help flex-col items-center justify-center text-xs md:w-[25%] xl:w-[20%]\"\n >\n <ClockIcon size={12} />\n <span>{text}</span>\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"w-80\">\n <div className=\"grid gap-4\">\n <div className=\"space-y-2\">\n <h4 className=\"leading-none font-medium\">Co to oznacza?</h4>\n <ul className=\"list-inside list-disc text-sm\">\n <li>\n <span className=\"font-semibold\">Rzadko</span> – powiadomienia\n będą wysyłane maksymalnie kilka razy w miesiącu.\n </li>\n <li>\n <span className=\"font-semibold\">Często</span> – powiadomienia\n mogę być wysyłane kilka razy w tygodniu.\n </li>\n <li>\n <span className=\"font-semibold\">Codzienne</span> – powiadomienia\n będą wysyłane nawet codziennie.\n </li>\n </ul>\n </div>\n <div className=\"grid gap-2\"></div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","import { cn } from \"@/src/lib/utils\";\nimport type { ComponentClassNames, CustomizationTexts } from \"./types\";\nimport { DEFAULT_TEXTS } from \"./constants\";\nimport { HOST } from \"../checkout/constants\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/src/ui/card\";\n\ninterface QRCodeSectionProps {\n showQRCode?: boolean;\n isManaging?: boolean;\n className?: ComponentClassNames;\n texts?: CustomizationTexts;\n}\n\nexport function QRCodeSection({\n showQRCode = true,\n isManaging: _isManaging,\n className,\n texts,\n}: QRCodeSectionProps) {\n const isBrowser = typeof window !== \"undefined\";\n const darkMode = isBrowser\n ? window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches\n ? true\n : false\n : false;\n\n function getURL(isBrowser: boolean) {\n if (isBrowser) {\n return window.location.href;\n }\n return \"\";\n }\n\n if (!showQRCode) {\n return null;\n }\n\n return (\n <Card\n className={cn(\n \"bg-beige-100 rounded-xl p-4 dark:bg-neutral-700\",\n className?.qrCodeSection\n )}\n >\n <CardHeader>\n <CardTitle\n className={cn(\n \"mb-3 text-base font-medium lg:text-lg\",\n className?.qrCodeTitle\n )}\n >\n {texts?.qrCodeSubtitle ?? DEFAULT_TEXTS.qrCodeSubtitle}\n {\" \" + (texts?.qrCodeTitle ?? DEFAULT_TEXTS.qrCodeTitle)}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-col items-center gap-2\">\n <div className=\"mt-1.5 mb-3 flex items-center gap-x-2\">\n <a\n href=\"https://apps.apple.com/us/app/bitsnap/id6741902807\"\n target=\"_blank\"\n className=\"max-w-28 flex-1 basis-1/2 lg:max-w-36\"\n >\n <img\n className=\"h-auto w-full\"\n src={HOST + \"/app-store-logo.png\"}\n alt=\"Download on App Store\"\n />\n </a>\n <a\n href=\"https://play.google.com/store/apps/details?id=com.bitsnap.Bitsnap&pli=1\"\n target=\"_blank\"\n className=\"max-w-28 flex-1 basis-1/2 lg:max-w-36\"\n >\n <img\n className=\"h-auto w-full\"\n src={HOST + \"/google-play-logo.png\"}\n alt=\"Get in on Google Play\"\n />\n </a>\n </div>\n {isBrowser && (\n <div className=\"flex items-center justify-center\">\n <div\n className={cn(\n \"flex min-w-[40%] flex-col items-center gap-2 rounded-xl bg-white p-2 dark:bg-neutral-900\",\n className?.qrCodeContainer\n )}\n >\n <img\n className=\"mt-3 w-[80%] p-1 pt-3\"\n src={\n HOST +\n `/api/qr-gen?url=${getURL(isBrowser)}&bgColor=${\n !darkMode ? \"F6F4F0\" : \"171717\"\n }&textColor=${!darkMode ? \"000000\" : \"ffffff\"}&margin=0`\n }\n />\n <p className=\"text-xs md:text-sm\">\n {texts?.qrCodeScanText ?? DEFAULT_TEXTS.qrCodeScanText}\n </p>\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n );\n}\n","import { useState } from \"react\";\nimport { isValidPhoneNumber } from \"react-phone-number-input\";\nimport { cn } from \"@/src/lib/utils\";\nimport { rpcProvider, useMutation } from \"src/rpc-provider\";\nimport { FailureMessage } from \"@/src/gen/proto/dashboard/v1/notifications_pb\";\nimport type {\n ComponentClassNames,\n CustomizationTexts,\n NotificationGroup,\n} from \"./types\";\nimport { DEFAULT_TEXTS } from \"./constants\";\nimport { FormInput } from \"./FormInput\";\nimport type { ReactNode } from \"react\";\nimport { NotificationGroupsList } from \"./NotificationGroupsList\";\n\nconst emailRegex =\n /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\ninterface AddUserToGroupsProps {\n slug: string;\n groups: NotificationGroup[];\n isUpdating?: boolean;\n wasChanged?: boolean;\n onToggle?: (id: string) => void;\n onCheckAll?: () => void;\n showPhoneInput?: boolean;\n agreementText?: string | ReactNode;\n className?: ComponentClassNames;\n texts?: CustomizationTexts;\n onSuccess?: (\n userAlreadyExists: boolean,\n userID: string | undefined,\n accessToken: string | undefined\n ) => void;\n}\n\nexport function AddUserToGroups({\n groups,\n onToggle,\n onCheckAll,\n slug,\n showPhoneInput = false,\n agreementText,\n className,\n texts,\n isUpdating,\n wasChanged,\n onSuccess,\n}: AddUserToGroupsProps) {\n const [errMsg, setErrMsg] = useState(\"\");\n const [warnMsg, setWarnMsg] = useState(\"\");\n const [isSubmited, setIsSubmited] = useState(false);\n const [agreementLack, setAgreementLack] = useState(false);\n const [emailLack, setEmailLack] = useState(false);\n const {\n mutateAsync: createNotificationUserMutation,\n isPending: isCreateNotificationUserPending,\n } = useMutation(rpcProvider.notifications.createNotificationUser);\n\n function validatePhoneNumber(phone: string): boolean {\n if (phone == null) {\n return false;\n }\n return isValidPhoneNumber(phone, \"PL\");\n }\n\n async function save(email: string, phone: string, agreement: boolean) {\n setErrMsg(\"\");\n setWarnMsg(\"\");\n setEmailLack(false);\n setIsSubmited(false);\n setAgreementLack(false);\n\n if (!agreement) {\n setAgreementLack(true);\n const msg = \"Zgoda w tym przypadku jest wymagana.\";\n setErrMsg(msg);\n return;\n }\n\n if (emailRegex.test(email) === false) {\n setErrMsg(\"Email jest nieprawidłowy.\");\n setEmailLack(true);\n return;\n }\n\n if (phone.length > 0) {\n if (validatePhoneNumber(phone) === false) {\n const msg =\n \"Numer telefonu może być nieprawidłowy. Zapisaliśmy go ale jeśli jest nieprawidłowy to wpisz jeszcze raz i kliknij przycisk.\";\n setWarnMsg(msg);\n }\n }\n\n try {\n const newNotificationUser = await createNotificationUserMutation({\n slug: slug,\n email: email,\n phone: phone,\n groups: groups.filter((el) => el.isOn == true).map((el) => el.id),\n mobileNotificationEnabled: true,\n emailNotificationEnabled: true,\n smsNotificationEnabled: true,\n });\n\n if (newNotificationUser.result.case === \"success\") {\n setIsSubmited(true);\n setTimeout(() => {\n onSuccess?.(\n false,\n newNotificationUser.userId,\n newNotificationUser.accessToken\n );\n }, 1000);\n return;\n } else {\n setIsSubmited(true);\n const failureMessage = newNotificationUser.result.value;\n\n if (failureMessage != null) {\n if (\n failureMessage == FailureMessage.NOTIFICATION_USER_ALREADY_EXIST\n ) {\n onSuccess?.(true, undefined, undefined);\n return;\n }\n console.log(`Code error: ${FailureMessage[failureMessage]}`);\n setErrMsg(\"Wystąpił błąd: \" + FailureMessage[failureMessage]);\n return;\n }\n\n return;\n }\n } catch (e) {\n setErrMsg(\"Wystąpił błąd podczas zapisywania. Spróbuj ponownie.\");\n console.log(`Error: ${e}`);\n }\n }\n\n const text = texts?.formTitle ?? DEFAULT_TEXTS.formTitle;\n\n return (\n <div\n className={cn(\n \"bg-beige-100 rounded-xl p-4 dark:bg-neutral-700\",\n className?.formSection\n )}\n >\n {text.length > 0 && (\n <h3\n className={cn(\n \"mb-3 text-base font-medium lg:text-lg\",\n className?.formTitle\n )}\n >\n {text}\n </h3>\n )}\n\n <NotificationGroupsList\n groups={groups}\n isManaging={false}\n onToggle={onToggle ?? (() => {})}\n onCheckAll={onCheckAll ?? (() => {})}\n isUpdating={isUpdating ?? false}\n wasChanged={wasChanged ?? false}\n isUserGroupsUpdated={false}\n className={className}\n texts={texts}\n />\n\n <FormInput\n errMsg={errMsg}\n emailLack={emailLack}\n warnMsg={warnMsg}\n submit={save}\n isLoading={isCreateNotificationUserPending}\n isSubmited={isSubmited}\n agreementLack={agreementLack}\n showPhoneInput={showPhoneInput}\n agreementText={\n agreementText ?? texts?.agreementText ?? DEFAULT_TEXTS.agreementText\n }\n className={className}\n texts={texts}\n />\n </div>\n );\n}\n","import { Input } from \"@/src/ui/input\";\nimport { cn } from \"@/src/lib/utils\";\nimport { useAutoAnimate } from \"@formkit/auto-animate/react\";\nimport { Label } from \"@radix-ui/react-label\";\nimport {\n CheckCircleIcon,\n CircleAlertIcon,\n TriangleAlertIcon,\n} from \"lucide-react\";\nimport { useState, type FormEvent } from \"react\";\nimport { Button } from \"@/src/ui/button\";\nimport { Spinner } from \"@/src/ui/spinner\";\nimport type { ComponentClassNames, CustomizationTexts } from \"./types\";\nimport { DEFAULT_TEXTS } from \"./constants\";\nimport type { ReactNode } from \"react\";\n\ninterface FormInputProps {\n isLoading: boolean;\n submit: (email: string, phone: string, agreement: boolean) => void;\n errMsg: string;\n agreementLack?: boolean;\n emailLack?: boolean;\n warnMsg: string;\n isSubmited: boolean;\n showPhoneInput?: boolean;\n agreementText?: string | ReactNode;\n className?: ComponentClassNames;\n texts?: CustomizationTexts;\n}\n\nexport function FormInput({\n submit,\n isLoading,\n errMsg,\n emailLack,\n warnMsg,\n isSubmited,\n agreementLack,\n showPhoneInput = false,\n agreementText,\n className,\n texts,\n}: FormInputProps) {\n const [email, setEmail] = useState(\"\");\n const [phone, setPhone] = useState(\"\");\n const [isChecked, setIsChecked] = useState(false);\n\n const [parent] = useAutoAnimate();\n\n function submitForm(e: FormEvent) {\n e.preventDefault();\n submit(email, phone, isChecked);\n }\n\n return (\n <form\n ref={parent}\n onSubmit={submitForm}\n className={cn(\"flex flex-col gap-3 text-left\", className?.formContainer)}\n >\n <div className=\"flex flex-col gap-1 text-left\">\n <Label className=\"text-sm\" htmlFor=\"bts-notifications-form-email\">\n {texts?.formEmailLabel ?? DEFAULT_TEXTS.formEmailLabel}\n </Label>\n <Input\n value={email}\n onChange={(newVal) => {\n setEmail(newVal.currentTarget.value);\n }}\n id=\"bts-notifications-form-email\"\n className={cn(emailLack === true ? \"border-red-400\" : \"\")}\n type=\"email\"\n placeholder={\n texts?.formEmailPlaceholder ?? DEFAULT_TEXTS.formEmailPlaceholder\n }\n />\n </div>\n\n {showPhoneInput && (\n <div className=\"flex flex-col gap-1 text-left\">\n <Label className=\"text-sm\" htmlFor=\"bts-notifications-form-phone\">\n {texts?.formPhoneLabel ?? DEFAULT_TEXTS.formPhoneLabel}{\" \"}\n <span className=\"text-neutral-500 dark:text-neutral-500\">\n {texts?.formPhoneOptional ?? DEFAULT_TEXTS.formPhoneOptional}\n </span>\n </Label>\n <Input\n value={phone}\n onChange={(newVal) => {\n setPhone(newVal.currentTarget.value);\n }}\n id=\"bts-notifications-form-phone\"\n className=\"\"\n type=\"tel\"\n autoComplete=\"tel\"\n autoCorrect=\"off\"\n placeholder={\n texts?.formPhonePlaceholder ?? DEFAULT_TEXTS.formPhonePlaceholder\n }\n />\n </div>\n )}\n <div className=\"flex items-start gap-x-1.5\">\n <input\n className=\"cursor-pointer\"\n id=\"bts-notifications-form-marketing-consent\"\n type=\"checkbox\"\n checked={isChecked}\n onChange={() => {\n setIsChecked(!isChecked);\n }}\n />\n <label\n htmlFor=\"bts-notifications-form-marketing-consent\"\n className={cn(\n \"cursor-pointer text-xs leading-4 transition-colors md:text-sm md:leading-4\",\n agreementLack === true ? \"text-yellow-700\" : \"\"\n )}\n >\n {agreementText}\n </label>\n </div>\n {errMsg.length > 0 && (\n <p className=\"mb-3 flex items-center gap-1 text-sm text-red-400\">\n <TriangleAlertIcon color=\"#ff6467\" size={16} /> {errMsg}\n </p>\n )}\n {warnMsg.length > 0 && (\n <p className=\"mb-3 flex items-center gap-1 text-sm text-amber-400\">\n <CircleAlertIcon color=\"var(--color-amber-400)\" size={16} /> {warnMsg}\n </p>\n )}\n {isSubmited == false && (\n <div className=\"flex justify-start\">\n <Button\n variant=\"default\"\n disabled={isLoading}\n className={cn(\n isLoading ? \"cursor-not-allowed text-transparent\" : \"\",\n \"relative\"\n )}\n >\n {texts?.formSubmitButton ?? DEFAULT_TEXTS.formSubmitButton}\n {isLoading && (\n <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2\">\n <Spinner />\n </div>\n )}\n </Button>\n </div>\n )}\n {isSubmited && (\n <div className=\"flex items-center gap-3 text-sm text-green-400\">\n <CheckCircleIcon size={16} />{\" \"}\n {texts?.formSuccessMessage ?? DEFAULT_TEXTS.formSuccessMessage}\n </div>\n )}\n </form>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { Skeleton } from \"@/src/ui/skeleton\";\nimport { Switch } from \"@/src/ui/switch\";\nimport { cn } from \"@/src/lib/utils\";\nimport { Label } from \"@radix-ui/react-label\";\nimport { MessageCircleWarningIcon } from \"lucide-react\";\nimport { rpcProvider, useMutation, useQuery } from \"src/rpc-provider\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { UnsubscribeDialog } from \"./UnsubscribeDialog\";\nimport { Button } from \"@/src/ui/button\";\nimport { Spinner } from \"@/src/ui/spinner\";\nimport type { ComponentClassNames, CustomizationTexts } from \"./types\";\nimport { DEFAULT_TEXTS } from \"./constants\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/src/ui/card\";\nimport { useAutoAnimate } from \"@formkit/auto-animate/react\";\n\ninterface ManageMyDataProps {\n accessToken: string;\n slug: string;\n userID: string;\n className?: ComponentClassNames;\n texts?: CustomizationTexts;\n}\n\nexport function ManageMyData({\n accessToken,\n slug,\n userID,\n className,\n texts,\n}: ManageMyDataProps) {\n const [parent] = useAutoAnimate();\n const [parentCard] = useAutoAnimate();\n const { mutateAsync: deleteMyData, isPending: isDeleting } = useMutation(\n rpcProvider.notifications.deleteNotificationUser\n );\n const { mutateAsync: updateNotificationUser, isPending: isUpdating } =\n useMutation(rpcProvider.notifications.updateNotificationUser);\n\n const { data: userSettings, isFetching: isLoading } = useQuery(\n rpcProvider.notifications.getNotificationUserSettings,\n {\n userId: userID,\n slug: slug,\n accessToken: accessToken,\n }\n );\n\n const [email, setEmail] = useState(false);\n const [phone, setPhone] = useState(false);\n const [isDataUpdated, setIsDataUpdated] = useState(false);\n const [push, setPush] = useState(false);\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n\n const details =\n userSettings?.result.case === \"success\"\n ? userSettings?.result?.value\n : undefined;\n\n function deleteData() {\n setIsDialogOpen(true);\n }\n\n async function handleConfirmDelete() {\n await deleteMyData({\n accessToken: accessToken,\n slug: slug,\n userId: userID,\n });\n setIsDialogOpen(false);\n }\n\n async function updateData() {\n await updateNotificationUser({\n accessToken: accessToken,\n slug: slug,\n notificationUserId: userID,\n mobileNotificationEnabled: push,\n emailNotificationEnabled: email,\n smsNotificationEnabled: phone,\n });\n setIsDataUpdated(true);\n setTimeout(() => {\n setIsDataUpdated(false);\n }, 3000);\n }\n const debouncedUpdateData = useDebouncedCallback((_: boolean) => {\n updateData();\n }, 300);\n\n useEffect(() => {\n const details =\n userSettings?.result.case === \"success\"\n ? userSettings?.result?.value\n : undefined;\n\n setEmail(details?.emailNotificationEnabled ?? false);\n setPhone(details?.smsNotificationEnabled ?? false);\n setPush(details?.mobileNotificationEnabled ?? false);\n }, [userSettings]);\n\n function setData(key: \"email\" | \"phone\" | \"push\", value: boolean) {\n if (key === \"email\") {\n setEmail(value);\n }\n if (key === \"phone\") {\n setPhone(value);\n }\n if (key === \"push\") {\n setPush(value);\n }\n debouncedUpdateData(true);\n }\n\n return (\n <div\n className={cn(\n \"bg-beige-100 rounded-xl p-4 dark:bg-neutral-700\",\n className?.manageDataSection\n )}\n >\n <div className=\"flex justify-start\">\n <h3\n className={cn(\n \"mb-3 text-base font-medium lg:text-lg\",\n className?.manageDataTitle\n )}\n >\n {texts?.manageDataTitle ?? DEFAULT_TEXTS.manageDataTitle}\n </h3>\n </div>\n\n {isLoading ? (\n <Skeleton className=\"h-64 w-full\" />\n ) : (\n <Card ref={parentCard} className={cn(isUpdating && \"relative\")}>\n <CardHeader>\n <CardTitle>\n <p className=\"text-sm text-left\">\n {texts?.manageDataDescription ??\n DEFAULT_TEXTS.manageDataDescription}\n </p>\n </CardTitle>\n </CardHeader>\n <CardContent ref={parent}>\n <div\n className={cn(\n isUpdating && \"opacity-50 pointer-events-none\",\n \"flex flex-col gap-2\"\n )}\n >\n <div className=\"flex flex-col items-start gap-5 gap-x-2\">\n {details?.emailNotificationAvailable && (\n <div className=\"flex items-center gap-3\">\n <Switch\n id=\"email-enabled\"\n className=\"data-[state=checked]:bg-blue-500 dark:data-[state=unchecked]:bg-neutral-600\"\n checked={email}\n onCheckedChange={() => {\n setData(\"email\", !email);\n }}\n />\n <Label htmlFor=\"email-enabled\" className=\"text-sm\">\n Email\n </Label>\n </div>\n )}\n {details?.smsNotificationAvailable && (\n <div className=\"flex items-center gap-3\">\n <Switch\n id=\"sms-enabled\"\n className=\"data-[state=checked]:bg-blue-500 dark:data-[state=unchecked]:bg-neutral-600\"\n checked={phone}\n onCheckedChange={() => {\n setData(\"phone\", !phone);\n }}\n />\n <Label htmlFor=\"sms-enabled\" className=\"text-sm\">\n SMS\n </Label>\n </div>\n )}\n {details?.mobileNotificationAvailable && (\n <>\n <div className=\"flex items-center gap-3\">\n <Switch\n id=\"push-enabled\"\n className=\"data-[state=checked]:bg-blue-500 dark:data-[state=unchecked]:bg-neutral-600\"\n checked={push}\n onCheckedChange={() => {\n setData(\"push\", !push);\n }}\n />\n <Label htmlFor=\"push-enabled\" className=\"text-sm\">\n Powiadomienia na telefon\n </Label>\n </div>\n {details?.hasUserInstalledApp === false && (\n <div className=\"flex items-center gap-3\">\n <MessageCircleWarningIcon\n color=\"var(--color-amber-500)\"\n size={26}\n />\n <p className=\"text-xs text-amber-500\">\n Wygląda na to, że nie masz zainstalowanej aplikacji\n mobilnej. Zainstaluj i wyraź zgodę na otrzymywanie\n powiadomień na telefon.\n </p>\n </div>\n )}\n </>\n )}\n </div>\n </div>\n\n <div className=\"mt-5 flex flex-col gap-2 text-left\">\n <hr />\n {isDataUpdated && (\n <p className=\"text-xs text-green-500\">\n {texts?.manageDataUpdatedMessage ??\n DEFAULT_TEXTS.manageDataUpdatedMessage}\n </p>\n )}\n <div className=\"flex items-center gap-x-2\">\n <Button\n size=\"sm\"\n variant=\"link\"\n className={cn(\n \"pl-0 ml-0\",\n isDeleting && \"cursor-not-allowed\"\n )}\n onClick={deleteData}\n >\n {texts?.manageDataUnsubscribeButton ??\n DEFAULT_TEXTS.manageDataUnsubscribeButton}\n {isDeleting && (\n <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2\">\n <Spinner />\n </div>\n )}\n </Button>\n </div>\n </div>\n </CardContent>\n {isUpdating && (\n <div className=\"bg-black/30 absolute inset-0 rounded-xl\">\n <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2\">\n <Spinner />\n </div>\n </div>\n )}\n </Card>\n )}\n <UnsubscribeDialog\n open={isDialogOpen}\n onOpenChange={setIsDialogOpen}\n onConfirm={handleConfirmDelete}\n isDeleting={isDeleting}\n />\n </div>\n );\n}\n","import { cn } from \"../../lib/utils\";\nimport { TriangleAlertIcon, XIcon } from \"lucide-react\";\nimport { createPortal } from \"react-dom\";\nimport { useEffect, useState } from \"react\";\nimport { Button } from \"@/src/ui/button\";\n\ninterface UnsubscribeDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void;\n isDeleting?: boolean;\n}\n\nexport function UnsubscribeDialog({\n open,\n onOpenChange,\n onConfirm,\n isDeleting = false,\n}: UnsubscribeDialogProps) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n return () => setMounted(false);\n }, []);\n\n useEffect(() => {\n if (open) {\n document.body.style.overflow = \"hidden\";\n } else {\n document.body.style.overflow = \"\";\n }\n return () => {\n document.body.style.overflow = \"\";\n };\n }, [open]);\n\n if (!mounted || !open) {\n return null;\n }\n\n const handleBackdropClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) {\n onOpenChange(false);\n }\n };\n\n const handleConfirm = () => {\n onConfirm();\n };\n\n return createPortal(\n <div\n className=\"fixed inset-0 z-[9999] flex items-center justify-center bg-black/50 p-4\"\n onClick={handleBackdropClick}\n >\n <div\n className={cn(\n \"relative w-full max-w-md rounded-2xl bg-white p-6 shadow-lg\",\n \"dark:bg-neutral-800\",\n \"animate-in fade-in-0 zoom-in-95 duration-200\"\n )}\n onClick={(e) => e.stopPropagation()}\n >\n <button\n onClick={() => onOpenChange(false)}\n className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-neutral-950 focus:ring-offset-2 disabled:pointer-events-none dark:ring-offset-neutral-950 dark:focus:ring-neutral-300\"\n disabled={isDeleting}\n >\n <XIcon className=\"h-4 w-4\" />\n <span className=\"sr-only\">Zamknij</span>\n </button>\n\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex-shrink-0\">\n <TriangleAlertIcon\n className=\"h-6 w-6 text-amber-500\"\n aria-hidden=\"true\"\n />\n </div>\n <div className=\"flex-1\">\n <h2 className=\"text-lg font-semibold text-black dark:text-neutral-100\">\n Czy na pewno chcesz się wypisać?\n </h2>\n </div>\n </div>\n\n <p className=\"text-sm text-neutral-600 dark:text-neutral-400\">\n Kliknięcie tego przycisku spowoduje wypisanie z wszelkich\n powiadomień i grup, które zapisałeś.\n </p>\n\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => onOpenChange(false)}\n disabled={isDeleting}\n className=\"sm:min-w-[100px]\"\n >\n Anuluj\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={handleConfirm}\n disabled={isDeleting}\n className={cn(\n isDeleting && \"cursor-not-allowed text-transparent\",\n \"relative sm:min-w-[100px]\"\n )}\n >\n Usuń\n {isDeleting && (\n <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2\">\n <div className=\"h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent\" />\n </div>\n )}\n </Button>\n </div>\n </div>\n </div>\n </div>,\n document.body\n );\n}\n","import { useAutoAnimate } from \"@formkit/auto-animate/react\";\nimport { ArrowLeft } from \"lucide-react\";\nimport { useMemo, useRef } from \"react\";\nimport { rpcProvider, RpcProvider, useMutation } from \"src/rpc-provider\";\nimport { Button } from \"@/src/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogTitle,\n} from \"@/src/ui/dialog\";\nimport { EmailCodeLoginForm } from \"@/src/ui/email-code-login/EmailCodeLoginForm\";\nimport { LoginBrandLogo } from \"@/src/ui/email-code-login/LoginBrandLogo\";\nimport { pendingLoginKey } from \"@/src/ui/email-code-login/pending\";\nimport { useEmailCodeLogin } from \"@/src/ui/email-code-login/useEmailCodeLogin\";\nimport {\n createNotificationsAdapter,\n notificationsLoginTexts,\n type NotificationsLoginResult,\n} from \"./login-adapter\";\nimport type { LoginScreenTexts } from \"./types\";\n\nexport type { LoginScreenTexts };\n\ninterface LoginScreenProps {\n /**\n * Unique identifier for the project (if not provided, productID will be used via CartProvider).\n */\n slug: string;\n\n /**\n * Callback function called when login is successful with the access token.\n */\n onSuccess?: (userID: string | undefined, accessToken: string) => void;\n\n /**\n * Callback function called when an error occurs.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback function called when the close button is clicked.\n */\n onClose?: () => void;\n\n /**\n * If true, the dialog is open.\n */\n isOpen: boolean;\n\n /**\n * Custom CSS class names for styling.\n */\n className?: string;\n\n /**\n * Custom texts used throughout the component for i18n or personalisation.\n */\n texts: LoginScreenTexts;\n\n /** Name and logos of the project, when the page already has them. */\n projectName?: string;\n projectLogo?: string;\n projectLogoDark?: string;\n\n /** `false` hides the logo above the login. Default `true`. */\n showLogo?: boolean;\n}\n\n/**\n * The dialog content. It mounts each time the dialog opens, so a finished or\n * abandoned login never leaves a locked form behind; a pending code step is\n * restored from `sessionStorage`.\n */\nfunction LoginDialogBody({\n slug,\n onSuccess,\n onError,\n texts,\n projectName,\n projectLogo,\n projectLogoDark,\n showLogo,\n}: Pick<\n LoginScreenProps,\n | \"slug\"\n | \"onSuccess\"\n | \"onError\"\n | \"texts\"\n | \"projectName\"\n | \"projectLogo\"\n | \"projectLogoDark\"\n | \"showLogo\"\n>) {\n const [parentHeader] = useAutoAnimate();\n const { mutateAsync: verifyUserEmail } = useMutation(\n rpcProvider.notifications.verifyUserEmail,\n );\n\n const loginTexts = useMemo(() => notificationsLoginTexts(texts), [texts]);\n const [before, after] = loginTexts.codeSentTo.split(\"{email}\");\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const adapter = useMemo(() => {\n const base = createNotificationsAdapter(\n (request) => verifyUserEmail(request),\n slug,\n texts,\n );\n return {\n ...base,\n // The hook reports every failure but a wrong code; `onError` always\n // got that one too, so keep it.\n async verify(input) {\n const outcome = await base.verify(input);\n if (!outcome.ok && outcome.kind === \"wrongCode\") {\n onErrorRef.current?.(\n outcome.cause instanceof Error\n ? outcome.cause\n : new Error(outcome.message ?? \"wrongCode\"),\n );\n }\n return outcome;\n },\n } satisfies typeof base;\n }, [verifyUserEmail, slug, texts]);\n\n const login = useEmailCodeLogin<NotificationsLoginResult>({\n adapter,\n texts: loginTexts,\n storageKey: slug ? pendingLoginKey(\"notifications\", slug) : undefined,\n onVerified: ({ userId, accessToken }) => onSuccess?.(userId, accessToken),\n onFailure: (kind, cause) =>\n onError?.(cause instanceof Error ? cause : new Error(kind)),\n });\n\n const onCodeStep = login.step === \"code\";\n // The title of the code step is the code label, as before.\n const title =\n onCodeStep && !login.needsEmail\n ? texts.loginCodeLabel ?? \"\"\n : texts.loginTitle ?? \"\";\n\n return (\n <div className=\"flex h-full flex-col\">\n <LoginBrandLogo\n projectId={slug}\n name={projectName}\n showLogo={showLogo}\n logoUrl={projectLogo}\n logoDarkUrl={projectLogoDark}\n className=\"text-foreground mb-3\"\n />\n <div ref={parentHeader} className=\"mb-2 flex items-start gap-2\">\n {onCodeStep && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"-mt-2 -ml-2 size-11 shrink-0\"\n aria-label={loginTexts.changeEmail}\n disabled={login.isBusy}\n onClick={login.changeEmail}\n >\n <ArrowLeft className=\"h-5 w-5\" aria-hidden />\n </Button>\n )}\n <DialogTitle className=\"text-lg leading-6 font-semibold\">\n {title}\n </DialogTitle>\n </div>\n {/* The form announces \"step 2 of 2\" itself; the description of the\n code step is the address, so nothing is read twice. */}\n <DialogDescription className={onCodeStep ? \"sr-only\" : \"mb-4\"}>\n {onCodeStep\n ? `${before}${login.email}${after ?? \"\"}`\n : texts.loginDescription ?? \"\"}\n </DialogDescription>\n <EmailCodeLoginForm login={login} texts={loginTexts} />\n </div>\n );\n}\n\nexport function LoginScreen({\n slug,\n onSuccess,\n onError,\n className: _className,\n isOpen,\n onClose,\n texts,\n projectName,\n projectLogo,\n projectLogoDark,\n showLogo,\n}: LoginScreenProps) {\n return (\n <Dialog open={isOpen} onOpenChange={onClose}>\n <DialogContent className=\"max-h-[100dvh] overflow-y-auto sm:max-w-[425px]\">\n <LoginDialogBody\n slug={slug}\n onSuccess={onSuccess}\n onError={onError}\n texts={texts}\n projectName={projectName}\n projectLogo={projectLogo}\n projectLogoDark={projectLogoDark}\n showLogo={showLogo}\n />\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction Wrapper(props: LoginScreenProps) {\n return (\n <RpcProvider>\n <LoginScreen {...props} />\n </RpcProvider>\n );\n}\n\nexport default Wrapper;\n","import * as React from \"react\"\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"@/src/lib/utils\"\n\nfunction Dialog({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\n}\n\nfunction DialogClose({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n showCloseButton?: boolean\n}) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\"\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n","import { Code, ConnectError } from \"@connectrpc/connect\";\nimport { kindFromRpcError } from \"@/src/ui/email-code-login/errors\";\nimport {\n resolveEmailCodeTexts,\n type EmailCodeTexts,\n} from \"@/src/ui/email-code-login/texts\";\nimport type {\n EmailCodeAdapter,\n FailureKind,\n SendOutcome,\n VerifyOutcome,\n} from \"@/src/ui/email-code-login/useEmailCodeLogin\";\nimport type { LoginScreenTexts } from \"./types\";\n\nexport type NotificationsLoginResult = {\n userId: string | undefined;\n accessToken: string;\n};\n\n/** The one RPC both calls use (`VerifyUserEmail`), reduced to what is read. */\nexport type VerifyUserEmailCall = (request: {\n email?: string;\n code?: string;\n slug: string;\n}) => Promise<{\n ok?: boolean;\n accessToken?: string;\n userId?: string;\n retryIn?: number;\n /** `false`: a throttled resend, nothing went out. Absent (old servers): sent. */\n sent?: boolean;\n}>;\n\n/** Login texts of the notifications component mapped onto the shared ones. */\nexport function notificationsLoginTexts(\n texts: LoginScreenTexts,\n locale = \"pl\",\n): EmailCodeTexts {\n const sentTo = texts.loginCodeSentMessage;\n const overrides: Partial<EmailCodeTexts> = {\n emailLabel: texts.loginEmailLabel,\n emailPlaceholder: texts.loginEmailPlaceholder,\n sendCode: texts.loginSendCodeButton,\n sending: texts.loginSendingButton,\n invalidEmail: texts.loginInvalidEmailError,\n codeSentTo: sentTo != null ? `${sentTo} {email}.` : undefined,\n changeEmail: texts.loginChangeEmailButton,\n verify: texts.loginVerifyButton,\n spamHint: texts.loginSpamHint,\n validity: texts.loginValidityHint,\n resend: texts.loginResendCodeButton,\n resendIn: texts.loginResendInText,\n resent: texts.loginResentMessage,\n haveCodePrompt: \"\",\n haveCode: texts.loginIHaveCode,\n wrongCode: texts.loginInvalidCodeError,\n expired: texts.loginExpiredError,\n tooManyAttempts: texts.loginTooManyAttemptsError,\n rateLimited: texts.loginRateLimitedError,\n network: texts.loginNetworkError,\n generic: texts.loginVerifyCodeError,\n deliveryFailed: texts.loginSendEmailError,\n verifying: texts.loginVerifyingButton,\n stepEmail: texts.loginStepEmailHint,\n stepCode: texts.loginStepCodeHint,\n alreadySent: texts.loginAlreadySentMessage,\n emailNotFound: texts.loginEmailNotFoundError,\n deliveryUnavailable: texts.loginDeliveryUnavailableError,\n resendNew: texts.loginResendNewCodeButton,\n noCode: texts.loginNoCodeButton,\n codeIncomplete: texts.loginCodeIncompleteError,\n };\n return resolveEmailCodeTexts(locale, overrides);\n}\n\n/**\n * Kind of failure for an error thrown by `VerifyUserEmail`. The backend answers\n * a wrong code with \"Invalid code\" and the fifth wrong one (and per-IP limits)\n * with `ResourceExhausted`, \"Too many attempts\" for the former.\n */\nexport function notificationsFailureKind(error: unknown): FailureKind {\n const connect = ConnectError.from(error);\n const message = connect.rawMessage || connect.message;\n if (connect.code === Code.ResourceExhausted) {\n return /too many attempts/i.test(message) ? \"tooManyAttempts\" : \"rateLimited\";\n }\n if (/invalid code/i.test(message)) return \"wrongCode\";\n if (/expired/i.test(message)) return \"expired\";\n // Redis outage on the backend: not the customer's connection, so the\n // generic \"try again shortly\" copy.\n if (connect.code === Code.Unavailable) return \"unknown\";\n return kindFromRpcError(error);\n}\n\nexport function createNotificationsAdapter(\n call: VerifyUserEmailCall,\n slug: string,\n texts: LoginScreenTexts,\n): EmailCodeAdapter<NotificationsLoginResult> {\n return {\n async send(email, { resend }): Promise<SendOutcome> {\n if (!slug) {\n return { ok: false, kind: \"unknown\", message: texts.loginSlugRequiredError };\n }\n try {\n const response = await call({ email, slug });\n if (response.ok === false) {\n // `retryIn` without `ok`: the per-IP limit, nothing was sent. (A\n // throttled resend of a code that went out is `ok: true`.)\n return response.retryIn != null && response.retryIn > 0\n ? { ok: false, kind: \"rateLimited\", retryIn: response.retryIn }\n : {\n ok: false,\n kind: \"deliveryFailed\",\n message: resend ? texts.loginResendEmailError : texts.loginSendEmailError,\n };\n }\n if (response.sent === false) {\n // Throttled: an earlier code is still valid and `retryIn` is the\n // time left until a new one may be requested.\n return {\n ok: false,\n kind: \"alreadySent\",\n retryIn: response.retryIn || undefined,\n };\n }\n return { ok: true, retryIn: response.retryIn || undefined };\n } catch (cause) {\n const kind = notificationsFailureKind(cause);\n return {\n ok: false,\n kind,\n cause,\n message:\n kind === \"unknown\"\n ? resend\n ? texts.loginResendEmailError\n : texts.loginSendEmailError\n : undefined,\n };\n }\n },\n async verify({ email, code }): Promise<VerifyOutcome<NotificationsLoginResult>> {\n try {\n const response = await call({ email, code, slug });\n if (response.ok && response.accessToken) {\n return {\n ok: true,\n value: { userId: response.userId, accessToken: response.accessToken },\n };\n }\n return {\n ok: false,\n kind: \"wrongCode\",\n message: texts.loginVerificationFailedError,\n };\n } catch (cause) {\n return { ok: false, kind: notificationsFailureKind(cause), cause };\n }\n },\n };\n}\n","import React from \"react\";\nimport { cn } from \"@/src/lib/utils\";\nimport { useCheckoutSlot } from \"./appearance.context\";\nimport {\n manualPaymentTitleKey,\n type PaymentMethod,\n type PaymentMethodChoice as Choice,\n} from \"./payment-method\";\nimport { useCheckoutTextResolver } from \"./texts.context\";\n\n/**\n * \"Pay online\", \"transfer / BLIK to the seller's phone\" or \"cash on delivery\",\n * shown above the checkout button when the shop offers two or more of them.\n * Native radios give the group semantics and the arrow-key navigation; the\n * whole card is the label.\n */\nexport function PaymentMethodChoice({\n choice,\n selected,\n onChange,\n disabled,\n}: {\n choice: Choice;\n selected: PaymentMethod;\n onChange: (method: PaymentMethod) => void;\n disabled?: boolean;\n}) {\n const text = useCheckoutTextResolver();\n const group = useCheckoutSlot(\"paymentMethods\");\n const option = useCheckoutSlot(\"paymentMethodOption\");\n const name = React.useId();\n const legendId = React.useId();\n\n const hasBlik =\n choice.manualAccountTypes.length === 0 ||\n choice.manualAccountTypes.includes(\"blik\");\n\n const options: Record<\n PaymentMethod,\n { title: string; description: string; note?: string }\n > = {\n online: {\n title: text(\"paymentMethodOnline\"),\n description: text(\"paymentMethodOnlineDescription\"),\n },\n manual: {\n title: text(manualPaymentTitleKey(choice.manualAccountTypes)),\n description: text(\"paymentMethodManualDescription\"),\n note: hasBlik ? text(\"paymentMethodManualBlikNote\") : undefined,\n },\n cod: {\n title: text(\"paymentMethodCod\"),\n description: text(\"paymentMethodCodDescription\"),\n },\n };\n\n return (\n <fieldset\n data-bitsnap-checkout-slot=\"paymentMethods\"\n aria-labelledby={legendId}\n className={cn(\"mx-2 mt-4 mb-2 flex min-w-0 flex-col gap-2 border-0 p-0\", group.className)}\n style={group.style}\n disabled={disabled}\n >\n <legend id={legendId} className=\"mb-1 px-1 text-sm font-medium\">\n {text(\"paymentMethodLegend\")}\n </legend>\n {choice.methods.map((method) => {\n const card = options[method];\n const isSelected = method === selected;\n const descriptionId = `${name}-${method}-description`;\n return (\n <label\n key={method}\n data-bitsnap-checkout-slot=\"paymentMethodOption\"\n data-payment-method={method}\n data-selected={isSelected ? \"\" : undefined}\n className={cn(\n \"flex cursor-pointer items-start gap-3 rounded-md border px-3 py-2.5 transition-colors\",\n option.className,\n )}\n style={option.style}\n >\n <input\n type=\"radio\"\n name={name}\n value={method}\n checked={isSelected}\n onChange={() => onChange(method)}\n aria-describedby={descriptionId}\n className=\"mt-0.5 size-4 shrink-0 cursor-pointer\"\n />\n <span className=\"flex min-w-0 flex-col gap-0.5\">\n <span className=\"text-sm font-semibold leading-snug\">{card.title}</span>\n <span\n id={descriptionId}\n data-bitsnap-checkout-payment-method-description=\"\"\n className=\"text-xs leading-snug\"\n >\n {card.description}\n {isSelected && card.note != null && (\n <span className=\"mt-1 block font-medium\">{card.note}</span>\n )}\n </span>\n </span>\n </label>\n );\n })}\n </fieldset>\n );\n}\n"],"mappings":"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","names":["useEffect","useId","useRef","zod","useAutoAnimate","Dialog","useCallback","useRef","useState","createPortal","createContext","useContext","useMemo","CHECKOUT_SLOT_NAMES","CHECKOUT_TOKEN_VARIABLES","CHECKOUT_THEME_PRESETS","CHECKOUT_SHADCN_VARIABLES","resolveDropdownStyle","tokens","resolveCheckoutAppearance","appearance","resolved","resolveAppearanceCore","getCheckoutSlotAppearance","slot","getSlotAppearance","jsx","CheckoutAppearanceContext","createContext","resolveCheckoutAppearance","CheckoutAppearanceProvider","appearance","children","resolved","useMemo","useCheckoutAppearance","useContext","useCheckoutSlot","slot","getCheckoutSlotAppearance","useAutoAnimate","React","useEffect","useState","SelectPrimitive","CheckIcon","ChevronDownIcon","ChevronUpIcon","jsx","jsxs","Select","props","SelectValue","props","jsx","selectTriggerThemeClasses","SelectTrigger","className","size","theme","children","jsxs","cn","ChevronDownIcon","SelectContent","position","align","SelectScrollUpButton","SelectScrollDownButton","SelectItem","className","children","props","jsxs","cn","jsx","CheckIcon","SelectScrollUpButton","className","props","jsx","cn","ChevronUpIcon","SelectScrollDownButton","ChevronDownIcon","jsx","jsxs","CountrySelector","id","open","disabled","onToggle","onChange","selectedValue","countries","query","setQuery","useState","isCustomized","boundaryClassName","boundaryStyle","dropdownStyle","useCheckoutAppearance","countryTrigger","useCheckoutSlot","countryDropdown","countrySearch","countryOption","searchCountryText","useCheckoutText","noCountriesFoundText","useEffect","filteredCountries","country","selectedCountry","el","Select","value","isOpen","SelectTrigger","cn","SelectValue","SelectContent","e","SelectItem","CountrySelector_default","useEffect","useRef","useState","MinusIcon","PlusIcon","Slot","cva","jsx","buttonGroupVariants","cva","ButtonGroup","className","orientation","props","cn","Fragment","jsx","jsxs","ProductPrice","price","currency","pricing","quantity","lowestPriceText","useCheckoutText","noPriceHistoryText","regular","effective","onSale","formatCurrency","clampQuantity","value","quantityFromInput","raw","current","parsed","Fragment","jsx","jsxs","SingleProduct","isNotAvailable","quantity","details","url","shouldUpdate","product","useCheckoutSlot","productImage","productName","productPrice","removeButton","removeText","useCheckoutText","imageUrl","brokenImageUrl","setBrokenImageUrl","useState","showImage","name","cn","ProductLink","ProductPrice","QuantityComponent","Button","SingleProduct_default","children","props","className","quantityString","setQuantityString","sent","useRef","quantityControl","quantityInput","quantityButton","quantityText","increaseText","decreaseText","shownQuantity","useEffect","commit","newQuantity","ButtonGroup","clampQuantity","MinusIcon","e","quantityFromInput","PlusIcon","jsx","Skeleton","className","props","ApplePayButtonModule","currentProjectID","getProjectID","useQuery","jsx","ApplePayButton","ApplePayButtonModule","ApplePayButtonComponent","style","buttonType","colorType","items","onClick","checkIfApplePayIsAvailable","getApplePayPaymentRequest","completeApplePayPayment","setCountry","setCouponCodeIfPossible","setDeliveryMethod","setEmail","setPostalCode","clearCart","getApplePayPreview","useCartProvider","instrument","useInstrumentContext","paymentForCartText","useCheckoutText","isApplePayAvailable","useQuery","itemsKey","el","selection","getCheckoutSelection","preview","loadedPreview","isErr","round","acc","item","expectedItems","beginSession","reported","report","outcome","sendAnalyticEvent","requiresShipping","session","apRequest","event","result","PublicApiClient","HOST","getProjectID","error","Wrapper","props","useInstrument","currentProjectID","InstrumentProvider","CartProvider_default","ApplePay_default","GooglePayButton","useQuery","useMutation","Fragment","jsx","jsxs","GooglePayButtonComponent","items","style","buttonColor","buttonSizeMode","test","getGooglePayConfiguration","completeGooglePayPayment","setCountry","setCouponCodeIfPossible","setDeliveryMethod","setEmail","setPostalCode","clearCart","useCartProvider","instrument","useInstrumentContext","googlePayConfiguration","useQuery","el","completeGooglePayPaymentAsync","isPending","useMutation","GooglePayButton","paymentData","sendAnalyticEvent","config","paymentRequest","result","isErr","e","Spinner","Wrapper","props","useInstrument","currentProjectID","InstrumentProvider","CartProvider_default","GooglePay_default","createElement","useCallback","useEffect","useMemo","useRef","useState","CART_TOKEN_HEADER","warned","warnOnce","key","message","detail","expressApiUrl","host","projectID","path","request","options","body","cartToken","fetchImpl","input","init","response","clientHeaders","CART_TOKEN_HEADER","text","json","error","isRecord","value","networkFailure","isAbortError","isUnsupportedStatus","status","mapFailureCode","fallback","fetchExpressAvailability","cart","raw","warnOnce","writeExpressCart","current","snapshot","mapCartFailure","code","readExpressCart","cartId","startExpressProvider","provider","args","failure","fetchRevolutPayStatus","fetchExpressPayStatus","fetchInpostPayStatus","EXPRESS_CART_KEY_PREFIX","activePendingAttempt","record","now","pending","defaultStorage","expressCartKey","host","projectID","EXPRESS_CART_KEY_PREFIX","readExpressCartRecord","args","storage","key","value","raw","clearExpressCartRecord","isRecord","line","isPendingAttempt","writeExpressCartRecord","isRecord","value","isPendingAttempt","line","CART_ATTEMPTS","ExpressCartSession","options","readExpressCartRecord","locale","args","record","clearExpressCartRecord","lastFailure","attempts","attempt","upload","signatureBefore","result","cartToken","snapshot","item","writeExpressCartRecord","nextRevision","merged","mergeRevisionConflict","snapshotLinesToLocal","sameLines","before","countLines","after","synced","baseline","added","additionsBeyond","current","reuploaded","provider","ensured","started","line","basketBindingApiKey","lines","purchased","_pending","rest","fetchStatus","task","next","counts","a","b","left","right","id","quantity","base","local","server","ids","conflicts","l","localChanged","serverChanged","conflict","extra","quotes","QUOTE_TTL_MS","deliveryQuoteKey","host","projectID","upload","selection","getCheckoutSelection","item","readDeliveryQuote","key","entry","quotes","QUOTE_TTL_MS","rememberDeliveryQuote","quote","withDeliveryQuote","loadDeliveryQuote","args","response","PublicApiClient","delivery","method","deliveryMethod","error","prepareExpressCartUpload","cached","sdkLocalCart","options","readLocalCartLines","line","readLocalCartSignature","locale","upload","buildLocalCartUpload","withDeliveryQuote","readDeliveryQuote","snapshot","replaceLocalCartLines","appendLocalCartLines","removeLocalCartLines","lines","createExpressSession","host","HOST","clientOptions","ExpressCartSession","current","writeExpressCart","cartId","cartToken","readExpressCart","startProviderForCart","provider","session","preview","prepared","prepareExpressCartUpload","request","startExpressProvider","getRevolutStatus","getProviderStatus","getInpostStatus","fetchInpostPayStatus","fetchRevolutPayStatus","inpostWindow","INPOST_IZI_BUTTON_TAG","INPOST_THANK_YOU_TAG","inpostLanguage","locale","INPOST_SANDBOX_API_BASE_URL","INPOST_PRODUCTION_API_BASE_URL","INPOST_WIDGET_SCRIPT_URL","INPOST_WIDGET_API_BASE_URL","widgetEnvironment","value","fallback","isSandboxURL","readInpostPublicConfig","config","fallbackEnvironment","merchantClientId","environment","requestedApiBaseUrl","requestedScriptUrl","apiBaseUrl","scriptUrl","widgetLoader","loadInpostWidget","alreadyLoaded","inpostWindow","widgetLoader","module","record","fromModule","namespace","error","initInpostWidget","args","win","currentOwner","existing","hasInpostElements","widget","INPOST_IZI_BUTTON_TAG","INPOST_THANK_YOU_TAG","inpostIziButtonAttributes","useEffect","useMemo","useRef","useState","useSyncExternalStore","resolveExpressCart","args","productQuantity","base","item","cart","readLocalCartLines","line","present","expressCartSignature","lines","expressCartLocal","locale","options","sdkLocalCart","upload","withDeliveryQuote","readDeliveryQuote","useLocalCartVersion","useSyncExternalStore","subscribeToLocalCart","localCartVersionSnapshot","useExpressAvailability","latest","useRef","signature","cartVersion","state","setState","useState","useEffect","current","resolved","controller","active","previous","getExpressAvailability","availability","provider","resolveExpressHost","host","HOST","expressUploadFor","cart","locale","options","upload","buildLocalCartUpload","item","withDeliveryQuote","readDeliveryQuote","getExpressAvailability","prepared","prepareExpressCartUpload","availability","fetchExpressAvailability","revolutPay","readRevolutPublicConfig","config","publicKey","mode","revolutOrderToken","start","fromConfig","revolutLocale","locale","DEFAULT_TIMEOUT_MS","DEFAULT_INTERVAL_MS","defaultSleep","ms","resolve","pollProviderStatus","options","timeoutMs","intervalMs","sleep","startedAt","maxAttempts","attempts","last","pollRevolutStatus","jsx","PHASE_TEXT","ALERT_PHASES","ExpressStatus","phase","resolve","useCheckoutTextResolver","errorSlot","useCheckoutSlot","isAlert","cn","jsx","jsxs","isProductUnavailable","error","InPostPayButtonInner","props","projectID","host","resolveExpressHost","locale","getLocale","instrument","useInstrumentContext","confirmationTimeoutMs","confirmationIntervalMs","confirmationSleep","confirmationNow","cartVersion","useLocalCartVersion","cart","useMemo","resolveExpressCart","signature","expressCartSignature","availability","useExpressAvailability","provider","environment","config","readInpostPublicConfig","merchantClientId","apiBaseUrl","session","createExpressSession","expressCartLocal","phase","setPhase","useState","widgetRef","useRef","pendingStart","mounted","confirmingOrder","reportedOrder","useEffect","latest","startBinding","useCallback","start","startProviderForCart","result","ensureProduct","productId","readLocalCartLines","line","Bitsnap","unboundWidgetClicked","basketBindingApiKey","addToBasketClicked","id","confirmInpostOrder","active","pending","status","pollProviderStatus","getInpostStatus","providerOrderId","snapshot","lines","handleBasketEvent","event","cancelled","loadInpostWidget","namespace","widget","initInpostWidget","inpostLanguage","ExpressStatus","bindingPlace","createElement","INPOST_THANK_YOU_TAG","INPOST_IZI_BUTTON_TAG","inpostIziButtonAttributes","InPostPayButton","currentProjectID","useInstrument","setProjectID","InstrumentProvider","CheckoutTextsProvider","CheckoutAppearanceProvider","InPostPayButton_default","useEffect","useMemo","useRef","useState","REVOLUT_SCRIPT_URL","SCRIPT_ID","loading","loadRevolutCheckout","mode","options","existing","cached","loading","doc","timeoutMs","promise","resolve","reject","settled","script","SCRIPT_ID","timer","cleanup","onLoad","onError","finish","callback","loaded","REVOLUT_SCRIPT_URL","createRevolutPayments","namespace","EXPRESS_RETURN_PARAM","EXPRESS_CART_PARAM","EXPRESS_RESULT_PARAM","REVOLUT_ORDER_PARAM","readExpressReturn","search","params","provider","orderToken","cartId","rawResult","result","isProvider","withExpressReturn","url","args","base","parsed","withoutExpressReturn","jsx","jsxs","RevolutPayButtonInner","props","projectID","host","resolveExpressHost","locale","getLocale","instrument","useInstrumentContext","confirmationTimeoutMs","confirmationIntervalMs","confirmationSleep","confirmationNow","buttonStyleKey","cartVersion","useLocalCartVersion","cart","useMemo","resolveExpressCart","signature","line","availability","useExpressAvailability","config","readRevolutPublicConfig","environment","containerRef","useRef","phase","setPhase","useState","mountNonce","setMountNonce","mounted","mountedAmount","surfacedPhase","useEffect","controller","cancelled","destroySdk","local","expressCartLocal","session","createExpressSession","returnBase","confirming","settled","confirm","activeSession","status","pollRevolutStatus","getRevolutStatus","confirmOnce","handlePayment","event","surfaced","ensured","snapshot","namespace","loadRevolutCheckout","payments","createRevolutPayments","revolutLocale","revolutPay","orderInFlight","createOrder","current","sameMountedAmount","value","result","startProviderForCart","revolutOrderToken","withExpressReturn","returned","readExpressReturn","shouldReconcile","activePendingAttempt","withoutExpressReturn","ExpressStatus","RevolutPayButton","currentProjectID","useInstrument","setProjectID","InstrumentProvider","CheckoutTextsProvider","CheckoutAppearanceProvider","RevolutPayButton_default","useReducer","useRef","useEffect","UQ","Settings","Fragment","jsx","jsxs","LOGIN","EMAIL_CODE_TEXT_TABLES","DEFAULT_TEXTS","LogOutIcon","Fragment","jsx","jsxs","NotificationHeader","projectName","projectLogo","projectLogoDark","description","className","onLogout","cn","Button","SwitchPrimitive","jsx","Switch","className","props","cn","useAutoAnimate","CheckCircleIcon","TriangleAlertIcon","PopoverPrimitive","jsx","Popover","props","PopoverTrigger","PopoverContent","className","align","sideOffset","cn","ClockIcon","jsx","jsxs","HowOftenComponent","regularity","text","Popover","PopoverTrigger","e","PopoverContent","Fragment","jsx","jsxs","NotificationGroupsList","groups","isManaging","onToggle","onCheckAll","onUpdate","isUpdating","wasChanged","isUserGroupsUpdated","className","texts","groupsParent","useAutoAnimate","updateGroupsParent","hasNoSelection","group","hasUnchecked","content","cn","e","Switch","HowOftenComponent","Button","DEFAULT_TEXTS","Spinner","CheckCircleIcon","TriangleAlertIcon","Card","CardHeader","CardTitle","CardContent","jsx","jsxs","QRCodeSection","showQRCode","_isManaging","className","texts","isBrowser","darkMode","getURL","Card","cn","CardHeader","CardTitle","DEFAULT_TEXTS","CardContent","HOST","useState","isValidPhoneNumber","useAutoAnimate","Label","CheckCircleIcon","CircleAlertIcon","TriangleAlertIcon","useState","jsx","jsxs","FormInput","submit","isLoading","errMsg","emailLack","warnMsg","isSubmited","agreementLack","showPhoneInput","agreementText","className","texts","email","setEmail","useState","phone","setPhone","isChecked","setIsChecked","parent","useAutoAnimate","submitForm","e","cn","Label","DEFAULT_TEXTS","Input","newVal","TriangleAlertIcon","CircleAlertIcon","Button","Spinner","CheckCircleIcon","jsx","jsxs","emailRegex","AddUserToGroups","groups","onToggle","onCheckAll","slug","showPhoneInput","agreementText","className","texts","isUpdating","wasChanged","onSuccess","errMsg","setErrMsg","useState","warnMsg","setWarnMsg","isSubmited","setIsSubmited","agreementLack","setAgreementLack","emailLack","setEmailLack","createNotificationUserMutation","isCreateNotificationUserPending","useMutation","rpcProvider","validatePhoneNumber","phone","isValidPhoneNumber","save","email","agreement","newNotificationUser","el","failureMessage","FailureMessage","e","text","DEFAULT_TEXTS","cn","NotificationGroupsList","FormInput","useEffect","useState","Label","MessageCircleWarningIcon","useDebouncedCallback","TriangleAlertIcon","XIcon","createPortal","useEffect","useState","jsx","jsxs","UnsubscribeDialog","open","onOpenChange","onConfirm","isDeleting","mounted","setMounted","useState","useEffect","handleBackdropClick","e","handleConfirm","createPortal","cn","XIcon","TriangleAlertIcon","Button","useAutoAnimate","Fragment","jsx","jsxs","ManageMyData","accessToken","slug","userID","className","texts","parent","parentCard","deleteMyData","isDeleting","useMutation","rpcProvider","updateNotificationUser","isUpdating","userSettings","isLoading","useQuery","email","setEmail","useState","phone","setPhone","isDataUpdated","setIsDataUpdated","push","setPush","isDialogOpen","setIsDialogOpen","details","deleteData","handleConfirmDelete","updateData","debouncedUpdateData","useDebouncedCallback","_","useEffect","setData","key","value","cn","DEFAULT_TEXTS","Skeleton","Card","CardHeader","CardTitle","CardContent","Switch","Label","MessageCircleWarningIcon","Button","Spinner","UnsubscribeDialog","useAutoAnimate","ArrowLeft","useMemo","useRef","DialogPrimitive","XIcon","jsx","jsxs","Dialog","props","DialogPortal","props","jsx","DialogOverlay","className","props","jsx","cn","DialogContent","children","showCloseButton","jsxs","DialogPortal","XIcon","DialogTitle","className","props","jsx","cn","DialogDescription","Code","ConnectError","notificationsLoginTexts","texts","locale","sentTo","overrides","resolveEmailCodeTexts","notificationsFailureKind","error","connect","ConnectError","message","Code","kindFromRpcError","createNotificationsAdapter","call","slug","email","resend","response","cause","kind","code","jsx","jsxs","LoginDialogBody","slug","onSuccess","onError","texts","projectName","projectLogo","projectLogoDark","showLogo","parentHeader","useAutoAnimate","verifyUserEmail","useMutation","rpcProvider","loginTexts","useMemo","notificationsLoginTexts","before","after","onErrorRef","useRef","adapter","base","createNotificationsAdapter","request","input","outcome","login","useEmailCodeLogin","pendingLoginKey","userId","accessToken","kind","cause","onCodeStep","title","LoginBrandLogo","Button","ArrowLeft","DialogTitle","DialogDescription","EmailCodeLoginForm","LoginScreen","_className","isOpen","onClose","Dialog","DialogContent","useAutoAnimate","jsx","jsxs","reducer","state","action","group","g","isDefaultOn","newGroupsWithIsOn","updatedGroups","updated","NotificationsComponentPublic","slugProp","userID","productID","projectID","analytics","projectName","projectLogo","projectLogoDark","showLoginLogo","groups","isManaging","texts","showQRCode","showPhoneInput","hiddenGroupIds","className","parent","useAutoAnimate","instrument","useInstrument","currentProjectID","slug","getProjectID","useLoginBranding","updateUserGroups","isUpdating","useMutation","rpcProvider","userInfo","refetchAccessToken","UQ","groupsDownloaded","isGroupsDownloading","refetchGroups","useQuery","dispatch","useReducer","useEffect","newGroups","howOften","timeoutRef","useRef","preparedGroups","el","mergedTexts","DEFAULT_TEXTS","updateGroups","toggleGroup","groupID","checkAllGroups","handleSettingsClick","handleCloseSettings","handleLogout","handleLoginSuccess","accessToken","e","isManagingEnabled","cn","Button","Settings","NotificationHeader","Spinner","NotificationGroupsList","ManageMyData","QRCodeSection","AddUserToGroups","id","userAlreadyExists","LoginScreen","Wrapper","RpcProvider","NotificationsComponentPublic_default","useMutation","useQuery","useQueryClient","React","jsx","jsxs","PaymentMethodChoice","choice","selected","onChange","disabled","text","useCheckoutTextResolver","group","useCheckoutSlot","option","name","React","legendId","hasBlik","options","manualPaymentTitleKey","cn","method","card","isSelected","descriptionId","Fragment","jsx","jsxs","CartComponentContent","className","locale","provider","useCartProvider","instrument","useInstrumentContext","currentLocale","getLocale","productList","useCheckoutSlot","summary","totalLabel","totalValue","deliveryText","summaryNote","countryLabel","paymentButtons","checkoutButton","emptyState","error","skeleton","unavailableProductsText","useCheckoutText","resolveCheckoutText","useCheckoutTextResolver","emptyCartText","totalText","deliveryCopy","chooseCountryText","nextStepText","loadFailedText","retryText","countryRequiredText","extrasCalculatedNextText","countrySelectorId","React","countryHintId","removeProduct","useMutation","updateQuantity","setCountryAsync","clearCart","errMsg","setErrMsg","notice","useCheckoutStore","state","shownError","missingItemIds","setMissingItemIds","isCountryOpen","setIsCountryOpen","continueToCheckoutAsync","isContinueToCheckoutLoading","availableCountries","useQuery","isApplePayAvailable","data","isLoading","isError","refetch","countryData","refetchCountry","productsParent","useAutoAnimate","products","isErr","selectedCountry","queryClient","useQueryClient","cartSignature","el","paymentMethodsQuery","getProjectID","paymentMethodChoiceData","isPaymentMethodChoicePlaceholder","previous","withoutCod","paymentMethodChoice","selectedPaymentMethod","setSelectedPaymentMethod","isWaitingForChoice","setIsWaitingForChoice","paymentMethodsRef","hasLoadFailed","countries","sumOfProducts","prev","curr","currency","isSomeProductDeliverable","product","isCountryMissing","autoSelectedCountry","opened","sum","reportedQuantity","trackQuantityChange","id","newQuantity","line","delta","price","productID","startedCheckout","shouldUpdate","result","continueToCheckout","choice","paymentMethod","effectivePaymentMethod","sendAnalyticEvent","cartLinesBeforeBuy","getCartLines","response","buyErrorText","rememberPendingOrder","e","Skeleton","cn","SingleProduct_default","formatCurrency","CountrySelector_default","newValue","ApplePay_default","GooglePay_default","InPostPayButtonInner","RevolutPayButtonInner","PaymentMethodChoice","Spinner","CartComponentContent_default","jsx","jsxs","CartComponent","isVisible","shouldHide","panelId","locale","parent","useAutoAnimate","rootElement","setRootElement","useState","rootRef","useCallback","element","returnFocusTo","useRef","boundaryClassName","boundaryStyle","useCheckoutAppearance","root","useCheckoutSlot","overlay","panel","header","title","closeButton","cartText","useCheckoutText","closeText","cn","open","active","event","CartComponentContent_default","WrapperCartComponent","props","createPortal","CheckoutAppearanceProvider","CheckoutTextsProvider","CartProvider_default","CartComponent_default","Fragment","jsx","jsxs","cartAddToCartSchema","zod","visuallyHidden","BitsnapCart","projectID","locale","children","onVisibleChange","className","numberOfProductsInCartOptions","appearance","texts","analytics","instrument","useInstrument","useCartInstrument","isCartVisible","showCart","hideCart","numberOfProductsInCart","useCheckoutStore","panelId","useId","text","key","getCheckoutText","getLocale","textRef","useRef","showCartNotice","sentPostMessageToIframe","msg","iframe","useEffect","sendAnalyticEvent","setProjectID","setLocale","getProjectID","args","payload","methods","getCheckoutMethods","products","isErr","el","result","e","handleAddingToCart","id","data","handleAddingSubscriptionToCart","event","setupEventListener","type","parsedParams","refLink","jsxs","Fragment","jsx","InstrumentProvider","CartComponent_default","BitsnapCart_default"]}