JezK
Edit File: sc-checkout-autofill-provider_11.entry.js.map
{"file":"sc-checkout-autofill-provider.sc-checkout-geo-permission.sc-checkout-stock-alert.sc-checkout-test-complete.sc-checkout-unsaved-changes-warning.sc-form-components-validator.sc-form-error-provider.sc-form-state-provider.sc-login-provider.sc-order-confirm-provider.sc-session-provider.entry.js","mappings":"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","names":["onUserChange","onCheckoutChange","userState","checkoutState","onChange"],"sources":["src/components/providers/checkout-autofill-provider/sc-checkout-autofill-provider.tsx","src/functions/geolocation.ts","src/components/controllers/checkout-form/checkout/checkout-geo-permission/sc-checkout-geo-permission.scss?tag=sc-checkout-geo-permission&encapsulation=shadow","src/components/controllers/checkout-form/checkout/checkout-geo-permission/sc-checkout-geo-permission.tsx","src/functions/stock.ts","src/components/controllers/checkout-form/checkout/checkout-stock-alert/sc-checkout-stock-alert.scss?tag=sc-checkout-stock-alert&encapsulation=shadow","src/components/controllers/checkout-form/checkout/checkout-stock-alert/sc-checkout-stock-alert.tsx","src/components/controllers/checkout-form/checkout-test-complete/checkout-test-complete.scss?tag=sc-checkout-test-complete&encapsulation=shadow","src/components/controllers/checkout-form/checkout-test-complete/checkout-test-complete.tsx","src/components/providers/checkout-unsaved-changes-warning/sc-checkout-unsaved-changes-warning.tsx","src/components/providers/form-components-validator/sc-form-components-validator.tsx","src/components/providers/form-error-provider/sc-form-error-provider.tsx","src/components/providers/form-state-provider/sc-form-state-provider.tsx","src/components/providers/sc-login-provider/sc-login-provider.css?tag=sc-login-provider&encapsulation=shadow","src/components/providers/sc-login-provider/sc-login-provider.tsx","src/components/providers/order-confirm-provider/sc-order-confirm-provider.scss?tag=sc-order-confirm-provider&encapsulation=shadow","src/components/providers/order-confirm-provider/sc-order-confirm-provider.tsx","src/components/providers/session-provider/sc-session-provider.tsx"],"sourcesContent":["import { Component, h, Host } from '@stencil/core';\nimport { state as checkoutState, onChange as onCheckoutChange } from '@store/checkout';\nimport { lockCheckout, unLockCheckout } from '@store/checkout/mutations';\nimport { state as userState, onChange as onUserChange } from '@store/user';\nimport { Address, Checkout } from '../../../types';\nimport { createOrUpdateCheckout } from '../../../services/session';\nimport { getCurrentCustomer, hasAddressData, isAddressEmpty } from '../../../services/customer-address';\n\n@Component({\n tag: 'sc-checkout-autofill-provider',\n shadow: true,\n})\nexport class ScCheckoutAutofillProvider {\n private appliedForCheckoutId?: string;\n private removeUserListener?: () => void;\n private removeCheckoutListener?: () => void;\n\n componentWillLoad() {\n this.maybeApplyProfile();\n this.removeUserListener = onUserChange('loggedIn', loggedIn => {\n if (!loggedIn) {\n // A later login on the same checkout should re-apply.\n this.appliedForCheckoutId = undefined;\n return;\n }\n this.maybeApplyProfile();\n });\n this.removeCheckoutListener = onCheckoutChange('checkout', () => this.maybeApplyProfile());\n }\n\n disconnectedCallback() {\n this.removeUserListener?.();\n this.removeCheckoutListener?.();\n }\n\n async maybeApplyProfile() {\n if (!userState.loggedIn) return;\n\n const checkoutId = checkoutState.checkout?.id;\n if (!checkoutId) return;\n if (this.appliedForCheckoutId === checkoutId) return;\n\n this.appliedForCheckoutId = checkoutId;\n\n try {\n const customer = await getCurrentCustomer(checkoutState.mode);\n const patch: Record<string, any> = {};\n\n // The shipping/billing fields on Customer are typed as `string | Address`; here they\n // are expanded into Address objects via the `expand` param, so this cast is safe.\n const shippingAddress = customer?.shipping_address as Address | [] | undefined;\n const billingAddress = customer?.billing_address as Address | [] | undefined;\n\n if (hasAddressData(shippingAddress) && isAddressEmpty(checkoutState.checkout?.shipping_address)) {\n patch.shipping_address = shippingAddress;\n }\n if (hasAddressData(billingAddress) && isAddressEmpty(checkoutState.checkout?.billing_address)) {\n patch.billing_address = billingAddress;\n }\n if (customer?.first_name && !checkoutState.checkout?.first_name) {\n patch.first_name = customer.first_name;\n }\n if (customer?.last_name && !checkoutState.checkout?.last_name) {\n patch.last_name = customer.last_name;\n }\n if (customer?.phone && !checkoutState.checkout?.phone) {\n patch.phone = customer.phone;\n }\n\n // Respect the customer's saved billing-matches-shipping preference so the checkout\n // toggle reflects their profile instead of the checkout default.\n if (typeof customer?.billing_matches_shipping === 'boolean' && checkoutState.checkout?.billing_matches_shipping !== customer.billing_matches_shipping) {\n patch.billing_matches_shipping = customer.billing_matches_shipping;\n }\n\n // Nothing to apply — skip the lock entirely.\n if (!Object.keys(patch).length) return;\n\n lockCheckout('customer-profile-autofill');\n try {\n checkoutState.checkout = (await createOrUpdateCheckout({ id: checkoutState.checkout?.id, data: patch })) as Checkout;\n } finally {\n unLockCheckout('customer-profile-autofill');\n }\n } catch (e) {\n // Convenience feature — don't block checkout; clear the flag so a later trigger can retry.\n this.appliedForCheckoutId = undefined;\n console.error(e);\n }\n }\n\n render() {\n return (\n <Host>\n <slot />\n </Host>\n );\n }\n}\n","import { GeoCoordinates } from '../types';\n\n/**\n * Get the customer's coordinates via the browser Geolocation API.\n * The browser prompts for permission if not already granted; resolves\n * null when denied, unsupported, or the lookup fails — never throws.\n */\nexport const getGeoCoordinates = async (): Promise<GeoCoordinates | null> => {\n try {\n if (!navigator?.geolocation) {\n return null;\n }\n\n return await new Promise<GeoCoordinates | null>(resolve => {\n navigator.geolocation.getCurrentPosition(\n ({ coords }) => resolve({ latitude: coords.latitude, longitude: coords.longitude }),\n () => resolve(null),\n { maximumAge: 15 * 60 * 1000, timeout: 10000 },\n );\n });\n } catch {\n return null;\n }\n};\n",":host {\n display: block;\n}\n\n.geo-permission {\n --body-spacing: var(--sc-spacing-x-large);\n --width: 460px;\n\n // Inherit the dialog's themed (description-slot) color so it stays readable in light and dark.\n &__content {\n line-height: 1.5;\n\n p {\n margin: 0 0 var(--sc-spacing-small);\n\n &:first-child {\n margin-top: 0;\n }\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n}\n","import { Component, Host, h, State } from '@stencil/core';\nimport { state as checkoutState, onChange } from '@store/checkout';\nimport { getGeoCoordinates } from '../../../../../functions/geolocation';\nimport { getGeoPermissionDefaults } from '../../../../../functions/geo-permission';\n\n/** localStorage key that remembers the customer's decision so we honor it on future visits. */\nconst DECISION_KEY = 'sc_geo_capture_decision';\n\n/**\n * Explains why location is requested (e.g. regional / purchasing-power-parity pricing) and gates\n * the browser geolocation prompt behind an explicit opt-in when capture is enabled by the merchant.\n */\n@Component({\n tag: 'sc-checkout-geo-permission',\n styleUrl: 'sc-checkout-geo-permission.scss',\n shadow: true,\n})\nexport class ScCheckoutGeoPermission {\n /** Whether the explainer dialog is open. */\n @State() open: boolean = false;\n\n /** Disposer for the checkout store subscription while we wait for the cart to load. */\n private removeCartListener?: () => void;\n\n /** Whether the cart currently has at least one line item. */\n cartHasItems(): boolean {\n return !!checkoutState.checkout?.line_items?.pagination?.count;\n }\n\n /** Whether the customer dismissed our explainer (\"Not now\") on a previous visit. */\n wasDismissed(): boolean {\n try {\n return window.localStorage.getItem(DECISION_KEY) === 'declined';\n } catch {\n return false;\n }\n }\n\n /** Remember a dismissal so we don't re-show the explainer on every visit. */\n rememberDismissed() {\n try {\n window.localStorage.setItem(DECISION_KEY, 'declined');\n } catch {\n // Storage unavailable (private mode etc.) — the dismissal simply isn't remembered.\n }\n }\n\n /**\n * The browser's current geolocation permission, or null if the Permissions API is\n * unavailable (e.g. older Safari). Lets us avoid showing an explainer whose Allow\n * button can't actually trigger a prompt.\n */\n async getPermissionState(): Promise<PermissionState | null> {\n try {\n const status = await navigator.permissions?.query({ name: 'geolocation' as PermissionName });\n return status?.state ?? null;\n } catch {\n return null;\n }\n }\n\n async componentDidLoad() {\n // Nothing to do unless the merchant enabled capture and the browser can actually geolocate.\n if (!checkoutState.captureGeoAddressEnabled) return;\n if (!window?.isSecureContext || !navigator?.geolocation) return;\n\n // Don't request location for an empty cart — there's nothing to price yet, and a\n // full-screen prompt before adding items feels premature. The cart loads async, so\n // if it's not ready we wait for the first change that adds an item.\n if (this.cartHasItems()) {\n this.maybePromptForLocation();\n return;\n }\n\n this.removeCartListener = onChange('checkout', () => {\n if (!this.cartHasItems()) return;\n this.removeCartListener?.();\n this.removeCartListener = undefined;\n this.maybePromptForLocation();\n });\n }\n\n disconnectedCallback() {\n this.removeCartListener?.();\n }\n\n /** Decide, based on the browser permission, whether to capture silently, explain, or do nothing. */\n async maybePromptForLocation() {\n const permission = await this.getPermissionState();\n\n // Already granted at the browser level: capture silently — no need to ask again.\n if (permission === 'granted') {\n this.capture();\n return;\n }\n\n // Blocked at the browser level: JS can't re-prompt, so don't show an Allow button we can't fulfill.\n // Checkout continues normally with no capture; the customer can re-enable in their browser settings.\n if (permission === 'denied') return;\n\n // State is 'prompt' (or unknown): respect a prior \"Not now\", otherwise explain before prompting.\n if (this.wasDismissed()) return;\n this.open = true;\n }\n\n /** Capture coordinates into the checkout store. They ride along on the next update/finalize. */\n async capture() {\n if (checkoutState.geoCoordinates) return;\n checkoutState.geoCoordinates = await getGeoCoordinates();\n }\n\n /** Customer opted in — close and fire the native browser prompt. */\n onAllow() {\n this.open = false;\n this.capture();\n }\n\n /** Customer dismissed — remember it and close. Checkout continues with no capture. */\n onDecline() {\n this.rememberDismissed();\n this.open = false;\n }\n\n render() {\n const { geoCapture } = checkoutState;\n\n // Shared defaults (see getGeoPermissionDefaults) so merchant fields can stay empty and\n // the admin placeholders and this dialog never drift apart.\n const defaults = getGeoPermissionDefaults();\n const title = geoCapture?.title || defaults.title;\n const content = geoCapture?.content || defaults.content;\n const allowLabel = geoCapture?.allowLabel || defaults.allowLabel;\n const declineLabel = geoCapture?.declineLabel || defaults.declineLabel;\n\n return (\n <Host>\n <sc-dialog open={this.open} noHeader={true} onScRequestClose={() => this.onDecline()} class=\"geo-permission\">\n <sc-dashboard-module style={{ '--sc-dashboard-module-spacing': '1em' }}>\n <sc-flex slot=\"heading\" align-items=\"center\" justify-content=\"flex-start\">\n <sc-icon name=\"map-pin\" style={{ color: 'var(--sc-color-primary-500)' }}></sc-icon>\n {title}\n </sc-flex>\n\n <div slot=\"description\" class=\"geo-permission__content\" innerHTML={content}></div>\n </sc-dashboard-module>\n\n <sc-button slot=\"footer\" type=\"text\" onClick={() => this.onDecline()}>\n {declineLabel}\n </sc-button>\n <sc-button slot=\"footer\" type=\"primary\" onClick={() => this.onAllow()}>\n {allowLabel}\n <sc-icon name=\"map-pin\" slot=\"suffix\"></sc-icon>\n </sc-button>\n </sc-dialog>\n </Host>\n );\n }\n}\n","import { ImageAttributes, LineItem, LineItemData, Price, Product } from '../types';\nimport { getPerBundleQuantity } from './line-items';\n\nexport interface StockAlertRow {\n name?: string;\n variant?: string;\n image?: ImageAttributes;\n from: number;\n to: number;\n}\n\n/**\n * Reconstruct a bundle's `bundle_component_variants` map from its component\n * line items (componentProductId -> variantId).\n *\n * The platform treats `bundle_component_variants` on the parent as write-only:\n * it's accepted on create/update but reads back empty, so the live selection\n * has to be derived from each component line item's chosen variant. Any update\n * that re-posts the map (e.g. a stock swap) must rebuild the *full* map this way\n * — seeding from the empty parent field drops the other components and trips the\n * platform's \"selection required\" validation.\n */\nexport const getBundleComponentVariants = (parentId: string, lineItems: LineItem[] = []): Record<string, string> => {\n const map: Record<string, string> = {};\n (lineItems || []).forEach(item => {\n if (item?.bundle_line_item !== parentId) return;\n const productId = ((item?.price as Price)?.product as Product)?.id;\n const variantId = item?.variant?.id;\n if (productId && variantId) map[productId] = variantId;\n });\n return map;\n};\n\n/** Available stock for a line item (variant takes precedence over product). */\nexport const getAvailableStock = (lineItem: LineItem): number => {\n const product = lineItem?.price?.product as Product;\n const stock = lineItem?.variant?.id ? lineItem?.variant?.available_stock : product?.available_stock;\n return Math.max(Number(stock) || 0, 0);\n};\n\n/** Out-of-stock line items (standalone items and bundle components). */\nexport const getOutOfStockLineItems = (lineItems: LineItem[] = []): LineItem[] =>\n (lineItems || []).filter(lineItem => lineItem?.purchasable_status === 'out_of_stock' && getAvailableStock(lineItem) < lineItem.quantity);\n\n/**\n * A bundle is atomic, so a short component caps the bundle, not the component:\n * floor(stock / perBundleQty), smallest cap across components. Returns a map of\n * bundle parent id -> reduced quantity.\n *\n * `swappedProductsByParent` lists component products being swapped to an in-stock\n * variant — those are skipped so they don't cap a bundle they no longer limit.\n */\nexport const getBundleQuantityReductions = (lineItems: LineItem[] = [], swappedProductsByParent: Map<string, Set<string>> = new Map()): Map<string, number> => {\n const reductions = new Map<string, number>();\n\n getOutOfStockLineItems(lineItems).forEach(component => {\n if (!component.component_line_item || !component.bundle_line_item) return;\n const parent = (lineItems || []).find(li => li.id === component.bundle_line_item);\n if (!parent?.id) return;\n\n // Skip a component that's being swapped — its old stock no longer caps the bundle.\n const productId = ((component.price as Price)?.product as Product)?.id;\n if (productId && swappedProductsByParent.get(parent.id)?.has(productId)) return;\n\n const perBundle = getPerBundleQuantity(component, parent.quantity);\n const maxBundles = Math.floor(getAvailableStock(component) / perBundle);\n\n const current = reductions.get(parent.id) ?? parent.quantity;\n reductions.set(parent.id, Math.max(Math.min(current, maxBundles), 0));\n });\n\n return reductions;\n};\n\n/**\n * Payload to fix a stock alert. Posts parents only (components derive from the\n * parent): bundles drop to their reduced quantity, standalone items to available\n * stock. A swapped component is excluded from its bundle's cap, so any *other*\n * short component still reduces the bundle correctly.\n */\nexport const buildStockAdjustedLineItems = (lineItems: LineItem[] = [], bundleVariantOverrides: Map<string, Record<string, string>> = new Map()): LineItemData[] => {\n // Component products being swapped, keyed by bundle parent.\n const swappedProductsByParent = new Map<string, Set<string>>(Array.from(bundleVariantOverrides, ([parentId, map]) => [parentId, new Set(Object.keys(map))]));\n const reductions = getBundleQuantityReductions(lineItems, swappedProductsByParent);\n\n const standalone = new Map<string, number>();\n getOutOfStockLineItems(lineItems).forEach(lineItem => {\n if (lineItem.component_line_item || !lineItem.id) return;\n standalone.set(lineItem.id, getAvailableStock(lineItem));\n });\n\n return (lineItems || [])\n .filter(lineItem => !lineItem.component_line_item)\n .map(lineItem => {\n const id = lineItem.id;\n const hasSwap = !!id && bundleVariantOverrides.has(id);\n let quantity = lineItem.quantity;\n if (id && reductions.has(id)) quantity = reductions.get(id) ?? quantity;\n else if (id && standalone.has(id)) quantity = standalone.get(id) ?? quantity;\n\n return {\n id,\n price_id: (lineItem.price as Price)?.id,\n quantity,\n ...(lineItem?.variant?.id ? { variant: lineItem.variant.id } : {}),\n ...(id && hasSwap ? { bundle_component_variants: bundleVariantOverrides.get(id) } : {}),\n };\n });\n};\n\n/**\n * Rows for the stock alert dialog. Bundle components roll up into a single\n * parent row (the bundle quantity is what changes); standalone items show\n * themselves.\n */\nexport const buildStockAlertRows = (lineItems: LineItem[] = []): StockAlertRow[] => {\n const reductions = getBundleQuantityReductions(lineItems);\n const seenParents = new Set<string>();\n const rows: StockAlertRow[] = [];\n\n getOutOfStockLineItems(lineItems).forEach(lineItem => {\n if (lineItem.component_line_item && lineItem.bundle_line_item) {\n const parent = (lineItems || []).find(li => li.id === lineItem.bundle_line_item);\n if (!parent?.id || seenParents.has(parent.id)) return;\n seenParents.add(parent.id);\n const product = parent.price?.product as Product;\n rows.push({\n name: product?.name,\n variant: parent?.variant_display_options,\n image: parent?.image,\n from: parent.quantity,\n to: Math.max(reductions.get(parent.id) ?? parent.quantity, 0),\n });\n return;\n }\n\n const product = lineItem.price?.product as Product;\n rows.push({\n name: product?.name,\n variant: lineItem?.variant_display_options,\n image: lineItem?.image,\n from: lineItem.quantity,\n to: getAvailableStock(lineItem),\n });\n });\n\n return rows;\n};\n",":host {\n display: block;\n}\n\nsc-table {\n height: auto;\n}\n\nh4 {\n display: block;\n margin: 0;\n font-weight: var(--sc-font-weight-bold);\n font-size: var(--sc-font-size-medium);\n}\n\n.stock-alert {\n --body-spacing: var(--sc-spacing-x-large);\n --width: 500px;\n\n &__image {\n width: 50px;\n height: 50px;\n object-fit: cover;\n margin-right: 10px;\n display: block;\n }\n &__product-info {\n display: flex;\n flex-direction: column;\n gap: var(--sc-spacing-xx-small);\n }\n &__variant {\n color: var(--sc-color-gray-500);\n font-size: var(--sc-font-size-small);\n }\n &__quantity {\n color: var(--sc-color-gray-500);\n font-weight: var(--sc-font-weight-bold);\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--sc-spacing-xx-small);\n }\n}\n","import { Component, Host, h, State, EventEmitter, Event } from '@stencil/core';\nimport { __ } from '@wordpress/i18n';\nimport { Checkout, LineItemData, Product } from 'src/types';\nimport { state as checkoutState } from '@store/checkout';\nimport { updateCheckout } from '@services/session';\nimport { currentFormState } from '@store/form/getters';\nimport { buildStockAdjustedLineItems, buildStockAlertRows, getBundleComponentVariants, getBundleQuantityReductions, getOutOfStockLineItems } from '../../../../../functions/stock';\n\n/**\n * This component listens for stock requirements and displays a dialog to the user.\n */\n@Component({\n tag: 'sc-checkout-stock-alert',\n styleUrl: 'sc-checkout-stock-alert.scss',\n shadow: true,\n})\nexport class ScCheckoutStockAlert {\n /** Stock errors */\n @State() stockErrors: Array<any> = [];\n\n /** Toggle line item event */\n @Event() scUpdateLineItem: EventEmitter<LineItemData>;\n\n /** Is it busy */\n @State() busy: boolean;\n\n /** Update stock error. */\n @State() error: string;\n\n /** Current checkout line items. */\n get lineItems() {\n return checkoutState.checkout?.line_items?.data || [];\n }\n\n /**\n * Update the checkout to the max available stock.\n *\n * Bundle shortages reduce the whole bundle quantity (a bundle is atomic). A\n * bundle that can't make even one unit (reduced to 0) is first rescued by\n * swapping a gone variant to an in-stock sibling when one exists; otherwise\n * the unfulfillable bundle is dropped from the cart, matching the \"→ 0\" the\n * dialog already shows.\n */\n async onSubmit() {\n let attemptedBundleSwap = false;\n try {\n this.busy = true;\n this.error = null;\n\n const items = this.lineItems;\n const reductions = getBundleQuantityReductions(items);\n\n // Only bundles reduced to 0 need rescuing — try swapping the gone\n // variant to an in-stock sibling so we don't drop a recoverable bundle.\n // If no swap exists the bundle stays at 0 and is removed below.\n const parentOverrides = new Map<string, Record<string, string>>();\n getOutOfStockLineItems(items).forEach(oos => {\n if (!oos.component_line_item || !oos.bundle_line_item) return;\n const parent = items.find(li => li.id === oos.bundle_line_item);\n if (!parent?.id || (reductions.get(parent.id) ?? 0) >= 1) return;\n\n const product = oos.price?.product as Product;\n if (!product?.id) return;\n const swap = (product?.variants?.data || []).find(v => v.id !== oos.variant?.id && (v.available_stock ?? 0) > 0);\n if (!swap?.id) return;\n\n // Rebuild the full selection from the component line items (the parent\n // field reads back empty), then swap the gone variant — posting only the\n // swapped component would fail the platform's per-component requirement.\n const map = parentOverrides.get(parent.id) || getBundleComponentVariants(parent.id, items);\n map[product.id] = swap.id;\n parentOverrides.set(parent.id, map);\n });\n\n attemptedBundleSwap = parentOverrides.size > 0;\n\n // Bundles still capped at 0 (no in-stock swap) fall to quantity 0 and are\n // filtered out here — the unfulfillable bundle is simply removed.\n const lineItems = buildStockAdjustedLineItems(items, parentOverrides).filter(lineItem => !!lineItem.quantity);\n\n checkoutState.checkout = (await updateCheckout({\n id: checkoutState.checkout.id,\n data: { line_items: lineItems },\n })) as Checkout;\n } catch (error) {\n // A rejected bundle swap surfaces as a generic 500 — show an actionable\n // message so the shopper can remove the item or pick another bundle.\n if (attemptedBundleSwap) {\n this.error = __('We could not automatically update an out-of-stock bundle item. Please remove it or choose a different bundle.', 'surecart');\n } else {\n // Build the message defensively — `additionalErrors?.length && ...`\n // used to evaluate to the literal `0` when there were no additional\n // errors, which then got stringified into the displayed error.\n const additionalErrors = (error?.additional_errors || []).map(e => e?.message).filter(Boolean);\n const parts = [error?.message || __('Something went wrong.', 'surecart')];\n if (additionalErrors.length) parts.push(additionalErrors.join('. '));\n this.error = parts.join(' ');\n }\n } finally {\n this.busy = false;\n }\n }\n\n render() {\n const stockErrors = buildStockAlertRows(this.lineItems);\n\n // we have at least one fully out-of-stock item.\n const hasOutOfStockItems = stockErrors?.some(item => item?.to < 1);\n\n return (\n <Host>\n <sc-dialog open={!!stockErrors.length && currentFormState() === 'draft'} noHeader={true} onScRequestClose={e => e.preventDefault()} class=\"stock-alert\">\n <sc-dashboard-module class=\"subscription-cancel\" error={this.error} style={{ '--sc-dashboard-module-spacing': '1em' }}>\n <sc-flex slot=\"heading\" align-items=\"center\" justify-content=\"flex-start\">\n <sc-icon name=\"alert-circle\" style={{ color: 'var(--sc-color-primary-500' }}></sc-icon>\n {hasOutOfStockItems ? __('Out of Stock', 'surecart') : __('Quantity Update', 'surecart')}\n </sc-flex>\n <span slot=\"description\">\n {hasOutOfStockItems\n ? __('Some items are no longer available. Your cart will be updated.', 'surecart')\n : __('Available quantities for these items have changed. Your cart will be updated.', 'surecart')}\n </span>\n\n <sc-card no-padding>\n <sc-table>\n <sc-table-cell slot=\"head\">{__('Description', 'surecart')}</sc-table-cell>\n <sc-table-cell slot=\"head\" style={{ width: '100px', textAlign: 'right' }}>\n {__('Quantity', 'surecart')}\n </sc-table-cell>\n\n {stockErrors.map((item, index) => {\n const isLastChild = index === stockErrors.length - 1;\n return (\n <sc-table-row\n style={{\n '--columns': '2',\n ...(isLastChild ? { border: 'none' } : {}),\n }}\n >\n <sc-table-cell>\n <sc-flex justifyContent=\"flex-start\" alignItems=\"center\">\n {item?.image && <img {...(item.image as any)} class=\"stock-alert__image\" />}\n <div class=\"stock-alert__product-info\">\n <h4>{item.name}</h4>\n {item?.variant && <span class=\"stock-alert__variant\">{item.variant}</span>}\n </div>\n </sc-flex>\n </sc-table-cell>\n <sc-table-cell style={{ width: '100px', textAlign: 'right' }}>\n <span class=\"stock-alert__quantity\">\n <span>{item?.from}</span> <sc-icon name=\"arrow-right\" /> <span>{Math.max(item?.to, 0)}</span>\n </span>\n </sc-table-cell>\n </sc-table-row>\n );\n })}\n </sc-table>\n </sc-card>\n </sc-dashboard-module>\n\n <sc-button slot=\"footer\" type=\"primary\" loading={this.busy} onClick={() => this.onSubmit()}>\n {__('Continue', 'surecart')}\n <sc-icon name=\"arrow-right\" slot=\"suffix\" />\n </sc-button>\n\n {this.busy && <sc-block-ui spinner></sc-block-ui>}\n </sc-dialog>\n </Host>\n );\n }\n}\n",".confirm {\n &__icon {\n margin-bottom: var(--sc-spacing-medium);\n display: flex;\n justify-content: center;\n }\n\n &__icon-container {\n background: var(--sc-color-primary-500);\n width: 55px;\n height: 55px;\n border-radius: 999999px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 26px;\n line-height: 1;\n color: white;\n }\n}\n\nsc-dialog::part(overlay) {\n backdrop-filter: blur(4px);\n}\n","import { Component, Element, Event, EventEmitter, h, Host, Watch, Prop, State } from '@stencil/core';\nimport { __ } from '@wordpress/i18n';\nimport { state as processorsState } from '@store/processors';\nimport { state as selectedProcessorState } from '@store/selected-processor';\nimport { Checkout, ManualPaymentMethod } from '../../../../types';\nimport { clearCheckout } from '@store/checkout/mutations';\n/**\n * This component listens to the order status\n * and confirms the order when payment is successful.\n */\n@Component({\n tag: 'sc-checkout-test-complete',\n styleUrl: 'checkout-test-complete.scss',\n shadow: true,\n})\nexport class ScCheckoutTestComplete {\n private continueButton: HTMLScButtonElement;\n /** The order confirm provider element */\n @Element() el: HTMLScCheckoutTestCompleteElement;\n\n /** Whether to show success modal */\n @State() showSuccessModal: boolean = false;\n\n /** Whether to show success modal */\n @State() manualPaymentMethod: ManualPaymentMethod;\n\n /** Checkout status to listen and do payment related stuff. */\n @Prop() checkoutStatus: string;\n\n /** Success url. */\n @Prop() successUrl: string;\n\n /** The order is paid event. */\n @Event() scOrderPaid: EventEmitter<Checkout>;\n\n @Event() scSetState: EventEmitter<string>;\n\n /**\n * Watch for paid checkout machine state.\n * This is triggered by Stripe, Paypal or Paystack when payment succeeds.\n */\n @Watch('checkoutStatus')\n handleConfirmOrderEvent() {\n if (this.checkoutStatus === 'test_mode_restricted') {\n this.confirmOrder();\n }\n }\n\n /** Confirm the order. */\n async confirmOrder() {\n this.manualPaymentMethod = (processorsState.manualPaymentMethods || [])?.find(p => p.id === selectedProcessorState.id);\n this.showSuccessModal = true;\n clearCheckout();\n }\n\n @Watch('showSuccessModal')\n handleSuccessModal() {\n if (this.showSuccessModal) {\n setTimeout(() => {\n this.continueButton?.focus();\n }, 50);\n }\n }\n\n render() {\n return (\n <Host>\n <slot />\n <sc-dialog\n open={!!this.showSuccessModal}\n style={{ '--body-spacing': 'var(--sc-spacing-xxx-large)', '--width': '400px' }}\n noHeader\n onScRequestClose={e => e.preventDefault()}\n >\n <div class=\"confirm__icon\">\n <div class=\"confirm__icon-container\">\n <sc-icon name=\"check\" />\n </div>\n </div>\n <sc-dashboard-module\n heading={__('Test checkout successful!', 'surecart')}\n style={{ '--sc-dashboard-module-spacing': 'var(--sc-spacing-x-large)', 'textAlign': 'center' }}\n >\n <span slot=\"description\">\n {__('This is a simulated test checkout, and no orders were processed. To perform a test order, please contact your store administrator. ', 'surecart')}\n </span>\n {!!this.manualPaymentMethod?.name && !!this.manualPaymentMethod?.instructions && (\n <sc-alert type=\"info\" open style={{ 'text-align': 'left' }}>\n <span slot=\"title\">{this.manualPaymentMethod?.name}</span>\n <div innerHTML={this.manualPaymentMethod?.instructions}></div>\n </sc-alert>\n )}\n <sc-button href={window?.scData?.home_url} size=\"large\" type=\"primary\" ref={el => (this.continueButton = el as HTMLScButtonElement)}>\n {__('Go to Homepage', 'surecart')}\n <sc-icon name=\"arrow-right\" slot=\"suffix\" />\n </sc-button>\n </sc-dashboard-module>\n </sc-dialog>\n </Host>\n );\n }\n}\n","import { Component, Prop } from '@stencil/core';\nimport { __ } from '@wordpress/i18n';\nimport { FormState } from '../../../types';\n\n@Component({\n tag: 'sc-checkout-unsaved-changes-warning',\n shadow: true,\n})\nexport class ScCheckoutUnsavedChangesWarning {\n @Prop() state: FormState;\n\n /**\n * Add event listener for beforeunload.\n */\n componentDidLoad() {\n window.addEventListener('beforeunload', e => this.warnIfUnsavedChanges(e), { capture: true });\n }\n\n /**\n * Warn if status is updaing, finalizing, paying or confirming.\n */\n warnIfUnsavedChanges(e) {\n if (['updating', 'finalizing', 'confirming'].includes(this.state)) {\n console.log({ e });\n e.preventDefault();\n e.returnValue = __('Your payment is processing. Exiting this page could cause an error in your order. Please do not navigate away from this page.', 'surecart');\n return e.returnValue;\n }\n }\n}\n","import { Component, Element, h, Prop, State, Watch } from '@stencil/core';\nimport { __ } from '@wordpress/i18n';\nimport { state as checkoutState, onChange as onCheckoutChange } from '@store/checkout';\nimport { TaxProtocol } from '../../../types';\nimport { fullShippingAddressRequired, shippingAddressRequired } from '@store/checkout/getters';\nimport { getAvailableProcessor } from '@store/processors/getters';\n\n@Component({\n tag: 'sc-form-components-validator',\n shadow: true,\n})\nexport class ScFormComponentsValidator {\n @Element() el: HTMLScFormComponentsValidatorElement;\n\n private removeCheckoutListener: () => void;\n private removePaymentRequiresShippingListener: () => void;\n\n /** Disable validation? */\n @Prop() disabled: boolean;\n\n /** The tax protocol */\n @Prop() taxProtocol: TaxProtocol;\n\n /** Is there an address field? */\n @State() hasAddress: boolean;\n\n /** Is there a tax id field? */\n @State() hasTaxIDField: boolean;\n\n /** Is there a bumps field? */\n @State() hasBumpsField: boolean;\n\n /** Is there a tax line? */\n @State() hasTaxLine: boolean;\n\n /** Is there a bump line? */\n @State() hasBumpLine: boolean;\n\n /** Is there shipping choices */\n @State() hasShippingChoices: boolean;\n\n /** Is there a shipping amount */\n @State() hasShippingAmount: boolean;\n\n /** Is there an invoice details */\n @State() hasInvoiceDetails: boolean;\n\n /** Is there an invoice memo */\n @State() hasInvoiceMemo: boolean;\n\n /** Is there a trial line item */\n @State() hasTrialLineItem: boolean;\n\n /** Is there a customer phone field? */\n @State() hasCustomerPhone: boolean;\n\n handleOrderChange() {\n // bail if we don't have address invalid error or disabled.\n if (this.disabled) return;\n\n // make sure to add the address field if it's not there.\n if (shippingAddressRequired()) {\n this.addAddressField();\n }\n\n // add order bumps.\n if (checkoutState.checkout?.recommended_bumps?.data?.length) {\n this.addBumps();\n }\n if (!!checkoutState.checkout?.tax_amount) {\n this.addTaxLine();\n }\n\n // add shipping choices.\n if (checkoutState.checkout?.shipping_enabled && checkoutState.checkout?.selected_shipping_choice_required) {\n this.addShippingChoices();\n }\n\n if (!!checkoutState.checkout?.shipping_amount) {\n this.addShippingAmount();\n }\n\n // automatically add invoice details if we have an invoice.\n if (!!checkoutState.checkout?.invoice) {\n this.addInvoiceDetails();\n this.addInvoiceMemo();\n }\n\n // automatically add trial line item if we have a trial amount.\n if (!!checkoutState.checkout?.trial_amount) {\n this.addTrialLineItem();\n }\n }\n\n @Watch('hasAddress')\n handleHasAddressChange() {\n if (!this.hasAddress) return;\n this.handleShippingAddressRequired();\n }\n\n componentWillLoad() {\n this.hasAddress = !!this.el.querySelector('sc-order-shipping-address');\n this.hasTaxIDField = !!this.el.querySelector('sc-order-tax-id-input');\n this.hasBumpsField = !!this.el.querySelector('sc-order-bumps');\n this.hasTaxLine = !!this.el.querySelector('sc-line-item-tax');\n this.hasShippingChoices = !!this.el.querySelector('sc-shipping-choices');\n this.hasShippingAmount = !!this.el.querySelector('sc-line-item-shipping');\n this.hasInvoiceDetails = !!this.el.querySelector('sc-invoice-details');\n this.hasInvoiceMemo = !!this.el.querySelector('sc-invoice-memo');\n this.hasTrialLineItem = !!this.el.querySelector('sc-line-item-trial');\n this.hasCustomerPhone = !!this.el.querySelector('sc-customer-phone');\n\n // if eu vat is required, add the tax id field.\n if (this.taxProtocol?.tax_enabled && this.taxProtocol?.eu_vat_required) {\n this.addTaxIDField();\n }\n\n // if razorpay is available, add the customer phone field.\n if (getAvailableProcessor('razorpay')) {\n this.addCustomerPhone();\n }\n\n this.handleOrderChange();\n\n this.removeCheckoutListener = onCheckoutChange('checkout', () => this.handleOrderChange());\n this.removePaymentRequiresShippingListener = onCheckoutChange('paymentMethodRequiresShipping', () => this.handleOrderChange());\n }\n\n disconnectedCallback() {\n this.removeCheckoutListener();\n this.removePaymentRequiresShippingListener();\n }\n\n handleShippingAddressRequired() {\n if (!checkoutState.checkout?.shipping_address_required) return;\n\n // get the address\n const address = this.el.querySelector('sc-order-shipping-address');\n if (!address) return;\n\n // require the address.\n address.required = true;\n\n // if we have a customer name field, require that.\n const customerName = this.el.querySelector('sc-customer-name');\n if (!!customerName) {\n customerName.required = true;\n return;\n }\n\n // if we have a customer first name field, require that.\n const customerFirstName = this.el.querySelector('sc-customer-firstname');\n const customerLastName = this.el.querySelector('sc-customer-lastname');\n\n // if we have a customer first name field, require that.\n if (!!customerFirstName) {\n customerFirstName.required = true;\n\n // if we have a customer last name field, require that.\n if (!!customerLastName) {\n customerLastName.required = true;\n }\n\n return; // we're done here.\n }\n\n // require the name and show the name input.\n address.requireName = true;\n address.showName = true;\n }\n\n addAddressField() {\n if (this.hasAddress) {\n return;\n }\n\n const payment = this.el.querySelector('sc-payment');\n const shippingAddress = document.createElement('sc-order-shipping-address');\n payment.parentNode.insertBefore(shippingAddress, payment);\n\n if (fullShippingAddressRequired()) {\n const billingAddress = document.createElement('sc-order-billing-address');\n billingAddress.label = __('Billing Address', 'surecart');\n payment.parentNode.insertBefore(billingAddress, payment);\n } else {\n shippingAddress.label = __('Address', 'surecart');\n }\n\n this.hasAddress = true;\n }\n\n addTaxIDField() {\n if (this.hasTaxIDField) return;\n const payment = this.el.querySelector('sc-payment');\n const taxInput = document.createElement('sc-order-tax-id-input');\n payment.parentNode.insertBefore(taxInput, payment);\n this.hasTaxIDField = true;\n }\n\n addCustomerPhone() {\n if (this.hasCustomerPhone) return;\n const payment = this.el.querySelector('sc-payment');\n if (!payment) return;\n\n const customerPhone = document.createElement('sc-customer-phone');\n customerPhone.label = __('Phone', 'surecart');\n customerPhone.required = true;\n payment.parentNode.insertBefore(customerPhone, payment);\n this.hasCustomerPhone = true;\n }\n\n addBumps() {\n if (this.hasBumpsField) return;\n const attachReferenceElement = this.el.querySelector('sc-order-billing-address') || this.el.querySelector('sc-payment');\n const bumps = document.createElement('sc-order-bumps');\n attachReferenceElement?.parentNode.insertBefore(bumps, attachReferenceElement.nextSibling);\n this.hasBumpsField = true;\n }\n\n addTaxLine() {\n if (this.hasTaxLine) return;\n const total = this.el.querySelector('sc-line-item-total[total=total]');\n const tax = document.createElement('sc-line-item-tax');\n\n if (!total) return;\n\n if (total?.previousElementSibling?.tagName === 'SC-DIVIDER') {\n total.parentNode.insertBefore(tax, total.previousElementSibling);\n } else {\n total.parentNode.insertBefore(tax, total);\n }\n this.hasTaxLine = true;\n }\n\n addShippingChoices() {\n if (this.hasShippingChoices) return;\n\n const payment = this.el.querySelector('sc-payment');\n const shippingChoices = document.createElement('sc-shipping-choices');\n payment.parentNode.insertBefore(shippingChoices, payment);\n this.hasShippingChoices = true;\n }\n\n addShippingAmount() {\n if (this.hasShippingAmount) return;\n\n let insertBeforeElement: Element = this.el.querySelector('sc-line-item-tax');\n const total = this.el.querySelector('sc-line-item-total[total=total]');\n\n if (!total) return;\n\n if (!insertBeforeElement) {\n insertBeforeElement = total?.previousElementSibling?.tagName === 'SC-DIVIDER' ? total.previousElementSibling : total;\n }\n\n const shippingAmount = document.createElement('sc-line-item-shipping');\n insertBeforeElement.parentNode.insertBefore(shippingAmount, insertBeforeElement);\n this.hasShippingAmount = true;\n }\n\n addInvoiceDetails() {\n if (this.hasInvoiceDetails) return;\n\n let lineItems: Element = this.el.querySelector('sc-line-items');\n const invoiceDetails = document.createElement('sc-invoice-details');\n lineItems.parentNode.insertBefore(invoiceDetails, lineItems);\n\n // Add sc-line-item-invoice-number inside sc-invoice-details.\n const invoiceNumber = document.createElement('sc-line-item-invoice-number');\n invoiceDetails.appendChild(invoiceNumber);\n\n // Add sc-line-item-invoice-due-date inside sc-invoice-details.\n const invoiceDueDate = document.createElement('sc-line-item-invoice-due-date');\n invoiceDetails.appendChild(invoiceDueDate);\n\n // Add invoice sc-line-item-invoice-receipt-download inside sc-invoice-details.\n const invoiceReceiptDownload = document.createElement('sc-line-item-invoice-receipt-download');\n invoiceDetails.appendChild(invoiceReceiptDownload);\n\n // Add sc-divider inside sc-invoice-details.\n const divider = document.createElement('sc-divider');\n invoiceDetails.appendChild(divider);\n\n this.hasInvoiceDetails = true;\n }\n\n addInvoiceMemo() {\n if (this.hasInvoiceMemo) return;\n\n const orderSummary = this.el.querySelector('sc-order-summary');\n\n const invoiceDetails = document.createElement('sc-invoice-details');\n\n // Add sc-divider inside sc-invoice-details.\n orderSummary.parentNode.insertBefore(invoiceDetails, orderSummary.nextSibling);\n\n // Add sc-invoice-memo inside sc-invoice-details.\n const invoiceMemo = document.createElement('sc-invoice-memo');\n invoiceDetails.appendChild(invoiceMemo);\n\n this.hasInvoiceMemo = true;\n }\n\n addTrialLineItem() {\n if (this.hasTrialLineItem) return;\n\n const subtotal = this.el.querySelector('sc-line-item-total[total=subtotal]');\n const trialItem = document.createElement('sc-line-item-trial');\n\n if (!subtotal) return;\n\n // Insert the trial item before the coupon form.\n subtotal.parentNode.insertBefore(trialItem, subtotal.nextSibling);\n\n this.hasTrialLineItem = true;\n }\n\n render() {\n return <slot />;\n }\n}\n","/**\n * External dependencies.\n */\nimport { Component, h, Element } from '@stencil/core';\nimport { __ } from '@wordpress/i18n';\n\n/**\n * This component checks to make sure there is an error component\n * and adds one if it's missing.\n */\n@Component({\n tag: 'sc-form-error-provider',\n shadow: true,\n})\nexport class ScFormErrorProvider {\n /** The element. */\n @Element() el: HTMLScFormErrorProviderElement;\n\n componentWillLoad() {\n this.maybeAddErrorsComponent();\n }\n\n maybeAddErrorsComponent() {\n if (!!this.el.querySelector('sc-checkout-form-errors')) return;\n const errorsComponent = document.createElement('sc-checkout-form-errors');\n this.el.querySelector('sc-form')?.prepend?.(errorsComponent);\n }\n\n render() {\n return <slot />;\n }\n}\n","import { Component, h, State, Event, EventEmitter, Listen, Watch } from '@stencil/core';\nimport { checkoutMachine } from './checkout-machine';\nimport { interpret } from '@xstate/fsm';\nimport { __ } from '@wordpress/i18n';\nimport { FormState, FormStateSetter } from '../../../types';\nimport { updateFormState } from '@store/form/mutations';\n\n/**\n * This component listens for a confirmed event and redirects to the success url.\n */\n@Component({\n tag: 'sc-form-state-provider',\n shadow: true,\n})\nexport class ScFormStateProvider {\n /** Holds our state machine service */\n private _stateService = interpret(checkoutMachine);\n\n /** Loading states for different parts of the form. */\n @State() checkoutState = checkoutMachine.initialState;\n\n /** Set the state. */\n @Event() scSetCheckoutFormState: EventEmitter<FormState>;\n\n /** Set the state. */\n setState(name) {\n const { send } = this._stateService;\n updateFormState(name);\n return send(name);\n }\n\n /** Watch for checkout state changes and emit to listeners. */\n @Watch('checkoutState')\n handleCheckoutStateChange(state) {\n this.scSetCheckoutFormState.emit(state.value);\n }\n\n /** Init the state service. */\n componentWillLoad() {\n // Start state machine.\n this._stateService.subscribe(state => (this.checkoutState = state));\n this._stateService.start();\n }\n\n /** Remove state machine on disconnect. */\n disconnectedCallback() {\n this._stateService.stop();\n }\n\n /** Allow children to set the form state. */\n @Listen('scSetState')\n handleSetStateEvent(e) {\n this.setState(e.detail as FormStateSetter);\n }\n\n /** Update the state when the order is paid. */\n @Listen('scPaid')\n async handlePaid() {\n this.setState('PAID');\n }\n\n render() {\n // handle expired.\n if (this.checkoutState.value === 'expired') {\n return (\n <sc-block-ui>\n <div>{__('Please refresh the page.', 'surecart')}</div>\n </sc-block-ui>\n );\n }\n\n return <slot />;\n }\n}\n",":host {\n display: block;\n}\n","import { Component, Prop, h, Watch, State, Host, Listen, Event, EventEmitter } from '@stencil/core';\nimport { __ } from '@wordpress/i18n';\nimport apiFetch from '../../../functions/fetch';\nimport { Checkout } from '../../../types';\n\n@Component({\n tag: 'sc-login-provider',\n styleUrl: 'sc-login-provider.css',\n shadow: true,\n})\nexport class ScLoginProvider {\n private loginForm: HTMLScFormElement;\n\n /** Is the user logged in. */\n @Prop() loggedIn: boolean;\n @Prop() order: Checkout;\n\n @Event() scSetLoggedIn: EventEmitter<boolean>;\n @Event() scSetCustomer: EventEmitter<{ email: string; name?: string }>;\n\n @State() notice: boolean;\n @State() open: boolean;\n @State() loading: boolean;\n @State() error: string;\n\n /** Listen for open event. */\n @Listen('scLoginPrompt')\n handleLoginPrompt() {\n this.open = true;\n }\n\n /** Focus on first input. */\n @Watch('open')\n handleLoginDialogChange(val) {\n if (val) {\n setTimeout(() => {\n this.loginForm.querySelector('sc-input').triggerFocus();\n }, 100);\n }\n }\n\n @Watch('loggedIn')\n handleLoggedInChange(val, prev) {\n if (prev === false && val) {\n this.notice = true;\n }\n }\n\n @Watch('order')\n handleOrderChange(val, prev) {\n if (val?.updated_at !== prev?.updated_at) {\n this.notice = false;\n }\n }\n\n /** Handle form submit. */\n async handleFormSubmit(e) {\n e.preventDefault();\n e.stopImmediatePropagation();\n this.error = null;\n\n const { login, password } = await e.target.getFormJson();\n\n try {\n this.loading = true;\n const { name, email } = (await apiFetch({\n method: 'POST',\n path: 'surecart/v1/login',\n data: {\n login,\n password,\n },\n })) as { name: string; email: string };\n this.scSetLoggedIn.emit(true);\n this.scSetCustomer.emit({ name, email });\n this.open = false;\n } catch (e) {\n console.error(e);\n this.error = e?.message || __('Something went wrong', 'surecart');\n } finally {\n this.loading = false;\n }\n }\n\n render() {\n return (\n <Host>\n <slot />\n\n {!this.loggedIn && (\n <sc-dialog label={__('Login to your account', 'surecart')} open={this.open} onScRequestClose={() => (this.open = false)}>\n <sc-form\n ref={el => (this.loginForm = el as HTMLScFormElement)}\n onScFormSubmit={e => {\n e.preventDefault();\n e.stopImmediatePropagation();\n }}\n onScSubmit={e => this.handleFormSubmit(e)}\n >\n {!!this.error && (\n <sc-alert type=\"danger\" open={!!this.error}>\n {this.error}\n </sc-alert>\n )}\n <sc-input label={__('Email or Username', 'surecart')} type=\"text\" name=\"login\" required autofocus={this.open}></sc-input>\n <sc-input label={__('Password', 'surecart')} type=\"password\" name=\"password\" required></sc-input>\n <sc-button type=\"primary\" full loading={this.loading} submit>\n {__('Login', 'surecart')}\n </sc-button>\n </sc-form>\n </sc-dialog>\n )}\n </Host>\n );\n }\n}\n",".confirm {\n &__icon {\n margin-bottom: var(--sc-spacing-medium);\n display: flex;\n justify-content: center;\n }\n\n &__icon-container {\n background: var(--sc-color-primary-500);\n width: 55px;\n height: 55px;\n border-radius: 999999px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 26px;\n line-height: 1;\n color: white;\n }\n}\n\nsc-dialog::part(overlay) {\n backdrop-filter: blur(4px);\n}\n","import { Component, Element, Event, EventEmitter, h, Host, Watch, Prop, State } from '@stencil/core';\nimport { __ } from '@wordpress/i18n';\nimport { addQueryArgs } from '@wordpress/url';\nimport { speak } from '@wordpress/a11y';\n\nimport apiFetch from '../../../functions/fetch';\nimport { expand } from '../../../services/session';\nimport { state as checkoutState } from '@store/checkout';\nimport { state as formState } from '@store/form';\nimport { Checkout, ManualPaymentMethod } from '../../../types';\nimport { createErrorNotice } from '@store/notices/mutations';\nimport { clearCheckout } from '@store/checkout/mutations';\n/**\n * This component listens to the order status\n * and confirms the order when payment is successful.\n */\n@Component({\n tag: 'sc-order-confirm-provider',\n styleUrl: 'sc-order-confirm-provider.scss',\n shadow: true,\n})\nexport class ScOrderConfirmProvider {\n private continueButton: HTMLScButtonElement;\n /** The order confirm provider element */\n @Element() el: HTMLScOrderConfirmProviderElement;\n\n /** Whether to show success modal */\n @State() showSuccessModal: boolean = false;\n\n /** Whether to show success modal */\n @State() manualPaymentMethod: ManualPaymentMethod;\n\n /** Checkout status to listen and do payment related stuff. */\n @Prop() checkoutStatus: string;\n\n /** Success url. */\n @Prop() successUrl: string;\n\n /** The order is paid event. */\n @Event() scOrderPaid: EventEmitter<Checkout>;\n\n @Event() scSetState: EventEmitter<string>;\n\n /**\n * Watch for paid checkout machine state.\n * This is triggered by Stripe, Paypal or Paystack when payment succeeds.\n */\n @Watch('checkoutStatus')\n handleConfirmOrderEvent() {\n if (this.checkoutStatus === 'confirming') {\n this.confirmOrder();\n } else if (this.checkoutStatus === 'confirmed') {\n speak(__('Order has been confirmed. Please select continue to go to the next step.', 'surecart'));\n }\n }\n\n /** Confirm the order. */\n async confirmOrder() {\n try {\n checkoutState.checkout = (await apiFetch({\n method: 'PATCH',\n path: addQueryArgs(`surecart/v1/checkouts/${checkoutState?.checkout?.id}/confirm`, { expand }),\n })) as Checkout;\n this.scSetState.emit('CONFIRMED');\n } catch (e) {\n console.error(e);\n createErrorNotice(e);\n } finally {\n this.manualPaymentMethod = (checkoutState.checkout?.manual_payment_method as ManualPaymentMethod) || null;\n const checkout = checkoutState.checkout;\n const formId = checkoutState.formId;\n\n // If there is an initial upsell redirect to it.\n if (!!checkout?.current_upsell?.permalink) {\n setTimeout(\n () =>\n window.location.assign(\n addQueryArgs(checkout?.current_upsell?.permalink, {\n sc_checkout_id: checkout?.id,\n sc_form_id: formId,\n }),\n ),\n 50,\n );\n clearCheckout();\n return;\n }\n\n // get success url.\n const successUrl = checkout?.metadata?.success_url || this.successUrl;\n if (successUrl) {\n // set state to redirecting.\n this.scSetState.emit('REDIRECT');\n const redirectUrl = addQueryArgs(successUrl, { sc_order: checkout?.id });\n setTimeout(() => window.location.assign(redirectUrl), 50);\n } else {\n this.showSuccessModal = true;\n }\n clearCheckout();\n }\n }\n\n getSuccessUrl() {\n const url = checkoutState.checkout?.metadata?.success_url || this.successUrl;\n return url ? addQueryArgs(url, { sc_order: checkoutState.checkout?.id }) : window?.scData?.pages?.dashboard;\n }\n\n @Watch('showSuccessModal')\n handleSuccessModal() {\n if (this.showSuccessModal) {\n setTimeout(() => {\n this.continueButton?.focus();\n }, 50);\n }\n }\n\n render() {\n return (\n <Host>\n <slot />\n <sc-dialog\n open={!!this.showSuccessModal}\n style={{ '--body-spacing': 'var(--sc-spacing-xxx-large)', '--width': '400px' }}\n noHeader\n onScRequestClose={e => e.preventDefault()}\n >\n <div class=\"confirm__icon\">\n <div class=\"confirm__icon-container\">\n <sc-icon name=\"check\" />\n </div>\n </div>\n <sc-dashboard-module\n heading={formState?.text?.success?.title || __('Thanks for your order!', 'surecart')}\n style={{ '--sc-dashboard-module-spacing': 'var(--sc-spacing-x-large)', 'textAlign': 'center' }}\n >\n <span slot=\"description\">{formState?.text?.success?.description || __('Your payment was successful. A receipt is on its way to your inbox.', 'surecart')}</span>\n {!!this.manualPaymentMethod?.name && !!this.manualPaymentMethod?.instructions && (\n <sc-alert type=\"info\" open style={{ 'text-align': 'left' }}>\n <span slot=\"title\">{this.manualPaymentMethod?.name}</span>\n <div innerHTML={this.manualPaymentMethod?.instructions}></div>\n </sc-alert>\n )}\n <sc-button href={this.getSuccessUrl()} size=\"large\" type=\"primary\" ref={el => (this.continueButton = el as HTMLScButtonElement)}>\n {formState?.text?.success?.button || __('Continue', 'surecart')}\n <sc-icon name=\"arrow-right\" slot=\"suffix\" />\n </sc-button>\n </sc-dashboard-module>\n </sc-dialog>\n </Host>\n );\n }\n}\n","import { Component, Element, Event, EventEmitter, h, Listen, Method, Prop, Watch } from '@stencil/core';\nimport { state as checkoutState } from '@store/checkout';\nimport { clearCheckout } from '@store/checkout/mutations';\nimport { state as selectedProcessor } from '@store/selected-processor';\nimport { state as processorsState } from '@store/processors';\nimport { __ } from '@wordpress/i18n';\nimport { addQueryArgs, getQueryArg, getQueryArgs, removeQueryArgs } from '@wordpress/url';\nimport { updateFormState } from '@store/form/mutations';\n\nimport { parseFormData } from '../../../functions/form-data';\nimport { createCheckout, createOrUpdateCheckout, fetchCheckout, finalizeCheckout } from '../../../services/session';\nimport { Checkout, FormStateSetter, LineItemData, PriceChoice } from '../../../types';\nimport { createErrorNotice, createInfoNotice, removeNotice } from '@store/notices/mutations';\n\n@Component({\n tag: 'sc-session-provider',\n shadow: true,\n})\nexport class ScSessionProvider {\n /** Element */\n @Element() el: HTMLElement;\n\n /** An array of prices to pre-fill in the form. */\n @Prop() prices: Array<PriceChoice> = [];\n\n /** Should we persist the session. */\n @Prop() persist: boolean = true;\n\n /** Update line items event */\n @Event() scUpdateOrderState: EventEmitter<Checkout>;\n\n /** Update line items event */\n @Event() scUpdateDraftState: EventEmitter<Checkout>;\n\n @Event() scPaid: EventEmitter<void>;\n\n /** Set the state */\n @Event() scSetState: EventEmitter<FormStateSetter>;\n\n @Watch('prices')\n handlePricesChange() {\n let line_items = this.addInitialPrices() || [];\n // line_items = this.addPriceChoices(line_items);\n if (!line_items?.length) {\n return;\n }\n return this.loadUpdate({ line_items });\n }\n\n /**\n * Finalize the order.\n *\n * @returns {Promise<Order>}\n */\n @Method()\n async finalize() {\n return await this.handleFormSubmit();\n }\n\n async getFormData() {\n let data = {};\n const form = this.el.querySelector('sc-form');\n if (form) {\n const json = await form.getFormJson();\n data = parseFormData(json);\n }\n return data;\n }\n\n /**\n * Handles the form submission.\n * @param e\n */\n @Listen('scFormSubmit')\n async handleFormSubmit() {\n removeNotice();\n\n updateFormState('FINALIZE');\n\n if (checkoutState?.checkout?.payment_method_required && selectedProcessor?.id === 'stripe' && processorsState.config.stripe.paymentElement) {\n // not initialized.\n if (!processorsState?.instances?.stripeElements) {\n updateFormState('REJECT');\n this.handleErrorResponse({ message: 'Stripe Elements not found.', code: 'stripe_elements_not_found' });\n return new Error('Stripe Elements not found.');\n }\n // submit the elements.\n const { error } = await processorsState?.instances?.stripeElements.submit();\n if (error) {\n console.error({ error });\n updateFormState('REJECT');\n createErrorNotice(error);\n return;\n }\n }\n\n // Get current form state.\n let data = await this.getFormData();\n\n if (window?.scData?.recaptcha_site_key && window?.grecaptcha) {\n try {\n data['grecaptcha'] = await window.grecaptcha.execute(window.scData.recaptcha_site_key, { action: 'surecart_checkout_submit' });\n } catch (e) {\n console.error(e);\n updateFormState('REJECT');\n this.handleErrorResponse(e);\n return new Error(e?.message);\n }\n }\n\n // first lets make sure the session is updated before we process it.\n try {\n await this.update(data);\n } catch (e) {\n console.error(e);\n updateFormState('REJECT');\n this.handleErrorResponse(e);\n }\n\n // first validate server-side and get key\n try {\n checkoutState.checkout = await finalizeCheckout({\n id: checkoutState?.checkout?.id,\n query: {\n ...(selectedProcessor?.method ? { payment_method_type: selectedProcessor?.method } : {}),\n return_url: addQueryArgs(window.location.href, {\n ...(checkoutState?.checkout?.id ? { checkout_id: checkoutState?.checkout?.id } : {}),\n is_surecart_payment_redirect: true,\n }),\n },\n data,\n processor: {\n id: selectedProcessor.id,\n manual: selectedProcessor.manual,\n },\n });\n\n if (checkoutState.checkout?.payment_intent?.processor_data?.mollie?.checkout_url) {\n updateFormState('PAYING');\n return setTimeout(() => window.location.assign(checkoutState.checkout?.payment_intent?.processor_data?.mollie?.checkout_url), 50);\n }\n\n // the checkout is paid.\n if (['paid', 'processing'].includes(checkoutState.checkout?.status)) {\n this.scPaid.emit();\n }\n\n setTimeout(() => {\n updateFormState('PAYING');\n }, 50);\n\n return checkoutState.checkout;\n } catch (e) {\n console.error(e);\n this.handleErrorResponse(e);\n return new Error(e?.message);\n }\n }\n\n /**\n * Handle paid event and update the\n */\n @Listen('scPaid')\n async handlePaid() {\n updateFormState('PAID');\n }\n\n @Listen('scUpdateAbandonedCart')\n async handleAbandonedCartUpdate(e) {\n const abandoned_checkout_enabled = e.detail;\n this.loadUpdate({\n abandoned_checkout_enabled,\n });\n }\n\n /** Find or create session on load. */\n componentDidLoad() {\n this.findOrCreateOrder();\n }\n\n /** Find or create an order */\n async findOrCreateOrder() {\n // get URL params.\n const { redirect_status, checkout_id, line_items, coupon, is_surecart_payment_redirect } = getQueryArgs(window.location.href);\n // remove params we don't want.\n window.history.replaceState(\n {},\n document.title,\n removeQueryArgs(window.location.href, 'redirect_status', 'coupon', 'line_items', 'confirm_checkout_id', 'checkout_id', 'no_cart', 'is_surecart_payment_redirect'),\n );\n\n // handle abandoned checkout.\n if (!!is_surecart_payment_redirect && !!checkout_id) {\n updateFormState('FINALIZE');\n updateFormState('PAYING');\n return this.handleCheckoutIdFromUrl(checkout_id, coupon as string, {\n refresh_status: true,\n });\n }\n\n // handle redirect status.\n if (!!redirect_status) {\n return this.handleRedirectStatus(redirect_status, checkout_id);\n }\n\n // handle abandoned checkout.\n if (!!checkout_id) {\n return this.handleCheckoutIdFromUrl(checkout_id, coupon as string);\n }\n\n // handle initial line items.\n if (!!line_items) {\n return this.handleInitialLineItems(line_items, coupon as string);\n }\n\n // we have an existing saved checkout id in the session, and we are persisting.\n const id = checkoutState?.checkout?.id;\n if (id && this.persist) {\n return this.handleExistingCheckout(id, coupon as string);\n }\n\n return this.handleNewCheckout(coupon as string);\n }\n\n /** Handle payment instrument redirect status */\n async handleRedirectStatus(status, id) {\n console.info('Handling payment redirect.');\n // status failed.\n if (status === 'failed') {\n createErrorNotice(__('Payment unsuccessful. Please try again.', 'surecart'));\n return;\n }\n\n // get the\n if (!id) {\n createErrorNotice(__('Could not find checkout. Please contact us before attempting to purchase again.', 'surecart'));\n return;\n }\n\n // success, refetch the checkout\n try {\n updateFormState('FINALIZE');\n checkoutState.checkout = (await fetchCheckout({\n id,\n query: {\n refresh_status: true,\n },\n })) as Checkout;\n\n // TODO: should we even check this?\n if (checkoutState.checkout?.status && ['paid', 'processing'].includes(checkoutState.checkout?.status)) {\n setTimeout(() => {\n updateFormState('PAID');\n this.scPaid.emit();\n }, 100);\n }\n } catch (e) {\n this.handleErrorResponse(e);\n }\n }\n\n /** Handle abandoned checkout from URL */\n async handleCheckoutIdFromUrl(id, promotion_code = '', query = {}) {\n console.info('Handling existing checkout from url.', promotion_code, id);\n\n // if coupon code, load the checkout with the code.\n if (promotion_code) {\n return this.loadUpdate({\n id,\n discount: { promotion_code },\n refresh_line_items: true,\n ...query,\n });\n }\n\n try {\n updateFormState('FETCH');\n checkoutState.checkout = (await fetchCheckout({\n id,\n query: {\n refresh_line_items: true,\n ...query,\n },\n })) as Checkout;\n\n updateFormState('RESOLVE');\n } catch (e) {\n this.handleErrorResponse(e);\n }\n\n // handle status.\n switch (checkoutState.checkout?.status) {\n case 'paid':\n case 'processing':\n return setTimeout(() => {\n updateFormState('FINALIZE');\n updateFormState('PAID');\n this.scPaid.emit();\n }, 100);\n\n case 'payment_failed':\n createErrorNotice({\n message: __('Payment unsuccessful.', 'surecart'),\n });\n updateFormState('REJECT');\n return;\n\n case 'payment_intent_canceled':\n updateFormState('REJECT');\n return;\n case 'canceled':\n clearCheckout();\n createErrorNotice({\n message: __('Payment canceled. Please try again.', 'surecart'),\n });\n updateFormState('REJECT');\n return;\n }\n }\n\n /** Handle line items (and maybe ) */\n async handleInitialLineItems(line_items, promotion_code) {\n console.info('Handling initial line items.');\n // TODO: move this to central store.\n const address = this.el.querySelector('sc-order-shipping-address');\n return this.loadUpdate({\n line_items,\n refresh_line_items: true,\n ...(promotion_code ? { discount: { promotion_code } } : {}),\n ...(address?.defaultCountry\n ? {\n shipping_address: {\n country: address?.defaultCountry,\n },\n }\n : {}),\n });\n }\n\n /** Handle a brand new checkout. */\n async handleNewCheckout(promotion_code) {\n // get existing form data from defaults (default country selection, etc).\n const data = this.getFormData();\n let line_items = checkoutState.initialLineItems || [];\n const address = this.el.querySelector('sc-order-shipping-address');\n\n try {\n updateFormState('FETCH');\n checkoutState.checkout = (await createCheckout({\n data: {\n ...data,\n ...(promotion_code ? { discount: { promotion_code } } : {}),\n ...(address?.defaultCountry\n ? {\n shipping_address: {\n country: address?.defaultCountry,\n },\n }\n : {}),\n line_items,\n ...(checkoutState.taxProtocol?.eu_vat_required ? { tax_identifier: { number_type: 'eu_vat' } } : {}),\n },\n })) as Checkout;\n updateFormState('RESOLVE');\n } catch (e) {\n console.error(e);\n this.handleErrorResponse(e);\n\n // Handle any invalid coupon set on checkout URL.\n if (e?.additional_errors?.[0]?.code === 'checkout.discount.coupon.blank') {\n await this.handleNewCheckout(false);\n createErrorNotice(e);\n }\n }\n }\n\n /** Handle existing checkout */\n async handleExistingCheckout(id, promotion_code) {\n if (!id) return this.handleNewCheckout(promotion_code);\n console.info('Handling existing checkout.');\n try {\n updateFormState('FETCH');\n checkoutState.checkout = (await createOrUpdateCheckout({\n id,\n data: {\n ...(promotion_code ? { discount: { promotion_code } } : {}),\n ...(checkoutState.taxProtocol?.eu_vat_required ? { tax_identifier: { number_type: 'eu_vat' } } : {}),\n refresh_line_items: true,\n },\n })) as Checkout;\n updateFormState('RESOLVE');\n } catch (e) {\n console.error(e);\n this.handleErrorResponse(e);\n\n // Handle any invalid coupon set on checkout URL.\n if (e?.additional_errors?.[0]?.code === 'checkout.discount.coupon.blank') {\n await this.handleExistingCheckout(id, false);\n createErrorNotice(e);\n }\n }\n }\n\n /** Handle the error response. */\n async handleErrorResponse(e) {\n // reinitalize if order not found.\n if (['checkout.not_found'].includes(e?.code)) {\n clearCheckout();\n return this.handleNewCheckout(false);\n }\n\n if (['test_mode_restricted'].includes(e?.code)) {\n updateFormState('TEST_MODE_RESTRICTED');\n return;\n }\n\n const hasPriceVersionChangeError = (e?.additional_errors || []).some(error => {\n const purchasableStatuses = error?.data?.options?.purchasable_statuses || [];\n return ['price_old_version', 'variant_old_version'].some(status => purchasableStatuses.includes(status));\n });\n\n if (hasPriceVersionChangeError) {\n await this.loadUpdate({\n id: checkoutState?.checkout?.id,\n refresh_line_items: true,\n status: 'draft',\n });\n createInfoNotice(\n e?.additional_errors?.[0]?.message ||\n __('Some products in your order were outdated and have been updated. Please review your order summary before proceeding to payment.', 'surecart'),\n );\n updateFormState('REJECT');\n return;\n }\n\n // If got Product out of stock error, then fetch the checkout again.\n if (e?.additional_errors?.[0]?.code === 'checkout.product.out_of_stock') {\n this.fetch();\n updateFormState('REJECT');\n return;\n }\n\n if (['order.invalid_status_transition'].includes(e?.code)) {\n await this.loadUpdate({\n id: checkoutState?.checkout?.id,\n status: 'draft',\n });\n this.handleFormSubmit();\n return;\n }\n\n // expired\n if (e?.code === 'rest_cookie_invalid_nonce') {\n updateFormState('EXPIRE');\n return;\n }\n\n // paid\n if (e?.code === 'readonly') {\n clearCheckout();\n window.location.assign(removeQueryArgs(window.location.href, 'order'));\n return;\n }\n\n createErrorNotice(e);\n updateFormState('REJECT');\n }\n\n /** Looks through children and finds items needed for initial session. */\n async initialize(args = {}) {\n let line_items = checkoutState.initialLineItems || [];\n return this.loadUpdate({ ...(line_items?.length ? { line_items } : {}), ...args });\n }\n\n /** Add prices that are passed into the component. */\n addInitialPrices() {\n if (!this?.prices?.length) return [];\n\n // check for id\n if (this.prices.some(p => !p?.id)) {\n return;\n }\n\n // add prices that are passed into this component.\n return this.prices.map(price => {\n return {\n price_id: price.id,\n quantity: price.quantity,\n variant: price.variant,\n };\n });\n }\n\n // /** Add default prices that may be selected in form. */\n // addPriceChoices(line_items = []) {\n // // const elements = this.el.querySelectorAll('[price-id]') as any;\n // // elements.forEach(el => {\n // // // handle price choices.\n // // if (el.checked) {\n // // line_items.push({\n // // quantity: el.quantity || 1,\n // // price_id: el.priceId,\n // // ...(el.defaultAmount ? { ad_hoc_amount: el.defaultAmount } : {}),\n // // });\n // // }\n // // // handle donation default amount.\n // // if (el.defaultAmount) {\n // // line_items.push({\n // // quantity: el.quantity || 1,\n // // price_id: el.priceId,\n // // ad_hoc_amount: el.defaultAmount,\n // // });\n // // }\n // // });\n // // return line_items;\n // }\n\n getSessionId() {\n // check url first.\n const checkoutId = getQueryArg(window.location.href, 'checkout_id');\n if (!!checkoutId) {\n return checkoutId;\n }\n\n // check existing order.\n if (checkoutState?.checkout?.id) {\n return checkoutState?.checkout?.id;\n }\n\n // we don't have and order id.\n return null;\n }\n\n async fetchCheckout(id, { query = {}, data = {} } = {}) {\n try {\n updateFormState('FETCH');\n const checkout = (await createOrUpdateCheckout({\n id,\n query,\n data,\n })) as Checkout;\n updateFormState('RESOLVE');\n return checkout;\n } catch (e) {\n this.handleErrorResponse(e);\n }\n }\n\n /** Fetch a session. */\n async fetch(query = {}) {\n try {\n updateFormState('FETCH');\n checkoutState.checkout = (await fetchCheckout({\n id: this.getSessionId(),\n query,\n })) as Checkout;\n updateFormState('RESOLVE');\n } catch (e) {\n this.handleErrorResponse(e);\n }\n }\n\n /** Update a session */\n async update(data: any = {}, query = {}) {\n try {\n checkoutState.checkout = (await createOrUpdateCheckout({\n id: data?.id ? data.id : this.getSessionId(),\n data,\n query,\n })) as Checkout;\n } catch (e) {\n // reinitalize if order not found.\n if (['checkout.not_found'].includes(e?.code)) {\n clearCheckout();\n return this.initialize();\n }\n console.error(e);\n throw e;\n }\n }\n\n /** Updates a session with loading status changes. */\n async loadUpdate(data = {}) {\n try {\n updateFormState('FETCH');\n await this.update(data);\n updateFormState('RESOLVE');\n } catch (e) {\n this.handleErrorResponse(e);\n }\n }\n\n render() {\n return (\n <sc-line-items-provider order={checkoutState?.checkout} onScUpdateLineItems={e => this.loadUpdate({ line_items: e.detail as Array<LineItemData> })}>\n <slot />\n </sc-line-items-provider>\n );\n }\n}\n"],"version":3}