@fluid-app/portal-sdk 0.1.499 → 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 (37) hide show
  1. package/dist/{FluidProvider-uiAG1e1c.cjs → FluidProvider-DqMKDA_x.cjs} +2 -1
  2. package/dist/{FluidProvider-uiAG1e1c.cjs.map → FluidProvider-DqMKDA_x.cjs.map} +1 -1
  3. package/dist/{FluidProvider-BY-IWBBl.mjs → FluidProvider-pfuaCUAu.mjs} +2 -1
  4. package/dist/{FluidProvider-BY-IWBBl.mjs.map → FluidProvider-pfuaCUAu.mjs.map} +1 -1
  5. package/dist/{MessagingScreen-6yKtIQrt.mjs → MessagingScreen-CEPrekjI.mjs} +2 -2
  6. package/dist/{MessagingScreen-BzEMYknm.cjs → MessagingScreen-DLomIoTO.cjs} +2 -2
  7. package/dist/{MessagingScreen-BA0Bsjhu.mjs → MessagingScreen-ILHCTccW.mjs} +2 -2
  8. package/dist/{MessagingScreen-BA0Bsjhu.mjs.map → MessagingScreen-ILHCTccW.mjs.map} +1 -1
  9. package/dist/{MessagingScreen-CHcWfgsC.cjs → MessagingScreen-izL-CVh1.cjs} +2 -2
  10. package/dist/{MessagingScreen-CHcWfgsC.cjs.map → MessagingScreen-izL-CVh1.cjs.map} +1 -1
  11. package/dist/{OrdersScreen-ClQpYrU8.mjs → OrdersScreen-Cr-3CBfD.mjs} +2 -2
  12. package/dist/{OrdersScreen-JCTiIxCr.cjs → OrdersScreen-Do_di0Vk.cjs} +2 -2
  13. package/dist/{OrdersScreen-JCTiIxCr.cjs.map → OrdersScreen-Do_di0Vk.cjs.map} +1 -1
  14. package/dist/{OrdersScreen-LaaKMS1l.mjs → OrdersScreen-Q6IftqCN.mjs} +2 -2
  15. package/dist/{OrdersScreen-LaaKMS1l.mjs.map → OrdersScreen-Q6IftqCN.mjs.map} +1 -1
  16. package/dist/{OrdersScreen-B4TQJMrX.cjs → OrdersScreen-VcvBe-UI.cjs} +2 -2
  17. package/dist/{ProfileScreen-Bb2UCqei.cjs → ProfileScreen-BG6ZCv_K.cjs} +3 -2
  18. package/dist/{ProfileScreen-Bb2UCqei.cjs.map → ProfileScreen-BG6ZCv_K.cjs.map} +1 -1
  19. package/dist/{ProfileScreen-PtQeT_Tx.cjs → ProfileScreen-BsTDYXwS.cjs} +3 -3
  20. package/dist/{ProfileScreen-CPKQamjq.mjs → ProfileScreen-DHBVul4x.mjs} +3 -2
  21. package/dist/{ProfileScreen-CPKQamjq.mjs.map → ProfileScreen-DHBVul4x.mjs.map} +1 -1
  22. package/dist/{ProfileScreen-BQADmCT1.mjs → ProfileScreen-DHG9QVyt.mjs} +3 -3
  23. package/dist/{SubscriptionsScreen-bLbgcoWU.cjs → SubscriptionsScreen-BNNFQ9k0.cjs} +5 -4
  24. package/dist/{SubscriptionsScreen-bLbgcoWU.cjs.map → SubscriptionsScreen-BNNFQ9k0.cjs.map} +1 -1
  25. package/dist/{SubscriptionsScreen-BuKop-5w.cjs → SubscriptionsScreen-CCz4s3uD.cjs} +3 -3
  26. package/dist/{SubscriptionsScreen-Bdb0863a.mjs → SubscriptionsScreen-CiedAyPM.mjs} +3 -3
  27. package/dist/{SubscriptionsScreen-YrSM9ea-.mjs → SubscriptionsScreen-gizzDVc6.mjs} +5 -4
  28. package/dist/{SubscriptionsScreen-YrSM9ea-.mjs.map → SubscriptionsScreen-gizzDVc6.mjs.map} +1 -1
  29. package/dist/index.cjs +14 -14
  30. package/dist/index.mjs +14 -14
  31. package/dist/{use-portal-card-add-3ds-flow-fFNO6XU3.cjs → use-portal-card-add-3ds-flow-BD_RPuyR.cjs} +269 -228
  32. package/dist/use-portal-card-add-3ds-flow-BD_RPuyR.cjs.map +1 -0
  33. package/dist/{use-portal-card-add-3ds-flow-Cu9yqnIn.mjs → use-portal-card-add-3ds-flow-y2cBmujb.mjs} +269 -228
  34. package/dist/use-portal-card-add-3ds-flow-y2cBmujb.mjs.map +1 -0
  35. package/package.json +18 -18
  36. package/dist/use-portal-card-add-3ds-flow-Cu9yqnIn.mjs.map +0 -1
  37. package/dist/use-portal-card-add-3ds-flow-fFNO6XU3.cjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { D as SelectItem, E as SelectContent, Ft as Checkbox, G as DropdownMenuContent, H as Label, K as DropdownMenuItem, N as Input, O as SelectTrigger, Rn as useZodForm, T as Select, Tn as Button, U as DropdownMenu, X as DropdownMenuSeparator, at as DialogFooter, et as DropdownMenuTrigger, k as SelectValue, lt as DialogTitle, o as Textarea, rt as DialogContent, tt as Dialog, zn as cn } from "./src-BfINy9nC.mjs";
