@fluid-app/portal-sdk 0.1.498 → 0.1.500

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 (66) hide show
  1. package/dist/{ActivityScreen-BHNUUl5N.mjs → ActivityScreen-8n5MUTqb.mjs} +72 -13
  2. package/dist/ActivityScreen-8n5MUTqb.mjs.map +1 -0
  3. package/dist/{ActivityScreen-CI8YhKBs.cjs → ActivityScreen-BtJZDBL8.cjs} +2 -2
  4. package/dist/{ActivityScreen-wpyJhHPK.cjs → ActivityScreen-DqNFQ0L-.cjs} +72 -13
  5. package/dist/ActivityScreen-DqNFQ0L-.cjs.map +1 -0
  6. package/dist/{FluidProvider-BMwY9-iq.cjs → FluidProvider-DqMKDA_x.cjs} +3 -2
  7. package/dist/{FluidProvider-BMwY9-iq.cjs.map → FluidProvider-DqMKDA_x.cjs.map} +1 -1
  8. package/dist/{FluidProvider-BG7D2WE_.mjs → FluidProvider-pfuaCUAu.mjs} +3 -2
  9. package/dist/{FluidProvider-BG7D2WE_.mjs.map → FluidProvider-pfuaCUAu.mjs.map} +1 -1
  10. package/dist/{MessagingScreen-DxeNig66.mjs → MessagingScreen-CEPrekjI.mjs} +5 -5
  11. package/dist/{MessagingScreen-_OoquxUK.cjs → MessagingScreen-DLomIoTO.cjs} +5 -5
  12. package/dist/{MessagingScreen-CPtQwSDv.mjs → MessagingScreen-ILHCTccW.mjs} +2 -2
  13. package/dist/{MessagingScreen-CPtQwSDv.mjs.map → MessagingScreen-ILHCTccW.mjs.map} +1 -1
  14. package/dist/{MessagingScreen-F4wILtII.cjs → MessagingScreen-izL-CVh1.cjs} +2 -2
  15. package/dist/{MessagingScreen-F4wILtII.cjs.map → MessagingScreen-izL-CVh1.cjs.map} +1 -1
  16. package/dist/{OrdersScreen-E2OXymPQ.mjs → OrdersScreen-Cr-3CBfD.mjs} +5 -5
  17. package/dist/{OrdersScreen-C5SI6kEM.cjs → OrdersScreen-Do_di0Vk.cjs} +3 -3
  18. package/dist/{OrdersScreen-C5SI6kEM.cjs.map → OrdersScreen-Do_di0Vk.cjs.map} +1 -1
  19. package/dist/{OrdersScreen-Cm7aNQ6W.mjs → OrdersScreen-Q6IftqCN.mjs} +3 -3
  20. package/dist/{OrdersScreen-Cm7aNQ6W.mjs.map → OrdersScreen-Q6IftqCN.mjs.map} +1 -1
  21. package/dist/{OrdersScreen-DcT_LmrE.cjs → OrdersScreen-VcvBe-UI.cjs} +5 -5
  22. package/dist/{ProfileScreen-CqhTJvXs.cjs → ProfileScreen-BG6ZCv_K.cjs} +4 -3
  23. package/dist/{ProfileScreen-CqhTJvXs.cjs.map → ProfileScreen-BG6ZCv_K.cjs.map} +1 -1
  24. package/dist/{ProfileScreen-B7xaDVqM.cjs → ProfileScreen-BsTDYXwS.cjs} +6 -6
  25. package/dist/{ProfileScreen-CQY8BnZm.mjs → ProfileScreen-DHBVul4x.mjs} +4 -3
  26. package/dist/{ProfileScreen-CQY8BnZm.mjs.map → ProfileScreen-DHBVul4x.mjs.map} +1 -1
  27. package/dist/{ProfileScreen-CgrFxz1m.mjs → ProfileScreen-DHG9QVyt.mjs} +6 -6
  28. package/dist/{RecentActivityWidget-DemnPXZR.cjs → RecentActivityWidget-BQXZR4_G.cjs} +3 -7
  29. package/dist/RecentActivityWidget-BQXZR4_G.cjs.map +1 -0
  30. package/dist/{RecentActivityWidget-CJcOQPUf.cjs → RecentActivityWidget-CSZeB4Pp.cjs} +2 -2
  31. package/dist/{RecentActivityWidget-BIgJS_kr.mjs → RecentActivityWidget-DLtQZmo3.mjs} +3 -7
  32. package/dist/RecentActivityWidget-DLtQZmo3.mjs.map +1 -0
  33. package/dist/{SubscriptionsScreen-ljALMAX-.cjs → SubscriptionsScreen-BNNFQ9k0.cjs} +6 -5
  34. package/dist/{SubscriptionsScreen-ljALMAX-.cjs.map → SubscriptionsScreen-BNNFQ9k0.cjs.map} +1 -1
  35. package/dist/{SubscriptionsScreen-DDhm_w13.cjs → SubscriptionsScreen-CCz4s3uD.cjs} +6 -6
  36. package/dist/{SubscriptionsScreen-CbvJj7kc.mjs → SubscriptionsScreen-CiedAyPM.mjs} +6 -6
  37. package/dist/{SubscriptionsScreen-ChWqn480.mjs → SubscriptionsScreen-gizzDVc6.mjs} +6 -5
  38. package/dist/{SubscriptionsScreen-ChWqn480.mjs.map → SubscriptionsScreen-gizzDVc6.mjs.map} +1 -1
  39. package/dist/{activity-presentation-CUBIlrYQ.mjs → activity-presentation-DN7WG2W8.mjs} +20 -2
  40. package/dist/{activity-presentation-CUBIlrYQ.mjs.map → activity-presentation-DN7WG2W8.mjs.map} +1 -1
  41. package/dist/{activity-presentation-DbBDc0oA.cjs → activity-presentation-OSfAUOoY.cjs} +25 -1
  42. package/dist/{activity-presentation-DbBDc0oA.cjs.map → activity-presentation-OSfAUOoY.cjs.map} +1 -1
  43. package/dist/{build-widget-registry-DSu1FrDF.cjs → build-widget-registry-BQLi4JqV.cjs} +3 -3
  44. package/dist/{build-widget-registry-DSu1FrDF.cjs.map → build-widget-registry-BQLi4JqV.cjs.map} +1 -1
  45. package/dist/{build-widget-registry-Du6Ssx7x.mjs → build-widget-registry-C-WhTBEe.mjs} +3 -3
  46. package/dist/{build-widget-registry-Du6Ssx7x.mjs.map → build-widget-registry-C-WhTBEe.mjs.map} +1 -1
  47. package/dist/index.cjs +20 -20
  48. package/dist/index.d.cts.map +1 -1
  49. package/dist/index.d.mts.map +1 -1
  50. package/dist/index.mjs +20 -20
  51. package/dist/styles/remote-widget-shadow.css +2 -2
  52. package/dist/{use-portal-card-add-3ds-flow-LyyuhE0C.cjs → use-portal-card-add-3ds-flow-BD_RPuyR.cjs} +270 -229
  53. package/dist/use-portal-card-add-3ds-flow-BD_RPuyR.cjs.map +1 -0
  54. package/dist/{use-portal-card-add-3ds-flow-66g15igj.mjs → use-portal-card-add-3ds-flow-y2cBmujb.mjs} +270 -229
  55. package/dist/use-portal-card-add-3ds-flow-y2cBmujb.mjs.map +1 -0
  56. package/dist/utils/build-remote-widget-plugin-manifests.cjs +3 -3
  57. package/dist/utils/build-remote-widget-plugin-manifests.mjs +3 -3
  58. package/dist/utils/build-widget-registry.cjs +3 -3
  59. package/dist/utils/build-widget-registry.mjs +3 -3
  60. package/package.json +15 -15
  61. package/dist/ActivityScreen-BHNUUl5N.mjs.map +0 -1
  62. package/dist/ActivityScreen-wpyJhHPK.cjs.map +0 -1
  63. package/dist/RecentActivityWidget-BIgJS_kr.mjs.map +0 -1
  64. package/dist/RecentActivityWidget-DemnPXZR.cjs.map +0 -1
  65. package/dist/use-portal-card-add-3ds-flow-66g15igj.mjs.map +0 -1
  66. package/dist/use-portal-card-add-3ds-flow-LyyuhE0C.cjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  require("./chunk-9hOWP6kD.cjs");
