fontdue-js 2.16.1 → 2.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/__generated__/AddressFieldsRefetchQuery.graphql.d.ts +1 -1
  3. package/dist/__generated__/AddressFieldsRefetchQuery.graphql.js +25 -4
  4. package/dist/__generated__/AddressFields_viewer.graphql.d.ts +5 -1
  5. package/dist/__generated__/AddressFields_viewer.graphql.js +23 -2
  6. package/dist/__generated__/CartOrderCompleteOrderMutation.graphql.d.ts +1 -1
  7. package/dist/__generated__/CartOrderCompleteOrderMutation.graphql.js +10 -4
  8. package/dist/__generated__/CartOrderRemoveDiscountMutation.graphql.d.ts +1 -1
  9. package/dist/__generated__/CartOrderRemoveDiscountMutation.graphql.js +10 -4
  10. package/dist/__generated__/CartOrderUpdateMutation.graphql.d.ts +3 -2
  11. package/dist/__generated__/CartOrderUpdateMutation.graphql.js +10 -4
  12. package/dist/__generated__/CartQuery.graphql.d.ts +1 -1
  13. package/dist/__generated__/CartQuery.graphql.js +22 -4
  14. package/dist/__generated__/CartStateRemoveDiscountMutation.graphql.d.ts +1 -1
  15. package/dist/__generated__/CartStateRemoveDiscountMutation.graphql.js +43 -4
  16. package/dist/__generated__/CartStateUpdateMutation.graphql.d.ts +4 -3
  17. package/dist/__generated__/CartStateUpdateMutation.graphql.js +75 -54
  18. package/dist/__generated__/CartState_order.graphql.d.ts +2 -1
  19. package/dist/__generated__/CartState_order.graphql.js +8 -2
  20. package/dist/__generated__/CheckoutUpdateCustomerMutation.graphql.d.ts +1 -1
  21. package/dist/__generated__/CheckoutUpdateCustomerMutation.graphql.js +10 -4
  22. package/dist/__generated__/CheckoutUpdateOrderMutation.graphql.d.ts +5 -4
  23. package/dist/__generated__/CheckoutUpdateOrderMutation.graphql.js +10 -4
  24. package/dist/__generated__/Checkout_UpdateOrderErrors.graphql.d.ts +3 -3
  25. package/dist/__generated__/Checkout_UpdateOrderErrors.graphql.js +3 -3
  26. package/dist/__generated__/Checkout_identity.graphql.d.ts +2 -2
  27. package/dist/__generated__/Checkout_identity.graphql.js +3 -3
  28. package/dist/__generated__/Checkout_order.graphql.d.ts +3 -3
  29. package/dist/__generated__/Checkout_order.graphql.js +2 -2
  30. package/dist/__generated__/CouponCodeInputApplyCouponMutation.graphql.d.ts +1 -1
  31. package/dist/__generated__/CouponCodeInputApplyCouponMutation.graphql.js +43 -4
  32. package/dist/__generated__/CustomerLoginFormLoginMutation.graphql.d.ts +4 -1
  33. package/dist/__generated__/CustomerLoginFormLoginMutation.graphql.js +1 -1
  34. package/dist/__generated__/FontFamiliesQuery.graphql.d.ts +2 -1
  35. package/dist/__generated__/FontFamiliesQuery.graphql.js +1 -1
  36. package/dist/__generated__/OrderVariableSelectionReduxRefetchQuery.graphql.d.ts +26 -0
  37. package/dist/__generated__/OrderVariableSelectionReduxRefetchQuery.graphql.js +154 -0
  38. package/dist/__generated__/OrderVariableSelectionRedux_viewer.graphql.d.ts +6 -1
  39. package/dist/__generated__/OrderVariableSelectionRedux_viewer.graphql.js +48 -5
  40. package/dist/__generated__/OrderVariableSelection_variables.graphql.d.ts +5 -1
  41. package/dist/__generated__/OrderVariableSelection_variables.graphql.js +41 -17
  42. package/dist/__generated__/PrecartAddToCartMutation.graphql.d.ts +2 -1
  43. package/dist/__generated__/PrecartAddToCartMutation.graphql.js +10 -4
  44. package/dist/__generated__/PriceBarSectionRefetchQuery.graphql.d.ts +2 -1
  45. package/dist/__generated__/PriceBarSectionRefetchQuery.graphql.js +1 -1
  46. package/dist/__generated__/StoreModalCartQuery.graphql.d.ts +8 -2
  47. package/dist/__generated__/StoreModalCartQuery.graphql.js +171 -114
  48. package/dist/__generated__/StoreModalIndexItem_fontCollection.graphql.d.ts +2 -1
  49. package/dist/__generated__/StoreModalIndexItem_fontCollection.graphql.js +8 -2
  50. package/dist/__generated__/StoreModalIndexQuery.graphql.d.ts +1 -1
  51. package/dist/__generated__/StoreModalIndexQuery.graphql.js +9 -3
  52. package/dist/__generated__/StoreModalOrderVariableSelectionHookQuery.graphql.d.ts +26 -0
  53. package/dist/__generated__/StoreModalOrderVariableSelectionRefetchQuery.graphql.d.ts +26 -0
  54. package/dist/__generated__/StoreModalOrderVariableSelection_order.graphql.d.ts +30 -0
  55. package/dist/__generated__/StoreModalOrderVariableSelection_order.graphql.js +98 -0
  56. package/dist/__generated__/StoreModalOrderVariableSelection_viewer.graphql.d.ts +1 -16
  57. package/dist/__generated__/StoreModalOrderVariableSelection_viewer.graphql.js +40 -104
  58. package/dist/__generated__/StoreModalProductContent_viewer.graphql.d.ts +30 -0
  59. package/dist/__generated__/StoreModalProductQuery.graphql.d.ts +2 -1
  60. package/dist/__generated__/StoreModalProductQuery.graphql.js +90 -63
  61. package/dist/__generated__/StoreModalProductRefetchQuery.graphql.d.ts +2 -1
  62. package/dist/__generated__/StoreModalProductRefetchQuery.graphql.js +1 -1
  63. package/dist/__generated__/StoreModalProductSummaryAddToCartMutation.graphql.d.ts +2 -1
  64. package/dist/__generated__/StoreModalProductSummaryAddToCartMutation.graphql.js +1 -1
  65. package/dist/__generated__/StoreModalProductSummaryRefetchQuery.graphql.d.ts +2 -1
  66. package/dist/__generated__/StoreModalProductSummaryRefetchQuery.graphql.js +1 -1
  67. package/dist/__generated__/StoreModalProductViewerRefetchQuery.graphql.d.ts +31 -0
  68. package/dist/__generated__/StoreModalUnifiedCheckoutCompleteOrderMutation.graphql.d.ts +1 -1
  69. package/dist/__generated__/StoreModalUnifiedCheckoutCompleteOrderMutation.graphql.js +43 -4
  70. package/dist/__generated__/StoreModalUnifiedCheckoutUpdateCustomerMutation.graphql.d.ts +6 -1
  71. package/dist/__generated__/StoreModalUnifiedCheckoutUpdateCustomerMutation.graphql.js +74 -24
  72. package/dist/__generated__/StoreModalUnifiedCheckoutUpdateOrderMutation.graphql.d.ts +5 -4
  73. package/dist/__generated__/StoreModalUnifiedCheckoutUpdateOrderMutation.graphql.js +43 -4
  74. package/dist/__generated__/StoreModalUnifiedCheckout_order.graphql.d.ts +13 -3
  75. package/dist/__generated__/StoreModalUnifiedCheckout_order.graphql.js +50 -4
  76. package/dist/__generated__/StoreModalUnifiedCheckout_viewer.graphql.d.ts +2 -1
  77. package/dist/__generated__/StoreModalUnifiedCheckout_viewer.graphql.js +8 -2
  78. package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.d.ts +1 -1
  79. package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.js +10 -4
  80. package/dist/__generated__/TypeTesterStandaloneChangedStylesQuery.graphql.d.ts +2 -1
  81. package/dist/__generated__/TypeTesterStandaloneChangedStylesQuery.graphql.js +9 -3
  82. package/dist/__generated__/TypeTesterStandaloneQuery.graphql.d.ts +1 -1
  83. package/dist/__generated__/TypeTesterStandaloneQuery.graphql.js +30 -14
  84. package/dist/__generated__/TypeTesterStyleSelectData_fontStyle.graphql.d.ts +2 -1
  85. package/dist/__generated__/TypeTesterStyleSelectData_fontStyle.graphql.js +8 -2
  86. package/dist/__generated__/TypeTesterStyleSelectData_viewer.graphql.d.ts +4 -1
  87. package/dist/__generated__/TypeTesterStyleSelectData_viewer.graphql.js +17 -2
  88. package/dist/__generated__/TypeTesterStyleSelect_family.graphql.d.ts +33 -0
  89. package/dist/__generated__/TypeTesterStyleSelect_fontStyle.graphql.d.ts +27 -0
  90. package/dist/__generated__/TypeTestersChangedStylesQuery.graphql.d.ts +2 -1
  91. package/dist/__generated__/TypeTestersChangedStylesQuery.graphql.js +9 -3
  92. package/dist/__generated__/TypeTestersIDQuery.graphql.d.ts +1 -1
  93. package/dist/__generated__/TypeTestersIDQuery.graphql.js +53 -37
  94. package/dist/__generated__/TypeTestersRefetchQuery.graphql.d.ts +2 -1
  95. package/dist/__generated__/TypeTestersRefetchQuery.graphql.js +9 -3
  96. package/dist/__generated__/TypeTestersSlugQuery.graphql.d.ts +1 -1
  97. package/dist/__generated__/TypeTestersSlugQuery.graphql.js +53 -37
  98. package/dist/components/Cart/AddressFields.d.ts +3 -2
  99. package/dist/components/Cart/AddressFields.js +45 -47
  100. package/dist/components/Cart/CartState.js +2 -2
  101. package/dist/components/Cart/CartTotals.d.ts +5 -2
  102. package/dist/components/Cart/CartTotals.js +24 -10
  103. package/dist/components/Cart/Checkout.js +33 -6
  104. package/dist/components/Cart/CustomerFields.d.ts +5 -0
  105. package/dist/components/Cart/CustomerFields.js +11 -3
  106. package/dist/components/Cart/types.d.ts +1 -1
  107. package/dist/components/ConfigContext.d.ts +10 -0
  108. package/dist/components/ConfigContext.js +4 -1
  109. package/dist/components/OrderVariableSelection/OrderVariableSelectionRedux.js +30 -1
  110. package/dist/components/OrderVariableSelection/index.d.ts +3 -1
  111. package/dist/components/OrderVariableSelection/index.js +31 -11
  112. package/dist/components/StoreModal/StoreModalCart.js +9 -6
  113. package/dist/components/StoreModal/StoreModalIndexItem.js +3 -3
  114. package/dist/components/StoreModal/StoreModalOrderVariableSelection.d.ts +3 -1
  115. package/dist/components/StoreModal/StoreModalOrderVariableSelection.js +25 -6
  116. package/dist/components/StoreModal/StoreModalProduct.js +1 -1
  117. package/dist/components/StoreModal/StoreModalStyleButton.js +1 -8
  118. package/dist/components/StripeProvider/index.js +5 -3
  119. package/dist/components/TypeTester/TypeTesterStyleSelectData.js +12 -3
  120. package/dist/components/elements/StoreModalUnifiedCheckout.d.ts +60 -1
  121. package/dist/components/elements/StoreModalUnifiedCheckout.js +425 -208
  122. package/dist/fontdue.css +36 -10
  123. package/dist/reducer.d.ts +1 -0
  124. package/dist/utils/interpolateOrderVariableDescription.d.ts +36 -0
  125. package/dist/utils/interpolateOrderVariableDescription.test.d.ts +1 -0
  126. package/dist/utils.d.ts +1 -0
  127. package/dist/utils.js +11 -2
  128. package/package.json +2 -1