2
2
  import { A as isCardPaymentDescriptor, B as normalizeCardBrand, F as resolvePaymentLogo, I as resolvePaymentMethodDisplay, N as normalizePaymentDescriptor, P as paymentDescriptorLabel, l as PhoneInput, yt as useAddressFieldsApiOptional } from "./build-widget-registry-C-WhTBEe.mjs";
3
3
  import { t as Combobox } from "./Combobox-D8ukt9Tb.mjs";
4
- import { o as createProfileTranslationAdapter, s as profileDomain, y as useAddressAutocompleteApiOptional } from "./FluidProvider-BY-IWBBl.mjs";
4
+ import { o as createProfileTranslationAdapter, s as profileDomain, y as useAddressAutocompleteApiOptional } from "./FluidProvider-pfuaCUAu.mjs";
5
5
  import { t as MobileBottomSheet } from "./MobileBottomSheet-BKm3ysnd.mjs";
6
6
  import { a as useActiveLocale, r as useDomainDict } from "./static-dict-adapter-DUyazFbx.mjs";
7
7
  import { t as createTranslationContext } from "./translation-api-context-factory-BTpIuUF0.mjs";
@@ -580,7 +580,7 @@ function AddressAutocompleteInput({ control, setValue, countryIso, addressLineFi
580
580
  const populate = useCallback((s) => {
581
581
  setValue(addressLineField, s.streetLine, SET_OPTS);
582
582
  setValue(cityField, s.city, SET_OPTS);
583
- setValue(stateField, resolveAdministrativeAreaState(s, stateOptions), SET_OPTS);
583
+ if (stateField) setValue(stateField, resolveAdministrativeAreaState(s, stateOptions), SET_OPTS);
584
584
  setValue(postalCodeField, s.postalCode, SET_OPTS);
585
585
  }, [
586
586
  addressLineField,
@@ -713,6 +713,115 @@ function AddressAutocompleteInput({ control, setValue, countryIso, addressLineFi
713
713
  });
714
714
  }
715
715
  //#endregion
716
+ //#region ../../platform/address-fields/src/field-layout.ts
717
+ /**
718
+ * Which address fields a country collects, in what order, and how they group
719
+ * into rows. The address-fields service is the authority: when it answers, its
720
+ * list decides presence and order, and its labels arrive already translated.
721
+ * The static values below cover only the window before it answers, or a host
722
+ * with no provider wired.
723
+ */
724
+ const ADDRESS_FIELD_NAMES = [
725
+ "name",
726
+ "address1",
727
+ "address2",
728
+ "city",
729
+ "state",
730
+ "postal_code",
731
+ "phone"
732
+ ];
733
+ const STATIC_LABEL_KEYS = {
734
+ name: "name",
735
+ address1: "address_line_1",
736
+ address2: "address_line_2",
737
+ city: "city",
738
+ state: "state",
739
+ postal_code: "zip_code",
740
+ phone: "phone_number"
741
+ };
742
+ const DEFAULT_HIDDEN_FIELDS = new Set(["phone"]);
743
+ const STATIC_REQUIRED_FIELDS = new Set([
744
+ "name",
745
+ "address1",
746
+ "city",
747
+ "state",
748
+ "postal_code"
749
+ ]);
750
+ const AUTOCOMPLETE_FIELD_PREFIX = [
751
+ "name",
752
+ "address1",
753
+ "address2"
754
+ ];
755
+ const ROW_GROUPED_FIELDS = new Set([
756
+ "city",
757
+ "state",
758
+ "postal_code"
759
+ ]);
760
+ function isAddressFieldName(value) {
761
+ return ADDRESS_FIELD_NAMES.includes(value);
762
+ }
763
+ function addressFieldOrder(fields) {
764
+ if (!fields) return ADDRESS_FIELD_NAMES.filter((field) => !DEFAULT_HIDDEN_FIELDS.has(field));
765
+ const fromService = fields.map((field) => field.field).filter(isAddressFieldName);
766
+ const prefix = AUTOCOMPLETE_FIELD_PREFIX.filter((field) => fromService.includes(field));
767
+ const rest = fromService.filter((field) => !AUTOCOMPLETE_FIELD_PREFIX.includes(field));
768
+ return [...prefix, ...rest];
769
+ }
770
+ /** Consecutive city, state and postal fields share one row. */
771
+ function groupAddressFields(fields) {
772
+ const groups = [];
773
+ let i = 0;
774
+ while (i < fields.length) {
775
+ const current = fields[i];
776
+ if (ROW_GROUPED_FIELDS.has(current)) {
777
+ const group = [current];
778
+ while (i + group.length < fields.length && ROW_GROUPED_FIELDS.has(fields[i + group.length])) group.push(fields[i + group.length]);
779
+ if (group.length > 1) {
780
+ groups.push(group);
781
+ i += group.length;
782
+ continue;
783
+ }
784
+ }
785
+ groups.push([current]);
786
+ i++;
787
+ }
788
+ return groups;
789
+ }
790
+ function isAddressFieldRequired(fields, fieldName) {
791
+ if (!fields) return STATIC_REQUIRED_FIELDS.has(fieldName);
792
+ return fields.find((field) => field.field === fieldName)?.required ?? false;
793
+ }
794
+ /**
795
+ * The service's label when it has one, otherwise a translation key for the
796
+ * caller to resolve. `regionKey` and `postalKey` let a caller pass the
797
+ * country-specific key it already has, such as province or postal_code.
798
+ */
799
+ function addressFieldLabel(fields, fieldName, fallbackKeys) {
800
+ const serviceLabel = fields?.find((field) => field.field === fieldName)?.label;
801
+ if (serviceLabel) return { label: serviceLabel };
802
+ if (fieldName === "state" && fallbackKeys?.regionKey) return { translationKey: fallbackKeys.regionKey };
803
+ if (fieldName === "postal_code" && fallbackKeys?.postalKey) return { translationKey: fallbackKeys.postalKey };
804
+ return { translationKey: STATIC_LABEL_KEYS[fieldName] };
805
+ }
806
+ createContext(null);
807
+ //#endregion
808
+ //#region ../../fluid-pay/core/src/context.ts
809
+ const FluidPayApiContext = createContext(null);
810
+ const FluidPayApiProvider = FluidPayApiContext.Provider;
811
+ function useFluidPayApi() {
812
+ const api = useContext(FluidPayApiContext);
813
+ if (!api) throw new Error("useFluidPayApi must be used within a FluidPayCoreProvider");
814
+ return api;
815
+ }
816
+ //#endregion
817
+ //#region ../../fluid-pay/core/src/provider.tsx
818
+ function FluidPayCoreProvider({ api, children }) {
819
+ return /* @__PURE__ */ jsx(FluidPayApiProvider, {
820
+ value: api,
821
+ children
822
+ });
823
+ }
824
+ //#endregion
716
825
  //#region ../../platform/address-fields/src/country-config.ts
717
826
  const US_STATES = [
718
827
  {
@@ -940,42 +1049,21 @@ const US_STATES = [
940
1049
  isoCode: "WY"
941
1050
  }
942
1051
  ];
943
- function isFieldRequired$1(addressFields, fieldName) {
944
- return addressFields.find((f) => f.field === fieldName)?.required ?? false;
945
- }
946
- createContext(null);
947
- //#endregion
948
- //#region ../../fluid-pay/core/src/context.ts
949
- const FluidPayApiContext = createContext(null);
950
- const FluidPayApiProvider = FluidPayApiContext.Provider;
951
- function useFluidPayApi() {
952
- const api = useContext(FluidPayApiContext);
953
- if (!api) throw new Error("useFluidPayApi must be used within a FluidPayCoreProvider");
954
- return api;
955
- }
956
- //#endregion
957
- //#region ../../fluid-pay/core/src/provider.tsx
958
- function FluidPayCoreProvider({ api, children }) {
959
- return /* @__PURE__ */ jsx(FluidPayApiProvider, {
960
- value: api,
961
- children
962
- });
963
- }
964
1052
  //#endregion
965
1053
  //#region ../../fluid-pay/core/src/utils/country-config.ts
966
1054
  const COUNTRY_CONFIGS = {
967
1055
  US: {
968
- regionLabel: "State",
969
- postalLabel: "ZIP Code"
1056
+ regionLabel: "state",
1057
+ postalLabel: "zip_code"
970
1058
  },
971
1059
  JP: {
972
- regionLabel: "Prefecture",
973
- postalLabel: "Postal Code"
1060
+ regionLabel: "prefecture",
1061
+ postalLabel: "postal_code"
974
1062
  }
975
1063
  };
976
1064
  const DEFAULT_REGION_CONFIG = {
977
- regionLabel: "Province",
978
- postalLabel: "Postal Code"
1065
+ regionLabel: "province",
1066
+ postalLabel: "postal_code"
979
1067
  };
980
1068
  function getRegionConfig(countryCode) {
981
1069
  return COUNTRY_CONFIGS[countryCode] ?? DEFAULT_REGION_CONFIG;
@@ -1021,18 +1109,59 @@ function useCountryStates() {
1021
1109
  function createEditPaymentMethodFormSchema(t) {
1022
1110
  return z.object({
1023
1111
  billing_address: z.object({
1024
- name: z.string().min(1, t("name_is_required")),
1025
- address1: z.string().min(1, t("address_line_1_is_required")),
1112
+ name: z.string(),
1113
+ address1: z.string(),
1026
1114
  address2: z.string().optional().nullable(),
1027
- city: z.string().min(1, t("city_is_required")),
1115
+ city: z.string(),
1028
1116
  state: z.string(),
1029
- zip: z.string().min(1, t("zip_code_is_required")),
1117
+ zip: z.string(),
1030
1118
  country_code: z.string().min(1, t("country_is_required"))
1031
1119
  }),
1032
1120
  set_as_default: z.boolean()
1033
1121
  });
1034
1122
  }
1035
- function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClose, onSubmit, isSubmitting, error, countries = [], fetchStates, onDelete, isDeleting = false, presentation = "dialog" }) {
1123
+ const FORM_PATHS_BY_FIELD = [
1124
+ {
1125
+ field: "name",
1126
+ key: "name",
1127
+ path: "billing_address.name"
1128
+ },
1129
+ {
1130
+ field: "address1",
1131
+ key: "address1",
1132
+ path: "billing_address.address1"
1133
+ },
1134
+ {
1135
+ field: "address2",
1136
+ key: "address2",
1137
+ path: "billing_address.address2"
1138
+ },
1139
+ {
1140
+ field: "city",
1141
+ key: "city",
1142
+ path: "billing_address.city"
1143
+ },
1144
+ {
1145
+ field: "state",
1146
+ key: "state",
1147
+ path: "billing_address.state"
1148
+ },
1149
+ {
1150
+ field: "postal_code",
1151
+ key: "zip",
1152
+ path: "billing_address.zip"
1153
+ }
1154
+ ];
1155
+ function pathForField(fieldName) {
1156
+ return FORM_PATHS_BY_FIELD.find((e) => e.field === fieldName)?.path ?? "billing_address.address1";
1157
+ }
1158
+ function valueForField(data, fieldName) {
1159
+ const entry = FORM_PATHS_BY_FIELD.find((e) => e.field === fieldName);
1160
+ if (!entry) return void 0;
1161
+ const value = data.billing_address[entry.key];
1162
+ return typeof value === "string" ? value : void 0;
1163
+ }
1164
+ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClose, onSubmit, isSubmitting, error, countries = [], fetchStates, languageIso, onDelete, isDeleting = false, presentation = "dialog" }) {
1036
1165
  const { t } = useProfileTranslation();
1037
1166
  const [confirmDelete, setConfirmDelete] = useState(false);
1038
1167
  useEffect(() => {
@@ -1112,7 +1241,7 @@ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClos
1112
1241
  if (!addressFieldsApi || !lookupCountry) return;
1113
1242
  let cancelled = false;
1114
1243
  setCountryFields(null);
1115
- addressFieldsApi.fetchAddressFields(lookupCountry).then((response) => {
1244
+ addressFieldsApi.fetchAddressFields(lookupCountry, languageIso).then((response) => {
1116
1245
  if (cancelled) return;
1117
1246
  setCountryFields({
1118
1247
  country: lookupCountry,
@@ -1127,50 +1256,50 @@ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClos
1127
1256
  return () => {
1128
1257
  cancelled = true;
1129
1258
  };
1130
- }, [addressFieldsApi, lookupCountry]);
1131
- const stateLabel = config?.regionLabel ? t(config.regionLabel) : t("state");
1132
- const stateDecision = useMemo(() => {
1133
- const answered = countryFields?.country === billingCountry;
1134
- const fields = answered ? countryFields?.fields : null;
1135
- if (fields) return {
1136
- ready: true,
1137
- used: fields.some((field) => field.field === "state") || stateSelectOptions.length > 0,
1138
- required: isFieldRequired$1(fields, "state")
1139
- };
1140
- if (addressFieldsApi && !answered) return {
1141
- ready: false,
1142
- used: true,
1143
- required: false
1144
- };
1145
- return {
1146
- ready: stateOptionsReady,
1147
- used: true,
1148
- required: stateSelectOptions.length > 0
1149
- };
1150
1259
  }, [
1151
1260
  addressFieldsApi,
1152
- billingCountry,
1153
- countryFields,
1154
- stateOptionsReady,
1155
- stateSelectOptions.length
1261
+ lookupCountry,
1262
+ languageIso
1156
1263
  ]);
1264
+ const answeredFields = countryFields?.country === billingCountry ? countryFields?.fields : null;
1265
+ const fieldOrder = useMemo(() => addressFieldOrder(answeredFields ?? null).filter((f) => f !== "phone"), [answeredFields]);
1266
+ const fieldGroups = useMemo(() => groupAddressFields(fieldOrder), [fieldOrder]);
1267
+ const layoutReady = addressFieldsApi ? lookupCountry === null || countryFields?.country === billingCountry : stateOptionsReady;
1268
+ const isRequired = (fieldName) => {
1269
+ if (answeredFields) return isAddressFieldRequired(answeredFields, fieldName);
1270
+ if (fieldName === "state") return stateSelectOptions.length > 0;
1271
+ return isAddressFieldRequired(null, fieldName);
1272
+ };
1273
+ const fieldLabel = (fieldName) => {
1274
+ const resolved = addressFieldLabel(answeredFields ?? null, fieldName, {
1275
+ regionKey: config?.regionLabel,
1276
+ postalKey: config?.postalLabel
1277
+ });
1278
+ return resolved.label ?? t(resolved.translationKey ?? fieldName);
1279
+ };
1280
+ const REQUIRED_MESSAGE_KEYS = {
1281
+ name: "name_is_required",
1282
+ address1: "address_line_1_is_required",
1283
+ city: "city_is_required",
1284
+ state: "state_is_required",
1285
+ postal_code: "zip_code_is_required"
1286
+ };
1157
1287
  const handleFormSubmit = handleSubmit((data) => {
1158
- clearErrors("billing_address.state");
1159
- if (!stateDecision.ready) return;
1160
- if (stateDecision.required && !data.billing_address.state) {
1161
- setError("billing_address.state", {
1162
- type: "manual",
1163
- message: t("state_is_required")
1164
- });
1288
+ clearErrors(FORM_PATHS_BY_FIELD.map((entry) => entry.path));
1289
+ if (!layoutReady) return;
1290
+ const missing = fieldOrder.filter((fieldName) => isRequired(fieldName) && !valueForField(data, fieldName)?.trim());
1291
+ if (missing.length > 0) {
1292
+ for (const fieldName of missing) {
1293
+ const key = REQUIRED_MESSAGE_KEYS[fieldName];
1294
+ if (!key) continue;
1295
+ setError(pathForField(fieldName), {
1296
+ type: "manual",
1297
+ message: t(key)
1298
+ });
1299
+ }
1165
1300
  return;
1166
1301
  }
1167
- onSubmit(stateDecision.used ? data : {
1168
- ...data,
1169
- billing_address: {
1170
- ...data.billing_address,
1171
- state: ""
1172
- }
1173
- });
1302
+ onSubmit(data);
1174
1303
  });
1175
1304
  const deleteButtonLabel = useMemo(() => {
1176
1305
  if (isDeleting) return t("deleting");
@@ -1186,6 +1315,33 @@ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClos
1186
1315
  const displayName = getCardDisplayName(paymentMethod, t("card_fallback"));
1187
1316
  const expMonth = details.exp_month;
1188
1317
  const expYear = details.exp_year;
1318
+ const renderField = (fieldName) => {
1319
+ const label = fieldLabel(fieldName);
1320
+ if (fieldName === "address1") return /* @__PURE__ */ jsx(AddressAutocompleteInput, {
1321
+ control,
1322
+ setValue,
1323
+ countryIso: billingCountry,
1324
+ addressLineField: "billing_address.address1",
1325
+ cityField: "billing_address.city",
1326
+ stateField: fieldOrder.includes("state") ? "billing_address.state" : void 0,
1327
+ postalCodeField: "billing_address.zip",
1328
+ stateOptions,
1329
+ label,
1330
+ disabled: isSubmitting
1331
+ }, fieldName);
1332
+ if (fieldName === "state" && stateSelectOptions.length > 0) return /* @__PURE__ */ jsx(FormSelectField, {
1333
+ control,
1334
+ name: "billing_address.state",
1335
+ label,
1336
+ options: stateSelectOptions,
1337
+ placeholder: t("select_state")
1338
+ }, fieldName);
1339
+ return /* @__PURE__ */ jsx(FormTextField$1, {
1340
+ control,
1341
+ name: pathForField(fieldName),
1342
+ label
1343
+ }, fieldName);
1344
+ };
1189
1345
  return /* @__PURE__ */ jsxs(ResponsiveDialog, {
1190
1346
  open: isOpen,
1191
1347
  onOpenChange: (open) => !open && onClose(),
@@ -1227,68 +1383,21 @@ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClos
1227
1383
  children: t("billing_address")
1228
1384
  }), /* @__PURE__ */ jsxs("div", {
1229
1385
  className: "space-y-3",
1230
- children: [
1231
- /* @__PURE__ */ jsx(FormSelectField, {
1232
- control,
1233
- name: "billing_address.country_code",
1234
- label: t("country"),
1235
- options: countryOptions,
1236
- placeholder: t("select_an_option"),
1237
- onChange: () => {
1238
- countryTouchedRef.current = true;
1239
- setValue("billing_address.state", "");
1240
- clearErrors("billing_address.state");
1241
- }
1242
- }),
1243
- /* @__PURE__ */ jsx(FormTextField$1, {
1244
- control,
1245
- name: "billing_address.name",
1246
- label: t("name")
1247
- }),
1248
- /* @__PURE__ */ jsx(AddressAutocompleteInput, {
1249
- control,
1250
- setValue,
1251
- countryIso: billingCountry,
1252
- addressLineField: "billing_address.address1",
1253
- cityField: "billing_address.city",
1254
- stateField: "billing_address.state",
1255
- postalCodeField: "billing_address.zip",
1256
- stateOptions,
1257
- label: t("address_line_1"),
1258
- disabled: isSubmitting
1259
- }),
1260
- /* @__PURE__ */ jsx(FormTextField$1, {
1261
- control,
1262
- name: "billing_address.address2",
1263
- label: t("address_line_2")
1264
- }),
1265
- /* @__PURE__ */ jsxs("div", {
1266
- className: cn("grid grid-cols-1 gap-3", stateDecision.used ? "sm:grid-cols-3" : "sm:grid-cols-2"),
1267
- children: [
1268
- /* @__PURE__ */ jsx(FormTextField$1, {
1269
- control,
1270
- name: "billing_address.city",
1271
- label: t("city")
1272
- }),
1273
- stateDecision.used && (stateSelectOptions.length > 0 ? /* @__PURE__ */ jsx(FormSelectField, {
1274
- control,
1275
- name: "billing_address.state",
1276
- label: stateLabel,
1277
- options: stateSelectOptions,
1278
- placeholder: t("select_state")
1279
- }) : /* @__PURE__ */ jsx(FormTextField$1, {
1280
- control,
1281
- name: "billing_address.state",
1282
- label: stateLabel
1283
- })),
1284
- /* @__PURE__ */ jsx(FormTextField$1, {
1285
- control,
1286
- name: "billing_address.zip",
1287
- label: config?.postalLabel ? t(config.postalLabel) : t("zip_code")
1288
- })
1289
- ]
1290
- })
1291
- ]
1386
+ children: [/* @__PURE__ */ jsx(FormSelectField, {
1387
+ control,
1388
+ name: "billing_address.country_code",
1389
+ label: t("country"),
1390
+ options: countryOptions,
1391
+ placeholder: t("select_an_option"),
1392
+ onChange: () => {
1393
+ countryTouchedRef.current = true;
1394
+ setValue("billing_address.state", "");
1395
+ clearErrors("billing_address.state");
1396
+ }
1397
+ }), fieldGroups.map((group) => /* @__PURE__ */ jsx("div", {
1398
+ className: cn("grid grid-cols-1 gap-3", group.length === 3 ? "sm:grid-cols-3" : group.length === 2 ? "sm:grid-cols-2" : void 0),
1399
+ children: group.map((fieldName) => renderField(fieldName))
1400
+ }, group.join("-")))]
1292
1401
  })] })]
1293
1402
  }),
1294
1403
  /* @__PURE__ */ jsx(Controller, {
@@ -1334,7 +1443,7 @@ function EditPaymentMethodDialog({ isOpen, paymentMethod, billingAddress, onClos
1334
1443
  }), /* @__PURE__ */ jsxs(Button, {
1335
1444
  type: "button",
1336
1445
  onClick: handleFormSubmit,
1337
- disabled: isSubmitting || isDeleting || !stateDecision.ready,
1446
+ disabled: isSubmitting || isDeleting || !layoutReady,
1338
1447
  children: [isSubmitting && /* @__PURE__ */ 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")]
1339
1448
  })]
1340
1449
  })]
@@ -1398,7 +1507,7 @@ function FormTextField({ control, name, label, placeholder, containerClassName,
1398
1507
  }
1399
1508
  //#endregion
1400
1509
  //#region ../../fluid-pay/ui/src/components/form-fields/FormComboboxField.tsx
1401
- function FormComboboxField({ control, name, label, placeholder = "Select", emptyText = "No results found.", options, containerClassName, disabled }) {
1510
+ function FormComboboxField({ control, name, label, placeholder = "Select", emptyText = "No results found.", options, containerClassName, disabled, onChange }) {
1402
1511
  const comboboxOptions = useMemo(() => options?.map((opt) => ({
1403
1512
  label: opt.name,
1404
1513
  value: opt.value.toString()
@@ -1412,10 +1521,13 @@ function FormComboboxField({ control, name, label, placeholder = "Select", empty
1412
1521
  }), /* @__PURE__ */ jsx(Controller, {
1413
1522
  control,
1414
1523
  name,
1415
- render: ({ field: { onChange, value }, fieldState: { error } }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Combobox, {
1524
+ render: ({ field: { onChange: fieldOnChange, value }, fieldState: { error } }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Combobox, {
1416
1525
  options: comboboxOptions,
1417
1526
  value: value?.toString() ?? "",
1418
- onValueChange: onChange,
1527
+ onValueChange: (next) => {
1528
+ fieldOnChange(next);
1529
+ onChange?.(next);
1530
+ },
1419
1531
  placeholder,
1420
1532
  emptyText,
1421
1533
  disabled
@@ -1439,32 +1551,6 @@ const addressFormSchema = z.object({
1439
1551
  country_code: z.string().min(1, "Country is required"),
1440
1552
  default: z.boolean()
1441
1553
  });
1442
- const STATIC_FIELD_ORDER = [
1443
- "name",
1444
- "address1",
1445
- "address2",
1446
- "city",
1447
- "state",
1448
- "postal_code",
1449
- "phone"
1450
- ];
1451
- const STATIC_LABELS = {
1452
- name: "name",
1453
- address1: "address_line_1",
1454
- address2: "address_line_2",
1455
- city: "city",
1456
- state: "state",
1457
- postal_code: "zip_code",
1458
- phone: "phone_number"
1459
- };
1460
- const DEFAULT_HIDDEN_FIELDS = new Set(["phone"]);
1461
- const STATIC_REQUIRED_FIELDS = new Set([
1462
- "name",
1463
- "address1",
1464
- "city",
1465
- "state",
1466
- "postal_code"
1467
- ]);
1468
1554
  const REQUIRED_FIELD_MESSAGES = {
1469
1555
  name: "Name is required",
1470
1556
  address1: "Address line 1 is required",
@@ -1474,47 +1560,6 @@ const REQUIRED_FIELD_MESSAGES = {
1474
1560
  postal_code: "Postal code is required",
1475
1561
  phone: "Phone is required"
1476
1562
  };
1477
- const AUTOCOMPLETE_FIELD_PREFIX = [
1478
- "name",
1479
- "address1",
1480
- "address2"
1481
- ];
1482
- function isAddressFieldName(value) {
1483
- return STATIC_FIELD_ORDER.includes(value);
1484
- }
1485
- function prioritizeAutocompleteFields(fields) {
1486
- const prefix = AUTOCOMPLETE_FIELD_PREFIX.filter((field) => fields.includes(field));
1487
- const rest = fields.filter((field) => !AUTOCOMPLETE_FIELD_PREFIX.includes(field));
1488
- return [...prefix, ...rest];
1489
- }
1490
- function groupFields(fields) {
1491
- const groups = [];
1492
- let i = 0;
1493
- while (i < fields.length) {
1494
- const current = fields[i];
1495
- const locationFields = new Set([
1496
- "city",
1497
- "state",
1498
- "postal_code"
1499
- ]);
1500
- if (locationFields.has(current)) {
1501
- const group = [current];
1502
- while (i + group.length < fields.length && locationFields.has(fields[i + group.length])) group.push(fields[i + group.length]);
1503
- if (group.length > 1) {
1504
- groups.push(group);
1505
- i += group.length;
1506
- continue;
1507
- }
1508
- }
1509
- groups.push([current]);
1510
- i++;
1511
- }
1512
- return groups;
1513
- }
1514
- function isFieldRequired(bffFields, fieldName) {
1515
- if (!bffFields) return STATIC_REQUIRED_FIELDS.has(fieldName);
1516
- return bffFields.find((field) => field.field === fieldName)?.required ?? false;
1517
- }
1518
1563
  function isBlank(value) {
1519
1564
  return value == null || value.trim().length === 0;
1520
1565
  }
@@ -1573,20 +1618,14 @@ function AddressFormDialog({ isOpen, onClose, selectedAddress, onSubmit, isSubmi
1573
1618
  selectedCountryCode,
1574
1619
  languageIso
1575
1620
  ]);
1576
- const fieldOrder = useMemo(() => {
1577
- if (!bffFields) return STATIC_FIELD_ORDER.filter((f) => !DEFAULT_HIDDEN_FIELDS.has(f));
1578
- return prioritizeAutocompleteFields(bffFields.map((f) => f.field).filter(isAddressFieldName));
1579
- }, [bffFields]);
1580
- const fieldGroups = useMemo(() => groupFields(fieldOrder), [fieldOrder]);
1621
+ const fieldOrder = useMemo(() => addressFieldOrder(bffFields), [bffFields]);
1622
+ const fieldGroups = useMemo(() => groupAddressFields(fieldOrder), [fieldOrder]);
1581
1623
  const getFieldLabel = (fieldName) => {
1582
- if (bffFields) {
1583
- const bffField = bffFields.find((f) => f.field === fieldName);
1584
- if (bffField) return bffField.label;
1585
- }
1586
- if (fieldName === "state" && config?.regionLabel) return t(config.regionLabel);
1587
- if (fieldName === "postal_code" && config?.postalLabel) return t(config.postalLabel);
1588
- const key = STATIC_LABELS[fieldName];
1589
- return key ? t(key) : fieldName;
1624
+ const resolved = addressFieldLabel(bffFields, fieldName, {
1625
+ regionKey: config?.regionLabel,
1626
+ postalKey: config?.postalLabel
1627
+ });
1628
+ return resolved.label ?? t(resolved.translationKey ?? fieldName);
1590
1629
  };
1591
1630
  const countrySelectOptions = [...countries].map((country) => ({
1592
1631
  name: country.name,
@@ -1643,8 +1682,8 @@ function AddressFormDialog({ isOpen, onClose, selectedAddress, onSubmit, isSubmi
1643
1682
  fetchStates
1644
1683
  ]);
1645
1684
  const handleFormSubmit = handleSubmit((data) => {
1646
- clearErrors(STATIC_FIELD_ORDER);
1647
- const missingRequiredFields = fieldOrder.filter((fieldName) => isFieldRequired(bffFields, fieldName) && isBlank(data[fieldName]));
1685
+ clearErrors(fieldOrder);
1686
+ const missingRequiredFields = fieldOrder.filter((fieldName) => isAddressFieldRequired(bffFields, fieldName) && isBlank(data[fieldName]));
1648
1687
  if (missingRequiredFields.length > 0) {
1649
1688
  for (const fieldName of missingRequiredFields) setError(fieldName, {
1650
1689
  type: "manual",
@@ -1652,14 +1691,12 @@ function AddressFormDialog({ isOpen, onClose, selectedAddress, onSubmit, isSubmi
1652
1691
  });
1653
1692
  return;
1654
1693
  }
1655
- const city = bffFields && !fieldOrder.includes("city") ? "" : data.city;
1656
- const state = bffFields && !fieldOrder.includes("state") ? "" : data.state;
1657
1694
  onSubmit({ address: {
1658
1695
  name: data.name,
1659
1696
  address1: data.address1,
1660
1697
  address2: data.address2 ?? null,
1661
- city,
1662
- state,
1698
+ city: data.city,
1699
+ state: data.state,
1663
1700
  postal_code: data.postal_code,
1664
1701
  phone: data.phone || null,
1665
1702
  country_code: data.country_code,
@@ -1689,7 +1726,7 @@ function AddressFormDialog({ isOpen, onClose, selectedAddress, onSubmit, isSubmi
1689
1726
  countryIso: selectedCountryCode,
1690
1727
  addressLineField: "address1",
1691
1728
  cityField: "city",
1692
- stateField: "state",
1729
+ stateField: fieldOrder.includes("state") ? "state" : void 0,
1693
1730
  postalCodeField: "postal_code",
1694
1731
  stateOptions,
1695
1732
  disabled: isSubmitting
@@ -1750,7 +1787,11 @@ function AddressFormDialog({ isOpen, onClose, selectedAddress, onSubmit, isSubmi
1750
1787
  label: t("country"),
1751
1788
  placeholder: t("select_an_option"),
1752
1789
  options: countrySelectOptions,
1753
- disabled: isSubmitting
1790
+ disabled: isSubmitting,
1791
+ onChange: () => {
1792
+ setValue("state", "");
1793
+ clearErrors("state");
1794
+ }
1754
1795
  }), fieldGroups.map((group) => {
1755
1796
  if (group.length === 1) return renderField(group[0]);
1756
1797
  return /* @__PURE__ */ jsx("div", {
@@ -3006,4 +3047,4 @@ function usePortalCardAdd3DSFlow({ payApi, onApproved, onFailed, onCanceled, t }
3006
3047
  //#endregion
3007
3048
  export { ProfileTranslationBridge as _, getBrowserInfo as a, EditPaymentMethodDialog as c, getCardDisplayName as d, getCardExpiry as f, EllipsesDropdown as g, ConfirmActionDialog as h, isThreeDsRequiredCreate as i, FluidPayCoreProvider as l, UserInfoDialog as m, createFluidPayApiAdapter as n, CreditCardFormDialog as o, getPaymentMethodLogoBrand as p, mapToFluidPayPaymentMethod as r, AddressFormDialog as s, usePortalCardAdd3DSFlow as t, PaymentIcon as u, useProfileTranslation as v };
3008
3049
 
3009
- //# sourceMappingURL=use-portal-card-add-3ds-flow-Cu9yqnIn.mjs.map
3050
+ //# sourceMappingURL=use-portal-card-add-3ds-flow-y2cBmujb.mjs.map