2
- const require_build_widget_registry = require("./build-widget-registry-DSu1FrDF.cjs");
2
+ const require_build_widget_registry = require("./build-widget-registry-BQLi4JqV.cjs");
3
3
  const require_Combobox = require("./Combobox-CReJLJfk.cjs");
4
- const require_FluidProvider = require("./FluidProvider-BMwY9-iq.cjs");
4
+ const require_FluidProvider = require("./FluidProvider-DqMKDA_x.cjs");
5
5
  const require_MobileBottomSheet = require("./MobileBottomSheet-HzfAr8dE.cjs");
6
6
  const require_static_dict_adapter = require("./static-dict-adapter-BCgoKiVT.cjs");
7
7
  const require_translation_api_context_factory = require("./translation-api-context-factory-mbsJk2UU.cjs");
@@ -581,7 +581,7 @@ function AddressAutocompleteInput({ control, setValue, countryIso, addressLineFi
581
581
  const populate = (0, react.useCallback)((s) => {
582
582
  setValue(addressLineField, s.streetLine, SET_OPTS);
583
583
  setValue(cityField, s.city, SET_OPTS);
584
- setValue(stateField, resolveAdministrativeAreaState(s, stateOptions), SET_OPTS);
584
+ if (stateField) setValue(stateField, resolveAdministrativeAreaState(s, stateOptions), SET_OPTS);
585
585
  setValue(postalCodeField, s.postalCode, SET_OPTS);
586
586
  }, [
587
587
  addressLineField,
@@ -714,6 +714,115 @@ function AddressAutocompleteInput({ control, setValue, countryIso, addressLineFi
714
714
  });
715
715
  }
716
716
  //#endregion
717
+ //#region ../../platform/address-fields/src/field-layout.ts
718
+ /**
719
+ * Which address fields a country collects, in what order, and how they group
720
+ * into rows. The address-fields service is the authority: when it answers, its
721
+ * list decides presence and order, and its labels arrive already translated.
722
+ * The static values below cover only the window before it answers, or a host
723
+ * with no provider wired.
724
+ */
725
+ const ADDRESS_FIELD_NAMES = [
726
+ "name",
727
+ "address1",
728
+ "address2",
729
+ "city",
730
+ "state",
731
+ "postal_code",
732
+ "phone"
733
+ ];
734
+ const STATIC_LABEL_KEYS = {
735
+ name: "name",
736
+ address1: "address_line_1",
737
+ address2: "address_line_2",
738
+ city: "city",
739
+ state: "state",
740
+ postal_code: "zip_code",
741
+ phone: "phone_number"
742
+ };
743
+ const DEFAULT_HIDDEN_FIELDS = new Set(["phone"]);
744
+ const STATIC_REQUIRED_FIELDS = new Set([
745
+ "name",
746
+ "address1",
747
+ "city",
748
+ "state",
749
+ "postal_code"
750
+ ]);
751
+ const AUTOCOMPLETE_FIELD_PREFIX = [
752
+ "name",
753
+ "address1",
754
+ "address2"
755
+ ];
756
+ const ROW_GROUPED_FIELDS = new Set([
757
+ "city",
758
+ "state",
759
+ "postal_code"
760
+ ]);
761
+ function isAddressFieldName(value) {
762
+ return ADDRESS_FIELD_NAMES.includes(value);
763
+ }
764
+ function addressFieldOrder(fields) {
765
+ if (!fields) return ADDRESS_FIELD_NAMES.filter((field) => !DEFAULT_HIDDEN_FIELDS.has(field));
766
+ const fromService = fields.map((field) => field.field).filter(isAddressFieldName);
767
+ const prefix = AUTOCOMPLETE_FIELD_PREFIX.filter((field) => fromService.includes(field));
768
+ const rest = fromService.filter((field) => !AUTOCOMPLETE_FIELD_PREFIX.includes(field));
769
+ return [...prefix, ...rest];
770
+ }
771
+ /** Consecutive city, state and postal fields share one row. */
772
+ function groupAddressFields(fields) {
773
+ const groups = [];
774
+ let i = 0;
775
+ while (i < fields.length) {
776
+ const current = fields[i];
777
+ if (ROW_GROUPED_FIELDS.has(current)) {
778
+ const group = [current];
779
+ while (i + group.length < fields.length && ROW_GROUPED_FIELDS.has(fields[i + group.length])) group.push(fields[i + group.length]);
780
+ if (group.length > 1) {
781
+ groups.push(group);
782
+ i += group.length;
783
+ continue;
784
+ }
785
+ }
786
+ groups.push([current]);
787
+ i++;
788
+ }
789
+ return groups;
790
+ }
791
+ function isAddressFieldRequired(fields, fieldName) {
792
+ if (!fields) return STATIC_REQUIRED_FIELDS.has(fieldName);
793
+ return fields.find((field) => field.field === fieldName)?.required ?? false;
794
+ }
795
+ /**
796
+ * The service's label when it has one, otherwise a translation key for the
797
+ * caller to resolve. `regionKey` and `postalKey` let a caller pass the
798
+ * country-specific key it already has, such as province or postal_code.
799
+ */
800
+ function addressFieldLabel(fields, fieldName, fallbackKeys) {
801
+ const serviceLabel = fields?.find((field) => field.field === fieldName)?.label;
802
+ if (serviceLabel) return { label: serviceLabel };
803
+ if (fieldName === "state" && fallbackKeys?.regionKey) return { translationKey: fallbackKeys.regionKey };
804
+ if (fieldName === "postal_code" && fallbackKeys?.postalKey) return { translationKey: fallbackKeys.postalKey };
805
+ return { translationKey: STATIC_LABEL_KEYS[fieldName] };
806
+ }
807
+ (0, react.createContext)(null);
808
+ //#endregion
809
+ //#region ../../fluid-pay/core/src/context.ts
810
+ const FluidPayApiContext = (0, react.createContext)(null);
811
+ const FluidPayApiProvider = FluidPayApiContext.Provider;
812
+ function useFluidPayApi() {
813
+ const api = (0, react.useContext)(FluidPayApiContext);
814
+ if (!api) throw new Error("useFluidPayApi must be used within a FluidPayCoreProvider");
815
+ return api;
816
+ }
817
+ //#endregion
818
+ //#region ../../fluid-pay/core/src/provider.tsx
819
+ function FluidPayCoreProvider({ api, children }) {
820
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FluidPayApiProvider, {
821
+ value: api,
822
+ children
823
+ });
824
+ }
825
+ //#endregion
717
826
  //#region ../../platform/address-fields/src/country-config.ts
718
827
  const US_STATES = [
719
828
  {
@@ -941,42 +1050,21 @@ const US_STATES = [
941
1050
  isoCode: "WY"
942
1051
  }
943
1052
  ];
944
- function isFieldRequired$1(addressFields, fieldName) {
945
- return addressFields.find((f) => f.field === fieldName)?.required ?? false;
946
- }
947
- (0, react.createContext)(null);
948
- //#endregion
949
- //#region ../../fluid-pay/core/src/context.ts
950
- const FluidPayApiContext = (0, react.createContext)(null);
951
- const FluidPayApiProvider = FluidPayApiContext.Provider;
952
- function useFluidPayApi() {
953
- const api = (0, react.useContext)(FluidPayApiContext);
954
- if (!api) throw new Error("useFluidPayApi must be used within a FluidPayCoreProvider");
955
- return api;
956
- }
957
- //#endregion
958
- //#region ../../fluid-pay/core/src/provider.tsx
959
- function FluidPayCoreProvider({ api, children }) {
960
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FluidPayApiProvider, {
961
- value: api,
962
- children
963
- });
964
- }
965
1053
  //#endregion
966
1054
  //#region ../../fluid-pay/core/src/utils/country-config.ts
967
1055
  const COUNTRY_CONFIGS = {
968
1056
  US: {
969
- regionLabel: "State",
970
- postalLabel: "ZIP Code"
1057
+ regionLabel: "state",
1058
+ postalLabel: "zip_code"
971
1059
  },
972
1060
  JP: {
973
- regionLabel: "Prefecture",
974
- postalLabel: "Postal Code"
1061
+ regionLabel: "prefecture",
1062
+ postalLabel: "postal_code"
975
1063
  }
976
1064
  };
977
1065
  const DEFAULT_REGION_CONFIG = {
978
- regionLabel: "Province",
979
- postalLabel: "Postal Code"
1066
+ regionLabel: "province",
1067
+ postalLabel: "postal_code"
980
1068
  };
981
1069
  function getRegionConfig(countryCode) {
982
1070
  return COUNTRY_CONFIGS[countryCode] ?? DEFAULT_REGION_CONFIG;
@@ -1022,18 +1110,59 @@ function useCountryStates() {
1022
1110
  function createEditPaymentMethodFormSchema(t) {
1023
1111
  return zod.z.object({
1024
1112
  billing_address: zod.z.object({
1025
- name: zod.z.string().min(1, t("name_is_required")),
1026
- address1: zod.z.string().min(1, t("address_line_1_is_required")),
1113
+ name: zod.z.string(),
1114
+ address1: zod.z.string(),
1027
1115
  address2: zod.z.string().optional().nullable(),
1028
- city: zod.z.string().min(1, t("city_is_required")),
1116
+ city: zod.z.string(),
1029
1117
  state: zod.z.string(),
1030
- zip: zod.z.string().min(1, t("zip_code_is_required")),
1118
+ zip: zod.z.string(),
1031
1119
  country_code: zod.z.string().min(1, t("country_is_required"))
1032
1120
  }),
1033
1121
  set_as_default: zod.z.boolean()
1034
1122
  });
1035
1123
  }
1036
- function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClose, onSubmit, isSubmitting, error, countries = [], fetchStates, onDelete, isDeleting = false, presentation = "dialog" }) {
1124
+ const FORM_PATHS_BY_FIELD = [
1125
+ {
1126
+ field: "name",
1127
+ key: "name",
1128
+ path: "billing_address.name"
1129
+ },
1130
+ {
1131
+ field: "address1",
1132
+ key: "address1",
1133
+ path: "billing_address.address1"
1134
+ },
1135
+ {
1136
+ field: "address2",
1137
+ key: "address2",
1138
+ path: "billing_address.address2"
1139
+ },
1140
+ {
1141
+ field: "city",
1142
+ key: "city",
1143
+ path: "billing_address.city"
1144
+ },
1145
+ {
1146
+ field: "state",
1147
+ key: "state",
1148
+ path: "billing_address.state"
1149
+ },
1150
+ {
1151
+ field: "postal_code",
1152
+ key: "zip",
1153
+ path: "billing_address.zip"
1154
+ }
1155
+ ];
1156
+ function pathForField(fieldName) {
1157
+ return FORM_PATHS_BY_FIELD.find((e) => e.field === fieldName)?.path ?? "billing_address.address1";
1158
+ }
1159
+ function valueForField(data, fieldName) {
1160
+ const entry = FORM_PATHS_BY_FIELD.find((e) => e.field === fieldName);
1161
+ if (!entry) return void 0;
1162
+ const value = data.billing_address[entry.key];
1163
+ return typeof value === "string" ? value : void 0;
1164
+ }
1165
+ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClose, onSubmit, isSubmitting, error, countries = [], fetchStates, languageIso, onDelete, isDeleting = false, presentation = "dialog" }) {
1037
1166
  const { t } = useProfileTranslation();
1038
1167
  const [confirmDelete, setConfirmDelete] = (0, react.useState)(false);
1039
1168
  (0, react.useEffect)(() => {
@@ -1113,7 +1242,7 @@ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClos
1113
1242
  if (!addressFieldsApi || !lookupCountry) return;
1114
1243
  let cancelled = false;
1115
1244
  setCountryFields(null);
1116
- addressFieldsApi.fetchAddressFields(lookupCountry).then((response) => {
1245
+ addressFieldsApi.fetchAddressFields(lookupCountry, languageIso).then((response) => {
1117
1246
  if (cancelled) return;
1118
1247
  setCountryFields({
1119
1248
  country: lookupCountry,
@@ -1128,50 +1257,50 @@ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClos
1128
1257
  return () => {
1129
1258
  cancelled = true;
1130
1259
  };
1131
- }, [addressFieldsApi, lookupCountry]);
1132
- const stateLabel = config?.regionLabel ? t(config.regionLabel) : t("state");
1133
- const stateDecision = (0, react.useMemo)(() => {
1134
- const answered = countryFields?.country === billingCountry;
1135
- const fields = answered ? countryFields?.fields : null;
1136
- if (fields) return {
1137
- ready: true,
1138
- used: fields.some((field) => field.field === "state") || stateSelectOptions.length > 0,
1139
- required: isFieldRequired$1(fields, "state")
1140
- };
1141
- if (addressFieldsApi && !answered) return {
1142
- ready: false,
1143
- used: true,
1144
- required: false
1145
- };
1146
- return {
1147
- ready: stateOptionsReady,
1148
- used: true,
1149
- required: stateSelectOptions.length > 0
1150
- };
1151
1260
  }, [
1152
1261
  addressFieldsApi,
1153
- billingCountry,
1154
- countryFields,
1155
- stateOptionsReady,
1156
- stateSelectOptions.length
1262
+ lookupCountry,
1263
+ languageIso
1157
1264
  ]);
1265
+ const answeredFields = countryFields?.country === billingCountry ? countryFields?.fields : null;
1266
+ const fieldOrder = (0, react.useMemo)(() => addressFieldOrder(answeredFields ?? null).filter((f) => f !== "phone"), [answeredFields]);
1267
+ const fieldGroups = (0, react.useMemo)(() => groupAddressFields(fieldOrder), [fieldOrder]);
1268
+ const layoutReady = addressFieldsApi ? lookupCountry === null || countryFields?.country === billingCountry : stateOptionsReady;
1269
+ const isRequired = (fieldName) => {
1270
+ if (answeredFields) return isAddressFieldRequired(answeredFields, fieldName);
1271
+ if (fieldName === "state") return stateSelectOptions.length > 0;
1272
+ return isAddressFieldRequired(null, fieldName);
1273
+ };
1274
+ const fieldLabel = (fieldName) => {
1275
+ const resolved = addressFieldLabel(answeredFields ?? null, fieldName, {
1276
+ regionKey: config?.regionLabel,
1277
+ postalKey: config?.postalLabel
1278
+ });
1279
+ return resolved.label ?? t(resolved.translationKey ?? fieldName);
1280
+ };
1281
+ const REQUIRED_MESSAGE_KEYS = {
1282
+ name: "name_is_required",
1283
+ address1: "address_line_1_is_required",
1284
+ city: "city_is_required",
1285
+ state: "state_is_required",
1286
+ postal_code: "zip_code_is_required"
1287
+ };
1158
1288
  const handleFormSubmit = handleSubmit((data) => {
1159
- clearErrors("billing_address.state");
1160
- if (!stateDecision.ready) return;
1161
- if (stateDecision.required && !data.billing_address.state) {
1162
- setError("billing_address.state", {
1163
- type: "manual",
1164
- message: t("state_is_required")
1165
- });
1289
+ clearErrors(FORM_PATHS_BY_FIELD.map((entry) => entry.path));
1290
+ if (!layoutReady) return;
1291
+ const missing = fieldOrder.filter((fieldName) => isRequired(fieldName) && !valueForField(data, fieldName)?.trim());
1292
+ if (missing.length > 0) {
1293
+ for (const fieldName of missing) {
1294
+ const key = REQUIRED_MESSAGE_KEYS[fieldName];
1295
+ if (!key) continue;
1296
+ setError(pathForField(fieldName), {
1297
+ type: "manual",
1298
+ message: t(key)
1299
+ });
1300
+ }
1166
1301
  return;
1167
1302
  }
1168
- onSubmit(stateDecision.used ? data : {
1169
- ...data,
1170
- billing_address: {
1171
- ...data.billing_address,
1172
- state: ""
1173
- }
1174
- });
1303
+ onSubmit(data);
1175
1304
  });
1176
1305
  const deleteButtonLabel = (0, react.useMemo)(() => {
1177
1306
  if (isDeleting) return t("deleting");
@@ -1187,6 +1316,33 @@ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClos
1187
1316
  const displayName = getCardDisplayName(paymentMethod, t("card_fallback"));
1188
1317
  const expMonth = details.exp_month;
1189
1318
  const expYear = details.exp_year;
1319
+ const renderField = (fieldName) => {
1320
+ const label = fieldLabel(fieldName);
1321
+ if (fieldName === "address1") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AddressAutocompleteInput, {
1322
+ control,
1323
+ setValue,
1324
+ countryIso: billingCountry,
1325
+ addressLineField: "billing_address.address1",
1326
+ cityField: "billing_address.city",
1327
+ stateField: fieldOrder.includes("state") ? "billing_address.state" : void 0,
1328
+ postalCodeField: "billing_address.zip",
1329
+ stateOptions,
1330
+ label,
1331
+ disabled: isSubmitting
1332
+ }, fieldName);
1333
+ if (fieldName === "state" && stateSelectOptions.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormSelectField, {
1334
+ control,
1335
+ name: "billing_address.state",
1336
+ label,
1337
+ options: stateSelectOptions,
1338
+ placeholder: t("select_state")
1339
+ }, fieldName);
1340
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
1341
+ control,
1342
+ name: pathForField(fieldName),
1343
+ label
1344
+ }, fieldName);
1345
+ };
1190
1346
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_ResponsiveDialog.ResponsiveDialog, {
1191
1347
  open: isOpen,
1192
1348
  onOpenChange: (open) => !open && onClose(),
@@ -1228,68 +1384,21 @@ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClos
1228
1384
  children: t("billing_address")
1229
1385
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1230
1386
  className: "space-y-3",
1231
- children: [
1232
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormSelectField, {
1233
- control,
1234
- name: "billing_address.country_code",
1235
- label: t("country"),
1236
- options: countryOptions,
1237
- placeholder: t("select_an_option"),
1238
- onChange: () => {
1239
- countryTouchedRef.current = true;
1240
- setValue("billing_address.state", "");
1241
- clearErrors("billing_address.state");
1242
- }
1243
- }),
1244
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
1245
- control,
1246
- name: "billing_address.name",
1247
- label: t("name")
1248
- }),
1249
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AddressAutocompleteInput, {
1250
- control,
1251
- setValue,
1252
- countryIso: billingCountry,
1253
- addressLineField: "billing_address.address1",
1254
- cityField: "billing_address.city",
1255
- stateField: "billing_address.state",
1256
- postalCodeField: "billing_address.zip",
1257
- stateOptions,
1258
- label: t("address_line_1"),
1259
- disabled: isSubmitting
1260
- }),
1261
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
1262
- control,
1263
- name: "billing_address.address2",
1264
- label: t("address_line_2")
1265
- }),
1266
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1267
- className: require_src.cn("grid grid-cols-1 gap-3", stateDecision.used ? "sm:grid-cols-3" : "sm:grid-cols-2"),
1268
- children: [
1269
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
1270
- control,
1271
- name: "billing_address.city",
1272
- label: t("city")
1273
- }),
1274
- stateDecision.used && (stateSelectOptions.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormSelectField, {
1275
- control,
1276
- name: "billing_address.state",
1277
- label: stateLabel,
1278
- options: stateSelectOptions,
1279
- placeholder: t("select_state")
1280
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
1281
- control,
1282
- name: "billing_address.state",
1283
- label: stateLabel
1284
- })),
1285
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormTextField$1, {
1286
- control,
1287
- name: "billing_address.zip",
1288
- label: config?.postalLabel ? t(config.postalLabel) : t("zip_code")
1289
- })
1290
- ]
1291
- })
1292
- ]
1387
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormSelectField, {
1388
+ control,
1389
+ name: "billing_address.country_code",
1390
+ label: t("country"),
1391
+ options: countryOptions,
1392
+ placeholder: t("select_an_option"),
1393
+ onChange: () => {
1394
+ countryTouchedRef.current = true;
1395
+ setValue("billing_address.state", "");
1396
+ clearErrors("billing_address.state");
1397
+ }
1398
+ }), fieldGroups.map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1399
+ className: require_src.cn("grid grid-cols-1 gap-3", group.length === 3 ? "sm:grid-cols-3" : group.length === 2 ? "sm:grid-cols-2" : void 0),
1400
+ children: group.map((fieldName) => renderField(fieldName))
1401
+ }, group.join("-")))]
1293
1402
  })] })]
