@capxul/sdk-react 4.20.0-beta.4 → 4.20.0-beta.5

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.
@@ -565,7 +565,7 @@ function CapxulIdentityProvider({ client, children }) {
565
565
  if (!active) return;
566
566
  state = runtime.snapshot();
567
567
  }
568
- if (state.phase === "authenticated" && state.profileComplete && state.account.at === "unknown") await runtime.send({ _tag: "EnsureAccount" }, { signal: controller.signal });
568
+ if (client._internal.accountSetup !== "explicit" && state.phase === "authenticated" && state.profileComplete && state.account.at === "unknown") await runtime.send({ _tag: "EnsureAccount" }, { signal: controller.signal });
569
569
  }).catch(() => void 0);
570
570
  return () => {
571
571
  active = false;
@@ -720,6 +720,7 @@ function clearClientScopedQueries(queryClient, ownsQueryClient) {
720
720
  }
721
721
  function CapxulProvider(props) {
722
722
  const { publishableKey, client: injectedClient, requirement, signer, observability, bootstrapBaseUrl, queryClient, children } = props;
723
+ const accountSetup = "accountSetup" in props ? props.accountSetup : void 0;
723
724
  const [resolvedQueryClient] = useState(() => queryClient ?? makeDefaultQueryClient());
724
725
  const [ownsQueryClient] = useState(() => queryClient === void 0);
725
726
  const [attempt, setAttempt] = useState(0);
@@ -731,13 +732,15 @@ function CapxulProvider(props) {
731
732
  ...requirement === void 0 ? {} : { requirement },
732
733
  ...signer === void 0 ? {} : { signer },
733
734
  ...observability === void 0 ? {} : { observability },
734
- ...bootstrapBaseUrl === void 0 ? {} : { bootstrapBaseUrl }
735
+ ...bootstrapBaseUrl === void 0 ? {} : { bootstrapBaseUrl },
736
+ ...accountSetup === void 0 ? {} : { accountSetup }
735
737
  }, [
736
738
  publishableKey,
737
739
  requirement,
738
740
  signer,
739
741
  observability,
740
742
  bootstrapBaseUrl,
743
+ accountSetup,
741
744
  attempt
742
745
  ]);
743
746
  const [ownedBootstrap, setOwnedBootstrap] = useState(null);
package/dist/index.d.mts CHANGED
@@ -28,6 +28,11 @@ type CapxulProviderPublishableKeyProps = CapxulProviderSharedProps & {
28
28
  * route cross-origin for the publishable key's allowed origins.
29
29
  */
30
30
  readonly bootstrapBaseUrl?: string;
31
+ /**
32
+ * AUTH A3. Pass `"explicit"` on `/connect` so restore and OTP do not write
33
+ * Profile, Account, or invitations. Default automatic.
34
+ */
35
+ readonly accountSetup?: "automatic" | "explicit";
31
36
  };
32
37
  /**
33
38
  * Node / server / test path — a pre-built client is supplied; lifecycle stays
@@ -456,7 +461,7 @@ interface CapxulContactsProps {
456
461
  readonly onFailed: (error: CapxulError, options?: InvocationOptions) => void;
457
462
  readonly children: ReactNode;
458
463
  }
459
- declare function Root$6({ actor, onAdded, onFailed, children }: CapxulContactsProps): import("react/jsx-runtime").JSX.Element;
464
+ declare function Root$7({ actor, onAdded, onFailed, children }: CapxulContactsProps): import("react/jsx-runtime").JSX.Element;
460
465
  declare function Summary$3({ children }: {
461
466
  readonly children: (slice: ContactsSummarySlice) => ReactNode;
462
467
  }): import("react/jsx-runtime").JSX.Element;
@@ -467,7 +472,7 @@ declare function Add({ children }: {
467
472
  readonly children: (slice: ContactsAddSlice) => ReactNode;
468
473
  }): import("react/jsx-runtime").JSX.Element;
469
474
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
470
- declare const CapxulContacts: typeof Root$6 & {
475
+ declare const CapxulContacts: typeof Root$7 & {
471
476
  Summary: typeof Summary$3;
472
477
  List: typeof List;
473
478
  Add: typeof Add;
@@ -637,7 +642,7 @@ interface CapxulActivityProps {
637
642
  readonly pageSize?: number;
638
643
  readonly children: ReactNode;
639
644
  }
640
- declare function Root$5({ actor, pageSize, children }: CapxulActivityProps): import("react/jsx-runtime").JSX.Element;
645
+ declare function Root$6({ actor, pageSize, children }: CapxulActivityProps): import("react/jsx-runtime").JSX.Element;
641
646
  /**
642
647
  * The one part that holds a query rather than reading the engine's: it takes a
643
648
  * `window` prop, and two placements can ask for different windows, so a single
@@ -668,7 +673,7 @@ declare function Export({ children }: {
668
673
  readonly children: (slice: ActivityExportSlice) => ReactNode;
669
674
  }): import("react/jsx-runtime").JSX.Element;
670
675
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
671
- declare const CapxulActivity: typeof Root$5 & {
676
+ declare const CapxulActivity: typeof Root$6 & {
672
677
  Summary: typeof Summary$2;
673
678
  Filters: typeof Filters;
674
679
  Search: typeof Search;
@@ -711,7 +716,7 @@ type SentPayment = {
711
716
  * Refusal CODES, never sentences (#1447 ruling 8). The app maps each code to
712
717
  * the words it already prints; no English refusal string ships from here.
713
718
  */
714
- type CapxulSendMoneyBlockedReason = "signer-not-ready" | "amount-invalid" | "recipient-unresolved" | "no-source" | "no-asset";
719
+ type CapxulSendMoneyBlockedReason = "signer-not-ready" | "amount-invalid" | "recipient-unresolved" | "no-source" | "no-asset" | "asset-unnamed";
715
720
  /**
716
721
  * One Budget the member can spend from — the id the payment carries, and
717
722
  * nothing else.
@@ -771,7 +776,7 @@ interface CapxulSendMoneyProps {
771
776
  readonly onFailed: (error: CapxulError) => void;
772
777
  readonly children: ReactNode;
773
778
  }
774
- declare function Root$4({ actor, onSent, onFailed, children }: CapxulSendMoneyProps): import("react/jsx-runtime").JSX.Element;
779
+ declare function Root$5({ actor, onSent, onFailed, children }: CapxulSendMoneyProps): import("react/jsx-runtime").JSX.Element;
775
780
  declare function Source({ children }: {
776
781
  readonly children: (slice: SendMoneySourceSlice) => ReactNode;
777
782
  }): import("react/jsx-runtime").JSX.Element;
@@ -788,7 +793,7 @@ declare function Actions$1({ children }: {
788
793
  readonly children: (slice: SendMoneyActionsSlice) => ReactNode;
789
794
  }): import("react/jsx-runtime").JSX.Element;
790
795
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
791
- declare const CapxulSendMoney: typeof Root$4 & {
796
+ declare const CapxulSendMoney: typeof Root$5 & {
792
797
  Source: typeof Source;
793
798
  Asset: typeof Asset$1;
794
799
  Amount: typeof Amount;
@@ -820,7 +825,7 @@ interface CapxulOrgMemberProps {
820
825
  readonly orgId: OrgId | string | undefined;
821
826
  readonly children: ReactNode;
822
827
  }
823
- declare function Root$3({ orgId, children }: CapxulOrgMemberProps): import("react/jsx-runtime").JSX.Element;
828
+ declare function Root$4({ orgId, children }: CapxulOrgMemberProps): import("react/jsx-runtime").JSX.Element;
824
829
  /**
825
830
  * One part serves all four denial idioms the app already uses: disabled with no
826
831
  * explanation, disabled plus a native `title`, a whole-surface swap, and
@@ -835,7 +840,7 @@ declare function Standing({ children }: {
835
840
  readonly children: (slice: OrgMemberStandingSlice) => ReactNode;
836
841
  }): import("react/jsx-runtime").JSX.Element;
837
842
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
838
- declare const CapxulOrgMember: typeof Root$3 & {
843
+ declare const CapxulOrgMember: typeof Root$4 & {
839
844
  Can: typeof Can;
840
845
  Standing: typeof Standing;
841
846
  };
@@ -871,9 +876,9 @@ interface CapxulDashboardAccessProps {
871
876
  readonly scope: DashboardScope;
872
877
  readonly children: ReactNode;
873
878
  }
874
- declare function Root$2({ scope, children }: CapxulDashboardAccessProps): import("react/jsx-runtime").JSX.Element;
879
+ declare function Root$3({ scope, children }: CapxulDashboardAccessProps): import("react/jsx-runtime").JSX.Element;
875
880
  /** Hands nothing — today's app renders `null` here, exactly as it does now. */
876
- declare function Checking({ children }: {
881
+ declare function Checking$1({ children }: {
877
882
  readonly children?: ReactNode;
878
883
  }): import("react/jsx-runtime").JSX.Element | null;
879
884
  declare function DashboardError({ children }: {
@@ -892,8 +897,8 @@ declare function Granted({ children }: {
892
897
  readonly children?: ReactNode;
893
898
  }): import("react/jsx-runtime").JSX.Element | null;
894
899
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
895
- declare const CapxulDashboardAccess: typeof Root$2 & {
896
- Checking: typeof Checking;
900
+ declare const CapxulDashboardAccess: typeof Root$3 & {
901
+ Checking: typeof Checking$1;
897
902
  Error: typeof DashboardError;
898
903
  Redirect: typeof Redirect;
899
904
  Granted: typeof Granted;
@@ -941,7 +946,7 @@ interface CapxulPayrollProps {
941
946
  readonly orgId: OrgId | undefined;
942
947
  readonly children: ReactNode;
943
948
  }
944
- declare function Root$1({ orgId, children }: CapxulPayrollProps): import("react/jsx-runtime").JSX.Element;
949
+ declare function Root$2({ orgId, children }: CapxulPayrollProps): import("react/jsx-runtime").JSX.Element;
945
950
  declare function Summary$1({ children }: {
946
951
  readonly children: (slice: PayrollSummarySlice) => ReactNode;
947
952
  }): import("react/jsx-runtime").JSX.Element;
@@ -953,7 +958,7 @@ declare function Groups({ children }: {
953
958
  * There is NO `.Runs` part (ruling Q6): no shipped region has the right shape
954
959
  * for a run list, and a part without a production caller may not ship.
955
960
  */
956
- declare const CapxulPayroll: typeof Root$1 & {
961
+ declare const CapxulPayroll: typeof Root$2 & {
957
962
  Summary: typeof Summary$1;
958
963
  Groups: typeof Groups;
959
964
  };
@@ -975,10 +980,10 @@ interface PayrollRecipientOption {
975
980
  //#region src/headless/payroll/use-payroll-run.d.ts
976
981
  /**
977
982
  * Refusal CODES, never sentences (ADR-0023 R1). `blockedReason` names the FIRST
978
- * false fact in the fixed order of the contract's seven-row table, so the same
979
- * composer state always yields the same code.
983
+ * false fact in the fixed order below, so the same composer state always
984
+ * yields the same code.
980
985
  */
981
- type CapxulPayrollRunBlockedReason = "signer-not-ready" | "no-source" | "ambiguous-source" | "no-asset" | "no-recipients" | "amount-invalid" | "insufficient-funds";
986
+ type CapxulPayrollRunBlockedReason = "signer-not-ready" | "no-source" | "ambiguous-source" | "no-asset" | "no-recipients" | "amount-invalid" | "insufficient-funds" | "asset-unnamed";
982
987
  interface PayrollRunGroupOption {
983
988
  readonly id: PayrollGroupId;
984
989
  readonly label: string;
@@ -1058,7 +1063,7 @@ interface CapxulPayrollRunProps {
1058
1063
  readonly onFailed: (error: CapxulError) => void;
1059
1064
  readonly children: ReactNode;
1060
1065
  }
1061
- declare function Root({ orgId, prefill, onRun, onFailed, children }: CapxulPayrollRunProps): import("react/jsx-runtime").JSX.Element;
1066
+ declare function Root$1({ orgId, prefill, onRun, onFailed, children }: CapxulPayrollRunProps): import("react/jsx-runtime").JSX.Element;
1062
1067
  declare function Recipients({ children }: {
1063
1068
  readonly children: (slice: PayrollRunRecipientsSlice) => ReactNode;
1064
1069
  }): import("react/jsx-runtime").JSX.Element;
@@ -1075,7 +1080,7 @@ declare function Actions({ children }: {
1075
1080
  readonly children: (slice: PayrollRunActionsSlice) => ReactNode;
1076
1081
  }): import("react/jsx-runtime").JSX.Element;
1077
1082
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
1078
- declare const CapxulPayrollRun: typeof Root & {
1083
+ declare const CapxulPayrollRun: typeof Root$1 & {
1079
1084
  Recipients: typeof Recipients;
1080
1085
  Amounts: typeof Amounts;
1081
1086
  Asset: typeof Asset;
@@ -1083,6 +1088,64 @@ declare const CapxulPayrollRun: typeof Root & {
1083
1088
  Actions: typeof Actions;
1084
1089
  };
1085
1090
  //#endregion
1091
+ //#region src/headless/client-connection/use-client-connection.d.ts
1092
+ interface OtpSlice {
1093
+ readonly email: string;
1094
+ readonly pending: boolean;
1095
+ readonly canResend: boolean;
1096
+ readonly verifyCode: (code: string) => Promise<void>;
1097
+ readonly resend: () => Promise<void>;
1098
+ }
1099
+ interface ConsentSlice {
1100
+ readonly verifiedEmail: string;
1101
+ readonly clientLabel: string;
1102
+ readonly scopeCodes: readonly string[];
1103
+ readonly purpose: "login" | "signup";
1104
+ readonly setupState: "not_required" | "new" | "resumable";
1105
+ readonly pending: boolean;
1106
+ readonly accept: () => Promise<void>;
1107
+ readonly cancel: () => Promise<void>;
1108
+ }
1109
+ interface CompleteSlice {
1110
+ readonly outcome: "connected";
1111
+ }
1112
+ interface FailureSlice {
1113
+ readonly code: string;
1114
+ readonly field?: string;
1115
+ readonly retry: () => Promise<void>;
1116
+ readonly cancel: () => Promise<void>;
1117
+ }
1118
+ //#endregion
1119
+ //#region src/headless/client-connection/client-connection.d.ts
1120
+ interface CapxulClientConnectionProps {
1121
+ readonly client: CapxulClient;
1122
+ readonly requestId: string;
1123
+ readonly children: ReactNode;
1124
+ }
1125
+ declare function Root({ client, requestId, children }: CapxulClientConnectionProps): import("react/jsx-runtime").JSX.Element;
1126
+ declare function Checking({ children }: {
1127
+ readonly children: ReactNode;
1128
+ }): import("react/jsx-runtime").JSX.Element | null;
1129
+ declare function Otp({ children }: {
1130
+ readonly children: (slice: OtpSlice) => ReactNode;
1131
+ }): import("react/jsx-runtime").JSX.Element | null;
1132
+ declare function Consent({ children }: {
1133
+ readonly children: (slice: ConsentSlice) => ReactNode;
1134
+ }): import("react/jsx-runtime").JSX.Element | null;
1135
+ declare function Complete({ children }: {
1136
+ readonly children: (slice: CompleteSlice) => ReactNode;
1137
+ }): import("react/jsx-runtime").JSX.Element | null;
1138
+ declare function Failure({ children }: {
1139
+ readonly children: (slice: FailureSlice) => ReactNode;
1140
+ }): import("react/jsx-runtime").JSX.Element | null;
1141
+ declare const CapxulClientConnection: typeof Root & {
1142
+ Checking: typeof Checking;
1143
+ Otp: typeof Otp;
1144
+ Consent: typeof Consent;
1145
+ Complete: typeof Complete;
1146
+ Failure: typeof Failure;
1147
+ };
1148
+ //#endregion
1086
1149
  //#region src/internal/reactivity-keys.d.ts
1087
1150
  declare const capxulKeys: {
1088
1151
  root: readonly ["capxul"];
@@ -1113,4 +1176,4 @@ declare const capxulKeys: {
1113
1176
  payment: (paymentId: string | undefined) => readonly ["capxul", "payments", string];
1114
1177
  };
1115
1178
  //#endregion
1116
- export { type AccountFailure, type AccountProgress, type ActionResult, type ActivityDetailSlice, type ActivityExportSlice, type ActivityFilterValues, type ActivityFiltersSlice, type ActivityLoadMoreSlice, type ActivityReceipt, type ActivityRow, type ActivityRowsSlice, type ActivitySearchSlice, type ActivitySummarySlice, type AuthenticatedState, type AuthenticationSlots, type CanReason, CapxulActivity, type CapxulActivityProps, type CapxulAuth, CapxulAuthenticationController, type CapxulBootstrapState, type CapxulBootstrapStatus, CapxulContacts, type CapxulContactsProps, CapxulDashboardAccess, type CapxulDashboardAccessProps, CapxulOnboardingController, CapxulOrgMember, type CapxulOrgMemberProps, CapxulPayroll, type CapxulPayrollProps, CapxulPayrollRun, type CapxulPayrollRunBlockedReason, type CapxulPayrollRunProps, CapxulProvider, type CapxulProviderProps, type CapxulSend, CapxulSendMoney, type CapxulSendMoneyBlockedReason, type CapxulSendMoneyProps, type Contact, type ContactRelationship, type ContactRow, type ContactsActor, type ContactsAddBlockedReason, type ContactsAddError, type ContactsAddSlice, type ContactsListOptions, type ContactsListSlice, type ContactsRefusal, type ContactsSummarySlice, type ControllerAction, type CreateOrganizationFailure, type CreateOrganizationSubmission, type CsvExport, type DashboardAccessErrorSlice, type DashboardAccessPhase, type DashboardAccessProbe, type DashboardAccessRedirectSlice, type DashboardScope, type Destination, type FaultedState, type HandleAvailability, type ImageUploadInput, type ImageUploadTarget, type InvocationOptions, type NavigationAction, type OnboardingControllerProps, type OnboardingIntent, type OnboardingJourney, type OnboardingJourneyPosition, type OnboardingOrigin, type OnboardingStep, type OrgFailure, type OrgMemberAction, type OrgMemberCanSlice, type OrgMemberStanding, type OrgMemberStandingSlice, type OrgProgress, type OrganizationDetails, type OrganizationDraft, type OtpPendingState, type PayoutDraftChain, type PayoutDraftEntry, type PayrollGroupRow, type PayrollGroupsSlice, type PayrollRecipientOption, type PayrollRunActionsSlice, type PayrollRunAmountEntry, type PayrollRunAmountsSlice, type PayrollRunAssetSlice, type PayrollRunGroupOption, type PayrollRunPrefill, type PayrollRunRecipientsSlice, type PayrollRunStatus, type PayrollRunSummarySlice, type PayrollSummarySlice, type PendingAuthState, type ProfileDetails, type ProfileDraft, type ProfileSlotProps, type ReadyDestination, type RetryAction, type SendActor, type SendMoneyActionsSlice, type SendMoneyAmountSlice, type SendMoneyAssetError, type SendMoneyAssetOption, type SendMoneyAssetSlice, type SendMoneyRecipientSlice, type SendMoneyRecipientStatus, type SendMoneySourceError, type SendMoneySourceOption, type SendMoneySourceSlice, type SendResult, type SentPayment, type SentPayrollRun, type SignedOutState, type Slot, type SummaryWindow, type UseCapxulAccountBalanceOptions, type UseCapxulAccountBalanceReturn, type UseCapxulAccountFundReturn, type UseCapxulCreateCommitmentReturn, type UseCapxulCreateOrgReturn, type UseCapxulHandleAvailabilityReturn, type UseCapxulImageUploadReturn, type UseCapxulInviteMemberInput, type UseCapxulInviteMemberReturn, type UseCapxulOrgMembersOptions, type UseCapxulOrgMembersReturn, type UseCapxulOrgRolesOptions, type UseCapxulOrgRolesReturn, type UseCapxulOrgTreasuryOptions, type UseCapxulOrgTreasuryReturn, type UseCapxulOrgsReturn, type UseCapxulPayReturn, type UseCapxulPaymentReturn, type UseCapxulPaymentsReturn, type UseCapxulProfileReturn, type UseCapxulRedirectPaymentReturn, type UseCapxulUploadImageReturn, acknowledgeOnboardingDestination, activeOnboardingRecovery, capxulKeys, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, isClaimed, isRestoring, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHandleAvailability, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions, useCapxulUploadImage };
1179
+ export { type AccountFailure, type AccountProgress, type ActionResult, type ActivityDetailSlice, type ActivityExportSlice, type ActivityFilterValues, type ActivityFiltersSlice, type ActivityLoadMoreSlice, type ActivityReceipt, type ActivityRow, type ActivityRowsSlice, type ActivitySearchSlice, type ActivitySummarySlice, type AuthenticatedState, type AuthenticationSlots, type CanReason, CapxulActivity, type CapxulActivityProps, type CapxulAuth, CapxulAuthenticationController, type CapxulBootstrapState, type CapxulBootstrapStatus, CapxulClientConnection, type CapxulClientConnectionProps, CapxulContacts, type CapxulContactsProps, CapxulDashboardAccess, type CapxulDashboardAccessProps, CapxulOnboardingController, CapxulOrgMember, type CapxulOrgMemberProps, CapxulPayroll, type CapxulPayrollProps, CapxulPayrollRun, type CapxulPayrollRunBlockedReason, type CapxulPayrollRunProps, CapxulProvider, type CapxulProviderProps, type CapxulSend, CapxulSendMoney, type CapxulSendMoneyBlockedReason, type CapxulSendMoneyProps, type CompleteSlice as ClientConnectionCompleteSlice, type ConsentSlice as ClientConnectionConsentSlice, type FailureSlice as ClientConnectionFailureSlice, type OtpSlice as ClientConnectionOtpSlice, type Contact, type ContactRelationship, type ContactRow, type ContactsActor, type ContactsAddBlockedReason, type ContactsAddError, type ContactsAddSlice, type ContactsListOptions, type ContactsListSlice, type ContactsRefusal, type ContactsSummarySlice, type ControllerAction, type CreateOrganizationFailure, type CreateOrganizationSubmission, type CsvExport, type DashboardAccessErrorSlice, type DashboardAccessPhase, type DashboardAccessProbe, type DashboardAccessRedirectSlice, type DashboardScope, type Destination, type FaultedState, type HandleAvailability, type ImageUploadInput, type ImageUploadTarget, type InvocationOptions, type NavigationAction, type OnboardingControllerProps, type OnboardingIntent, type OnboardingJourney, type OnboardingJourneyPosition, type OnboardingOrigin, type OnboardingStep, type OrgFailure, type OrgMemberAction, type OrgMemberCanSlice, type OrgMemberStanding, type OrgMemberStandingSlice, type OrgProgress, type OrganizationDetails, type OrganizationDraft, type OtpPendingState, type PayoutDraftChain, type PayoutDraftEntry, type PayrollGroupRow, type PayrollGroupsSlice, type PayrollRecipientOption, type PayrollRunActionsSlice, type PayrollRunAmountEntry, type PayrollRunAmountsSlice, type PayrollRunAssetSlice, type PayrollRunGroupOption, type PayrollRunPrefill, type PayrollRunRecipientsSlice, type PayrollRunStatus, type PayrollRunSummarySlice, type PayrollSummarySlice, type PendingAuthState, type ProfileDetails, type ProfileDraft, type ProfileSlotProps, type ReadyDestination, type RetryAction, type SendActor, type SendMoneyActionsSlice, type SendMoneyAmountSlice, type SendMoneyAssetError, type SendMoneyAssetOption, type SendMoneyAssetSlice, type SendMoneyRecipientSlice, type SendMoneyRecipientStatus, type SendMoneySourceError, type SendMoneySourceOption, type SendMoneySourceSlice, type SendResult, type SentPayment, type SentPayrollRun, type SignedOutState, type Slot, type SummaryWindow, type UseCapxulAccountBalanceOptions, type UseCapxulAccountBalanceReturn, type UseCapxulAccountFundReturn, type UseCapxulCreateCommitmentReturn, type UseCapxulCreateOrgReturn, type UseCapxulHandleAvailabilityReturn, type UseCapxulImageUploadReturn, type UseCapxulInviteMemberInput, type UseCapxulInviteMemberReturn, type UseCapxulOrgMembersOptions, type UseCapxulOrgMembersReturn, type UseCapxulOrgRolesOptions, type UseCapxulOrgRolesReturn, type UseCapxulOrgTreasuryOptions, type UseCapxulOrgTreasuryReturn, type UseCapxulOrgsReturn, type UseCapxulPayReturn, type UseCapxulPaymentReturn, type UseCapxulPaymentsReturn, type UseCapxulProfileReturn, type UseCapxulRedirectPaymentReturn, type UseCapxulUploadImageReturn, acknowledgeOnboardingDestination, activeOnboardingRecovery, capxulKeys, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, isClaimed, isRestoring, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHandleAvailability, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions, useCapxulUploadImage };
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { _ as useCapxul, a as useCapxulAuth, c as useCapxulIdentityOrNull, d as toInvocationControls, f as toInvocationOptions, g as useCapxulClientOrNull, h as capxulKeys, i as entered, l as useCapxulSend, m as actingAccount, n as CapxulOnboardingController, o as useCapxulDestination, p as accountKey, r as CapxulProvider, s as useCapxulIdentity, t as CapxulAuthenticationController, u as useCapxulTransitions } from "./controllers-DXmEHrnw.mjs";
2
+ import { _ as useCapxul, a as useCapxulAuth, c as useCapxulIdentityOrNull, d as toInvocationControls, f as toInvocationOptions, g as useCapxulClientOrNull, h as capxulKeys, i as entered, l as useCapxulSend, m as actingAccount, n as CapxulOnboardingController, o as useCapxulDestination, p as accountKey, r as CapxulProvider, s as useCapxulIdentity, t as CapxulAuthenticationController, u as useCapxulTransitions } from "./controllers-L1UqwWS1.mjs";
3
3
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
4
  import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
5
- import { CAPXUL_OPERATIONS, CapxulError, EVM_ADDRESS_RE, Errors, HANDLE_RE, PAYMENT_DIRECTIONS, PAYMENT_STATUSES, fingerprintPaymentIntent, formatMoney, isCapxulError, isClaimed, isClaimed as isClaimed$1, isMoneyParseError, isRestoring, isRestoring as isRestoring$1, parseMoney, paymentPhase, resolveIdentityDestination, toEvmAddress, toPartyId } from "@capxul/sdk";
5
+ import { CAPXUL_OPERATIONS, CapxulError, EVM_ADDRESS_RE, Errors, HANDLE_RE, PAYMENT_DIRECTIONS, PAYMENT_STATUSES, fingerprintPaymentIntent, formatAssetAmount, formatMoney, isCapxulError, isClaimed, isClaimed as isClaimed$1, isMoneyParseError, isRestoring, isRestoring as isRestoring$1, parseMoney, paymentPhase, positionPeg, resolveIdentityDestination, toEvmAddress, toPartyId } from "@capxul/sdk";
6
6
  import { Fragment, jsx } from "react/jsx-runtime";
7
7
  //#region src/internal/require-bootstrapped-client.ts
8
8
  /**
@@ -1079,7 +1079,7 @@ function useContactsContext() {
1079
1079
  if (engine === null) throw new Error("CapxulContacts parts must be used inside <CapxulContacts>");
1080
1080
  return engine;
1081
1081
  }
1082
- function Root$6({ actor, onAdded, onFailed, children }) {
1082
+ function Root$7({ actor, onAdded, onFailed, children }) {
1083
1083
  const engine = useContacts({
1084
1084
  actor,
1085
1085
  onAdded,
@@ -1103,7 +1103,7 @@ function Add({ children }) {
1103
1103
  return /* @__PURE__ */ jsx(Fragment, { children: children(useContactsContext().add) });
1104
1104
  }
1105
1105
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
1106
- const CapxulContacts = Object.assign(Root$6, {
1106
+ const CapxulContacts = Object.assign(Root$7, {
1107
1107
  Summary: Summary$3,
1108
1108
  List,
1109
1109
  Add
@@ -1283,14 +1283,9 @@ function compareNet(left, right) {
1283
1283
  return scaledLeft < scaledRight ? -1 : 1;
1284
1284
  }
1285
1285
  /**
1286
- * Which currency `.Summary` shows: the bucket matching the primary holding's
1287
- * currency, else the bucket with the largest absolute `net`, breaking a tie on
1288
- * currency code ascending so the choice is stable across reloads.
1289
- *
1290
- * The primary holding is matched on `available.currency` — the consumer
1291
- * `CurrencyCode` — and NOT on `Holding.symbol`, which is the raw token ticker
1292
- * ("USDX") and can never equal a bucket's currency ("USD"). See the contract
1293
- * correction on #1449.
1286
+ * Which currency `.Summary` shows: the bucket matching `primaryCurrency` when
1287
+ * one is given, else the bucket with the largest absolute `net`, breaking a tie
1288
+ * on currency code ascending so the choice is stable across reloads.
1294
1289
  */
1295
1290
  function pickBucket(totals, primaryCurrency) {
1296
1291
  if (primaryCurrency !== null) {
@@ -1363,13 +1358,8 @@ function useActivitySummary(actor, window) {
1363
1358
  enabled
1364
1359
  });
1365
1360
  const totals = summary.data?.totals;
1366
- const primaryCurrency = primary.data?.available.currency ?? null;
1367
1361
  const isLoading = summary.isLoading || primary.isLoading;
1368
- const bucket = useMemo(() => totals === void 0 || isLoading ? null : pickBucket(totals, primaryCurrency), [
1369
- isLoading,
1370
- primaryCurrency,
1371
- totals
1372
- ]);
1362
+ const bucket = useMemo(() => totals === void 0 || isLoading ? null : pickBucket(totals, null), [isLoading, totals]);
1373
1363
  if (bucket === null) return {
1374
1364
  currency: null,
1375
1365
  moneyIn: null,
@@ -1789,7 +1779,7 @@ function useActivityContext() {
1789
1779
  if (engine === null) throw new Error("CapxulActivity parts must be used inside <CapxulActivity>");
1790
1780
  return engine;
1791
1781
  }
1792
- function Root$5({ actor, pageSize, children }) {
1782
+ function Root$6({ actor, pageSize, children }) {
1793
1783
  const engine = useActivity({
1794
1784
  ...actor === void 0 ? {} : { actor },
1795
1785
  ...pageSize === void 0 ? {} : { pageSize }
@@ -1840,7 +1830,7 @@ function Export({ children }) {
1840
1830
  return /* @__PURE__ */ jsx(Fragment, { children: children(useActivityContext().csv) });
1841
1831
  }
1842
1832
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
1843
- const CapxulActivity = Object.assign(Root$5, {
1833
+ const CapxulActivity = Object.assign(Root$6, {
1844
1834
  Summary: Summary$2,
1845
1835
  Filters,
1846
1836
  Search,
@@ -1881,6 +1871,25 @@ function useOrgMeReading(orgId) {
1881
1871
  ]);
1882
1872
  }
1883
1873
  //#endregion
1874
+ //#region src/internal/write-names-asset.ts
1875
+ /**
1876
+ * Identity law 5 (`docs/campaigns/capabilities/treasury-cut/HANDOFF.md`): "A
1877
+ * payment names an asset or inherits it from an authorized fact. Missing asset
1878
+ * refuses."
1879
+ *
1880
+ * A Capxul payment writer takes `PaymentMoney` — a peg currency, a value and
1881
+ * `decimals` — and settles one fixed legacy token. No `AssetId` crosses that
1882
+ * seam, so a payment composed from a named position cannot name the asset it
1883
+ * moves: a position selected as USDT authorizes a different token.
1884
+ *
1885
+ * `false` until slice 02 (`02-named-pay`) makes the writer take the command's
1886
+ * asset. The Send and Payroll composers read this to refuse a submission
1887
+ * rather than authorize a token the person did not pick.
1888
+ */
1889
+ function writeNamesAsset() {
1890
+ return false;
1891
+ }
1892
+ //#endregion
1884
1893
  //#region src/headless/send-money/signer-status.ts
1885
1894
  const NO_SUBSCRIPTION = () => () => {};
1886
1895
  function useSignerStatus(client) {
@@ -2030,6 +2039,39 @@ function useSelectedOption(options) {
2030
2039
  }, [options]);
2031
2040
  return [options.find((option) => option.id === selectedId) ?? null, select];
2032
2041
  }
2042
+ /**
2043
+ * One Send `.Asset` option per position the Account holds, taken from
2044
+ * `account.balances` — never from `account.available`, which is the Account's
2045
+ * fiat VALUATION of those positions (ADR-0028 R5/R6). Labelling the valuation
2046
+ * was the false identity this cut removes, and it collapsed USDC+USDT into one
2047
+ * "USD" row.
2048
+ *
2049
+ * The option is keyed on the ASSET id, never the symbol and never the account:
2050
+ * several positions share one account id, and a symbol is display only
2051
+ * (ADR-0028 R3). Every row is listed, so a real multi-position Account still
2052
+ * offers its holdings.
2053
+ */
2054
+ function assetSelectionsFromAccount$1(account) {
2055
+ if (account === null) return [];
2056
+ return account.balances.map((position) => {
2057
+ const peg = positionPeg(position.asset);
2058
+ return {
2059
+ option: {
2060
+ id: position.asset,
2061
+ symbol: position.symbol,
2062
+ availableDisplay: formatAssetAmount({
2063
+ asset: position.asset,
2064
+ value: position.available
2065
+ })
2066
+ },
2067
+ money: peg === null ? null : {
2068
+ currency: peg,
2069
+ value: position.available,
2070
+ decimals: position.decimals
2071
+ }
2072
+ };
2073
+ });
2074
+ }
2033
2075
  function useSendMoney(input) {
2034
2076
  const { actor, onSent, onFailed } = input;
2035
2077
  const client = useCapxulClientOrNull();
@@ -2042,13 +2084,10 @@ function useSendMoney(input) {
2042
2084
  const treasury = useCapxulOrgTreasury(orgId, { enabled: actor.kind === "organization" });
2043
2085
  const accountQuery = actor.kind === "personal" ? balance : treasury;
2044
2086
  const account = accountQuery.data ?? null;
2045
- const assetOptions = useMemo(() => account === null ? [] : [{
2046
- id: account.id,
2047
- symbol: account.available.currency,
2048
- availableDisplay: formatMoney(account.available, { grammar: "code" })
2049
- }], [account]);
2087
+ const assetSelections = useMemo(() => assetSelectionsFromAccount$1(account), [account]);
2088
+ const assetOptions = useMemo(() => assetSelections.map((selection) => selection.option), [assetSelections]);
2050
2089
  const [selectedAssetOption, selectAsset] = useSelectedOption(assetOptions);
2051
- const selectedAssetMoney = selectedAssetOption !== null && account !== null ? account.available : null;
2090
+ const selectedAssetMoney = useMemo(() => assetSelections.find((selection) => selection.option.id === selectedAssetOption?.id)?.money ?? null, [assetSelections, selectedAssetOption]);
2052
2091
  const [amountText, setAmountText] = useState("");
2053
2092
  const parsed = useMemo(() => selectedAssetMoney === null || amountText.trim() === "" ? null : parseMoney(amountText, selectedAssetMoney), [amountText, selectedAssetMoney]);
2054
2093
  const parsedMoney = parsed !== null && !isMoneyParseError(parsed) ? parsed : null;
@@ -2062,7 +2101,7 @@ function useSendMoney(input) {
2062
2101
  const personalPay = useCapxulPay();
2063
2102
  const organizationPay = useCapxulOrganizationPay(orgId);
2064
2103
  const pay = actor.kind === "personal" ? personalPay : organizationPay;
2065
- const blockedReason = signerStatus !== "ready" ? "signer-not-ready" : actor.kind === "organization" && selectedSource === null ? "no-source" : selectedAssetOption === null ? "no-asset" : parsedMoney === null ? "amount-invalid" : resolvedReference === null ? "recipient-unresolved" : null;
2104
+ const blockedReason = signerStatus !== "ready" ? "signer-not-ready" : actor.kind === "organization" && selectedSource === null ? "no-source" : selectedAssetOption === null ? "no-asset" : parsedMoney === null ? "amount-invalid" : resolvedReference === null ? "recipient-unresolved" : writeNamesAsset() ? null : "asset-unnamed";
2066
2105
  const submitGate = useRef(false);
2067
2106
  const submit = useCallback(() => {
2068
2107
  if (blockedReason !== null || submitGate.current) return;
@@ -2149,7 +2188,7 @@ function useSendMoneyContext() {
2149
2188
  if (engine === null) throw new Error("CapxulSendMoney parts must be used inside <CapxulSendMoney>");
2150
2189
  return engine;
2151
2190
  }
2152
- function Root$4({ actor, onSent, onFailed, children }) {
2191
+ function Root$5({ actor, onSent, onFailed, children }) {
2153
2192
  const engine = useSendMoney({
2154
2193
  actor,
2155
2194
  onSent,
@@ -2176,7 +2215,7 @@ function Actions$1({ children }) {
2176
2215
  return /* @__PURE__ */ jsx(Fragment, { children: children(useSendMoneyContext().actions) });
2177
2216
  }
2178
2217
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
2179
- const CapxulSendMoney = Object.assign(Root$4, {
2218
+ const CapxulSendMoney = Object.assign(Root$5, {
2180
2219
  Source,
2181
2220
  Asset: Asset$1,
2182
2221
  Amount,
@@ -2266,7 +2305,7 @@ function useOrgMemberContext() {
2266
2305
  if (state === null) throw new Error("CapxulOrgMember parts must be used inside <CapxulOrgMember>");
2267
2306
  return state;
2268
2307
  }
2269
- function Root$3({ orgId, children }) {
2308
+ function Root$4({ orgId, children }) {
2270
2309
  const state = useOrgMember(orgId);
2271
2310
  return /* @__PURE__ */ jsx(OrgMemberContext.Provider, {
2272
2311
  value: state,
@@ -2286,7 +2325,7 @@ function Standing({ children }) {
2286
2325
  return /* @__PURE__ */ jsx(Fragment, { children: children(useOrgMemberContext().standing) });
2287
2326
  }
2288
2327
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
2289
- const CapxulOrgMember = Object.assign(Root$3, {
2328
+ const CapxulOrgMember = Object.assign(Root$4, {
2290
2329
  Can,
2291
2330
  Standing
2292
2331
  });
@@ -2446,7 +2485,7 @@ function usePart(phase) {
2446
2485
  }, [placed, phase]);
2447
2486
  return state.phase === phase ? state : null;
2448
2487
  }
2449
- function Root$2({ scope, children }) {
2488
+ function Root$3({ scope, children }) {
2450
2489
  const state = useDashboardAccess(scope);
2451
2490
  const [placed] = useState(() => /* @__PURE__ */ new Set());
2452
2491
  const value = useMemo(() => ({
@@ -2464,7 +2503,7 @@ function Root$2({ scope, children }) {
2464
2503
  });
2465
2504
  }
2466
2505
  /** Hands nothing — today's app renders `null` here, exactly as it does now. */
2467
- function Checking({ children }) {
2506
+ function Checking$1({ children }) {
2468
2507
  return usePart("checking") === null ? null : /* @__PURE__ */ jsx(Fragment, { children });
2469
2508
  }
2470
2509
  function DashboardError({ children }) {
@@ -2491,8 +2530,8 @@ function Granted({ children }) {
2491
2530
  return usePart("granted") === null ? null : /* @__PURE__ */ jsx(Fragment, { children });
2492
2531
  }
2493
2532
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
2494
- const CapxulDashboardAccess = Object.assign(Root$2, {
2495
- Checking,
2533
+ const CapxulDashboardAccess = Object.assign(Root$3, {
2534
+ Checking: Checking$1,
2496
2535
  Error: DashboardError,
2497
2536
  Redirect,
2498
2537
  Granted
@@ -2792,7 +2831,7 @@ function usePayrollContext() {
2792
2831
  if (engine === null) throw new Error("CapxulPayroll parts must be used inside <CapxulPayroll>");
2793
2832
  return engine;
2794
2833
  }
2795
- function Root$1({ orgId, children }) {
2834
+ function Root$2({ orgId, children }) {
2796
2835
  const engine = usePayroll(orgId);
2797
2836
  return /* @__PURE__ */ jsx(PayrollContext.Provider, {
2798
2837
  value: engine,
@@ -2810,7 +2849,7 @@ function Groups({ children }) {
2810
2849
  * There is NO `.Runs` part (ruling Q6): no shipped region has the right shape
2811
2850
  * for a run list, and a part without a production caller may not ship.
2812
2851
  */
2813
- const CapxulPayroll = Object.assign(Root$1, {
2852
+ const CapxulPayroll = Object.assign(Root$2, {
2814
2853
  Summary: Summary$1,
2815
2854
  Groups
2816
2855
  });
@@ -2820,8 +2859,14 @@ function record(value) {
2820
2859
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw Errors.invalidInput("payrollDraft", "Invalid run draft");
2821
2860
  return value;
2822
2861
  }
2862
+ /**
2863
+ * A draft-scoped opaque key. `/` is in the class so `asset.id` can be the
2864
+ * canonical CAIP-19 `AssetId` (`eip155:<chainId>/erc20:<address>`): the draft
2865
+ * records WHICH asset was authorized, and a symbol is not an identity
2866
+ * (ADR-0028 R3). The field never reaches the backend — only `input` is sent.
2867
+ */
2823
2868
  function identifier(value) {
2824
- if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u.test(value)) throw Errors.invalidInput("payrollDraft", "Invalid draft identifier");
2869
+ if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/u.test(value)) throw Errors.invalidInput("payrollDraft", "Invalid draft identifier");
2825
2870
  return value;
2826
2871
  }
2827
2872
  function minorAmount(value) {
@@ -3120,6 +3165,35 @@ function initialAmounts(prefill) {
3120
3165
  };
3121
3166
  return seeded;
3122
3167
  }
3168
+ /**
3169
+ * One `.Asset` option per position the treasury Account holds, taken from
3170
+ * `account.balances` — never from `account.available`, which is the Account's
3171
+ * fiat VALUATION of those positions (ADR-0028 R5/R6). The option is keyed on
3172
+ * the ASSET id: several positions share one account id, and a symbol is display
3173
+ * only (ADR-0028 R3). Every row is listed, so a real multi-position treasury
3174
+ * still offers its holdings.
3175
+ */
3176
+ function assetSelectionsFromAccount(account) {
3177
+ if (account === null) return [];
3178
+ return account.balances.map((position) => {
3179
+ const peg = positionPeg(position.asset);
3180
+ return {
3181
+ option: {
3182
+ id: position.asset,
3183
+ symbol: position.symbol,
3184
+ availableDisplay: formatAssetAmount({
3185
+ asset: position.asset,
3186
+ value: position.available
3187
+ })
3188
+ },
3189
+ money: peg === null ? null : {
3190
+ currency: peg,
3191
+ value: position.available,
3192
+ decimals: position.decimals
3193
+ }
3194
+ };
3195
+ });
3196
+ }
3123
3197
  function usePayrollRun(input) {
3124
3198
  const { orgId, prefill, onRun, onFailed } = input;
3125
3199
  const client = useCapxulClientOrNull();
@@ -3183,11 +3257,8 @@ function usePayrollRun(input) {
3183
3257
  draftError
3184
3258
  ]);
3185
3259
  const account = treasury.data ?? null;
3186
- const assetOptions = useMemo(() => account === null ? [] : [{
3187
- id: account.id,
3188
- symbol: account.available.currency,
3189
- availableDisplay: formatMoney(account.available, GRAMMAR)
3190
- }], [account]);
3260
+ const assetSelections = useMemo(() => assetSelectionsFromAccount(account), [account]);
3261
+ const assetOptions = useMemo(() => assetSelections.map((selection) => selection.option), [assetSelections]);
3191
3262
  const [selectedAssetId, setSelectedAssetId] = useState(null);
3192
3263
  useEffect(() => {
3193
3264
  if (!assetOptions.some((option) => option.id === selectedAssetId)) setSelectedAssetId(assetOptions[0]?.id ?? null);
@@ -3196,7 +3267,7 @@ function usePayrollRun(input) {
3196
3267
  const selectAsset = useCallback((id) => {
3197
3268
  if (!submitGate.current && !frozen) setSelectedAssetId((current) => assetOptions.some((option) => option.id === id) ? id : current);
3198
3269
  }, [assetOptions, frozen]);
3199
- const assetMoney = selectedAsset !== null && account !== null ? account.available : null;
3270
+ const assetMoney = assetSelections.find((selection) => selection.option.id === selectedAsset?.id)?.money ?? null;
3200
3271
  const named = useMemo(() => new Map(roster.options.map((option) => [option.id, option])), [roster.options]);
3201
3272
  const refs = roster.refs;
3202
3273
  const payableRefs = useMemo(() => {
@@ -3256,7 +3327,8 @@ function usePayrollRun(input) {
3256
3327
  signerReady: signerStatus === "ready",
3257
3328
  ...runAuthorityFacts(draft, budgets, selectedAsset, assetMoney, funds),
3258
3329
  recipientCount: payableRefs === null ? 0 : selected.length,
3259
- amountsParse: total !== null
3330
+ amountsParse: total !== null,
3331
+ writeNamesAsset: writeNamesAsset()
3260
3332
  });
3261
3333
  const authorize = useMutation({
3262
3334
  mutationFn: async ({ candidate, options }) => {
@@ -3412,7 +3484,7 @@ function runAuthorityFacts(draft, budgets, asset, money, funds) {
3412
3484
  };
3413
3485
  }
3414
3486
  /**
3415
- * The seven facts, in the ONE order the contract fixes. Exactly one code comes
3487
+ * The facts, in the ONE order the contract fixes. Exactly one code comes
3416
3488
  * out, and it is always the first thing that is false — so two problems never
3417
3489
  * race to name the button.
3418
3490
  */
@@ -3423,7 +3495,8 @@ function firstFalseFact(facts) {
3423
3495
  if (!facts.hasAsset) return "no-asset";
3424
3496
  if (facts.recipientCount === 0) return "no-recipients";
3425
3497
  if (!facts.amountsParse) return "amount-invalid";
3426
- return facts.funds === "insufficient" ? "insufficient-funds" : null;
3498
+ if (facts.funds === "insufficient") return "insufficient-funds";
3499
+ return facts.writeNamesAsset ? null : "asset-unnamed";
3427
3500
  }
3428
3501
  //#endregion
3429
3502
  //#region src/headless/payroll/payroll-run.tsx
@@ -3433,7 +3506,7 @@ function usePayrollRunContext() {
3433
3506
  if (engine === null) throw new Error("CapxulPayrollRun parts must be used inside <CapxulPayrollRun>");
3434
3507
  return engine;
3435
3508
  }
3436
- function Root({ orgId, prefill, onRun, onFailed, children }) {
3509
+ function Root$1({ orgId, prefill, onRun, onFailed, children }) {
3437
3510
  const engine = usePayrollRun({
3438
3511
  orgId,
3439
3512
  prefill,
@@ -3463,7 +3536,7 @@ function Actions({ children }) {
3463
3536
  return /* @__PURE__ */ jsx(Fragment, { children: children(engine.actions) });
3464
3537
  }
3465
3538
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
3466
- const CapxulPayrollRun = Object.assign(Root, {
3539
+ const CapxulPayrollRun = Object.assign(Root$1, {
3467
3540
  Recipients,
3468
3541
  Amounts,
3469
3542
  Asset,
@@ -3471,4 +3544,230 @@ const CapxulPayrollRun = Object.assign(Root, {
3471
3544
  Actions
3472
3545
  });
3473
3546
  //#endregion
3474
- export { CapxulActivity, CapxulAuthenticationController, CapxulContacts, CapxulDashboardAccess, CapxulOnboardingController, CapxulOrgMember, CapxulPayroll, CapxulPayrollRun, CapxulProvider, CapxulSendMoney, acknowledgeOnboardingDestination, activeOnboardingRecovery, capxulKeys, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, isClaimed, isRestoring, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHandleAvailability, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions, useCapxulUploadImage };
3547
+ //#region src/headless/client-connection/use-client-connection.ts
3548
+ function useClientConnection(input) {
3549
+ const [view, setView] = useState(null);
3550
+ const [pending, setPending] = useState(false);
3551
+ const [error, setError] = useState(null);
3552
+ const [resendReady, setResendReady] = useState(false);
3553
+ const identityRef = useRef({
3554
+ client: input.client,
3555
+ requestId: input.requestId
3556
+ });
3557
+ identityRef.current = {
3558
+ client: input.client,
3559
+ requestId: input.requestId
3560
+ };
3561
+ const belongsHere = useCallback((client, requestId) => identityRef.current.client === client && identityRef.current.requestId === requestId, []);
3562
+ const refresh = useCallback(async (signal) => {
3563
+ const { client, requestId } = identityRef.current;
3564
+ const result = await client.auth.clientRequests.read({ requestId }, signal === void 0 ? void 0 : { signal });
3565
+ if (signal?.aborted || !belongsHere(client, requestId)) return;
3566
+ if (result.ok) {
3567
+ setView(result.value);
3568
+ setError(null);
3569
+ return;
3570
+ }
3571
+ setError(result.error);
3572
+ }, [belongsHere]);
3573
+ useEffect(() => {
3574
+ setView(null);
3575
+ setError(null);
3576
+ setPending(false);
3577
+ setResendReady(false);
3578
+ const controller = new AbortController();
3579
+ refresh(controller.signal);
3580
+ return () => {
3581
+ controller.abort();
3582
+ };
3583
+ }, [
3584
+ input.client,
3585
+ input.requestId,
3586
+ refresh
3587
+ ]);
3588
+ useEffect(() => {
3589
+ if (view?.phase !== "otp_required") {
3590
+ setResendReady(false);
3591
+ return;
3592
+ }
3593
+ const remaining = view.resendAt - Date.now();
3594
+ if (remaining <= 0) {
3595
+ setResendReady(true);
3596
+ return;
3597
+ }
3598
+ setResendReady(false);
3599
+ const timer = setTimeout(() => setResendReady(true), remaining);
3600
+ return () => clearTimeout(timer);
3601
+ }, [view]);
3602
+ const run = useCallback(async (work) => {
3603
+ const { client, requestId } = identityRef.current;
3604
+ setPending(true);
3605
+ try {
3606
+ const result = await work();
3607
+ if (!belongsHere(client, requestId)) return;
3608
+ if (!result.ok) {
3609
+ setError(result.error);
3610
+ return;
3611
+ }
3612
+ await refresh();
3613
+ } finally {
3614
+ if (belongsHere(client, requestId)) setPending(false);
3615
+ }
3616
+ }, [belongsHere, refresh]);
3617
+ return useMemo(() => {
3618
+ if (error !== null && (view === null || view.phase !== "refused")) return {
3619
+ phase: "failure",
3620
+ otp: null,
3621
+ consent: null,
3622
+ complete: null,
3623
+ failure: {
3624
+ code: error.code,
3625
+ retry: () => refresh(),
3626
+ cancel: async () => {
3627
+ if (view === null) return;
3628
+ const { client, requestId } = identityRef.current;
3629
+ await run(() => client.auth.clientRequests.cancel({
3630
+ requestId,
3631
+ revision: view.revision
3632
+ }));
3633
+ }
3634
+ }
3635
+ };
3636
+ if (view === null) return {
3637
+ phase: "checking",
3638
+ otp: null,
3639
+ consent: null,
3640
+ complete: null,
3641
+ failure: null
3642
+ };
3643
+ if (view.phase === "otp_required") return {
3644
+ phase: view.phase,
3645
+ otp: {
3646
+ email: view.email,
3647
+ pending,
3648
+ canResend: resendReady,
3649
+ verifyCode: async (code) => {
3650
+ const { client, requestId } = identityRef.current;
3651
+ await run(() => client.auth.clientRequests.verifyOtp({
3652
+ requestId,
3653
+ code
3654
+ }));
3655
+ },
3656
+ resend: async () => {
3657
+ const { client, requestId } = identityRef.current;
3658
+ await run(() => client.auth.clientRequests.sendOtp({ requestId }));
3659
+ }
3660
+ },
3661
+ consent: null,
3662
+ complete: null,
3663
+ failure: null
3664
+ };
3665
+ if (view.phase === "review") return {
3666
+ phase: view.phase,
3667
+ otp: null,
3668
+ consent: {
3669
+ verifiedEmail: view.email,
3670
+ clientLabel: view.clientLabel,
3671
+ scopeCodes: view.scopes,
3672
+ purpose: view.intent.mode,
3673
+ setupState: view.setupState,
3674
+ pending,
3675
+ accept: async () => {
3676
+ const { client, requestId } = identityRef.current;
3677
+ await run(() => client.auth.clientRequests.accept({
3678
+ requestId,
3679
+ revision: view.revision
3680
+ }));
3681
+ },
3682
+ cancel: async () => {
3683
+ const { client, requestId } = identityRef.current;
3684
+ await run(() => client.auth.clientRequests.cancel({
3685
+ requestId,
3686
+ revision: view.revision
3687
+ }));
3688
+ }
3689
+ },
3690
+ complete: null,
3691
+ failure: null
3692
+ };
3693
+ if (view.phase === "connected") return {
3694
+ phase: view.phase,
3695
+ otp: null,
3696
+ consent: null,
3697
+ complete: { outcome: "connected" },
3698
+ failure: null
3699
+ };
3700
+ if (view.phase === "refused") return {
3701
+ phase: view.phase,
3702
+ otp: null,
3703
+ consent: null,
3704
+ complete: null,
3705
+ failure: {
3706
+ code: view.code,
3707
+ ...view.field === void 0 ? {} : { field: view.field },
3708
+ retry: () => refresh(),
3709
+ cancel: async () => void 0
3710
+ }
3711
+ };
3712
+ return {
3713
+ phase: view.phase,
3714
+ otp: null,
3715
+ consent: null,
3716
+ complete: null,
3717
+ failure: null
3718
+ };
3719
+ }, [
3720
+ error,
3721
+ pending,
3722
+ refresh,
3723
+ resendReady,
3724
+ run,
3725
+ view
3726
+ ]);
3727
+ }
3728
+ //#endregion
3729
+ //#region src/headless/client-connection/client-connection.tsx
3730
+ const ConnectionContext = createContext(null);
3731
+ function useConnection() {
3732
+ const engine = useContext(ConnectionContext);
3733
+ if (engine === null) throw new Error("CapxulClientConnection parts must be used inside <CapxulClientConnection>");
3734
+ return engine;
3735
+ }
3736
+ function Root({ client, requestId, children }) {
3737
+ const engine = useClientConnection({
3738
+ client,
3739
+ requestId
3740
+ });
3741
+ return /* @__PURE__ */ jsx(ConnectionContext.Provider, {
3742
+ value: engine,
3743
+ children
3744
+ });
3745
+ }
3746
+ function Checking({ children }) {
3747
+ return useConnection().phase === "checking" ? /* @__PURE__ */ jsx(Fragment, { children }) : null;
3748
+ }
3749
+ function Otp({ children }) {
3750
+ const otp = useConnection().otp;
3751
+ return otp === null ? null : /* @__PURE__ */ jsx(Fragment, { children: children(otp) });
3752
+ }
3753
+ function Consent({ children }) {
3754
+ const consent = useConnection().consent;
3755
+ return consent === null ? null : /* @__PURE__ */ jsx(Fragment, { children: children(consent) });
3756
+ }
3757
+ function Complete({ children }) {
3758
+ const complete = useConnection().complete;
3759
+ return complete === null ? null : /* @__PURE__ */ jsx(Fragment, { children: children(complete) });
3760
+ }
3761
+ function Failure({ children }) {
3762
+ const failure = useConnection().failure;
3763
+ return failure === null ? null : /* @__PURE__ */ jsx(Fragment, { children: children(failure) });
3764
+ }
3765
+ const CapxulClientConnection = Object.assign(Root, {
3766
+ Checking,
3767
+ Otp,
3768
+ Consent,
3769
+ Complete,
3770
+ Failure
3771
+ });
3772
+ //#endregion
3773
+ export { CapxulActivity, CapxulAuthenticationController, CapxulClientConnection, CapxulContacts, CapxulDashboardAccess, CapxulOnboardingController, CapxulOrgMember, CapxulPayroll, CapxulPayrollRun, CapxulProvider, CapxulSendMoney, acknowledgeOnboardingDestination, activeOnboardingRecovery, capxulKeys, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, isClaimed, isRestoring, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHandleAvailability, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions, useCapxulUploadImage };
@@ -1,4 +1,4 @@
1
- import { n as CapxulOnboardingController, r as CapxulProvider, t as CapxulAuthenticationController } from "../controllers-DXmEHrnw.mjs";
1
+ import { n as CapxulOnboardingController, r as CapxulProvider, t as CapxulAuthenticationController } from "../controllers-L1UqwWS1.mjs";
2
2
  import "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  import { createCapxulTestClient } from "@capxul/sdk/testing";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capxul/sdk-react",
3
- "version": "4.20.0-beta.4",
3
+ "version": "4.20.0-beta.5",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Xelmar-tech/infrastructure.git",
@@ -26,7 +26,7 @@
26
26
  "access": "public"
27
27
  },
28
28
  "dependencies": {
29
- "@capxul/sdk": "4.20.0-beta.4"
29
+ "@capxul/sdk": "4.20.0-beta.5"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@tanstack/react-query": "^5.66.9",