@@ -10,14 +10,13 @@ var _StoreModalUnifiedCheckoutUpdateCustomerMutation2 = _interopRequireDefault(r
10
10
  var _StoreModalUnifiedCheckout_order2 = _interopRequireDefault(require("../../__generated__/StoreModalUnifiedCheckout_order.graphql"));
11
11
  var _StoreModalUnifiedCheckout_viewer2 = _interopRequireDefault(require("../../__generated__/StoreModalUnifiedCheckout_viewer.graphql"));
12
12
  var _react = _interopRequireWildcard(require("react"));
13
+ var Sentry = _interopRequireWildcard(require("@sentry/react"));
13
14
  var _reactRelay = require("react-relay");
14
15
  var _AddressFields = _interopRequireDefault(require("../Cart/AddressFields"));
15
16
  var _CustomerFields = _interopRequireDefault(require("../Cart/CustomerFields"));
16
- var _StoreModalReviewIdentity = _interopRequireDefault(require("../StoreModal/StoreModalReviewIdentity"));
17
17
  var _reactStripeJs = require("@stripe/react-stripe-js");
18
18
  var _StoreModalLicenseeIsBillingIdentityElement = _interopRequireDefault(require("./StoreModalLicenseeIsBillingIdentityElement"));
19
19
  var _reactRedux = require("react-redux");
20
- var _reactErrorBoundary = require("react-error-boundary");
21
20
  var _StripeLogo = _interopRequireDefault(require("../StripeLogo"));
22
21
  var _Icons = require("../Icons");
23
22
  var _ConfigContext = _interopRequireDefault(require("../ConfigContext"));
@@ -25,9 +24,68 @@ var _Price = require("../Price");
25
24
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
26
25
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
27
26
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
27
+ /**
28
+ * StoreModalUnifiedCheckout
29
+ *
30
+ * This component handles the checkout flow for orders, collecting customer information,
31
+ * billing/licensee details, and processing payment through Stripe.
32
+ *
33
+ * Key implementation details:
34
+ *
35
+ * 1. Auto-save billing identity (fontdue tax system only):
36
+ * - When using fontdue's tax system (not Stripe Tax), we need the billing address
37
+ * to calculate taxes before showing the final amount
38
+ * - The billing identity is auto-saved (with 500ms debounce) once the Stripe Address
39
+ * Element reports complete (name + address fields)
40
+ * - Email is a separate field (not part of Address Element), so auto-save may trigger
41
+ * before email is filled, which will cause backend validation errors to display
42
+ * - This ensures taxes are calculated and displayed before the user clicks Pay
43
+ * - On page reload, if billing identity already exists, billingAddressComplete starts
44
+ * as true to prevent re-triggering auto-save
45
+ *
46
+ * 2. Billing identity diff tracking:
47
+ * - We track differences between local state and saved backend data (billingIdentityDiff)
48
+ * - This determines isBillingIdentitySaved, which controls when payment can proceed
49
+ * - If the user edits any field after auto-save, it triggers another save cycle
50
+ * - All fields are normalized (null/undefined/empty string treated as equivalent)
51
+ *
52
+ * 3. Pay button validation:
53
+ * - The Pay button is always enabled (as long as EULA is checked) even if billing
54
+ * info isn't fully saved yet
55
+ * - This is intentional: we need to allow the user to click Pay so we can call
56
+ * elements.submit(), which triggers Stripe's validation and shows any validation
57
+ * errors inline in the Stripe UI elements
58
+ * - After Stripe validation passes, we check if billing identity is saved
59
+ * - If not saved, we show an error message above the Pay button asking them to
60
+ * complete billing information (validation errors should now be visible above)
61
+ *
62
+ * 4. Customer info pre-fill:
63
+ * - When customer submits their contact info, if billing name/email are empty,
64
+ * we pre-fill them from customer data as a convenience
65
+ *
66
+ * 5. Country mismatch handling (order snapshots):
67
+ * - When loading a hydrated order (e.g., from quote/snapshot), the order may have
68
+ * a country variable that differs from the user's detected country
69
+ * - In this case, we force licenseeIsBillingIdentity to false and always collect
70
+ * separate licensee information to ensure the licensee country matches the quote
71
+ * - This preserves pricing/availability from the original quote
72
+ *
73
+ * 6. Licensee country syncing:
74
+ * - When licensee country changes, it automatically updates any country-type order
75
+ * variables to maintain consistent pricing based on the selected country
76
+ *
77
+ * 7. Zero-order/coupon flow:
78
+ * - Orders with $0 total (due to coupons) bypass Stripe payment entirely
79
+ * - These use the completeOrder mutation instead of confirmPayment
80
+ *
81
+ * 8. Tax system variations:
82
+ * - Stripe Tax system: Uses embedded checkout, billing handled by Stripe
83
+ * - Fontdue tax system: Collects billing info directly, auto-saves for tax calculation
84
+ */
85
+
28
86
  /* const LICENSEE_REQUIRED_FIELDS = ['organization', 'country'] as (keyof Identity)[]; */
29
87
 
30
- const IDENTITY_REQUIRED_FIELDS = ['name', 'email', 'phone', 'country'];
88
+ const IDENTITY_REQUIRED_FIELDS = ['name', 'email', 'country'];
31
89
  const defaultIdentity = {
32
90
  name: '',
33
91
  organization: '',
@@ -43,17 +101,18 @@ const defaultIdentity = {
43
101
  };
44
102
  function getIdentityFields(object) {
45
103
  if (!object) return;
46
- const identityKeys = Object.keys(defaultIdentity);
47
- const result = {};
48
- for (const key of identityKeys) {
49
- if (key in object) {
50
- const value = object[key];
51
- if (value) result[key] = value;
52
- }
53
- }
54
104
  return {
55
- ...defaultIdentity,
56
- ...result
105
+ name: object.name ?? '',
106
+ organization: object.organization ?? null,
107
+ email: object.email ?? '',
108
+ phone: object.phoneNullable ?? '',
109
+ country: object.country ?? '',
110
+ administrativeArea: object.administrativeArea ?? null,
111
+ street: object.street ?? null,
112
+ locality: object.locality ?? null,
113
+ sublocality: object.sublocality ?? null,
114
+ zip: object.zip ?? null,
115
+ vatNumber: object.vatNumber ?? null
57
116
  };
58
117
  }
59
118
  function EditableSection(_ref) {
@@ -67,7 +126,8 @@ function EditableSection(_ref) {
67
126
  editing,
68
127
  children: {
69
128
  show,
70
- edit
129
+ edit,
130
+ save
71
131
  }
72
132
  } = _ref;
73
133
  const [submitting, setSubmitting] = (0, _react.useState)(false);
@@ -101,24 +161,54 @@ function EditableSection(_ref) {
101
161
  className: "store-modal__cart__button",
102
162
  type: "submit",
103
163
  disabled: submitting || disableSubmit
104
- }, submitting ? 'Submitting...' : 'Save'))) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, show, /*#__PURE__*/_react.default.createElement("button", {
164
+ }, submitting ? 'Submitting...' : save))) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, show, /*#__PURE__*/_react.default.createElement("button", {
105
165
  type: "button",
106
166
  className: "store-modal__cart__edit-button",
107
167
  onClick: onEdit
108
168
  }, "Change")));