1294
1403
  }),
1295
1404
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_hook_form.Controller, {
@@ -1335,7 +1444,7 @@ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClos
1335
1444
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.Button, {
1336
1445
  type: "button",
1337
1446
  onClick: handleFormSubmit,
1338
- disabled: isSubmitting || isDeleting || !stateDecision.ready,
1447
+ disabled: isSubmitting || isDeleting || !layoutReady,
1339
1448
  children: [isSubmitting && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "mr-2 size-4 animate-spin rounded-full border-2 border-current/30 border-t-current" }), isSubmitting ? t("saving") : t("save_changes")]
1340
1449
  })]
1341
1450
  })]
@@ -1399,7 +1508,7 @@ function FormTextField({ control, name, label, placeholder, containerClassName,
1399
1508
  }
1400
1509
  //#endregion
1401
1510
  //#region ../../fluid-pay/ui/src/components/form-fields/FormComboboxField.tsx
1402
- function FormComboboxField({ control, name, label, placeholder = "Select", emptyText = "No results found.", options, containerClassName, disabled }) {
1511
+ function FormComboboxField({ control, name, label, placeholder = "Select", emptyText = "No results found.", options, containerClassName, disabled, onChange }) {
1403
1512
  const comboboxOptions = (0, react.useMemo)(() => options?.map((opt) => ({
1404
1513
  label: opt.name,
1405
1514
  value: opt.value.toString()
@@ -1413,10 +1522,13 @@ function FormComboboxField({ control, name, label, placeholder = "Select", empty
1413
1522
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_hook_form.Controller, {
1414
1523
  control,
1415
1524
  name,
1416
- render: ({ field: { onChange, value }, fieldState: { error } }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Combobox.Combobox, {
1525
+ render: ({ field: { onChange: fieldOnChange, value }, fieldState: { error } }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Combobox.Combobox, {
1417
1526
  options: comboboxOptions,
1418
1527
  value: value?.toString() ?? "",
1419
- onValueChange: onChange,
1528
+ onValueChange: (next) => {
1529
+ fieldOnChange(next);
1530
+ onChange?.(next);
1531
+ },
1420
1532
  placeholder,
1421
1533
  emptyText,
1422
1534
  disabled
@@ -1440,32 +1552,6 @@ const addressFormSchema = zod.z.object({
1440
1552
  country_code: zod.z.string().min(1, "Country is required"),
1441
1553
  default: zod.z.boolean()
1442
1554
  });
1443
- const STATIC_FIELD_ORDER = [
1444
- "name",
1445
- "address1",
1446
- "address2",
1447
- "city",
1448
- "state",
1449
- "postal_code",
1450
- "phone"
1451
- ];
1452
- const STATIC_LABELS = {
1453
- name: "name",
1454
- address1: "address_line_1",
1455
- address2: "address_line_2",
1456
- city: "city",
1457
- state: "state",
1458
- postal_code: "zip_code",
1459
- phone: "phone_number"
1460
- };
1461
- const DEFAULT_HIDDEN_FIELDS = new Set(["phone"]);
1462
- const STATIC_REQUIRED_FIELDS = new Set([
1463
- "name",
1464
- "address1",
1465
- "city",
1466
- "state",
1467
- "postal_code"
1468
- ]);
1469
1555
  const REQUIRED_FIELD_MESSAGES = {
1470
1556
  name: "Name is required",
1471
1557
  address1: "Address line 1 is required",
@@ -1475,47 +1561,6 @@ const REQUIRED_FIELD_MESSAGES = {
1475
1561
  postal_code: "Postal code is required",
1476
1562
  phone: "Phone is required"
1477
1563
  };
1478
- const AUTOCOMPLETE_FIELD_PREFIX = [
1479
- "name",
1480
- "address1",
1481
- "address2"
1482
- ];
1483
- function isAddressFieldName(value) {
1484
- return STATIC_FIELD_ORDER.includes(value);
1485
- }
1486
- function prioritizeAutocompleteFields(fields) {
1487
- const prefix = AUTOCOMPLETE_FIELD_PREFIX.filter((field) => fields.includes(field));
1488
- const rest = fields.filter((field) => !AUTOCOMPLETE_FIELD_PREFIX.includes(field));
1489
- return [...prefix, ...rest];
1490
- }
1491
- function groupFields(fields) {
1492
- const groups = [];
1493
- let i = 0;
1494
- while (i < fields.length) {
1495
- const current = fields[i];
1496
- const locationFields = new Set([
1497
- "city",
1498
- "state",
1499
- "postal_code"
1500
- ]);
1501
- if (locationFields.has(current)) {
1502
- const group = [current];
1503
- while (i + group.length < fields.length && locationFields.has(fields[i + group.length])) group.push(fields[i + group.length]);
1504
- if (group.length > 1) {
1505
- groups.push(group);
1506
- i += group.length;
1507
- continue;
1508
- }
1509
- }
1510
- groups.push([current]);
1511
- i++;
1512
- }
1513
- return groups;
1514
- }
1515
- function isFieldRequired(bffFields, fieldName) {
1516
- if (!bffFields) return STATIC_REQUIRED_FIELDS.has(fieldName);
1517
- return bffFields.find((field) => field.field === fieldName)?.required ?? false;
1518
- }
1519
1564
  function isBlank(value) {
1520
1565
  return value == null || value.trim().length === 0;
1521
1566
  }
@@ -1574,20 +1619,14 @@ function AddressFormDialog({ isOpen, onClose, selectedAddress, onSubmit, isSubmi
1574
1619
  selectedCountryCode,
1575
1620
  languageIso
1576
1621
  ]);
1577
- const fieldOrder = (0, react.useMemo)(() => {
1578
- if (!bffFields) return STATIC_FIELD_ORDER.filter((f) => !DEFAULT_HIDDEN_FIELDS.has(f));
1579
- return prioritizeAutocompleteFields(bffFields.map((f) => f.field).filter(isAddressFieldName));
1580
- }, [bffFields]);
1581
- const fieldGroups = (0, react.useMemo)(() => groupFields(fieldOrder), [fieldOrder]);
1622
+ const fieldOrder = (0, react.useMemo)(() => addressFieldOrder(bffFields), [bffFields]);
1623
+ const fieldGroups = (0, react.useMemo)(() => groupAddressFields(fieldOrder), [fieldOrder]);
1582
1624
  const getFieldLabel = (fieldName) => {
1583
- if (bffFields) {
1584
- const bffField = bffFields.find((f) => f.field === fieldName);
1585
- if (bffField) return bffField.label;
1586
- }
1587
- if (fieldName === "state" && config?.regionLabel) return t(config.regionLabel);
1588
- if (fieldName === "postal_code" && config?.postalLabel) return t(config.postalLabel);
1589
- const key = STATIC_LABELS[fieldName];
1590
- return key ? t(key) : fieldName;
1625
+ const resolved = addressFieldLabel(bffFields, fieldName, {
1626
+ regionKey: config?.regionLabel,
1627
+ postalKey: config?.postalLabel
1628
+ });
1629
+ return resolved.label ?? t(resolved.translationKey ?? fieldName);
1591
1630
  };
1592
1631
  const countrySelectOptions = [...countries].map((country) => ({
1593
1632
  name: country.name,
@@ -1644,8 +1683,8 @@ function AddressFormDialog({ isOpen, onClose, selectedAddress, onSubmit, isSubmi
1644
1683
  fetchStates
1645
1684
  ]);
1646
1685
  const handleFormSubmit = handleSubmit((data) => {
1647
- clearErrors(STATIC_FIELD_ORDER);
1648
- const missingRequiredFields = fieldOrder.filter((fieldName) => isFieldRequired(bffFields, fieldName) && isBlank(data[fieldName]));
1686
+ clearErrors(fieldOrder);
1687
+ const missingRequiredFields = fieldOrder.filter((fieldName) => isAddressFieldRequired(bffFields, fieldName) && isBlank(data[fieldName]));
1649
1688
  if (missingRequiredFields.length > 0) {
1650
1689
  for (const fieldName of missingRequiredFields) setError(fieldName, {
1651
1690
  type: "manual",
@@ -1653,14 +1692,12 @@ function AddressFormDialog({ isOpen, onClose, selectedAddress, onSubmit, isSubmi
1653
1692
  });
1654
1693
  return;
1655
1694
  }
1656
- const city = bffFields && !fieldOrder.includes("city") ? "" : data.city;
1657
- const state = bffFields && !fieldOrder.includes("state") ? "" : data.state;
1658
1695
  onSubmit({ address: {
1659
1696
  name: data.name,
1660
1697
  address1: data.address1,
1661
1698
  address2: data.address2 ?? null,
1662
- city,
1663
- state,
1699
+ city: data.city,
1700
+ state: data.state,
1664
1701
  postal_code: data.postal_code,
1665
1702
  phone: data.phone || null,
1666
1703
  country_code: data.country_code,
@@ -1690,7 +1727,7 @@ function AddressFormDialog({ isOpen, onClose, selectedAddress, onSubmit, isSubmi
1690
1727
  countryIso: selectedCountryCode,
1691
1728
  addressLineField: "address1",
1692
1729
  cityField: "city",
1693
- stateField: "state",
1730
+ stateField: fieldOrder.includes("state") ? "state" : void 0,
1694
1731
  postalCodeField: "postal_code",
1695
1732
  stateOptions,
1696
1733
  disabled: isSubmitting
@@ -1751,7 +1788,11 @@ function AddressFormDialog({ isOpen, onClose, selectedAddress, onSubmit, isSubmi
1751
1788
  label: t("country"),
1752
1789
  placeholder: t("select_an_option"),
1753
1790
  options: countrySelectOptions,
1754
- disabled: isSubmitting
1791
+ disabled: isSubmitting,
1792
+ onChange: () => {
1793
+ setValue("state", "");
1794
+ clearErrors("state");
1795
+ }
1755
1796
  }), fieldGroups.map((group) => {
1756
1797
  if (group.length === 1) return renderField(group[0]);
1757
1798
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -3114,4 +3155,4 @@ Object.defineProperty(exports, "useProfileTranslation", {
3114
3155
  }
3115
3156
  });
3116
3157
 
3117
- //# sourceMappingURL=use-portal-card-add-3ds-flow-LyyuhE0C.cjs.map
3158
+ //# sourceMappingURL=use-portal-card-add-3ds-flow-BD_RPuyR.cjs.map