@capxul/sdk-react 2.2.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -82,7 +82,7 @@ type OtpPendingState = Extract<IdentityState, {
82
82
  phase: "otp_pending";
83
83
  }>;
84
84
  type PendingAuthState = Extract<IdentityState, {
85
- phase: "otp_sending" | "otp_verifying" | "signing_out";
85
+ phase: "restoring" | "otp_sending" | "otp_verifying" | "signing_out";
86
86
  }>;
87
87
  type FaultedState = Extract<IdentityState, {
88
88
  phase: "faulted";
@@ -80,6 +80,18 @@ const capxulKeys = {
80
80
  orgId ?? "pending",
81
81
  "permissions"
82
82
  ],
83
+ orgMe: (orgId) => [
84
+ "capxul",
85
+ "org",
86
+ orgId ?? "pending",
87
+ "me"
88
+ ],
89
+ orgLifecycle: (orgId) => [
90
+ "capxul",
91
+ "org",
92
+ orgId ?? "pending",
93
+ "lifecycle"
94
+ ],
83
95
  contacts: (scope) => [
84
96
  "capxul",
85
97
  "contacts",
@@ -594,6 +606,7 @@ function CapxulAuthenticationController({ slots }) {
594
606
  verifyCode: auth.verifyCode,
595
607
  back: () => action(send, { _tag: "Reset" })
596
608
  });
609
+ case "restoring":
597
610
  case "otp_sending":
598
611
  case "otp_verifying":
599
612
  case "signing_out": return slots.pending({ state });
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { A as useCapxulAuth, C as CreateOrganizationSubmission, D as ProfileDetails, E as OrganizationDetails, M as useCapxulIdentity, N as useCapxulSend, O as SendResult, P as useCapxulTransitions, S as CapxulSend, T as InvocationOptions, _ as ReadyDestination, a as AuthenticationSlots, b as Slot, c as ControllerAction, d as OnboardingControllerProps, f as OrgFailure, g as ProfileSlotProps, h as PendingAuthState, i as AuthenticatedState, j as useCapxulDestination, k as entered, l as FaultedState, m as OtpPendingState, n as AccountProgress, o as CapxulAuthenticationController, p as OrgProgress, r as ActionResult, s as CapxulOnboardingController, t as AccountFailure, u as NavigationAction, v as RetryAction, w as Destination, x as CapxulAuth, y as SignedOutState } from "./controllers-D3_Q5d2t.mjs";
1
+ import { A as useCapxulAuth, C as CreateOrganizationSubmission, D as ProfileDetails, E as OrganizationDetails, M as useCapxulIdentity, N as useCapxulSend, O as SendResult, P as useCapxulTransitions, S as CapxulSend, T as InvocationOptions, _ as ReadyDestination, a as AuthenticationSlots, b as Slot, c as ControllerAction, d as OnboardingControllerProps, f as OrgFailure, g as ProfileSlotProps, h as PendingAuthState, i as AuthenticatedState, j as useCapxulDestination, k as entered, l as FaultedState, m as OtpPendingState, n as AccountProgress, o as CapxulAuthenticationController, p as OrgProgress, r as ActionResult, s as CapxulOnboardingController, t as AccountFailure, u as NavigationAction, v as RetryAction, w as Destination, x as CapxulAuth, y as SignedOutState } from "./controllers-BT4YzBr9.mjs";
2
2
  import { ReactNode } from "react";
3
3
  import { QueryClient, UseMutationResult, UseQueryResult } from "@tanstack/react-query";
4
- import { Account, AccountRequirement, ActivityAnnotationInput, ActivityDetail, ActivityListParams, ActivityPage, ActivityReference, AddressBookEntry, CapxulClient, CapxulError, CapxulSigner, CreateOrgInput, CurrentHoldings, HostObservability, InviteMemberInput, MemberView, Money, MoneyParseErrorReason, MovementAnnotation, OrgId, OrgView, OrganizationPaymentBatchInput, OrganizationPaymentInput, PartyId, Payment, PaymentTiming, PaymentsPayInput, Permission, PermissionReadResult, Profile, RoleView } from "@capxul/sdk";
4
+ import { Account, AccountRequirement, ActivityAnnotationInput, ActivityDetail, ActivityListParams, ActivityPage, ActivityReference, AddressBookEntry, CapxulClient, CapxulError, CapxulSigner, CreateOrgInput, CurrentHoldings, HostObservability, IdentityDestination, InviteMemberInput, MemberView, Money, MoneyParseErrorReason, MovementAnnotation, OrgId, OrgView, OrganizationPaymentBatchInput, OrganizationPaymentInput, PartyId, Payment, PaymentTiming, PaymentsPayInput, Permission, PermissionReadResult, Profile, RoleView, isClaimed, isRestoring } from "@capxul/sdk";
5
5
 
6
6
  //#region src/provider.d.ts
7
7
  type CapxulProviderSharedProps = {
@@ -600,7 +600,7 @@ interface CapxulContactsProps {
600
600
  readonly onFailed: (error: CapxulError) => void;
601
601
  readonly children: ReactNode;
602
602
  }
603
- declare function Root$1({
603
+ declare function Root$3({
604
604
  actor,
605
605
  onAdded,
606
606
  onFailed,
@@ -624,7 +624,7 @@ declare function Add({
624
624
  readonly children: (slice: ContactsAddSlice) => ReactNode;
625
625
  }): import("react/jsx-runtime").JSX.Element;
626
626
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
627
- declare const CapxulContacts: typeof Root$1 & {
627
+ declare const CapxulContacts: typeof Root$3 & {
628
628
  Summary: typeof Summary;
629
629
  List: typeof List;
630
630
  Add: typeof Add;
@@ -695,7 +695,7 @@ interface CapxulSendMoneyProps {
695
695
  readonly onFailed: (error: CapxulError) => void;
696
696
  readonly children: ReactNode;
697
697
  }
698
- declare function Root({
698
+ declare function Root$2({
699
699
  actor,
700
700
  onSent,
701
701
  onFailed,
@@ -722,11 +722,116 @@ declare function Actions({
722
722
  readonly children: (slice: SendMoneyActionsSlice) => ReactNode;
723
723
  }): import("react/jsx-runtime").JSX.Element;
724
724
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
725
- declare const CapxulSendMoney: typeof Root & {
725
+ declare const CapxulSendMoney: typeof Root$2 & {
726
726
  Asset: typeof Asset;
727
727
  Amount: typeof Amount;
728
728
  Recipient: typeof Recipient;
729
729
  Actions: typeof Actions;
730
730
  };
731
731
  //#endregion
732
- export { type AccountFailure, type AccountProgress, type ActionResult, type AuthenticatedState, type AuthenticationSlots, type CapxulAuth, CapxulAuthenticationController, type CapxulBootstrapState, type CapxulBootstrapStatus, CapxulContacts, type CapxulContactsProps, CapxulOnboardingController, 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 CreateOrganizationSubmission, type Destination, type FaultedState, type ImageUploadInput, type ImageUploadTarget, type InvocationOptions, type NavigationAction, type OnboardingControllerProps, type OnboardingIntent, type OnboardingJourney, type OnboardingJourneyPosition, type OnboardingOrigin, type OnboardingStep, type OrgFailure, type OrgProgress, type OrganizationDetails, type OrganizationDraft, type OtpPendingState, type PayoutDraftChain, type PayoutDraftEntry, 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 SendMoneyRecipientMethod, type SendMoneyRecipientSlice, type SendMoneyRecipientStatus, type SendResult, type SentPayment, type SignedOutState, type Slot, type UseCapxulAccountBalanceOptions, type UseCapxulAccountBalanceReturn, type UseCapxulAccountFundReturn, type UseCapxulCreateCommitmentReturn, type UseCapxulCreateOrgReturn, type UseCapxulImageUploadReturn, 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 UseCapxulUsernameAvailabilityReturn, type UsernameAvailability, acknowledgeOnboardingDestination, activeOnboardingRecovery, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions, useCapxulUsernameAvailability };
732
+ //#region src/headless/access/org-member.d.ts
733
+ /** The two enforcement facts, named the way a screen asks for them. */
734
+ type OrgMemberAction = "spend" | "managePeople";
735
+ /**
736
+ * Why an action is refused — a closed list of CODES (ruling R1). `null` exactly
737
+ * when the action is allowed. The app owns every sentence these map to.
738
+ */
739
+ type CanReason = "loading" | "no-permission" | "org-unavailable" | null;
740
+ interface OrgMemberCanSlice {
741
+ /** FAILS CLOSED: `false` until the read settles. */
742
+ readonly allowed: boolean;
743
+ readonly isLoading: boolean;
744
+ readonly reason: CanReason;
745
+ }
746
+ type OrgMemberStanding = "loading" | "unavailable" | "active" | "restricted";
747
+ interface OrgMemberStandingSlice {
748
+ readonly standing: OrgMemberStanding;
749
+ /** `standing === "active"` guarantees this is non-null — see the rule below. */
750
+ readonly roleLabel: string | null;
751
+ }
752
+ interface CapxulOrgMemberProps {
753
+ readonly orgId: OrgId | string | undefined;
754
+ readonly children: ReactNode;
755
+ }
756
+ declare function Root$1({
757
+ orgId,
758
+ children
759
+ }: CapxulOrgMemberProps): import("react/jsx-runtime").JSX.Element;
760
+ /**
761
+ * One part serves all four denial idioms the app already uses: disabled with no
762
+ * explanation, disabled plus a native `title`, a whole-surface swap, and
763
+ * buttons that vanish. The part branches on nothing — the root computes both
764
+ * slices and this picks the one the `do` prop names.
765
+ */
766
+ declare function Can({
767
+ do: action,
768
+ children
769
+ }: {
770
+ readonly do: OrgMemberAction;
771
+ readonly children: (slice: OrgMemberCanSlice) => ReactNode;
772
+ }): import("react/jsx-runtime").JSX.Element;
773
+ declare function Standing({
774
+ children
775
+ }: {
776
+ readonly children: (slice: OrgMemberStandingSlice) => ReactNode;
777
+ }): import("react/jsx-runtime").JSX.Element;
778
+ /** The compound shape the app's own design system already uses (`StatusTabs`). */
779
+ declare const CapxulOrgMember: typeof Root$1 & {
780
+ Can: typeof Can;
781
+ Standing: typeof Standing;
782
+ };
783
+ //#endregion
784
+ //#region src/headless/access/dashboard-access.d.ts
785
+ type DashboardScope = {
786
+ readonly kind: "personal";
787
+ } | {
788
+ readonly kind: "organization";
789
+ readonly orgId?: string;
790
+ };
791
+ type DashboardAccessPhase = "checking" | "error" | "redirect" | "granted";
792
+ interface DashboardAccessErrorSlice {
793
+ readonly error: CapxulError;
794
+ /** Re-runs each failed probe. */
795
+ readonly retry: () => void;
796
+ }
797
+ interface DashboardAccessRedirectSlice {
798
+ readonly destination: IdentityDestination;
799
+ }
800
+ interface CapxulDashboardAccessProps {
801
+ readonly scope: DashboardScope;
802
+ readonly children: ReactNode;
803
+ }
804
+ declare function Root({
805
+ scope,
806
+ children
807
+ }: CapxulDashboardAccessProps): import("react/jsx-runtime").JSX.Element;
808
+ /** Hands nothing — today's app renders `null` here, exactly as it does now. */
809
+ declare function Checking({
810
+ children
811
+ }: {
812
+ readonly children?: ReactNode;
813
+ }): import("react/jsx-runtime").JSX.Element | null;
814
+ declare function DashboardError({
815
+ children
816
+ }: {
817
+ readonly children: (slice: DashboardAccessErrorSlice) => ReactNode;
818
+ }): import("react/jsx-runtime").JSX.Element | null;
819
+ declare function Redirect({
820
+ children
821
+ }: {
822
+ readonly children: (slice: DashboardAccessRedirectSlice) => ReactNode;
823
+ }): import("react/jsx-runtime").JSX.Element | null;
824
+ declare function Granted({
825
+ children
826
+ }: {
827
+ readonly children?: ReactNode;
828
+ }): import("react/jsx-runtime").JSX.Element | null;
829
+ /** The compound shape the app's own design system already uses (`StatusTabs`). */
830
+ declare const CapxulDashboardAccess: typeof Root & {
831
+ Checking: typeof Checking;
832
+ Error: typeof DashboardError;
833
+ Redirect: typeof Redirect;
834
+ Granted: typeof Granted;
835
+ };
836
+ //#endregion
837
+ export { type AccountFailure, type AccountProgress, type ActionResult, type AuthenticatedState, type AuthenticationSlots, type CanReason, type CapxulAuth, CapxulAuthenticationController, type CapxulBootstrapState, type CapxulBootstrapStatus, CapxulContacts, type CapxulContactsProps, CapxulDashboardAccess, type CapxulDashboardAccessProps, CapxulOnboardingController, CapxulOrgMember, type CapxulOrgMemberProps, 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 CreateOrganizationSubmission, type DashboardAccessErrorSlice, type DashboardAccessPhase, type DashboardAccessRedirectSlice, type DashboardScope, type Destination, type FaultedState, 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 PendingAuthState, type ProfileDetails, type ProfileDraft, type ProfileSlotProps, type ReadyDestination, type RetryAction, type SendActor, type SendMoneyActionsSlice, type SendMoneyAmountSlice, type SendMoneyAssetError, type SendMoneyAssetOption, type SendMoneyAssetSlice, type SendMoneyRecipientMethod, type SendMoneyRecipientSlice, type SendMoneyRecipientStatus, type SendResult, type SentPayment, type SignedOutState, type Slot, type UseCapxulAccountBalanceOptions, type UseCapxulAccountBalanceReturn, type UseCapxulAccountFundReturn, type UseCapxulCreateCommitmentReturn, type UseCapxulCreateOrgReturn, type UseCapxulImageUploadReturn, 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 UseCapxulUsernameAvailabilityReturn, type UsernameAvailability, acknowledgeOnboardingDestination, activeOnboardingRecovery, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, isClaimed, isRestoring, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions, useCapxulUsernameAvailability };
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { a as useCapxulAuth, c as useCapxulIdentityOrNull, d as capxulKeys, f as useCapxulClientOrNull, i as entered, l as useCapxulSend, n as CapxulOnboardingController, o as useCapxulDestination, p as useCapxul, r as CapxulProvider, s as useCapxulIdentity, t as CapxulAuthenticationController, u as useCapxulTransitions } from "./controllers-ClhmseFL.mjs";
2
+ import { a as useCapxulAuth, c as useCapxulIdentityOrNull, d as capxulKeys, f as useCapxulClientOrNull, i as entered, l as useCapxulSend, n as CapxulOnboardingController, o as useCapxulDestination, p as useCapxul, r as CapxulProvider, s as useCapxulIdentity, t as CapxulAuthenticationController, u as useCapxulTransitions } from "./controllers-VwUPB619.mjs";
3
3
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
4
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
5
- import { Errors, fingerprintPaymentIntent, formatMoney, isMoneyParseError, parseMoney } from "@capxul/sdk";
5
+ import { CapxulError, Errors, fingerprintPaymentIntent, formatMoney, isClaimed, isClaimed as isClaimed$1, isMoneyParseError, isRestoring, isRestoring as isRestoring$1, parseMoney, resolveIdentityDestination } from "@capxul/sdk";
6
6
  import { Fragment, jsx } from "react/jsx-runtime";
7
7
  //#region src/internal/require-bootstrapped-client.ts
8
8
  /**
@@ -306,7 +306,7 @@ function useCapxulPayments(options) {
306
306
  queryFn: async () => {
307
307
  return unwrapCapxulResult(await requireBootstrappedClient(client, "payments.list").payments.list());
308
308
  },
309
- enabled: client !== null && identity?.phase === "authenticated" && identity.account.at === "claimed" && (options?.enabled ?? true)
309
+ enabled: client !== null && identity !== null && isClaimed$1(identity) && (options?.enabled ?? true)
310
310
  });
311
311
  }
312
312
  function useCapxulPayment(paymentId, options) {
@@ -396,12 +396,13 @@ const useCapxulPermissionRevoke = (orgId) => usePermissionMutation(orgId, "revok
396
396
  const useCapxulPermissionReplace = (orgId) => usePermissionMutation(orgId, "replace");
397
397
  function useCapxulPermissions(orgId, options) {
398
398
  const client = useCapxulClientOrNull();
399
+ const identity = useCapxulIdentityOrNull();
399
400
  return useQuery({
400
401
  queryKey: capxulKeys.orgPermissions(orgId),
401
402
  queryFn: async () => {
402
403
  return unwrapCapxulResult(await requireBootstrappedClient(client, "permissions.list").org(orgId).permissions.list());
403
404
  },
404
- enabled: client !== null && (options?.enabled ?? true)
405
+ enabled: client !== null && identity !== null && isClaimed$1(identity) && (options?.enabled ?? true)
405
406
  });
406
407
  }
407
408
  function useCapxulPermission(orgId, permissionId) {
@@ -425,7 +426,7 @@ function useCapxulActivity(params) {
425
426
  queryFn: async () => {
426
427
  return unwrapCapxulResult(await requireBootstrappedClient(client, "activity.list").activity.list(params));
427
428
  },
428
- enabled: client !== null && identity?.phase === "authenticated" && identity.account.at === "claimed"
429
+ enabled: client !== null && identity !== null && isClaimed$1(identity)
429
430
  });
430
431
  }
431
432
  function useCapxulActivityDetail(reference) {
@@ -437,7 +438,7 @@ function useCapxulActivityDetail(reference) {
437
438
  if (reference === void 0) throw Errors.invalidInput("reference", "required for activity.get");
438
439
  return unwrapCapxulResult(await requireBootstrappedClient(client, "activity.get").activity.get(reference));
439
440
  },
440
- enabled: client !== null && reference !== void 0 && identity?.phase === "authenticated" && identity.account.at === "claimed"
441
+ enabled: client !== null && reference !== void 0 && identity !== null && isClaimed$1(identity)
441
442
  });
442
443
  }
443
444
  function useCapxulAnnotateMovement() {
@@ -460,7 +461,7 @@ function useCapxulHoldings() {
460
461
  queryFn: async () => {
461
462
  return unwrapCapxulResult(await requireBootstrappedClient(client, "holdings.current").holdings.current());
462
463
  },
463
- enabled: client !== null && identity?.phase === "authenticated" && identity.account.at === "claimed"
464
+ enabled: client !== null && identity !== null && isClaimed$1(identity)
464
465
  });
465
466
  }
466
467
  //#endregion
@@ -1012,7 +1013,7 @@ function useContactsContext() {
1012
1013
  if (engine === null) throw new Error("CapxulContacts parts must be used inside <CapxulContacts>");
1013
1014
  return engine;
1014
1015
  }
1015
- function Root$1({ actor, onAdded, onFailed, children }) {
1016
+ function Root$3({ actor, onAdded, onFailed, children }) {
1016
1017
  const engine = useContacts({
1017
1018
  actor,
1018
1019
  onAdded,
@@ -1036,7 +1037,7 @@ function Add({ children }) {
1036
1037
  return /* @__PURE__ */ jsx(Fragment, { children: children(useContactsContext().add) });
1037
1038
  }
1038
1039
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
1039
- const CapxulContacts = Object.assign(Root$1, {
1040
+ const CapxulContacts = Object.assign(Root$3, {
1040
1041
  Summary,
1041
1042
  List,
1042
1043
  Add
@@ -1204,7 +1205,7 @@ function useSendMoneyContext() {
1204
1205
  if (engine === null) throw new Error("CapxulSendMoney parts must be used inside <CapxulSendMoney>");
1205
1206
  return engine;
1206
1207
  }
1207
- function Root({ actor, onSent, onFailed, children }) {
1208
+ function Root$2({ actor, onSent, onFailed, children }) {
1208
1209
  const engine = useSendMoney({
1209
1210
  actor,
1210
1211
  onSent,
@@ -1228,11 +1229,331 @@ function Actions({ children }) {
1228
1229
  return /* @__PURE__ */ jsx(Fragment, { children: children(useSendMoneyContext().actions) });
1229
1230
  }
1230
1231
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
1231
- const CapxulSendMoney = Object.assign(Root, {
1232
+ const CapxulSendMoney = Object.assign(Root$2, {
1232
1233
  Asset,
1233
1234
  Amount,
1234
1235
  Recipient,
1235
1236
  Actions
1236
1237
  });
1237
1238
  //#endregion
1238
- export { CapxulAuthenticationController, CapxulContacts, CapxulOnboardingController, CapxulProvider, CapxulSendMoney, acknowledgeOnboardingDestination, activeOnboardingRecovery, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions, useCapxulUsernameAvailability };
1239
+ //#region src/headless/access/org-member.tsx
1240
+ const DENIED_NO_ORG = {
1241
+ allowed: false,
1242
+ isLoading: false,
1243
+ reason: "org-unavailable"
1244
+ };
1245
+ const DENIED_LOADING = {
1246
+ allowed: false,
1247
+ isLoading: true,
1248
+ reason: "loading"
1249
+ };
1250
+ const ALLOWED = {
1251
+ allowed: true,
1252
+ isLoading: false,
1253
+ reason: null
1254
+ };
1255
+ const DENIED_NO_PERMISSION = {
1256
+ allowed: false,
1257
+ isLoading: false,
1258
+ reason: "no-permission"
1259
+ };
1260
+ function canSlice(reading, held) {
1261
+ switch (reading.kind) {
1262
+ case "no-org":
1263
+ case "unavailable": return DENIED_NO_ORG;
1264
+ case "loading": return DENIED_LOADING;
1265
+ case "ready": return held(reading.me) ? ALLOWED : DENIED_NO_PERMISSION;
1266
+ }
1267
+ }
1268
+ /**
1269
+ * The classification rule, derived line by line from the app's own expression
1270
+ * at `use-current-organization.ts:124-134`. Same order, same folds:
1271
+ *
1272
+ * | Test, in order | standing |
1273
+ * | ------------------------------------------- | -------------- |
1274
+ * | the `me()` read has not settled | `"loading"` |
1275
+ * | the read errored, or no `orgId` was given | `"unavailable"`|
1276
+ * | `role === null` | `"unavailable"`|
1277
+ * | `canManagePeople \|\| canSpend` | `"active"` |
1278
+ * | neither capability | `"restricted"` |
1279
+ *
1280
+ * `"unavailable"` folds TWO causes — a failed read and a member with no Role
1281
+ * label — exactly as today. And because the `role === null` test runs BEFORE
1282
+ * the capability test, `"active"` guarantees a non-null label, so no screen
1283
+ * needs a fallback word in that branch.
1284
+ */
1285
+ function standingSlice(reading) {
1286
+ if (reading.kind === "loading") return {
1287
+ standing: "loading",
1288
+ roleLabel: null
1289
+ };
1290
+ if (reading.kind !== "ready") return {
1291
+ standing: "unavailable",
1292
+ roleLabel: null
1293
+ };
1294
+ const { role, capabilities } = reading.me;
1295
+ if (role === null) return {
1296
+ standing: "unavailable",
1297
+ roleLabel: null
1298
+ };
1299
+ return {
1300
+ standing: capabilities.canManagePeople || capabilities.canSpend ? "active" : "restricted",
1301
+ roleLabel: role.label
1302
+ };
1303
+ }
1304
+ /** The engine — all the logic. NOT exported from the package barrel. */
1305
+ function useOrgMember(orgId) {
1306
+ const client = useCapxulClientOrNull();
1307
+ const identity = useCapxulIdentityOrNull();
1308
+ const ready = client !== null && identity !== null && isClaimed$1(identity);
1309
+ const mayStillOpen = client === null || identity === null || isRestoring$1(identity);
1310
+ const query = useQuery({
1311
+ queryKey: capxulKeys.orgMe(orgId),
1312
+ queryFn: async () => {
1313
+ return unwrapCapxulResult(await requireBootstrappedClient(client, "org.me").org(orgId).me());
1314
+ },
1315
+ enabled: ready && orgId !== void 0
1316
+ });
1317
+ const reading = useMemo(() => {
1318
+ if (orgId === void 0) return { kind: "no-org" };
1319
+ if (!ready) return { kind: mayStillOpen ? "loading" : "unavailable" };
1320
+ if (query.error !== null) return { kind: "unavailable" };
1321
+ if (query.data !== void 0) return {
1322
+ kind: "ready",
1323
+ me: query.data
1324
+ };
1325
+ return { kind: "loading" };
1326
+ }, [
1327
+ mayStillOpen,
1328
+ orgId,
1329
+ query.data,
1330
+ query.error,
1331
+ ready
1332
+ ]);
1333
+ return useMemo(() => ({
1334
+ can: {
1335
+ spend: canSlice(reading, (me) => me.capabilities.canSpend),
1336
+ managePeople: canSlice(reading, (me) => me.capabilities.canManagePeople)
1337
+ },
1338
+ standing: standingSlice(reading)
1339
+ }), [reading]);
1340
+ }
1341
+ const OrgMemberContext = createContext(null);
1342
+ function useOrgMemberContext() {
1343
+ const state = useContext(OrgMemberContext);
1344
+ if (state === null) throw new Error("CapxulOrgMember parts must be used inside <CapxulOrgMember>");
1345
+ return state;
1346
+ }
1347
+ function Root$1({ orgId, children }) {
1348
+ const state = useOrgMember(orgId);
1349
+ return /* @__PURE__ */ jsx(OrgMemberContext.Provider, {
1350
+ value: state,
1351
+ children
1352
+ });
1353
+ }
1354
+ /**
1355
+ * One part serves all four denial idioms the app already uses: disabled with no
1356
+ * explanation, disabled plus a native `title`, a whole-surface swap, and
1357
+ * buttons that vanish. The part branches on nothing — the root computes both
1358
+ * slices and this picks the one the `do` prop names.
1359
+ */
1360
+ function Can({ do: action, children }) {
1361
+ return /* @__PURE__ */ jsx(Fragment, { children: children(useOrgMemberContext().can[action]) });
1362
+ }
1363
+ function Standing({ children }) {
1364
+ return /* @__PURE__ */ jsx(Fragment, { children: children(useOrgMemberContext().standing) });
1365
+ }
1366
+ /** The compound shape the app's own design system already uses (`StatusTabs`). */
1367
+ const CapxulOrgMember = Object.assign(Root$1, {
1368
+ Can,
1369
+ Standing
1370
+ });
1371
+ //#endregion
1372
+ //#region src/headless/access/dashboard-access.tsx
1373
+ const PART_NAME = {
1374
+ checking: "Checking",
1375
+ error: "Error",
1376
+ redirect: "Redirect",
1377
+ granted: "Granted"
1378
+ };
1379
+ /**
1380
+ * Mirrors `publicIdentityFailure`, which is internal to `@capxul/sdk`
1381
+ * (`src/surface/_shared/effect-actor-bridge.ts`). The identity machine carries
1382
+ * its own failure representation; `.Error` hands a `CapxulError`, so the
1383
+ * projection happens once, here.
1384
+ */
1385
+ function identityError(state) {
1386
+ const { failure } = state;
1387
+ if (failure.error !== void 0) return failure.error;
1388
+ return new CapxulError(failure.code === "WORK_DIED" ? "UNKNOWN" : failure.code, failure.message, { layer: "identity" });
1389
+ }
1390
+ /**
1391
+ * Whether the Organization lane has reached a position that names a real
1392
+ * screen. `isRestoring` deliberately leaves this question to the gate (#1518),
1393
+ * because every org lane sits under a claimed account and `destination()`
1394
+ * already names a screen for each of its positions — except `loading`, which
1395
+ * means "still finding out" and whose destination is the provisioning screen.
1396
+ *
1397
+ * NEGATIVE classification, the same discipline `isRestoring` uses: only the
1398
+ * settled positions are enumerated, so a lane position added later HOLDS the
1399
+ * gate instead of bouncing a member who is in fact inside a ready Organization.
1400
+ * It gates the REDIRECT only, never the grant, so it can never blank a screen
1401
+ * the probes have already said yes to.
1402
+ */
1403
+ function isOrgLaneSettled(identity) {
1404
+ if (identity.phase !== "authenticated" || identity.account.at !== "claimed") return true;
1405
+ const org = identity.account.org;
1406
+ if (org === null) return true;
1407
+ switch (org.at) {
1408
+ case "ready":
1409
+ case "failed": return true;
1410
+ default: return false;
1411
+ }
1412
+ }
1413
+ /** Exactly the Organization asked for, and ready to be used. */
1414
+ function isExactOrgReady(lifecycle, orgId) {
1415
+ return lifecycle?.status === "ready" && String(lifecycle.orgId) === orgId;
1416
+ }
1417
+ function isLifecycleSettled(lifecycle) {
1418
+ return lifecycle?.status === "ready" || lifecycle?.status === "failed";
1419
+ }
1420
+ function destinationOrNull(identity) {
1421
+ return identity === null ? null : resolveIdentityDestination(identity);
1422
+ }
1423
+ function isClaimedOrFalse(identity) {
1424
+ return identity !== null && isClaimed$1(identity);
1425
+ }
1426
+ /**
1427
+ * The branch, as one pure decision over four settled facts.
1428
+ *
1429
+ * The order is the frozen one: an error wins over everything, an unsettled
1430
+ * probe holds, and only then does the judgment speak. The last two arms are the
1431
+ * whole bug class the deleted app guard kept re-fixing — a destination is
1432
+ * obeyed only once every lane that could still change it has settled, and
1433
+ * anything else HOLDS rather than guessing.
1434
+ */
1435
+ function decidePhase(input) {
1436
+ if (input.error !== null) return "error";
1437
+ if (!input.settled) return "checking";
1438
+ if (input.granted) return "granted";
1439
+ if (input.orgLaneSettled && input.destination !== null) return "redirect";
1440
+ return "checking";
1441
+ }
1442
+ /** The engine — all the logic. NOT exported from the package barrel. */
1443
+ function useDashboardAccess(scope) {
1444
+ const client = useCapxulClientOrNull();
1445
+ const identity = useCapxulIdentityOrNull();
1446
+ const destination = useMemo(() => destinationOrNull(identity), [identity]);
1447
+ const orgId = scope.kind === "organization" ? scope.orgId : void 0;
1448
+ const claimed = isClaimedOrFalse(identity);
1449
+ const sessionError = useMemo(() => identity?.phase === "faulted" ? identityError(identity) : null, [identity]);
1450
+ const wantsMemberships = orgId !== void 0 && claimed;
1451
+ const memberships = useCapxulOrgs({ enabled: wantsMemberships });
1452
+ const membershipError = wantsMemberships ? memberships.error : null;
1453
+ const membershipsSettled = !wantsMemberships || memberships.data !== void 0 || membershipError !== null;
1454
+ const hasMembership = orgId !== void 0 && (memberships.data ?? []).some((organization) => String(organization.id) === orgId);
1455
+ const wantsLifecycle = wantsMemberships && membershipsSettled && hasMembership;
1456
+ const lifecycle = useQuery({
1457
+ queryKey: capxulKeys.orgLifecycle(orgId),
1458
+ queryFn: async () => {
1459
+ return unwrapCapxulResult(await requireBootstrappedClient(client, "org.getLifecycle").org(orgId).getLifecycle());
1460
+ },
1461
+ enabled: wantsLifecycle && client !== null
1462
+ });
1463
+ const lifecycleError = wantsLifecycle ? lifecycle.error : null;
1464
+ const lifecycleSettled = !wantsLifecycle || lifecycleError !== null || isLifecycleSettled(lifecycle.data);
1465
+ const retry = useCallback(() => {
1466
+ if (sessionError !== null && client !== null) client.auth.getSession();
1467
+ if (membershipError !== null) memberships.refetch();
1468
+ if (lifecycleError !== null) lifecycle.refetch();
1469
+ }, [
1470
+ client,
1471
+ sessionError,
1472
+ membershipError,
1473
+ lifecycleError,
1474
+ memberships.refetch,
1475
+ lifecycle.refetch
1476
+ ]);
1477
+ const error = sessionError ?? membershipError ?? lifecycleError;
1478
+ const phase = decidePhase({
1479
+ error,
1480
+ settled: client !== null && identity !== null && !isRestoring$1(identity) && membershipsSettled && lifecycleSettled,
1481
+ granted: scope.kind === "personal" ? claimed : claimed && orgId !== void 0 && hasMembership && isExactOrgReady(lifecycle.data, orgId),
1482
+ orgLaneSettled: identity !== null && isOrgLaneSettled(identity),
1483
+ destination
1484
+ });
1485
+ return useMemo(() => ({
1486
+ phase,
1487
+ error,
1488
+ destination,
1489
+ retry
1490
+ }), [
1491
+ phase,
1492
+ error,
1493
+ destination,
1494
+ retry
1495
+ ]);
1496
+ }
1497
+ const DashboardAccessContext = createContext(null);
1498
+ function useDashboardAccessContext() {
1499
+ const value = useContext(DashboardAccessContext);
1500
+ if (value === null) throw new Error("CapxulDashboardAccess parts must be used inside <CapxulDashboardAccess>");
1501
+ return value;
1502
+ }
1503
+ /** A part's own turn, and its registration for the missing-part warning. */
1504
+ function usePart(phase) {
1505
+ const { state, placed } = useDashboardAccessContext();
1506
+ useEffect(() => {
1507
+ placed.add(phase);
1508
+ return () => {
1509
+ placed.delete(phase);
1510
+ };
1511
+ }, [placed, phase]);
1512
+ return state.phase === phase ? state : null;
1513
+ }
1514
+ function Root({ scope, children }) {
1515
+ const state = useDashboardAccess(scope);
1516
+ const [placed] = useState(() => /* @__PURE__ */ new Set());
1517
+ const value = useMemo(() => ({
1518
+ state,
1519
+ placed
1520
+ }), [state, placed]);
1521
+ useEffect(() => {
1522
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") return;
1523
+ if (placed.has(state.phase)) return;
1524
+ console.warn(`<CapxulDashboardAccess> reached "${state.phase}" but no <CapxulDashboardAccess.${PART_NAME[state.phase]}> is placed, so nothing renders.`);
1525
+ }, [placed, state.phase]);
1526
+ return /* @__PURE__ */ jsx(DashboardAccessContext.Provider, {
1527
+ value,
1528
+ children
1529
+ });
1530
+ }
1531
+ /** Hands nothing — today's app renders `null` here, exactly as it does now. */
1532
+ function Checking({ children }) {
1533
+ return usePart("checking") === null ? null : /* @__PURE__ */ jsx(Fragment, { children });
1534
+ }
1535
+ function DashboardError({ children }) {
1536
+ const state = usePart("error");
1537
+ if (state === null || state.error === null) return null;
1538
+ return /* @__PURE__ */ jsx(Fragment, { children: children({
1539
+ error: state.error,
1540
+ retry: state.retry
1541
+ }) });
1542
+ }
1543
+ function Redirect({ children }) {
1544
+ const state = usePart("redirect");
1545
+ if (state === null || state.destination === null) return null;
1546
+ return /* @__PURE__ */ jsx(Fragment, { children: children({ destination: state.destination }) });
1547
+ }
1548
+ function Granted({ children }) {
1549
+ return usePart("granted") === null ? null : /* @__PURE__ */ jsx(Fragment, { children });
1550
+ }
1551
+ /** The compound shape the app's own design system already uses (`StatusTabs`). */
1552
+ const CapxulDashboardAccess = Object.assign(Root, {
1553
+ Checking,
1554
+ Error: DashboardError,
1555
+ Redirect,
1556
+ Granted
1557
+ });
1558
+ //#endregion
1559
+ export { CapxulAuthenticationController, CapxulContacts, CapxulDashboardAccess, CapxulOnboardingController, CapxulOrgMember, CapxulProvider, CapxulSendMoney, acknowledgeOnboardingDestination, activeOnboardingRecovery, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, isClaimed, isRestoring, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions, useCapxulUsernameAvailability };
@@ -1,4 +1,4 @@
1
- import { a as AuthenticationSlots, d as OnboardingControllerProps } from "../controllers-D3_Q5d2t.mjs";
1
+ import { a as AuthenticationSlots, d as OnboardingControllerProps } from "../controllers-BT4YzBr9.mjs";
2
2
  import * as React from "react";
3
3
  import { ReactNode } from "react";
4
4
  import { CapxulTestClient, CapxulTestClock, CapxulTestObservation, CreateCapxulTestClientOptions, SeedTestIdentityInput, createCapxulTestClient } from "@capxul/sdk/testing";
@@ -1,4 +1,4 @@
1
- import { n as CapxulOnboardingController, r as CapxulProvider, t as CapxulAuthenticationController } from "../controllers-ClhmseFL.mjs";
1
+ import { n as CapxulOnboardingController, r as CapxulProvider, t as CapxulAuthenticationController } from "../controllers-VwUPB619.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": "2.2.0",
3
+ "version": "2.3.1",
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": "2.2.0"
29
+ "@capxul/sdk": "2.3.1"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@tanstack/react-query": "^5.66.9",
@@ -43,7 +43,7 @@
43
43
  "vite-plus": "0.1.23",
44
44
  "vitest": "npm:@voidzero-dev/vite-plus-test@0.1.23",
45
45
  "@capxul/errors": "0.0.1",
46
- "@capxul/types": "0.1.0",
46
+ "@capxul/types": "0.2.0",
47
47
  "@capxul/typescript-config": "0.0.0"
48
48
  },
49
49
  "peerDependencies": {