109
169
  }
110
170
  function StoreModalUnifiedCheckout(_ref2) {
111
- var _viewer$settings, _viewer$settings2, _viewer$settings3, _order$stripePaymentI, _order$stripePaymentI2;
171
+ var _order$orderVariableS, _viewer$settings, _viewer$settings2, _viewer$settings3, _order$stripePaymentI, _order$stripePaymentI2;
112
172
  let {
113
173
  order: orderKey,
114
174
  viewer: viewerKey,
115
- onScrollToTop
175
+ onScrollToTop,
176
+ onUpdateOrderVariableSelections
116
177
  } = _ref2;
117
- const viewer = (0, _reactRelay.useFragment)((_StoreModalUnifiedCheckout_viewer2.default.hash && _StoreModalUnifiedCheckout_viewer2.default.hash !== "568763fc3756be6256c132ebf0fcacb7" && console.error("The definition of 'StoreModalUnifiedCheckout_viewer' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckout_viewer2.default), viewerKey);
118
- const order = (0, _reactRelay.useFragment)((_StoreModalUnifiedCheckout_order2.default.hash && _StoreModalUnifiedCheckout_order2.default.hash !== "94683a80ba2c7104fd80f9e508cd6d70" && console.error("The definition of 'StoreModalUnifiedCheckout_order' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckout_order2.default), orderKey);
178
+ const viewer = (0, _reactRelay.useFragment)((_StoreModalUnifiedCheckout_viewer2.default.hash && _StoreModalUnifiedCheckout_viewer2.default.hash !== "83cc5e6f8d508fb1c2356a72b040f9b0" && console.error("The definition of 'StoreModalUnifiedCheckout_viewer' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckout_viewer2.default), viewerKey);
179
+ const order = (0, _reactRelay.useFragment)((_StoreModalUnifiedCheckout_order2.default.hash && _StoreModalUnifiedCheckout_order2.default.hash !== "ea43fb766c4dd1183b46ddf449aa85bd" && console.error("The definition of 'StoreModalUnifiedCheckout_order' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckout_order2.default), orderKey);
180
+
181
+ // Check if order has a country-type order variable with a different country than detected
182
+ // This is important for order snapshot/quote functionality where a quote was created for
183
+ // a different country than the user's detected country. In this case, we must collect
184
+ // licensee information to ensure the country variable matches the licensee's country.
185
+ // If the countries match (or no country variable exists), allow the normal checkout flow.
186
+ const countryVariableSelection = (_order$orderVariableS = order.orderVariableSelections) === null || _order$orderVariableS === void 0 ? void 0 : _order$orderVariableS.find(selection => selection.orderVariable.variableType === 'country');
187
+ const hasCountryMismatch = countryVariableSelection && countryVariableSelection.countryCode && countryVariableSelection.countryCode !== viewer.detectedCountry;
188
+
189
+ // When loading a hydrated order (e.g., from order snapshot/quote), initialize the
190
+ // licensee country from the order variable country if no licensee country exists yet.
191
+ // This is useful for the "order snapshot" functionality where we want to preserve
192
+ // the original country selection from the quote.
193
+ const getInitialCountry = () => {
194
+ var _order$licenseeIdenti, _order$orderVariableS2;
195
+ // If order already has a licensee identity with country, use that
196
+ if (order !== null && order !== void 0 && (_order$licenseeIdenti = order.licenseeIdentity) !== null && _order$licenseeIdenti !== void 0 && _order$licenseeIdenti.country) {
197
+ return order.licenseeIdentity.country;
198
+ }
199
+
200
+ // Otherwise, check if there's a country-type order variable selection
201
+ const countryVariableSelection = order === null || order === void 0 ? void 0 : (_order$orderVariableS2 = order.orderVariableSelections) === null || _order$orderVariableS2 === void 0 ? void 0 : _order$orderVariableS2.find(selection => selection.orderVariable.variableType === 'country');
202
+ if (countryVariableSelection !== null && countryVariableSelection !== void 0 && countryVariableSelection.countryCode) {
203
+ return countryVariableSelection.countryCode;
204
+ }
205
+
206
+ // Fall back to detected country or viewer country
207
+ return viewer.detectedCountry ?? viewer.country;
208
+ };
119
209
  const initialIdentity = {
120
210
  ...defaultIdentity,
121
- country: viewer.country
211
+ country: getInitialCountry()
122
212
  };
123
213
  const [customer, setCustomer] = (0, _react.useState)((order === null || order === void 0 ? void 0 : order.customer) ?? {
124
214
  name: null,
@@ -127,25 +217,73 @@ function StoreModalUnifiedCheckout(_ref2) {
127
217
  });
128
218
  const [licenseeIdentity, setLicenseeIdentity] = (0, _react.useState)(getIdentityFields(order === null || order === void 0 ? void 0 : order.licenseeIdentity) ?? initialIdentity);
129
219
  const [billingIdentity, setBillingIdentity] = (0, _react.useState)(getIdentityFields(order === null || order === void 0 ? void 0 : order.billingIdentity) ?? initialIdentity);
220
+
221
+ // Track if the Stripe Address Element reports as complete
222
+ // Start as true if order already has billing identity (page reload case)
223
+ const [billingAddressComplete, setBillingAddressComplete] = (0, _react.useState)(!!(order !== null && order !== void 0 && order.billingIdentity));
224
+
225
+ // Track differences between local state and saved backend data
226
+ const billingIdentityDiff = (0, _react.useMemo)(() => {
227
+ const savedIdentity = order === null || order === void 0 ? void 0 : order.billingIdentity;
228
+ if (!savedIdentity) return null;
229
+
230
+ // Helper to normalize values (treat null, undefined, and empty string as equivalent)
231
+ const normalize = val => val || '';
232
+ const differences = {};
233
+ const checkField = (field, localValue, savedValue) => {
234
+ const normalizedLocal = normalize(localValue);
235
+ const normalizedSaved = normalize(savedValue);
236
+ if (normalizedLocal !== normalizedSaved) {
237
+ differences[field] = {
238
+ local: normalizedLocal,
239
+ saved: normalizedSaved
240
+ };
241
+ }
242
+ };
243
+ checkField('name', billingIdentity.name, savedIdentity.name);
244
+ checkField('email', billingIdentity.email, savedIdentity.email);
245
+ checkField('phone', billingIdentity.phone, savedIdentity.phoneNullable);
246
+ checkField('country', billingIdentity.country, savedIdentity.country);
247
+ checkField('street', billingIdentity.street, savedIdentity.street);
248
+ checkField('locality', billingIdentity.locality, savedIdentity.locality);
249
+ checkField('sublocality', billingIdentity.sublocality, savedIdentity.sublocality);
250
+ checkField('administrativeArea', billingIdentity.administrativeArea, savedIdentity.administrativeArea);
251
+ checkField('zip', billingIdentity.zip, savedIdentity.zip);
252
+ checkField('organization', billingIdentity.organization, savedIdentity.organization);
253
+ checkField('vatNumber', billingIdentity.vatNumber, savedIdentity.vatNumber);
254
+ return Object.keys(differences).length > 0 ? differences : null;
255
+ }, [billingIdentity, order === null || order === void 0 ? void 0 : order.billingIdentity]);
256
+ const isBillingIdentitySaved = billingIdentityDiff === null && !!(order !== null && order !== void 0 && order.billingIdentity);
130
257
  const handleCustomerChange = (0, _react.useCallback)(value => setCustomer(currentValue => ({
131
258
  ...currentValue,
132
259
  ...value
133
260
  })), [setCustomer]);
134
261
  const handleLicenseeChange = (0, _react.useCallback)(value => {
262
+ setErrorsObject(currentValue => {
263
+ if (currentValue !== null && currentValue !== void 0 && currentValue.licenseeIdentity) {
264
+ const keys = Object.keys(value);
265
+ return {
266
+ ...currentValue,
267
+ licenseeIdentity: {
268
+ ...currentValue.licenseeIdentity,
269
+ ...keys.reduce((acc, field) => {
270
+ acc[field] = null;
271
+ return acc;
272
+ }, {})
273
+ }
274
+ };
275
+ }
276
+ return currentValue;
277
+ });
135
278
  setLicenseeIdentity(currentValue => ({
136
279
  ...currentValue,
137
280
  ...value
138
281
  }));
139
282
  }, [setLicenseeIdentity]);
140
- const handleBillingChange = (0, _react.useCallback)(value => {
141
- setBillingIdentity(currentValue => ({
142
- ...currentValue,
143
- ...value
144
- }));
145
- }, [setBillingIdentity]);
146
283
  const environment = (0, _reactRelay.useRelayEnvironment)();
147
284
  const [error, setError] = (0, _react.useState)(null);
148
285
  const [errorsObject, setErrorsObject] = (0, _react.useState)(null);
286
+ const [customerErrorsObject, setCustomerErrorsObject] = (0, _react.useState)(null);
149
287
  const [_submitting, setSubmitting] = (0, _react.useState)(false);
150
288
  /* const [licenseeRequiredFields, setLicenseeRequiredFields] = useState<
151
289
  * (keyof Identity)[]
@@ -155,11 +293,15 @@ function StoreModalUnifiedCheckout(_ref2) {
155
293
  form: config
156
294
  } = (0, _react.useContext)(_ConfigContext.default);
157
295
  const onCompleted = (res, errors, onSuccess, onError) => {
158
- var _res$updateOrder;
296
+ var _res$updateCustomer, _res$updateOrder;
159
297
  if (errors && errors.length > 0) {
160
298
  setError(errors[0].message);
161
299
  setSubmitting(false);
162
300
  onError === null || onError === void 0 ? void 0 : onError();
301
+ } else if ('updateCustomer' in res && (_res$updateCustomer = res.updateCustomer) !== null && _res$updateCustomer !== void 0 && _res$updateCustomer.errors && (res.updateCustomer.errors.name || res.updateCustomer.errors.email || res.updateCustomer.errors.newsletterOptIn)) {
302
+ setSubmitting(false);
303
+ setCustomerErrorsObject(res.updateCustomer.errors);
304
+ onError === null || onError === void 0 ? void 0 : onError();
163
305
  } else if ('updateOrder' in res && (_res$updateOrder = res.updateOrder) !== null && _res$updateOrder !== void 0 && _res$updateOrder.errors) {
164
306
  setSubmitting(false);
165
307
  setErrorsObject(res.updateOrder.errors);
@@ -168,18 +310,19 @@ function StoreModalUnifiedCheckout(_ref2) {
168
310
  onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess();
169
311
  setSubmitting(false);
170
312
  setError(null);
313
+ setCustomerErrorsObject(null);
314
+ setErrorsObject(null);
171
315
  }
172
316
  };
173
317
  const onError = error => {
174
318
  setError(error.message);
175
319
  setSubmitting(false);
176
- onScrollToTop();
177
320
  };
178
- const updateCustomer = (0, _react.useCallback)((variables, onSuccess) => {
321
+ const updateCustomer = (0, _react.useCallback)((variables, onSuccess, onErrorCallback) => {
179
322
  (0, _reactRelay.commitMutation)(environment, {
180
- mutation: (_StoreModalUnifiedCheckoutUpdateCustomerMutation2.default.hash && _StoreModalUnifiedCheckoutUpdateCustomerMutation2.default.hash !== "1927e9fb21dbae898062200a560b1277" && console.error("The definition of 'StoreModalUnifiedCheckoutUpdateCustomerMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckoutUpdateCustomerMutation2.default),
323
+ mutation: (_StoreModalUnifiedCheckoutUpdateCustomerMutation2.default.hash && _StoreModalUnifiedCheckoutUpdateCustomerMutation2.default.hash !== "a41e423a93ba20f15ebbe826dd802514" && console.error("The definition of 'StoreModalUnifiedCheckoutUpdateCustomerMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckoutUpdateCustomerMutation2.default),
181
324
  variables,
182
- onCompleted: (res, errors) => onCompleted(res, errors, onSuccess),
325
+ onCompleted: (res, errors) => onCompleted(res, errors, onSuccess, onErrorCallback),
183
326
  onError
184
327
  });
185
328
  }, [environment]);
@@ -187,21 +330,82 @@ function StoreModalUnifiedCheckout(_ref2) {
187
330
  (0, _reactRelay.commitMutation)(environment, {
188
331
  mutation: (_StoreModalUnifiedCheckoutUpdateOrderMutation2.default.hash && _StoreModalUnifiedCheckoutUpdateOrderMutation2.default.hash !== "189cd7ac579c6898dca2f4b6e07861d1" && console.error("The definition of 'StoreModalUnifiedCheckoutUpdateOrderMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckoutUpdateOrderMutation2.default),
189
332
  variables,
190
- onCompleted: (res, errors) => onCompleted(res, errors, onSuccess),
333
+ onCompleted: (res, errors) => onCompleted(res, errors, onSuccess, onError),
191
334
  onError
192
335
  });
193
336
  }, [environment]);
337
+
338
+ // Update country order variable when licensee address country changes
339
+ (0, _react.useEffect)(() => {
340
+ if (!licenseeIdentity.country || !order.orderVariableSelections) return;
341
+
342
+ // Find country-type order variable
343
+ const countryVariableSelection = order.orderVariableSelections.find(selection => selection.orderVariable.variableType === 'country');
344
+ if (!countryVariableSelection) return;
345
+
346
+ // Only update if the country has actually changed
347
+ if (countryVariableSelection.countryCode === licenseeIdentity.country) return;
348
+
349
+ // Build updated selections array
350
+ const updatedSelections = order.orderVariableSelections.map(selection => {
351
+ var _selection$orderVaria;
352
+ return {
353
+ orderVariableId: selection.orderVariable.id,
354
+ orderVariableOptionId: ((_selection$orderVaria = selection.orderVariableOption) === null || _selection$orderVaria === void 0 ? void 0 : _selection$orderVaria.id) ?? null,
355
+ countryCode: selection.orderVariable.variableType === 'country' ? licenseeIdentity.country : selection.countryCode ?? null
356
+ };
357
+ });
358
+
359
+ // Update the order with new country via callback
360
+ onUpdateOrderVariableSelections(updatedSelections);
361
+ }, [licenseeIdentity.country, order.orderVariableSelections, onUpdateOrderVariableSelections]);
362
+
363
+ // When a country mismatch exists, force licenseeIsBillingIdentity to false
364
+ // This ensures we always collect licensee information for orders with mismatched country
365
+ (0, _react.useEffect)(() => {
366
+ if (hasCountryMismatch && (order.licenseeIsBillingIdentity ?? true)) {
367
+ // Update order to force separate licensee collection
368
+ updateOrder({
369
+ input: {
370
+ licenseeIsBillingIdentity: false
371
+ }
372
+ });
373
+ }
374
+ }, [hasCountryMismatch, order.licenseeIsBillingIdentity, updateOrder]);
375
+
376
+ // Auto-save billing identity when complete (for fontdue tax system only)
377
+ // This ensures taxes are calculated before showing the payment element
378
+ (0, _react.useEffect)(() => {
379
+ const taxSystem = viewer.settings.taxSystem;
380
+ const canUseEmbeddedCheckout = taxSystem === 'stripe';
381
+
382
+ // Only for fontdue tax system (not Stripe Tax/embedded checkout)
383
+ if (!canUseEmbeddedCheckout && order.customer && !isBillingIdentitySaved) {
384
+ // Check if the Stripe Address Element reports as complete AND email is filled
385
+ const isComplete = billingAddressComplete;
386
+ if (isComplete) {
387
+ // Debounce the update to avoid sending on every character change
388
+ const timeoutId = setTimeout(() => {
389
+ // Save billing identity to backend for tax calculation
390
+ updateOrder({
391
+ input: {
392
+ billingIdentity
393
+ }
394
+ });
395
+ }, 500); // 500ms debounce
396
+
397
+ return () => clearTimeout(timeoutId);
398
+ }
399
+ }
400
+ }, [billingIdentity, isBillingIdentitySaved, billingAddressComplete, order.customer, updateOrder, viewer.settings]);
194
401
  let initialEditingState = null;
195
402
  // set initial state depending on if checkout is already in progress
196
- if (!order.billingIdentity) initialEditingState = 'billing';
197
- if (order.licenseeIsBillingIdentity === false && !order.licenseeIdentity) {
198
- initialEditingState = 'licensee';
199
- }
200
403
  if (!order.customer) initialEditingState = 'customer';
201
404
  const [editing, setEditing] = (0, _react.useState)(initialEditingState);
202
405
  const handleCustomerSubmit = _ref3 => {
203
406
  let {
204
- onSuccess
407
+ onSuccess,
408
+ onError
205
409
  } = _ref3;
206
410
  if (!billingIdentity.name && !billingIdentity.email) {
207
411
  setBillingIdentity({
@@ -215,140 +419,192 @@ function StoreModalUnifiedCheckout(_ref2) {
215
419
  }, () => {
216
420
  onSuccess();
217
421
  setEditing(null);
218
- if (order.licenseeIsBillingIdentity) {
219
- if (!order.billingIdentity) setEditing('billing');
220
- } else {
221
- if (!order.licenseeIdentity) setEditing('licensee');
222
- }
223
- });
422
+ }, onError);
224
423
  };
225
424
  const handleLicenseeIsBillingIdentityChange = (0, _react.useCallback)(value => {
226
425
  updateOrder({
227
426
  input: {
228
427
  licenseeIsBillingIdentity: value
229
428
  }
230
- }, () => {
231
- if (!value && !order.licenseeIdentity) {
232
- setEditing('licensee');
233
- }
234
- if (value && !order.billingIdentity) {
235
- setEditing('billing');
236
- }
237
429
  });
238
- }, [updateOrder, order.licenseeIdentity]);
239
- const handleLicenseeSubmit = _ref4 => {
240
- let {
241
- onSuccess,
242
- onError
243
- } = _ref4;
244
- updateOrder({
245
- input: {
246
- licenseeIdentity
430
+ }, [updateOrder]);
431
+ const handleBillingChange = (0, _react.useCallback)((value, complete) => {
432
+ setError(null);
433
+ setErrorsObject(currentValue => {
434
+ if (currentValue !== null && currentValue !== void 0 && currentValue.billingIdentity) {
435
+ const keys = Object.keys(value);
436
+ return {
437
+ ...currentValue,
438
+ billingIdentity: {
439
+ ...currentValue.billingIdentity,
440
+ ...keys.reduce((acc, field) => {
441
+ acc[field] = null;
442
+ return acc;
443
+ }, {})
444
+ }
445
+ };
247
446
  }
248
- }, () => {
249
- onSuccess();
250
- setEditing(null);
251
- if (!order.billingIdentity) setEditing('billing');
252
- }, onError);
253
- };
254
- const handleBillingSubmit = _ref5 => {
255
- let {
256
- onSuccess
257
- } = _ref5;
258
- updateOrder({
259
- input: {
260
- billingIdentity
447
+ return currentValue;
448
+ });
449
+ setBillingIdentity(currentValue => {
450
+ const newValue = {
451
+ ...currentValue,
452
+ ...value
453
+ };
454
+ if (typeof complete === 'boolean') {
455
+ setBillingAddressComplete(complete);
261
456
  }
262
- }, () => {
263
- onSuccess();
264
- setEditing(null);
457
+ return newValue;
265
458
  });
266
- };
459
+ }, [order === null || order === void 0 ? void 0 : order.billingIdentity]);
267
460
  const stripe = (0, _reactStripeJs.useStripe)();
268
461
  const elements = (0, _reactStripeJs.useElements)();
269
462
  const [completing, setCompleting] = (0, _react.useState)(false);
463
+ const [checkingOut, setCheckingOut] = (0, _react.useState)(false);
270
464
  const dispatch = (0, _reactRedux.useDispatch)();
271
- const handleCheckout = (0, _react.useCallback)(() => {
272
- dispatch({
273
- type: 'STORE_MODAL_NAVIGATE',
274
- route: 'checkout'
275
- });
276
- }, []);
277
- const handleComplete = e => {
278
- var _billingIdentity$stre, _billingIdentity$stre2;
465
+
466
+ // When a country mismatch exists, always show licensee section (force collection)
467
+ // Otherwise, only show when user has selected "Your client" option
468
+ const showLicenseeSection = order.customer && (hasCountryMismatch || !(order.licenseeIsBillingIdentity ?? false));
469
+ const handleCheckout = (0, _react.useCallback)(async () => {
470
+ // Validate Stripe elements first
471
+ if (elements) {
472
+ const result = await elements.submit();
473
+ if (result.error) {
474
+ // Stripe will show validation errors in the UI
475
+ return;
476
+ }
477
+ }
478
+
479
+ // If licensee section is shown, save licensee data before navigating to checkout
480
+ if (showLicenseeSection) {
481
+ setCheckingOut(true);
482
+ updateOrder({
483
+ input: {
484
+ licenseeIdentity
485
+ }
486
+ }, () => {
487
+ setCheckingOut(false);
488
+ dispatch({
489
+ type: 'STORE_MODAL_NAVIGATE',
490
+ route: 'checkout'
491
+ });
492
+ }, () => {
493
+ setCheckingOut(false);
494
+ });
495
+ } else {
496
+ dispatch({
497
+ type: 'STORE_MODAL_NAVIGATE',
498
+ route: 'checkout'
499
+ });
500
+ }
501
+ }, [showLicenseeSection, licenseeIdentity, updateOrder, dispatch, elements]);
502
+ const handleComplete = async e => {
279
503
  e.preventDefault();
280
504
  if (!order) return;
281
505
  if (!billingIdentity) {
282
506
  console.error('No billing identity, required for payment');
283
507
  return;
284
508
  }
509
+
510
+ // Validate Stripe elements first
511
+ if (elements) {
512
+ const result = await elements.submit();
513
+ if (result.error) {
514
+ // Stripe will show validation errors in the UI
515
+ return;
516
+ }
517
+ }
518
+
519
+ // If billing identity is not saved yet, don't proceed with payment
520
+ // The validation above will show errors for incomplete fields
521
+ if (!isBillingIdentitySaved) {
522
+ setError('Please complete all billing information above');
523
+ return;
524
+ }
285
525
  setCompleting(true);
286
526
  setError(null);
287
- if (order.canCompleteWithCoupon) {
288
- (0, _reactRelay.commitMutation)(environment, {
289
- mutation: (_StoreModalUnifiedCheckoutCompleteOrderMutation2.default.hash && _StoreModalUnifiedCheckoutCompleteOrderMutation2.default.hash !== "ea880419670573334e55529f454f8026" && console.error("The definition of 'StoreModalUnifiedCheckoutCompleteOrderMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckoutCompleteOrderMutation2.default),
290
- variables: {},
291
- onCompleted: (_response, errors) => {
292
- if (errors && errors.length > 0) {
293
- setCompleting(false);
294
- setError(errors[0].message);
295
- return;
527
+ const processPayment = () => {
528
+ var _billingIdentity$stre, _billingIdentity$stre2;
529
+ if (order.canCompleteWithCoupon) {
530
+ (0, _reactRelay.commitMutation)(environment, {
531
+ mutation: (_StoreModalUnifiedCheckoutCompleteOrderMutation2.default.hash && _StoreModalUnifiedCheckoutCompleteOrderMutation2.default.hash !== "ea880419670573334e55529f454f8026" && console.error("The definition of 'StoreModalUnifiedCheckoutCompleteOrderMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalUnifiedCheckoutCompleteOrderMutation2.default),
532
+ variables: {},
533
+ onCompleted: (_response, errors) => {
534
+ if (errors && errors.length > 0) {
535
+ setCompleting(false);
536
+ setError(errors[0].message);
537
+ return;
538
+ }
539
+ window.location.href = order.completeUrl;
296
540
  }
297
- window.location.href = order.completeUrl;
298
- }
299
- });
300
- return;
301
- }
302
- if (!stripe || !elements) return;
303
- stripe === null || stripe === void 0 ? void 0 : stripe.confirmPayment({
304
- elements,
305
- confirmParams: {
306
- return_url: order.completeUrl,
307
- payment_method_data: {
308
- billing_details: {
309
- email: billingIdentity.email,
310
- name: billingIdentity.name,
311
- phone: billingIdentity.phone,
312
- address: {
313
- line1: (_billingIdentity$stre = billingIdentity.street) === null || _billingIdentity$stre === void 0 ? void 0 : _billingIdentity$stre.split(/\n/)[0],
314
- line2: ((_billingIdentity$stre2 = billingIdentity.street) === null || _billingIdentity$stre2 === void 0 ? void 0 : _billingIdentity$stre2.split(/\n/)[1]) ?? '',
315
- city: billingIdentity.locality ?? '',
316
- state: billingIdentity.administrativeArea ?? '',
317
- country: billingIdentity.country,
318
- postal_code: billingIdentity.zip ?? ''
541
+ });
542
+ return;
543
+ }
544
+ if (!stripe || !elements) return;
545
+ stripe === null || stripe === void 0 ? void 0 : stripe.confirmPayment({
546
+ elements,
547
+ confirmParams: {
548
+ return_url: order.completeUrl,
549
+ payment_method_data: {
550
+ billing_details: {
551
+ email: billingIdentity.email,
552
+ name: billingIdentity.name,
553
+ phone: billingIdentity.phone,
554
+ address: {
555
+ line1: (_billingIdentity$stre = billingIdentity.street) === null || _billingIdentity$stre === void 0 ? void 0 : _billingIdentity$stre.split(/\n/)[0],
556
+ line2: ((_billingIdentity$stre2 = billingIdentity.street) === null || _billingIdentity$stre2 === void 0 ? void 0 : _billingIdentity$stre2.split(/\n/)[1]) ?? '',
557
+ city: billingIdentity.locality ?? '',
558
+ state: billingIdentity.administrativeArea ?? '',
559
+ country: billingIdentity.country,
560
+ postal_code: billingIdentity.zip ?? ''
561
+ }
319
562
  }
320
563
  }
321
564
  }
322
- }
323
- }).then(result => {
324
- if ('error' in result) {
565
+ }).then(result => {
566
+ if ('error' in result) {
567
+ setCompleting(false);
568
+ setError(result.error.message ?? 'Payment failed. Please try another payment method.');
569
+ }
570
+ }).catch(error => {
571
+ console.log(error);
325
572
  setCompleting(false);
326
- setError(result.error.message ?? 'Payment failed. Please try another payment method.');
327
- }
328
- }).catch(error => {
329
- console.log(error);
573
+ });
574
+ };
575
+
576
+ // Save both licensee (if shown) and billing info before processing payment
577
+ const orderInput = {
578
+ billingIdentity
579
+ };
580
+ if (showLicenseeSection) {
581
+ orderInput.licenseeIdentity = licenseeIdentity;
582
+ }
583
+ updateOrder({
584
+ input: orderInput
585
+ }, () => {
586
+ processPayment();
587
+ }, () => {
330
588
  setCompleting(false);
331
589
  });
332
590
  };
333
591
  const taxSystem = viewer.settings.taxSystem;
334
592
  const canUseEmbeddedCheckout = taxSystem === 'stripe';
335
- const showLicenseeSection = order.customer && !order.licenseeIsBillingIdentity;
336
- const hasLicensee = order.licenseeIsBillingIdentity ? true : Boolean(order.licenseeIdentity);
337
- const showBillingSection = !canUseEmbeddedCheckout && (order.customer && hasLicensee || order.billingIdentity);
593
+ const showBillingSection = !canUseEmbeddedCheckout && order.customer;
338
594
 
339
595
  // billing info will be handled by embedded checkout
340
596
  const showCheckoutButton = canUseEmbeddedCheckout && order.customer;
341
597
  const zeroOrder = order.canCompleteWithCoupon;
342
- const showPaymentSection = !canUseEmbeddedCheckout && order.customer && order.billingIdentity && hasLicensee;
343
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, error && /*#__PURE__*/_react.default.createElement("div", {
344
- className: "store-modal__cart__error"
345
- }, error), /*#__PURE__*/_react.default.createElement(EditableSection, {
598
+ const showPaymentSection = !canUseEmbeddedCheckout && order.customer;
599
+ const billingComplete = IDENTITY_REQUIRED_FIELDS.every(key => Boolean(billingIdentity[key]));
600
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(EditableSection, {
346
601
  editing: editing === 'customer',
347
602
  disabled: false,
348
603
  onEdit: () => setEditing('customer'),
349
604
  onSubmit: handleCustomerSubmit,
350
- disableSubmit: !customer.name || !customer.email
605
+ disableSubmit: false
351
606
  }, {
607
+ save: canUseEmbeddedCheckout ? order.customer ? 'Save' : 'Continue' : 'Checkout',
352
608
  show: /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h3", {
353
609
  className: "store-modal__cart__checkout-section-title"
354
610
  }, "Contact information"), order.customer ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, order.customer.name, /*#__PURE__*/_react.default.createElement("br", null), order.customer.email) : 'Loading...'),
@@ -357,11 +613,12 @@ function StoreModalUnifiedCheckout(_ref2) {
357
613
  }, "Contact information"), /*#__PURE__*/_react.default.createElement(_CustomerFields.default, {
358
614
  value: customer,
359
615
  onChange: handleCustomerChange,
360
- optInLabel: (_viewer$settings = viewer.settings) === null || _viewer$settings === void 0 ? void 0 : _viewer$settings.newsletterOptInLabel
616
+ optInLabel: (_viewer$settings = viewer.settings) === null || _viewer$settings === void 0 ? void 0 : _viewer$settings.newsletterOptInLabel,
617
+ errors: customerErrorsObject
361
618
  }))
362
- }), order.customer ? /*#__PURE__*/_react.default.createElement(_StoreModalLicenseeIsBillingIdentityElement.default, {
619
+ }), order.customer && !hasCountryMismatch ? /*#__PURE__*/_react.default.createElement(_StoreModalLicenseeIsBillingIdentityElement.default, {
363
620
  disabled: false,
364
- value: order.licenseeIsBillingIdentity,
621
+ value: order.licenseeIsBillingIdentity ?? false,
365
622
  onChange: handleLicenseeIsBillingIdentityChange
366
623
  }, {
367
624
  label: /*#__PURE__*/_react.default.createElement("div", {
@@ -369,72 +626,42 @@ function StoreModalUnifiedCheckout(_ref2) {
369
626
  __html: ((_viewer$settings2 = viewer.settings) === null || _viewer$settings2 === void 0 ? void 0 : _viewer$settings2.storeModalSelectLicenseeLabel) ?? ''
370
627
  }
371
628
  })
372
- }) : null, showLicenseeSection ? /*#__PURE__*/_react.default.createElement(EditableSection, {
373
- disabled: false,
374
- editing: editing === 'licensee',
375
- onEdit: () => setEditing('licensee'),
376
- disableSubmit: Object.keys(licenseeIdentity).some(key => {
377
- if (IDENTITY_REQUIRED_FIELDS.includes(key)) return Boolean(licenseeIdentity[key]) === false;
378
- return false;
379
- }),
380
- onSubmit: handleLicenseeSubmit
381
- }, {
382
- edit: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("h3", {
383
- className: "store-modal__cart__checkout-section-title"
384
- }, "Licensee information (your client)"), /*#__PURE__*/_react.default.createElement("div", {
385
- className: "store-modal__cart__identity-fields"
386
- }, /*#__PURE__*/_react.default.createElement(_AddressFields.default, {
387
- viewer: viewer,
388
- value: licenseeIdentity,
389
- onChange: handleLicenseeChange,
390
- errorsObject: errorsObject === null || errorsObject === void 0 ? void 0 : errorsObject.licenseeIdentity,
391
- identityType: "licensee"
392
- }))),
393
- show: /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h3", {
394
- className: "store-modal__cart__checkout-section-title"
395
- }, "Licensee information (your client)"), order.licenseeIdentity ? /*#__PURE__*/_react.default.createElement("div", {
396
- className: "store-modal__cart__identity"
397
- }, /*#__PURE__*/_react.default.createElement(_StoreModalReviewIdentity.default, {
398
- identity: order.licenseeIdentity
399
- })) : 'Loading...')
400
- }) : null, showBillingSection ? /*#__PURE__*/_react.default.createElement(EditableSection, {
401
- disabled: false,
402
- editing: editing === 'billing',
403
- onEdit: () => setEditing('billing'),
404
- disableSubmit: Object.keys(billingIdentity).some(key => {
405
- if (IDENTITY_REQUIRED_FIELDS.includes(key)) return Boolean(billingIdentity[key]) === false;
406
- return false;
407
- }),
408
- onSubmit: handleBillingSubmit
409
- }, {
410
- edit: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("h3", {
411
- className: "store-modal__cart__checkout-section-title"
412
- }, "Billing information"), /*#__PURE__*/_react.default.createElement("div", {
413
- className: "store-modal__cart__identity-fields"
414
- }, /*#__PURE__*/_react.default.createElement(_AddressFields.default, {
415
- viewer: viewer,
416
- value: billingIdentity,
417
- onChange: handleBillingChange,
418
- errorsObject: errorsObject === null || errorsObject === void 0 ? void 0 : errorsObject.billingIdentity,
419
- identityType: "billing"
420
- }))),
421
- show: /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h3", {
422
- className: "store-modal__cart__checkout-section-title"
423
- }, "Billing information"), order.billingIdentity ? /*#__PURE__*/_react.default.createElement("div", {
424
- className: "store-modal__cart__identity"
425
- }, /*#__PURE__*/_react.default.createElement(_StoreModalReviewIdentity.default, {
426
- identity: order.billingIdentity
427
- })) : 'Loading...')
428
- }) : null, showCheckoutButton ? /*#__PURE__*/_react.default.createElement("div", {
629
+ }) : null, showLicenseeSection ? /*#__PURE__*/_react.default.createElement("div", {
630
+ className: "store-modal__cart__checkout-section"
631
+ }, /*#__PURE__*/_react.default.createElement("h3", {
632
+ className: "store-modal__cart__checkout-section-title"
633
+ }, hasCountryMismatch ? 'Licensee information' : 'Licensee information (your client)'), /*#__PURE__*/_react.default.createElement("div", {
634
+ className: "store-modal__cart__identity-fields"
635
+ }, /*#__PURE__*/_react.default.createElement(_AddressFields.default, {
636
+ viewer: viewer,
637
+ value: licenseeIdentity,
638
+ onChange: handleLicenseeChange,
639
+ errorsObject: errorsObject === null || errorsObject === void 0 ? void 0 : errorsObject.licenseeIdentity,
640
+ identityType: "licensee"
641
+ }))) : null, showBillingSection ? /*#__PURE__*/_react.default.createElement("div", {
429
642
  className: "store-modal__cart__checkout-section",
430
- "data-disabled": showLicenseeSection ? editing === 'licensee' : false
643
+ "data-disabled": !order.customer
644
+ }, /*#__PURE__*/_react.default.createElement("h3", {
645
+ className: "store-modal__cart__checkout-section-title"
646
+ }, "Billing information"), /*#__PURE__*/_react.default.createElement("div", {
647
+ className: "store-modal__cart__identity-fields"
648
+ }, /*#__PURE__*/_react.default.createElement(_AddressFields.default, {
649
+ viewer: viewer,
650
+ value: billingIdentity,
651
+ onChange: handleBillingChange,
652
+ errorsObject: errorsObject === null || errorsObject === void 0 ? void 0 : errorsObject.billingIdentity,
653
+ identityType: "billing"
654
+ }))) : null, showCheckoutButton ? /*#__PURE__*/_react.default.createElement("div", {
655
+ className: "store-modal__cart__checkout-section",
656
+ "data-disabled": false
431
657
  }, /*#__PURE__*/_react.default.createElement("button", {
432
658
  type: "button",
433
659
  className: "store-modal__cart__button",
434
- onClick: handleCheckout
435
- }, "Checkout")) : null, showPaymentSection ? /*#__PURE__*/_react.default.createElement("div", {
660
+ onClick: handleCheckout,
661
+ disabled: checkingOut
662
+ }, checkingOut ? 'Submitting...' : 'Checkout')) : null, showPaymentSection ? /*#__PURE__*/_react.default.createElement("div", {
436
663
  className: "store-modal__cart__checkout-section",
437
- "data-disabled": editing !== null
664
+ "data-disabled": false
438
665
  }, /*#__PURE__*/_react.default.createElement("form", {
439
666
  onSubmit: handleComplete
440
667
  }, !zeroOrder && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("h3", {
@@ -447,7 +674,7 @@ function StoreModalUnifiedCheckout(_ref2) {
447
674
  rel: "noopener"
448
675
  }, "Powered by ", /*#__PURE__*/_react.default.createElement(_StripeLogo.default, null)))), /*#__PURE__*/_react.default.createElement("div", {
449
676
  className: "store-modal__cart__payment"
450
- }, /*#__PURE__*/_react.default.createElement(_reactErrorBoundary.ErrorBoundary, {
677
+ }, /*#__PURE__*/_react.default.createElement(Sentry.ErrorBoundary, {
451
678
  fallback: /*#__PURE__*/_react.default.createElement("div", null, "Something went wrong")
452
679
  }, /*#__PURE__*/_react.default.createElement(_reactStripeJs.PaymentElement, {
453
680
  options: {
@@ -456,21 +683,11 @@ function StoreModalUnifiedCheckout(_ref2) {
456
683
  defaultCollapsed: false,
457
684
  radios: true,
458
685
  spacedAccordionItems: true
459
- },
460
- defaultValues: {
461
- billingDetails: {
462
- name: order.customer.name ?? undefined,
463
- email: order.customer.email ?? undefined,
464
- phone: order.billingIdentity.phone ?? undefined
465
- }
466
- },
467
- fields: {
468
- billingDetails: {
469
- address: 'never'
470
- }
471
686
  }
472
687
  }
473
- })))), /*#__PURE__*/_react.default.createElement("div", {
688
+ })))), error && /*#__PURE__*/_react.default.createElement("div", {
689
+ className: "store-modal__cart__error"
690
+ }, error), /*#__PURE__*/_react.default.createElement("div", {
474
691
  className: "store-modal__cart__agreement"
475
692
  }, /*#__PURE__*/_react.default.createElement("div", {
476
693
  className: "checkbox"