@capxul/sdk-react 2.6.1 → 2.7.0

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.
package/README.md CHANGED
@@ -49,11 +49,11 @@ export function Providers({ children }: { children: React.ReactNode }) {
49
49
  - `useCapxulHoldings` takes an optional `actor`, and its cache entry is keyed by
50
50
  that actor.
51
51
  - `CapxulSendMoney` is the compound send component. One root owns the send
52
- behaviour and draws nothing. The `.Asset`, `.Amount`, `.Recipient`, and
53
- `.Actions` region parts each hand the screen one finished slice. The engine
54
- hook stays module-scoped. This release ships the personal actor path;
55
- `.Source` and the organization path follow the Access & session budgets
56
- read.
52
+ behaviour and draws nothing. The `.Source`, `.Asset`, `.Amount`, `.Recipient`,
53
+ and `.Actions` region parts each hand the screen one finished slice. The
54
+ engine hook stays module-scoped. Both actor paths ship: a personal actor omits
55
+ `.Source` and spends the personal Account; an organization actor holds the
56
+ Budget the payment is drawn from and spends the treasury Account.
57
57
  - `CapxulContacts` is the compound address-book component. One root owns the
58
58
  book behaviour and draws nothing. The `.Summary`, `.List`, and `.Add` region
59
59
  parts each hand the screen one finished slice, and a `.List` row carries its
@@ -201,10 +201,12 @@ function normalizeOrganization(organization) {
201
201
  function createAuth(client, clearAuthenticatedQueries) {
202
202
  const runtime = client._internal.identity;
203
203
  const read = async (invocation) => {
204
- return failure(await runtime.send({ _tag: "ReadSession" }, invocation)) ?? { ok: true };
204
+ const result = await runtime.send({ _tag: "ReadSession" }, invocation);
205
+ return failure(result) ?? { ok: true };
205
206
  };
206
207
  const ensureAccount = async (invocation) => {
207
- return failure(await runtime.send({ _tag: "EnsureAccount" }, invocation)) ?? { ok: true };
208
+ const result = await runtime.send({ _tag: "EnsureAccount" }, invocation);
209
+ return failure(result) ?? { ok: true };
208
210
  };
209
211
  const reachClaimed = async (invocation) => {
210
212
  let state = runtime.snapshot();
@@ -271,15 +273,18 @@ function createAuth(client, clearAuthenticatedQueries) {
271
273
  verifyCode: (otp, options) => guarded(runtime, "verifyCode", options, async (invocation) => {
272
274
  const state = runtime.snapshot();
273
275
  const email = state.phase === "otp_pending" ? state.email : state.phase === "faulted" && state.resume !== null ? state.resume.email : "";
274
- if (!/^\d{6}$/.test(otp)) return failure(await runtime.send({
275
- _tag: "VerifyOtp",
276
- email,
277
- otp,
278
- now: Date.now()
279
- }, invocation)) ?? {
280
- ok: false,
281
- reason: "UNKNOWN"
282
- };
276
+ if (!/^\d{6}$/.test(otp)) {
277
+ const refused = await runtime.send({
278
+ _tag: "VerifyOtp",
279
+ email,
280
+ otp,
281
+ now: Date.now()
282
+ }, invocation);
283
+ return failure(refused) ?? {
284
+ ok: false,
285
+ reason: "UNKNOWN"
286
+ };
287
+ }
283
288
  const result = await client.auth.verifyOtp({
284
289
  email,
285
290
  code: otp
@@ -327,7 +332,8 @@ function createAuth(client, clearAuthenticatedQueries) {
327
332
  ok: false,
328
333
  reason: org.failure.code
329
334
  };
330
- return failure(await runtime.send({ _tag: "RetryOrganization" }, invocation)) ?? {
335
+ const retried = await runtime.send({ _tag: "RetryOrganization" }, invocation);
336
+ return failure(retried) ?? {
331
337
  ok: true,
332
338
  orgId: org.orgId
333
339
  };
@@ -354,7 +360,8 @@ function createAuth(client, clearAuthenticatedQueries) {
354
360
  retry: (options) => guarded(runtime, "retry", options, async (invocation) => {
355
361
  const state = runtime.snapshot();
356
362
  const event = state.phase === "authenticated" && state.account.at === "claimed" ? { _tag: "RetryOrganization" } : { _tag: "RetryAccount" };
357
- return failure(await runtime.send(event, invocation)) ?? { ok: true };
363
+ const result = await runtime.send(event, invocation);
364
+ return failure(result) ?? { ok: true };
358
365
  }),
359
366
  resumeSubmittedOrganization: (submission, options) => guarded(runtime, "createOrganization", options, async (invocation) => {
360
367
  const prepared = await prepareOrganization(submission, invocation);
@@ -456,7 +463,8 @@ function useResumeSubmittedOrganization() {
456
463
  return useIdentityContext().resumeSubmittedOrganization;
457
464
  }
458
465
  function useCapxulDestination() {
459
- const next = resolveIdentityDestination(useCapxulIdentity());
466
+ const state = useCapxulIdentity();
467
+ const next = resolveIdentityDestination(state);
460
468
  const held = useRef(null);
461
469
  const key = JSON.stringify(next);
462
470
  if (held.current?.key !== key) held.current = {
@@ -481,7 +489,7 @@ const entered = (record, target) => record.outcome === "applied" && record.from
481
489
  * old blanket `retry: 2` tripled that (and every other deterministic) failed
482
490
  * action for zero benefit (#1031).
483
491
  */
484
- const RETRYABLE_QUERY_ERROR_CODES = new Set([
492
+ const RETRYABLE_QUERY_ERROR_CODES = /* @__PURE__ */ new Set([
485
493
  "NETWORK_ERROR",
486
494
  "RATE_LIMITED",
487
495
  "PROVIDER_ERROR",
@@ -1,6 +1,5 @@
1
1
  import { ReactNode } from "react";
2
2
  import { CapxulClient, CapxulErrorCode, IdentityDestination, IdentityEvent, IdentityProfileDetails, IdentityState, IdentityTransition, OrgLane, Readiness, StateLabel } from "@capxul/sdk";
3
-
4
3
  //#region src/identity.d.ts
5
4
  type Destination = IdentityDestination;
6
5
  interface InvocationOptions {
@@ -132,9 +131,7 @@ interface AuthenticationSlots {
132
131
  destination: IdentityDestination | null;
133
132
  }>;
134
133
  }
135
- declare function CapxulAuthenticationController({
136
- slots
137
- }: {
134
+ declare function CapxulAuthenticationController({ slots }: {
138
135
  readonly slots: AuthenticationSlots;
139
136
  }): ReactNode;
140
137
  type ProfileSlotProps = {
package/dist/index.d.mts CHANGED
@@ -1,18 +1,20 @@
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";
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-CJEsthW2.mjs";
2
2
  import { ReactNode, RefCallback } from "react";
3
3
  import { QueryClient, UseMutationResult, UseQueryResult } from "@tanstack/react-query";
4
4
  import { Account, AccountRequirement, ActivityAnnotation, ActivityAnnotationInput, ActivityDetail, ActivityKind, ActivityListParams, ActivityPage, ActivityPhase, ActivityRange, ActivityReference, ActorReference, AddressBookEntry, CapxulClient, CapxulError, CapxulResult, CapxulSigner, CreateOrgInput, CurrentHoldings, HostObservability, IdentityDestination, InviteMemberInput, MemberView, Money, MoneyParseErrorReason, OrgId, OrgView, OrganizationPaymentBatchInput, OrganizationPaymentInput, PartyId, Payment, PaymentDirection, PaymentDocumentRef, PaymentDocumentRender, PaymentStatus, PaymentTiming, PaymentType, PaymentsPayInput, PayrollGroupId, PayrollGroupInput, PayrollRunId, PayrollRunStatus, Permission, PermissionReadResult, Profile, RoleView, isClaimed, isRestoring } from "@capxul/sdk";
5
-
6
5
  //#region src/provider.d.ts
7
6
  type CapxulProviderSharedProps = {
8
- /** Bring your own QueryClient; otherwise the provider creates one. */readonly queryClient?: QueryClient;
7
+ /** Bring your own QueryClient; otherwise the provider creates one. */
8
+ readonly queryClient?: QueryClient;
9
9
  readonly children: ReactNode;
10
10
  };
11
11
  /** Browser / app path — the provider bootstraps the client from a publishable key. */
12
12
  type CapxulProviderPublishableKeyProps = CapxulProviderSharedProps & {
13
13
  readonly publishableKey: string;
14
- readonly client?: never; /** One host-owned product/failure observability module. */
15
- readonly observability?: HostObservability; /** Init-time account readiness target. Default `"none"`. */
14
+ readonly client?: never;
15
+ /** One host-owned product/failure observability module. */
16
+ readonly observability?: HostObservability;
17
+ /** Init-time account readiness target. Default `"none"`. */
16
18
  readonly requirement?: AccountRequirement;
17
19
  /**
18
20
  * Optional consumer-held signer for the deploy lane. Omitted in browser apps
@@ -33,7 +35,8 @@ type CapxulProviderPublishableKeyProps = CapxulProviderSharedProps & {
33
35
  */
34
36
  type CapxulProviderInjectedClientProps = CapxulProviderSharedProps & {
35
37
  readonly client: CapxulClient;
36
- readonly publishableKey?: never; /** Injected clients must be created with observability at their owning factory. */
38
+ readonly publishableKey?: never;
39
+ /** Injected clients must be created with observability at their owning factory. */
37
40
  readonly observability?: never;
38
41
  readonly requirement?: never;
39
42
  readonly signer?: never;
@@ -66,7 +69,8 @@ declare function useCapxulProfile(): UseCapxulProfileReturn;
66
69
  //#region src/hooks/use-capxul-account-balance.d.ts
67
70
  type UseCapxulAccountBalanceReturn = UseQueryResult<Account, CapxulError>;
68
71
  type UseCapxulAccountBalanceOptions = {
69
- /** When false, skips the Convex readBalance action until the account ladder is ready. */readonly enabled?: boolean;
72
+ /** When false, skips the Convex readBalance action until the account ladder is ready. */
73
+ readonly enabled?: boolean;
70
74
  };
71
75
  declare function useCapxulAccountBalance(options?: UseCapxulAccountBalanceOptions): UseCapxulAccountBalanceReturn;
72
76
  //#endregion
@@ -100,7 +104,13 @@ declare function useCapxulPayment(paymentId: string | undefined, options?: {
100
104
  }): UseCapxulPaymentReturn;
101
105
  //#endregion
102
106
  //#region src/hooks/use-capxul-organization-payments.d.ts
103
- declare function useCapxulOrganizationPay(orgId: OrgId): UseMutationResult<Payment, CapxulError, OrganizationPaymentInput>;
107
+ /**
108
+ * `orgId` may be absent because a screen has no branded org id until its org
109
+ * context loads (`OrgView.id` is the branded one). An absent id refuses the
110
+ * mutation the way every other org read refuses one, rather than forcing a
111
+ * `as OrgId` cast at the call site.
112
+ */
113
+ declare function useCapxulOrganizationPay(orgId: OrgId | undefined): UseMutationResult<Payment, CapxulError, OrganizationPaymentInput>;
104
114
  declare function useCapxulOrganizationPayBatch(orgId: OrgId): UseMutationResult<readonly Payment[], CapxulError, OrganizationPaymentBatchInput>;
105
115
  //#endregion
106
116
  //#region ../types/src/brand.d.ts
@@ -119,6 +129,7 @@ type Brand<T, B extends string> = T & {
119
129
  type Address = Brand<string, "Address">;
120
130
  type PermissionId = Brand<string, "PermissionId">;
121
131
  type PermissionAssignmentId = Brand<string, "PermissionAssignmentId">;
132
+ type BudgetId = Brand<string, "BudgetId">;
122
133
  type PaymentCommandId = Brand<string, "PaymentCommandId">;
123
134
  type OrgId$1 = Brand<string, "OrgId">;
124
135
  type CurrencyCode = Brand<SupportedCurrencyCode, "CurrencyCode">;
@@ -635,27 +646,14 @@ interface CapxulContactsProps {
635
646
  readonly onFailed: (error: CapxulError) => void;
636
647
  readonly children: ReactNode;
637
648
  }
638
- declare function Root$6({
639
- actor,
640
- onAdded,
641
- onFailed,
642
- children
643
- }: CapxulContactsProps): import("react/jsx-runtime").JSX.Element;
644
- declare function Summary$3({
645
- children
646
- }: {
649
+ declare function Root$6({ actor, onAdded, onFailed, children }: CapxulContactsProps): import("react/jsx-runtime").JSX.Element;
650
+ declare function Summary$3({ children }: {
647
651
  readonly children: (slice: ContactsSummarySlice) => ReactNode;
648
652
  }): import("react/jsx-runtime").JSX.Element;
649
- declare function List({
650
- limit,
651
- show,
652
- children
653
- }: ContactsListOptions & {
653
+ declare function List({ limit, show, children }: ContactsListOptions & {
654
654
  readonly children: (slice: ContactsListSlice) => ReactNode;
655
655
  }): import("react/jsx-runtime").JSX.Element;
656
- declare function Add({
657
- children
658
- }: {
656
+ declare function Add({ children }: {
659
657
  readonly children: (slice: ContactsAddSlice) => ReactNode;
660
658
  }): import("react/jsx-runtime").JSX.Element;
661
659
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
@@ -736,7 +734,8 @@ interface ActivityFiltersSlice {
736
734
  readonly values: ActivityFilterValues;
737
735
  readonly set: {
738
736
  readonly kind: (value?: ActivityKind) => void;
739
- readonly direction: (value?: PaymentDirection) => void; /** REPLACES the array; it does not toggle one value. */
737
+ readonly direction: (value?: PaymentDirection) => void;
738
+ /** REPLACES the array; it does not toggle one value. */
740
739
  readonly status: (value: readonly PaymentStatus[]) => void;
741
740
  readonly clear: () => void;
742
741
  };
@@ -810,54 +809,34 @@ interface CapxulActivityProps {
810
809
  readonly pageSize?: number;
811
810
  readonly children: ReactNode;
812
811
  }
813
- declare function Root$5({
814
- actor,
815
- pageSize,
816
- children
817
- }: CapxulActivityProps): import("react/jsx-runtime").JSX.Element;
812
+ declare function Root$5({ actor, pageSize, children }: CapxulActivityProps): import("react/jsx-runtime").JSX.Element;
818
813
  /**
819
814
  * The one part that holds a query rather than reading the engine's: it takes a
820
815
  * `window` prop, and two placements can ask for different windows, so a single
821
816
  * pre-fetched result cannot serve both. It still holds no logic and draws
822
817
  * nothing.
823
818
  */
824
- declare function Summary$2({
825
- window,
826
- children
827
- }: {
819
+ declare function Summary$2({ window, children }: {
828
820
  readonly window?: SummaryWindow;
829
821
  readonly children: (slice: ActivitySummarySlice) => ReactNode;
830
822
  }): import("react/jsx-runtime").JSX.Element;
831
- declare function Filters({
832
- children
833
- }: {
823
+ declare function Filters({ children }: {
834
824
  readonly children: (slice: ActivityFiltersSlice) => ReactNode;
835
825
  }): import("react/jsx-runtime").JSX.Element;
836
- declare function Search({
837
- children
838
- }: {
826
+ declare function Search({ children }: {
839
827
  readonly children: (slice: ActivitySearchSlice) => ReactNode;
840
828
  }): import("react/jsx-runtime").JSX.Element;
841
- declare function Rows({
842
- children
843
- }: {
829
+ declare function Rows({ children }: {
844
830
  readonly children: (slice: ActivityRowsSlice) => ReactNode;
845
831
  }): import("react/jsx-runtime").JSX.Element;
846
- declare function LoadMore({
847
- children
848
- }: {
832
+ declare function LoadMore({ children }: {
849
833
  readonly children: (slice: ActivityLoadMoreSlice) => ReactNode;
850
834
  }): import("react/jsx-runtime").JSX.Element;
851
- declare function Detail({
852
- reference,
853
- children
854
- }: {
835
+ declare function Detail({ reference, children }: {
855
836
  readonly reference?: ActivityReference;
856
837
  readonly children: (slice: ActivityDetailSlice) => ReactNode;
857
838
  }): import("react/jsx-runtime").JSX.Element;
858
- declare function Export({
859
- children
860
- }: {
839
+ declare function Export({ children }: {
861
840
  readonly children: (slice: ActivityExportSlice) => ReactNode;
862
841
  }): import("react/jsx-runtime").JSX.Element;
863
842
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
@@ -892,8 +871,11 @@ type SendActor = {
892
871
  readonly orgId: OrgId$1 | undefined;
893
872
  };
894
873
  type SentPayment = {
895
- /** The backend payment row. */readonly payment: Payment; /** What we parsed and sent — `.value` is the comma-stripped major-unit string. */
896
- readonly amount: Money; /** The trimmed text the person typed — the app's success toast interpolates it. */
874
+ /** The backend payment row. */
875
+ readonly payment: Payment;
876
+ /** What we parsed and sent — `.value` is the comma-stripped major-unit string. */
877
+ readonly amount: Money;
878
+ /** The trimmed text the person typed — the app's success toast interpolates it. */
897
879
  readonly recipient: string;
898
880
  };
899
881
  /**
@@ -901,6 +883,28 @@ type SentPayment = {
901
883
  * the words it already prints; no English refusal string ships from here.
902
884
  */
903
885
  type CapxulSendMoneyBlockedReason = "signer-not-ready" | "amount-invalid" | "recipient-unresolved" | "no-source" | "no-asset";
886
+ /**
887
+ * One Budget the member can spend from — the id the payment carries, and
888
+ * nothing else.
889
+ *
890
+ * THE CONTRACT (amended 3) reverses amendment 7: the From row keeps the app's
891
+ * frozen `"<Org> Treasury"` string, and no budget label and no limit display
892
+ * cross this seam until the budgets build ships a remaining figure that is
893
+ * actually computable (ADR-0024 R3). The app already holds the org name and
894
+ * already builds that sentence today, so the option carries only what the app
895
+ * cannot know — which Budget the send is drawn from.
896
+ */
897
+ interface SendMoneySourceOption {
898
+ readonly id: BudgetId;
899
+ }
900
+ /** ADR-0023 R1: a code, never a sentence — the app owns the words. */
901
+ type SendMoneySourceError = "read-failed";
902
+ interface SendMoneySourceSlice {
903
+ readonly options: ReadonlyArray<SendMoneySourceOption>;
904
+ readonly selected: SendMoneySourceOption | null;
905
+ readonly select: (id: string) => void;
906
+ readonly error: SendMoneySourceError | null;
907
+ }
904
908
  interface SendMoneyAssetOption {
905
909
  readonly id: string;
906
910
  readonly symbol: string;
@@ -936,34 +940,25 @@ interface CapxulSendMoneyProps {
936
940
  readonly onFailed: (error: CapxulError) => void;
937
941
  readonly children: ReactNode;
938
942
  }
939
- declare function Root$4({
940
- actor,
941
- onSent,
942
- onFailed,
943
- children
944
- }: CapxulSendMoneyProps): import("react/jsx-runtime").JSX.Element;
945
- declare function Asset$1({
946
- children
947
- }: {
943
+ declare function Root$4({ actor, onSent, onFailed, children }: CapxulSendMoneyProps): import("react/jsx-runtime").JSX.Element;
944
+ declare function Source({ children }: {
945
+ readonly children: (slice: SendMoneySourceSlice) => ReactNode;
946
+ }): import("react/jsx-runtime").JSX.Element;
947
+ declare function Asset$1({ children }: {
948
948
  readonly children: (slice: SendMoneyAssetSlice) => ReactNode;
949
949
  }): import("react/jsx-runtime").JSX.Element;
950
- declare function Amount({
951
- children
952
- }: {
950
+ declare function Amount({ children }: {
953
951
  readonly children: (slice: SendMoneyAmountSlice) => ReactNode;
954
952
  }): import("react/jsx-runtime").JSX.Element;
955
- declare function Recipient({
956
- children
957
- }: {
953
+ declare function Recipient({ children }: {
958
954
  readonly children: (slice: SendMoneyRecipientSlice) => ReactNode;
959
955
  }): import("react/jsx-runtime").JSX.Element;
960
- declare function Actions$1({
961
- children
962
- }: {
956
+ declare function Actions$1({ children }: {
963
957
  readonly children: (slice: SendMoneyActionsSlice) => ReactNode;
964
958
  }): import("react/jsx-runtime").JSX.Element;
965
959
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
966
960
  declare const CapxulSendMoney: typeof Root$4 & {
961
+ Source: typeof Source;
967
962
  Asset: typeof Asset$1;
968
963
  Amount: typeof Amount;
969
964
  Recipient: typeof Recipient;
@@ -994,26 +989,18 @@ interface CapxulOrgMemberProps {
994
989
  readonly orgId: OrgId | string | undefined;
995
990
  readonly children: ReactNode;
996
991
  }
997
- declare function Root$3({
998
- orgId,
999
- children
1000
- }: CapxulOrgMemberProps): import("react/jsx-runtime").JSX.Element;
992
+ declare function Root$3({ orgId, children }: CapxulOrgMemberProps): import("react/jsx-runtime").JSX.Element;
1001
993
  /**
1002
994
  * One part serves all four denial idioms the app already uses: disabled with no
1003
995
  * explanation, disabled plus a native `title`, a whole-surface swap, and
1004
996
  * buttons that vanish. The part branches on nothing — the root computes both
1005
997
  * slices and this picks the one the `do` prop names.
1006
998
  */
1007
- declare function Can({
1008
- do: action,
1009
- children
1010
- }: {
999
+ declare function Can({ do: action, children }: {
1011
1000
  readonly do: OrgMemberAction;
1012
1001
  readonly children: (slice: OrgMemberCanSlice) => ReactNode;
1013
1002
  }): import("react/jsx-runtime").JSX.Element;
1014
- declare function Standing({
1015
- children
1016
- }: {
1003
+ declare function Standing({ children }: {
1017
1004
  readonly children: (slice: OrgMemberStandingSlice) => ReactNode;
1018
1005
  }): import("react/jsx-runtime").JSX.Element;
1019
1006
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
@@ -1042,29 +1029,18 @@ interface CapxulDashboardAccessProps {
1042
1029
  readonly scope: DashboardScope;
1043
1030
  readonly children: ReactNode;
1044
1031
  }
1045
- declare function Root$2({
1046
- scope,
1047
- children
1048
- }: CapxulDashboardAccessProps): import("react/jsx-runtime").JSX.Element;
1032
+ declare function Root$2({ scope, children }: CapxulDashboardAccessProps): import("react/jsx-runtime").JSX.Element;
1049
1033
  /** Hands nothing — today's app renders `null` here, exactly as it does now. */
1050
- declare function Checking({
1051
- children
1052
- }: {
1034
+ declare function Checking({ children }: {
1053
1035
  readonly children?: ReactNode;
1054
1036
  }): import("react/jsx-runtime").JSX.Element | null;
1055
- declare function DashboardError({
1056
- children
1057
- }: {
1037
+ declare function DashboardError({ children }: {
1058
1038
  readonly children: (slice: DashboardAccessErrorSlice) => ReactNode;
1059
1039
  }): import("react/jsx-runtime").JSX.Element | null;
1060
- declare function Redirect({
1061
- children
1062
- }: {
1040
+ declare function Redirect({ children }: {
1063
1041
  readonly children: (slice: DashboardAccessRedirectSlice) => ReactNode;
1064
1042
  }): import("react/jsx-runtime").JSX.Element | null;
1065
- declare function Granted({
1066
- children
1067
- }: {
1043
+ declare function Granted({ children }: {
1068
1044
  readonly children?: ReactNode;
1069
1045
  }): import("react/jsx-runtime").JSX.Element | null;
1070
1046
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
@@ -1085,7 +1061,8 @@ interface PayrollGroupRow {
1085
1061
  /** `formatMoney` over the amounts the employer typed on this group. */
1086
1062
  readonly totalDisplay: string;
1087
1063
  readonly members: readonly {
1088
- /** The `partyId` — the stable id (ruling Q1), never an email. */readonly recipientId: string;
1064
+ /** The `partyId` — the stable id (ruling Q1), never an email. */
1065
+ readonly recipientId: string;
1089
1066
  readonly amount: string;
1090
1067
  readonly currency: CurrencyCode;
1091
1068
  }[];
@@ -1110,18 +1087,11 @@ interface CapxulPayrollProps {
1110
1087
  readonly orgId: OrgId | undefined;
1111
1088
  readonly children: ReactNode;
1112
1089
  }
1113
- declare function Root$1({
1114
- orgId,
1115
- children
1116
- }: CapxulPayrollProps): import("react/jsx-runtime").JSX.Element;
1117
- declare function Summary$1({
1118
- children
1119
- }: {
1090
+ declare function Root$1({ orgId, children }: CapxulPayrollProps): import("react/jsx-runtime").JSX.Element;
1091
+ declare function Summary$1({ children }: {
1120
1092
  readonly children: (slice: PayrollSummarySlice) => ReactNode;
1121
1093
  }): import("react/jsx-runtime").JSX.Element;
1122
- declare function Groups({
1123
- children
1124
- }: {
1094
+ declare function Groups({ children }: {
1125
1095
  readonly children: (slice: PayrollGroupsSlice) => ReactNode;
1126
1096
  }): import("react/jsx-runtime").JSX.Element;
1127
1097
  /**
@@ -1225,36 +1195,20 @@ interface CapxulPayrollRunProps {
1225
1195
  readonly onFailed: (error: CapxulError) => void;
1226
1196
  readonly children: ReactNode;
1227
1197
  }
1228
- declare function Root({
1229
- orgId,
1230
- prefill,
1231
- onRun,
1232
- onFailed,
1233
- children
1234
- }: CapxulPayrollRunProps): import("react/jsx-runtime").JSX.Element;
1235
- declare function Recipients({
1236
- children
1237
- }: {
1198
+ declare function Root({ orgId, prefill, onRun, onFailed, children }: CapxulPayrollRunProps): import("react/jsx-runtime").JSX.Element;
1199
+ declare function Recipients({ children }: {
1238
1200
  readonly children: (slice: PayrollRunRecipientsSlice) => ReactNode;
1239
1201
  }): import("react/jsx-runtime").JSX.Element;
1240
- declare function Amounts({
1241
- children
1242
- }: {
1202
+ declare function Amounts({ children }: {
1243
1203
  readonly children: (slice: PayrollRunAmountsSlice) => ReactNode;
1244
1204
  }): import("react/jsx-runtime").JSX.Element;
1245
- declare function Asset({
1246
- children
1247
- }: {
1205
+ declare function Asset({ children }: {
1248
1206
  readonly children: (slice: PayrollRunAssetSlice) => ReactNode;
1249
1207
  }): import("react/jsx-runtime").JSX.Element;
1250
- declare function Summary({
1251
- children
1252
- }: {
1208
+ declare function Summary({ children }: {
1253
1209
  readonly children: (slice: PayrollRunSummarySlice) => ReactNode;
1254
1210
  }): import("react/jsx-runtime").JSX.Element;
1255
- declare function Actions({
1256
- children
1257
- }: {
1211
+ declare function Actions({ children }: {
1258
1212
  readonly children: (slice: PayrollRunActionsSlice) => ReactNode;
1259
1213
  }): import("react/jsx-runtime").JSX.Element;
1260
1214
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
@@ -1296,4 +1250,4 @@ declare const capxulKeys: {
1296
1250
  payment: (paymentId: string | undefined) => readonly ["capxul", "payments", string];
1297
1251
  };
1298
1252
  //#endregion
1299
- 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 CreateOrganizationSubmission, type CsvExport, 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 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 SendMoneyRecipientMethod, type SendMoneyRecipientSlice, type SendMoneyRecipientStatus, type SendResult, type SentPayment, type SentPayrollRun, type SignedOutState, type Slot, type SummaryWindow, 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, capxulKeys, 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 };
1253
+ 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 CreateOrganizationSubmission, type CsvExport, 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 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 SendMoneyRecipientMethod, 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 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, capxulKeys, 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,5 +1,5 @@
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-ClPgcB4L.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-BkL0hHuk.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
5
  import { CapxulError, Errors, PAYMENT_DIRECTIONS, PAYMENT_STATUSES, fingerprintPaymentIntent, formatMoney, isCapxulError, isClaimed, isClaimed as isClaimed$1, isMoneyParseError, isRestoring, isRestoring as isRestoring$1, parseMoney, paymentPhase, resolveIdentityDestination } from "@capxul/sdk";
@@ -152,7 +152,7 @@ async function beginPaymentRequestKey(operation, intent) {
152
152
  const manager = paymentLockManager();
153
153
  const key = await manager.request(storageSlot, async () => {
154
154
  let state = readState(storageSlot) ?? {
155
- key: `pay_${Array.from(crypto.getRandomValues(new Uint8Array(16)), (byte) => byte.toString(16).padStart(2, "0")).join("")}`,
155
+ key: `pay_${Array.from(crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16)), (byte) => byte.toString(16).padStart(2, "0")).join("")}`,
156
156
  active: [],
157
157
  resolved: false
158
158
  };
@@ -322,12 +322,19 @@ function useCapxulPayment(paymentId, options) {
322
322
  }
323
323
  //#endregion
324
324
  //#region src/hooks/use-capxul-organization-payments.ts
325
+ /**
326
+ * `orgId` may be absent because a screen has no branded org id until its org
327
+ * context loads (`OrgView.id` is the branded one). An absent id refuses the
328
+ * mutation the way every other org read refuses one, rather than forcing a
329
+ * `as OrgId` cast at the call site.
330
+ */
325
331
  function useCapxulOrganizationPay(orgId) {
326
332
  const client = useCapxulClientOrNull();
327
333
  const backendScope = client === null ? "pending" : `${client._internal.bootstrap.convexUrl}:${String(client._internal.bootstrap.chainId)}`;
328
334
  const queryClient = useQueryClient();
329
335
  return useMutation({
330
336
  mutationFn: async (input) => {
337
+ if (orgId === void 0) throw Errors.invalidInput("orgId", "required for useCapxulOrganizationPay");
331
338
  const bootstrapped = requireBootstrappedClient(client, "organizationPayments.pay");
332
339
  return withPaymentRequestKey("organization-pay", {
333
340
  backendScope,
@@ -339,6 +346,7 @@ function useCapxulOrganizationPay(orgId) {
339
346
  })));
340
347
  },
341
348
  onSuccess: async (payment) => {
349
+ if (orgId === void 0) return;
342
350
  return invalidateMoneyState(queryClient, {
343
351
  actor: {
344
352
  kind: "organization",
@@ -1706,6 +1714,37 @@ const CapxulActivity = Object.assign(Root$5, {
1706
1714
  Export
1707
1715
  });
1708
1716
  //#endregion
1717
+ //#region src/internal/use-org-me-reading.ts
1718
+ function useOrgMeReading(orgId) {
1719
+ const client = useCapxulClientOrNull();
1720
+ const identity = useCapxulIdentityOrNull();
1721
+ const ready = client !== null && identity !== null && isClaimed$1(identity);
1722
+ const mayStillOpen = client === null || identity === null || isRestoring$1(identity);
1723
+ const query = useQuery({
1724
+ queryKey: capxulKeys.orgMe(orgId),
1725
+ queryFn: async () => {
1726
+ return unwrapCapxulResult(await requireBootstrappedClient(client, "org.me").org(orgId).me());
1727
+ },
1728
+ enabled: ready && orgId !== void 0
1729
+ });
1730
+ return useMemo(() => {
1731
+ if (orgId === void 0) return { kind: "no-org" };
1732
+ if (!ready) return { kind: mayStillOpen ? "loading" : "unavailable" };
1733
+ if (query.error !== null) return { kind: "unavailable" };
1734
+ if (query.data !== void 0) return {
1735
+ kind: "ready",
1736
+ me: query.data
1737
+ };
1738
+ return { kind: "loading" };
1739
+ }, [
1740
+ mayStillOpen,
1741
+ orgId,
1742
+ query.data,
1743
+ query.error,
1744
+ ready
1745
+ ]);
1746
+ }
1747
+ //#endregion
1709
1748
  //#region src/headless/send-money/signer-status.ts
1710
1749
  const NO_SUBSCRIPTION = () => () => {};
1711
1750
  function useSignerStatus(client) {
@@ -1742,18 +1781,18 @@ function useRecipientResolution(client) {
1742
1781
  setOutcome({
1743
1782
  reference: debouncedReference,
1744
1783
  status: "checking",
1745
- target: null
1784
+ label: null
1746
1785
  });
1747
1786
  client.targets.resolve(debouncedReference, { signal: controller.signal }).then((result) => {
1748
1787
  if (controller.signal.aborted) return;
1749
1788
  setOutcome(result.ok ? {
1750
1789
  reference: debouncedReference,
1751
1790
  status: "found",
1752
- target: result.value
1791
+ label: result.value.label
1753
1792
  } : {
1754
1793
  reference: debouncedReference,
1755
1794
  status: result.error.code === "INVALID_INPUT" ? "not-found" : "failed",
1756
- target: null
1795
+ label: null
1757
1796
  });
1758
1797
  });
1759
1798
  return () => controller.abort();
@@ -1764,7 +1803,7 @@ function useRecipientResolution(client) {
1764
1803
  }, []);
1765
1804
  const settled = outcome !== null && outcome.reference === debouncedReference ? outcome : null;
1766
1805
  const status = reference === null ? "empty" : reference !== debouncedReference || settled === null ? "checking" : settled.status;
1767
- const resolvedTarget = status === "found" ? settled?.target ?? null : null;
1806
+ const resolvedReference = status === "found" ? settled?.reference ?? null : null;
1768
1807
  return {
1769
1808
  slice: {
1770
1809
  method,
@@ -1772,53 +1811,66 @@ function useRecipientResolution(client) {
1772
1811
  value: text,
1773
1812
  change: setText,
1774
1813
  status,
1775
- label: resolvedTarget?.label ?? null
1814
+ label: status === "found" ? settled?.label ?? null : null
1776
1815
  },
1777
- resolvedTarget,
1816
+ resolvedReference,
1778
1817
  trimmed: text.trim()
1779
1818
  };
1780
1819
  }
1781
1820
  //#endregion
1782
1821
  //#region src/headless/send-money/use-send-money.ts
1822
+ /**
1823
+ * One dropdown's selection. It reconciles whenever the held id is absent from
1824
+ * the option list — first mount AND a swap under a mounted root both land here
1825
+ * — and `select` narrows internally, so an id the caller does not hold is
1826
+ * ignored and no cast reaches app code.
1827
+ */
1828
+ function useSelectedOption(options) {
1829
+ const [selectedId, setSelectedId] = useState(null);
1830
+ useEffect(() => {
1831
+ if (!options.some((option) => option.id === selectedId)) setSelectedId(options[0]?.id ?? null);
1832
+ }, [options, selectedId]);
1833
+ const select = useCallback((id) => {
1834
+ setSelectedId((current) => options.some((option) => option.id === id) ? id : current);
1835
+ }, [options]);
1836
+ return [options.find((option) => option.id === selectedId) ?? null, select];
1837
+ }
1783
1838
  function useSendMoney(input) {
1784
1839
  const { actor, onSent, onFailed } = input;
1785
1840
  const client = useCapxulClientOrNull();
1786
1841
  const signerStatus = useSignerStatus(client);
1842
+ const orgId = actor.kind === "organization" ? actor.orgId : void 0;
1843
+ const meReading = useOrgMeReading(orgId);
1844
+ const sourceOptions = useMemo(() => meReading.kind === "ready" ? meReading.me.budgets.map((budget) => ({ id: budget.id })) : [], [meReading]);
1845
+ const [selectedSource, selectSource] = useSelectedOption(sourceOptions);
1787
1846
  const balance = useCapxulAccountBalance({ enabled: actor.kind === "personal" });
1788
- const account = actor.kind === "personal" ? balance.data ?? null : null;
1847
+ const treasury = useCapxulOrgTreasury(orgId, { enabled: actor.kind === "organization" });
1848
+ const accountQuery = actor.kind === "personal" ? balance : treasury;
1849
+ const account = accountQuery.data ?? null;
1789
1850
  const assetOptions = useMemo(() => account === null ? [] : [{
1790
1851
  id: account.id,
1791
1852
  symbol: account.available.currency,
1792
1853
  availableDisplay: formatMoney(account.available, { grammar: "code" })
1793
1854
  }], [account]);
1794
- const [selectedAssetId, setSelectedAssetId] = useState(null);
1795
- useEffect(() => {
1796
- if (!assetOptions.some((option) => option.id === selectedAssetId)) setSelectedAssetId(assetOptions[0]?.id ?? null);
1797
- }, [assetOptions, selectedAssetId]);
1798
- const selectedAssetOption = assetOptions.find((option) => option.id === selectedAssetId) ?? null;
1855
+ const [selectedAssetOption, selectAsset] = useSelectedOption(assetOptions);
1799
1856
  const selectedAssetMoney = selectedAssetOption !== null && account !== null ? account.available : null;
1800
- const selectAsset = useCallback((id) => {
1801
- setSelectedAssetId((current) => assetOptions.some((option) => option.id === id) ? id : current);
1802
- }, [assetOptions]);
1803
1857
  const [amountText, setAmountText] = useState("");
1804
1858
  const parsed = useMemo(() => selectedAssetMoney === null || amountText.trim() === "" ? null : parseMoney(amountText, selectedAssetMoney), [amountText, selectedAssetMoney]);
1805
1859
  const parsedMoney = parsed !== null && !isMoneyParseError(parsed) ? parsed : null;
1806
1860
  const amountError = parsed !== null && isMoneyParseError(parsed) ? parsed.reason : null;
1807
1861
  const recipient = useRecipientResolution(client);
1808
- const resolvedTarget = recipient.resolvedTarget;
1809
- const pay = useCapxulPay();
1810
- const blockedReason = signerStatus !== "ready" ? "signer-not-ready" : actor.kind === "organization" ? "no-source" : selectedAssetOption === null ? "no-asset" : parsedMoney === null ? "amount-invalid" : resolvedTarget === null ? "recipient-unresolved" : null;
1862
+ const resolvedReference = recipient.resolvedReference;
1863
+ const personalPay = useCapxulPay();
1864
+ const organizationPay = useCapxulOrganizationPay(orgId);
1865
+ const pay = actor.kind === "personal" ? personalPay : organizationPay;
1866
+ 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;
1811
1867
  const submitGate = useRef(false);
1812
1868
  const submit = useCallback(() => {
1813
1869
  if (blockedReason !== null || submitGate.current) return;
1814
- if (parsedMoney === null || resolvedTarget === null) return;
1815
- submitGate.current = true;
1870
+ if (parsedMoney === null || resolvedReference === null) return;
1816
1871
  const amount = parsedMoney;
1817
1872
  const sentRecipient = recipient.trimmed;
1818
- pay.mutate({
1819
- to: resolvedTarget.reference,
1820
- amount
1821
- }, {
1873
+ const callbacks = {
1822
1874
  onSuccess: (payment) => onSent({
1823
1875
  payment,
1824
1876
  amount,
@@ -1828,22 +1880,46 @@ function useSendMoney(input) {
1828
1880
  onSettled: () => {
1829
1881
  submitGate.current = false;
1830
1882
  }
1831
- });
1883
+ };
1884
+ if (actor.kind === "personal") {
1885
+ submitGate.current = true;
1886
+ personalPay.mutate({
1887
+ to: resolvedReference,
1888
+ amount
1889
+ }, callbacks);
1890
+ return;
1891
+ }
1892
+ if (selectedSource === null) return;
1893
+ submitGate.current = true;
1894
+ organizationPay.mutate({
1895
+ permissionId: selectedSource.id,
1896
+ to: resolvedReference,
1897
+ amount
1898
+ }, callbacks);
1832
1899
  }, [
1900
+ actor.kind,
1833
1901
  blockedReason,
1834
1902
  onFailed,
1835
1903
  onSent,
1904
+ organizationPay,
1836
1905
  parsedMoney,
1837
- pay,
1906
+ personalPay,
1838
1907
  recipient.trimmed,
1839
- resolvedTarget
1908
+ resolvedReference,
1909
+ selectedSource
1840
1910
  ]);
1841
1911
  return {
1912
+ source: {
1913
+ options: sourceOptions,
1914
+ selected: selectedSource,
1915
+ select: selectSource,
1916
+ error: meReading.kind === "unavailable" ? "read-failed" : null
1917
+ },
1842
1918
  asset: {
1843
1919
  options: assetOptions,
1844
1920
  selected: selectedAssetOption,
1845
1921
  select: selectAsset,
1846
- error: actor.kind === "personal" && balance.error !== null ? "read-failed" : null
1922
+ error: accountQuery.error !== null ? "read-failed" : null
1847
1923
  },
1848
1924
  amount: {
1849
1925
  value: amountText,
@@ -1879,6 +1955,9 @@ function Root$4({ actor, onSent, onFailed, children }) {
1879
1955
  children
1880
1956
  });
1881
1957
  }
1958
+ function Source({ children }) {
1959
+ return /* @__PURE__ */ jsx(Fragment, { children: children(useSendMoneyContext().source) });
1960
+ }
1882
1961
  function Asset$1({ children }) {
1883
1962
  return /* @__PURE__ */ jsx(Fragment, { children: children(useSendMoneyContext().asset) });
1884
1963
  }
@@ -1893,6 +1972,7 @@ function Actions$1({ children }) {
1893
1972
  }
1894
1973
  /** The compound shape the app's own design system already uses (`StatusTabs`). */
1895
1974
  const CapxulSendMoney = Object.assign(Root$4, {
1975
+ Source,
1896
1976
  Asset: Asset$1,
1897
1977
  Amount,
1898
1978
  Recipient,
@@ -1966,33 +2046,7 @@ function standingSlice(reading) {
1966
2046
  }
1967
2047
  /** The engine — all the logic. NOT exported from the package barrel. */
1968
2048
  function useOrgMember(orgId) {
1969
- const client = useCapxulClientOrNull();
1970
- const identity = useCapxulIdentityOrNull();
1971
- const ready = client !== null && identity !== null && isClaimed$1(identity);
1972
- const mayStillOpen = client === null || identity === null || isRestoring$1(identity);
1973
- const query = useQuery({
1974
- queryKey: capxulKeys.orgMe(orgId),
1975
- queryFn: async () => {
1976
- return unwrapCapxulResult(await requireBootstrappedClient(client, "org.me").org(orgId).me());
1977
- },
1978
- enabled: ready && orgId !== void 0
1979
- });
1980
- const reading = useMemo(() => {
1981
- if (orgId === void 0) return { kind: "no-org" };
1982
- if (!ready) return { kind: mayStillOpen ? "loading" : "unavailable" };
1983
- if (query.error !== null) return { kind: "unavailable" };
1984
- if (query.data !== void 0) return {
1985
- kind: "ready",
1986
- me: query.data
1987
- };
1988
- return { kind: "loading" };
1989
- }, [
1990
- mayStillOpen,
1991
- orgId,
1992
- query.data,
1993
- query.error,
1994
- ready
1995
- ]);
2049
+ const reading = useOrgMeReading(orgId);
1996
2050
  return useMemo(() => ({
1997
2051
  can: {
1998
2052
  spend: canSlice(reading, (me) => me.capabilities.canSpend),
@@ -2401,6 +2455,7 @@ function usePayroll(orgId) {
2401
2455
  const treasury = useOrgTreasury(orgId);
2402
2456
  const runs = usePayrollRuns(orgId);
2403
2457
  const groups = usePayrollGroups(orgId);
2458
+ const invalidate = useCallback(() => queryClient.invalidateQueries({ queryKey: capxulKeys.payrollGroups(orgId) }), [orgId, queryClient]);
2404
2459
  const write = useMutation({
2405
2460
  mutationFn: async (command) => {
2406
2461
  const payroll = scopedClient(client, `org.payroll.groups.${command.kind}`, orgId).payroll;
@@ -2410,7 +2465,7 @@ function usePayroll(orgId) {
2410
2465
  }
2411
2466
  return unwrapCapxulResult(await payroll.groups.save(command.input));
2412
2467
  },
2413
- onSettled: useCallback(() => queryClient.invalidateQueries({ queryKey: capxulKeys.payrollGroups(orgId) }), [orgId, queryClient])
2468
+ onSettled: invalidate
2414
2469
  });
2415
2470
  const mutateAsync = write.mutateAsync;
2416
2471
  const save = useCallback(async (input) => {
@@ -1,8 +1,7 @@
1
- import { a as AuthenticationSlots, d as OnboardingControllerProps } from "../controllers-BT4YzBr9.mjs";
1
+ import { a as AuthenticationSlots, d as OnboardingControllerProps } from "../controllers-CJEsthW2.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";
5
-
6
5
  //#region src/testing/index.d.ts
7
6
  interface CreateCapxulReactTestHarnessOptions extends CreateCapxulTestClientOptions {
8
7
  readonly testing?: CapxulTestClient;
@@ -1,4 +1,4 @@
1
- import { n as CapxulOnboardingController, r as CapxulProvider, t as CapxulAuthenticationController } from "../controllers-ClPgcB4L.mjs";
1
+ import { n as CapxulOnboardingController, r as CapxulProvider, t as CapxulAuthenticationController } from "../controllers-BkL0hHuk.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.6.1",
3
+ "version": "2.7.0",
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.6.1"
29
+ "@capxul/sdk": "2.7.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@tanstack/react-query": "^5.66.9",
@@ -34,17 +34,18 @@
34
34
  "@types/jsdom": "^28.0.3",
35
35
  "@types/react": "^19.2.15",
36
36
  "@typescript/native": "npm:typescript@7.0.2",
37
- "@vitest/coverage-v8": "4.1.7",
37
+ "@vitest/coverage-v8": "4.1.11",
38
38
  "ink": "^7.0.3",
39
39
  "ink-testing-library": "^4.0.0",
40
40
  "jsdom": "^29.1.1",
41
41
  "react": "^19.2.6",
42
42
  "react-dom": "^19.2.6",
43
- "vite-plus": "0.1.23",
44
- "vitest": "npm:@voidzero-dev/vite-plus-test@0.1.23",
43
+ "vite": "npm:@voidzero-dev/vite-plus-core@0.3.0",
44
+ "vite-plus": "0.3.0",
45
+ "vitest": "4.1.11",
45
46
  "@capxul/errors": "0.0.2",
46
- "@capxul/types": "0.2.1",
47
- "@capxul/typescript-config": "0.0.0"
47
+ "@capxul/typescript-config": "0.0.0",
48
+ "@capxul/types": "0.2.1"
48
49
  },
49
50
  "peerDependencies": {
50
51
  "@tanstack/react-query": "^5.66.9",
@@ -55,7 +56,7 @@
55
56
  },
56
57
  "scripts": {
57
58
  "check-types": "vp exec ../../node_modules/@typescript/native/bin/tsc -p tsconfig.json --noEmit",
58
- "lint": "oxlint -c ../../.oxlintrc.json . --deny-warnings",
59
+ "lint": "vp lint -c ../../.oxlintrc.json . --deny-warnings",
59
60
  "build": "vp pack",
60
61
  "_vp-tasks-allowed": "vp-allowed: `test` + `test:coverage` are vp tasks in vite.config.ts so vitest self-writes don't bust cache (#205)."
61
62
  }