@zautha/react 0.10.0 → 0.12.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
@@ -95,6 +95,18 @@ const transfer = useReverification(async () =>
95
95
  );
96
96
  ```
97
97
 
98
+ ## Impersonation
99
+
100
+ `useAuth().actor` (and `useSession().session.actor`) is `{ sub, iss }` in an impersonation session and `null`
101
+ otherwise. With `ui` on `<ZauthaProvider>`, the provider shows the impersonation band at the bottom of every page of
102
+ such a session ("End session" signs out); nothing to add yourself. Without `ui` (headless use) there is no band, but `actor` is still set: show your own notice
103
+ from `useAuth().actor`.
104
+
105
+ ```tsx
106
+ const { actor } = useAuth();
107
+ if (actor !== null) console.log(`support agent ${actor.sub} is signed in as this user`);
108
+ ```
109
+
98
110
  ## License
99
111
 
100
112
  MIT, see [LICENSE](./LICENSE).
package/dist/index.cjs CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  let _zautha_js = require("@zautha/js");
4
4
  let react = require("react");
5
5
  let react_jsx_runtime = require("react/jsx-runtime");
6
- //#region src/provider.tsx
6
+ // src/provider.tsx
7
7
  const ZauthaContext = (0, react.createContext)(void 0);
8
8
  /**
9
9
  * Creates the Zautha instance after mount (never during render, so StrictMode's double mount and SSR
@@ -67,8 +67,105 @@ function useZauthaState() {
67
67
  const { zautha, pending } = useZauthaContext();
68
68
  return (0, react.useSyncExternalStore)(zautha?.subscribe ?? noop, () => zautha?.getSnapshot() ?? pending, () => pending);
69
69
  }
70
- //#endregion
71
- //#region src/hooks.ts
70
+ // src/pagination.ts
71
+ /**
72
+ * The pages of one list. Without a source nothing is read and the list is empty; a source with a new key starts again on
73
+ * the initial page. A response to an older request (another page, key or revalidation) is dropped, so it never
74
+ * overwrites a newer one.
75
+ */
76
+ function usePages(source, params) {
77
+ const key = source?.key ?? null;
78
+ const { pageSize = 10, initialPage = 1 } = params === true || params === void 0 ? {} : params;
79
+ const [at, setAt] = (0, react.useState)({
80
+ key,
81
+ page: initialPage,
82
+ version: 0
83
+ });
84
+ const [settled, setSettled] = (0, react.useState)(null);
85
+ const latest = (0, react.useRef)(0);
86
+ const waiting = (0, react.useRef)([]);
87
+ if (at.key !== key) {
88
+ setAt({
89
+ key,
90
+ page: initialPage,
91
+ version: 0
92
+ });
93
+ setSettled(null);
94
+ }
95
+ const { page, version } = at.key === key ? at : {
96
+ page: initialPage,
97
+ version: 0
98
+ };
99
+ const request = JSON.stringify([
100
+ key,
101
+ page,
102
+ pageSize,
103
+ version
104
+ ]);
105
+ const loader = (0, react.useRef)(source?.load);
106
+ (0, react.useEffect)(() => {
107
+ loader.current = source?.load;
108
+ });
109
+ (0, react.useEffect)(() => {
110
+ const id = ++latest.current;
111
+ const settle = (data, count, error) => {
112
+ if (latest.current !== id) return;
113
+ if (key !== null) setSettled({
114
+ request,
115
+ key,
116
+ page,
117
+ data,
118
+ count,
119
+ error
120
+ });
121
+ for (const resolve of waiting.current.splice(0)) resolve();
122
+ };
123
+ if (key === null || loader.current === void 0) return settle([], 0, null);
124
+ loader.current({
125
+ limit: pageSize,
126
+ offset: (page - 1) * pageSize
127
+ }).then((r) => settle(r.data, r.totalCount, null), (error) => settle([], 0, error instanceof Error ? error : new Error(String(error))));
128
+ }, [request]);
129
+ const shown = settled !== null && settled.key === key && settled.page === page ? settled : null;
130
+ const isFetching = key !== null && settled?.request !== request;
131
+ const count = shown?.count ?? 0;
132
+ const pageCount = Math.ceil(count / pageSize);
133
+ const go = (0, react.useCallback)((to) => setAt((a) => {
134
+ const from = a.key === key ? a.page : initialPage;
135
+ return {
136
+ key,
137
+ page: Math.max(1, to(from)),
138
+ version: a.key === key ? a.version : 0
139
+ };
140
+ }), [key, initialPage]);
141
+ const revalidate = (0, react.useCallback)(() => new Promise((resolve) => {
142
+ waiting.current.push(resolve);
143
+ setAt((a) => a.key === key ? {
144
+ ...a,
145
+ version: a.version + 1
146
+ } : {
147
+ key,
148
+ page: initialPage,
149
+ version: 1
150
+ });
151
+ }), [key, initialPage]);
152
+ return {
153
+ data: shown?.data ?? [],
154
+ count,
155
+ page,
156
+ pageCount,
157
+ isLoading: isFetching && shown === null,
158
+ isFetching,
159
+ error: shown?.error ?? null,
160
+ hasNextPage: page < pageCount,
161
+ hasPreviousPage: page > 1,
162
+ fetchNext: (0, react.useCallback)(() => go((p) => p + 1), [go]),
163
+ fetchPrevious: (0, react.useCallback)(() => go((p) => p - 1), [go]),
164
+ fetchPage: (0, react.useCallback)((n) => go(() => n), [go]),
165
+ revalidate
166
+ };
167
+ }
168
+ // src/hooks.ts
72
169
  const isLoadedStatus = (status) => status === "ready" || status === "degraded";
73
170
  /** The signed-in session: a pending one (tasks left, e.g. setting up two-step verification) counts as signed out. */
74
171
  const activeSession = (state) => state.session?.status === "active" ? state.session : null;
@@ -83,6 +180,7 @@ function useAuth() {
83
180
  const sessionId = initial === null ? session?.id ?? null : initial.sessionId;
84
181
  const signedIn = userId !== null;
85
182
  const organization = initial === null ? session === null ? null : state.organization : initial.organization;
183
+ const actor = initial === null ? session?.actor ?? null : initial.actor;
86
184
  const has = (0, react.useCallback)((params) => (0, _zautha_js.checkAuthorization)(organization, params), [organization]);
87
185
  return {
88
186
  isLoaded: isLoadedStatus(state.status) || initial !== null,
@@ -93,6 +191,7 @@ function useAuth() {
93
191
  orgRole: organization?.role ?? null,
94
192
  orgSlug: organization?.slug ?? null,
95
193
  orgPermissions: organization?.permissions ?? null,
194
+ actor,
96
195
  getToken,
97
196
  signOut,
98
197
  has
@@ -169,8 +268,81 @@ function useSignUp() {
169
268
  fetchStatus: snapshot?.fetchStatus ?? "idle"
170
269
  };
171
270
  }
172
- //#endregion
173
- //#region src/control.tsx
271
+ /** A list's filters: its params without the page size and the first page. */
272
+ function filtersOf(params) {
273
+ const filters = { ...params === true ? {} : params };
274
+ delete filters.pageSize;
275
+ delete filters.initialPage;
276
+ return filters;
277
+ }
278
+ /** A list of `owner` read with `load`: its key (`owner` and the params, so new filters start the list again). */
279
+ const list = (owner, params, load) => ({
280
+ key: `${owner}:${JSON.stringify(params)}`,
281
+ load
282
+ });
283
+ /** The signed-in user (an active session's) and whether hooks that read it are loaded. */
284
+ function useSignedInUser() {
285
+ const zautha = useZautha();
286
+ const state = useZauthaState();
287
+ const user = activeSession(state) === null ? null : zautha?.user ?? null;
288
+ return {
289
+ isLoaded: isLoadedStatus(state.status) && (activeSession(state) === null || user !== null),
290
+ state,
291
+ user
292
+ };
293
+ }
294
+ /**
295
+ * The session's active organization and the user's membership of it, from the session token and the user (no request of
296
+ * its own), and on request its members and invitations, page by page. The lists start again on their first page when
297
+ * the active organization changes.
298
+ */
299
+ function useOrganization(params = {}) {
300
+ const { isLoaded, state, user } = useSignedInUser();
301
+ const id = state.organization?.id;
302
+ const membership = user?.organizationMemberships.find((m) => m.organization.id === id) ?? null;
303
+ const organization = membership?.organization ?? null;
304
+ const owner = membership === null ? "" : `${membership.publicUserData.userId}:${membership.organization.id}`;
305
+ const { memberships, invitations } = params;
306
+ const manages = membership?.permissions.includes("org:sys_memberships:manage") === true;
307
+ const members = usePages(organization === null || memberships === void 0 ? null : list(owner, memberships, (page) => organization.getMemberships({
308
+ ...filtersOf(memberships),
309
+ ...page
310
+ })), memberships);
311
+ const invited = usePages(organization === null || invitations === void 0 || !manages ? null : list(owner, invitations, (page) => organization.getInvitations({
312
+ ...filtersOf(invitations),
313
+ ...page
314
+ })), invitations);
315
+ return {
316
+ isLoaded,
317
+ organization,
318
+ membership,
319
+ ...memberships === void 0 ? {} : { memberships: members },
320
+ ...invitations === void 0 ? {} : { invitations: invited }
321
+ };
322
+ }
323
+ /**
324
+ * Creating an organization and choosing the active one, and on request the user's memberships and the invitations to
325
+ * the user, page by page.
326
+ */
327
+ function useOrganizationList(params = {}) {
328
+ const zautha = useZautha();
329
+ const { isLoaded, user } = useSignedInUser();
330
+ const { userMemberships, userInvitations } = params;
331
+ const memberships = usePages(user === null || userMemberships === void 0 ? null : list(user.id, userMemberships, (page) => user.getOrganizationMemberships(page)), userMemberships);
332
+ const invitations = usePages(user === null || userInvitations === void 0 ? null : list(user.id, userInvitations, (page) => user.getOrganizationInvitations({
333
+ ...filtersOf(userInvitations),
334
+ ...page
335
+ })), userInvitations);
336
+ return {
337
+ isLoaded,
338
+ createOrganization: (0, react.useCallback)((p) => zautha?.createOrganization(p) ?? notLoaded(), [zautha]),
339
+ setActive: (0, react.useCallback)((p) => zautha?.setActive(p) ?? notLoaded(), [zautha]),
340
+ ...userMemberships === void 0 ? {} : { userMemberships: memberships },
341
+ ...userInvitations === void 0 ? {} : { userInvitations: invitations }
342
+ };
343
+ }
344
+ const notLoaded = () => Promise.reject(new _zautha_js.ZauthaError("Zautha is not loaded yet."));
345
+ // src/control.tsx
174
346
  /**
175
347
  * Renders `children` when the condition holds, else `fallback`. Renders nothing until Zautha has
176
348
  * loaded, so a signed-in user never sees a signed-out flash.
@@ -224,8 +396,7 @@ function RedirectToSignUp(props) {
224
396
  ]);
225
397
  return null;
226
398
  }
227
- //#endregion
228
- //#region src/buttons.tsx
399
+ // src/buttons.tsx
229
400
  /** Wraps its single child (or renders a plain button) and wires the click. Unstyled by design. */
230
401
  function Trigger(props) {
231
402
  const child = react.Children.count(props.children) === 1 ? react.Children.only(props.children) : null;
@@ -268,8 +439,7 @@ function SignOutButton(props) {
268
439
  children: props.children
269
440
  });
270
441
  }
271
- //#endregion
272
- //#region src/prebuilt.tsx
442
+ // src/prebuilt.tsx
273
443
  /**
274
444
  * Mounts a @zautha/ui component into a div once the instance exists; later prop changes update it in
275
445
  * place. SSR renders only the empty div.
@@ -334,9 +504,29 @@ function OAuthConsent(props) {
334
504
  componentProps: props
335
505
  });
336
506
  }
337
- //#endregion
507
+ function CreateOrganization(props) {
508
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Mounted, {
509
+ name: "CreateOrganization",
510
+ componentProps: props
511
+ });
512
+ }
513
+ function OrganizationProfile(props) {
514
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Mounted, {
515
+ name: "OrganizationProfile",
516
+ componentProps: props
517
+ });
518
+ }
519
+ function OrganizationSwitcher(props) {
520
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Mounted, {
521
+ name: "OrganizationSwitcher",
522
+ componentProps: props
523
+ });
524
+ }
338
525
  exports.AuthenticateWithRedirectCallback = AuthenticateWithRedirectCallback;
526
+ exports.CreateOrganization = CreateOrganization;
339
527
  exports.OAuthConsent = OAuthConsent;
528
+ exports.OrganizationProfile = OrganizationProfile;
529
+ exports.OrganizationSwitcher = OrganizationSwitcher;
340
530
  exports.RedirectToSignIn = RedirectToSignIn;
341
531
  exports.RedirectToSignUp = RedirectToSignUp;
342
532
  Object.defineProperty(exports, "ReverificationCancelledError", {
@@ -449,6 +639,8 @@ Object.defineProperty(exports, "isZauthaPasskeyError", {
449
639
  }
450
640
  });
451
641
  exports.useAuth = useAuth;
642
+ exports.useOrganization = useOrganization;
643
+ exports.useOrganizationList = useOrganizationList;
452
644
  exports.useReverification = useReverification;
453
645
  exports.useSession = useSession;
454
646
  exports.useSignIn = useSignIn;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["createContext","useState","Zautha","useMemo","useContext","useSyncExternalStore","useCallback","checkAuthorization","useRef","withReverification","useSyncExternalStore","Children","isValidElement","cloneElement","useRef"],"sources":["../src/provider.tsx","../src/hooks.ts","../src/control.tsx","../src/buttons.tsx","../src/prebuilt.tsx"],"sourcesContent":["import { Zautha, type ZauthaOptions, type ZauthaState } from \"@zautha/js\";\nimport { createContext, useContext, useEffect, useMemo, useState, useSyncExternalStore, type ReactNode } from \"react\";\n\ninterface ZauthaContextValue {\n readonly zautha: Zautha | null;\n /** The snapshot before the instance exists and during server rendering (carries `initialState`). */\n readonly pending: ZauthaState;\n}\n\nconst ZauthaContext = createContext<ZauthaContextValue | undefined>(undefined);\n\nexport interface ZauthaProviderProps extends Omit<ZauthaOptions, \"fetch\"> {\n publishableKey: string;\n children?: ReactNode;\n}\n\n/**\n * Creates the Zautha instance after mount (never during render, so StrictMode's double mount and SSR\n * create no timers or channels), loads it, and disposes it on unmount. Until then hooks report\n * `isLoaded: false`, unless `initialState` (the server's view, e.g. from @zautha/nextjs) says who is signed in.\n */\nexport function ZauthaProvider({ publishableKey, children, ...options }: ZauthaProviderProps): ReactNode {\n const [zautha, setZautha] = useState<Zautha | null>(null);\n const { ui, appearance, localization, signInUrl, signUpUrl, navigate, initialState } = options;\n const [pending] = useState<ZauthaState>(() => ({ ...NO_STATE, initialState: initialState ?? null }));\n\n useEffect(() => {\n const instance = new Zautha(publishableKey, {\n ...(ui === undefined ? {} : { ui }),\n ...(appearance === undefined ? {} : { appearance }),\n ...(localization === undefined ? {} : { localization }),\n ...(signInUrl === undefined ? {} : { signInUrl }),\n ...(signUpUrl === undefined ? {} : { signUpUrl }),\n ...(navigate === undefined ? {} : { navigate }),\n ...(initialState === undefined ? {} : { initialState }),\n });\n // The instance is an external system: it is created here, never during render, and published through state.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setZautha(instance);\n void instance.load();\n return () => {\n instance.dispose();\n setZautha(null);\n };\n // Appearance/localization objects are read at mount; changing the key re-creates the instance.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [publishableKey]);\n\n const value = useMemo(() => ({ zautha, pending }), [zautha, pending]);\n return <ZauthaContext.Provider value={value}>{children}</ZauthaContext.Provider>;\n}\n\n/** The Zautha instance, or null before the provider has created it. */\nexport function useZautha(): Zautha | null {\n return useZauthaContext().zautha;\n}\n\nfunction useZauthaContext(): ZauthaContextValue {\n const value = useContext(ZauthaContext);\n if (value === undefined) throw new Error(\"Zautha hooks and components must be used inside <ZauthaProvider>.\");\n return value;\n}\n\nconst NO_STATE: ZauthaState = {\n status: \"loading\",\n environment: null,\n client: null,\n session: null,\n user: null,\n organization: null,\n initialState: null,\n};\nconst noop = (): (() => void) => () => undefined;\n\n/** Reactive snapshot of the instance state (the loading state, with any initial state, before the instance exists). */\nexport function useZauthaState(): ZauthaState {\n const { zautha, pending } = useZauthaContext();\n return useSyncExternalStore(\n zautha?.subscribe ?? noop,\n () => zautha?.getSnapshot() ?? pending,\n () => pending,\n );\n}\n","import {\n checkAuthorization,\n withReverification,\n type AttemptErrors,\n type FetchStatus,\n type Session,\n type SignInResource,\n type SignUpResource,\n type UserResource,\n type ZauthaState,\n} from \"@zautha/js\";\nimport { useCallback, useLayoutEffect, useRef, useSyncExternalStore } from \"react\";\nimport { useZautha, useZauthaState } from \"./provider\";\n\n/**\n * What `has` checks in the session's active organization: full keys (`org:admin`, `org:invoices:read`). Every condition\n * given must hold; with none, false.\n */\nexport type HasParams = { role?: string; permission?: string };\nexport type Has = (params: HasParams) => boolean;\n\nexport interface UseAuthResult {\n isLoaded: boolean;\n isSignedIn: boolean;\n userId: string | null;\n sessionId: string | null;\n /** The active organization (`org_…`); null without one, and while signed out. */\n orgId: string | null;\n /** The user's role in it, a full key such as `org:admin`. */\n orgRole: string | null;\n /** Its slug; null without one or while the instance has slugs off. */\n orgSlug: string | null;\n /** The role's custom permissions, full keys such as `org:invoices:read`. */\n orgPermissions: readonly string[] | null;\n getToken: (options?: { skipCache?: boolean }) => Promise<string | null>;\n signOut: (options?: { redirectUrl?: string }) => Promise<void>;\n /**\n * From the session token alone, the same rule as every Zautha SDK and your server: false without an active\n * organization, and always false for a system permission (`org:sys_…`, never in the token).\n */\n has: Has;\n}\n\nconst isLoadedStatus = (status: string): boolean => status === \"ready\" || status === \"degraded\";\n\n/** The signed-in session: a pending one (tasks left, e.g. setting up two-step verification) counts as signed out. */\nconst activeSession = (state: ZauthaState): Session | null =>\n state.session?.status === \"active\" ? state.session : null;\n\nexport function useAuth(): UseAuthResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const getToken = useCallback(\n (options?: { skipCache?: boolean }) => zautha?.getToken(options) ?? Promise.resolve(null),\n [zautha],\n );\n const signOut = useCallback(\n (options?: { redirectUrl?: string }) => zautha?.signOut(options) ?? Promise.resolve(),\n [zautha],\n );\n // Until the first load settles, the server's initial state (if any) answers, so nothing flickers.\n const initial = state.status === \"loading\" ? state.initialState : null;\n const session = activeSession(state);\n const userId = initial === null ? (session?.userId ?? null) : initial.userId;\n const sessionId = initial === null ? (session?.id ?? null) : initial.sessionId;\n const signedIn = userId !== null;\n const organization = initial === null ? (session === null ? null : state.organization) : initial.organization;\n const has = useCallback<Has>((params) => checkAuthorization(organization, params), [organization]);\n return {\n isLoaded: isLoadedStatus(state.status) || initial !== null,\n isSignedIn: signedIn,\n userId,\n sessionId,\n orgId: organization?.id ?? null,\n orgRole: organization?.role ?? null,\n orgSlug: organization?.slug ?? null,\n orgPermissions: organization?.permissions ?? null,\n getToken,\n signOut,\n has,\n };\n}\n\n/** The signed-in user with its self-service actions (`user.update`, `user.createEmailAddress`, …). */\nexport function useUser(): { isLoaded: boolean; isSignedIn: boolean; user: UserResource | null } {\n const zautha = useZautha();\n const state = useZauthaState();\n const signedIn = activeSession(state) !== null;\n // zautha.user is rebuilt only when state.user changes, so the resource is stable between renders.\n const user = !signedIn || state.user === null ? null : (zautha?.user ?? null);\n return { isLoaded: isLoadedStatus(state.status), isSignedIn: signedIn, user };\n}\n\n/**\n * Wraps a sensitive action so that it completes after an identity check when it needs one: when `fetcher` throws\n * `ReverificationRequiredError` (e.g. `user.updatePassword`) or resolves to a `Response` with the `403\n * reverification_required` body (your backend with @zautha/backend, @zautha/nextjs or Zautha.AspNetCore), the\n * reverification modal opens and, once the user has verified, `fetcher` runs once more with the same arguments (its\n * token is fresh by then). Closing the modal rejects with `ReverificationCancelledError`. Needs `ui` from @zautha/ui on\n * the provider. The returned function is stable; it always calls the latest `fetcher`.\n */\nexport function useReverification<Args extends unknown[], Result>(\n fetcher: (...args: Args) => Promise<Result>,\n): (...args: Args) => Promise<Result> {\n const zautha = useZautha();\n const latest = useRef(fetcher);\n useLayoutEffect(() => {\n latest.current = fetcher;\n });\n return useCallback(\n (...args: Args) => {\n const call = (...callArgs: Args): Promise<Result> => latest.current(...callArgs);\n // Before the provider has created the instance no modal can open: the action runs as it is.\n return zautha === null ? call(...args) : withReverification(zautha, call)(...args);\n },\n [zautha],\n );\n}\n\n/** The signed-in session; null while signed out or while the session is pending (tasks left). */\nexport function useSession(): { isLoaded: boolean; isSignedIn: boolean; session: Session | null } {\n const state = useZauthaState();\n const session = activeSession(state);\n return { isLoaded: isLoadedStatus(state.status), isSignedIn: session !== null, session };\n}\n\nconst noopSubscribe = (): (() => void) => () => undefined;\n\nfunction useResource<T extends SignInResource | SignUpResource>(resource: T | null) {\n const snapshot = useSyncExternalStore(\n resource?.subscribe ?? noopSubscribe,\n () => resource?.snapshot ?? null,\n () => null,\n );\n return snapshot;\n}\n\nexport interface UseSignInResult {\n isLoaded: boolean;\n /** The sign-in resource; null until the provider has created the instance. */\n signIn: SignInResource | null;\n errors: AttemptErrors;\n fetchStatus: FetchStatus;\n}\n\nconst NO_ERRORS: AttemptErrors = { fields: {}, global: [] };\n\nexport function useSignIn(): UseSignInResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const snapshot = useResource(zautha?.signIn ?? null);\n return {\n isLoaded: isLoadedStatus(state.status),\n signIn: zautha?.signIn ?? null,\n errors: snapshot?.errors ?? NO_ERRORS,\n fetchStatus: snapshot?.fetchStatus ?? \"idle\",\n };\n}\n\nexport interface UseSignUpResult {\n isLoaded: boolean;\n signUp: SignUpResource | null;\n errors: AttemptErrors;\n fetchStatus: FetchStatus;\n}\n\nexport function useSignUp(): UseSignUpResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const snapshot = useResource(zautha?.signUp ?? null);\n return {\n isLoaded: isLoadedStatus(state.status),\n signUp: zautha?.signUp ?? null,\n errors: snapshot?.errors ?? NO_ERRORS,\n fetchStatus: snapshot?.fetchStatus ?? \"idle\",\n };\n}\n","import { useEffect, type ReactNode } from \"react\";\nimport { useAuth, type Has, type HasParams } from \"./hooks\";\nimport { useZautha, useZauthaState } from \"./provider\";\n\nexport type ShowWhen = \"signed-in\" | \"signed-out\" | HasParams | ((has: Has) => boolean);\n\n/**\n * Renders `children` when the condition holds, else `fallback`. Renders nothing until Zautha has\n * loaded, so a signed-in user never sees a signed-out flash.\n */\nexport function Show(props: { when: ShowWhen; fallback?: ReactNode; children?: ReactNode }): ReactNode {\n const { isLoaded, isSignedIn, has } = useAuth();\n if (!isLoaded) return null;\n const { when } = props;\n const pass =\n when === \"signed-in\"\n ? isSignedIn\n : when === \"signed-out\"\n ? !isSignedIn\n : typeof when === \"function\"\n ? when(has)\n : has(when);\n return pass ? props.children : (props.fallback ?? null);\n}\n\nexport function ZauthaLoading(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"loading\" ? props.children : null;\n}\n\n/** Loaded, including degraded (network trouble after load: last known state is shown). */\nexport function ZauthaLoaded(props: { children?: ReactNode }): ReactNode {\n const { status } = useZauthaState();\n return status === \"ready\" || status === \"degraded\" ? props.children : null;\n}\n\nexport function ZauthaDegraded(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"degraded\" ? props.children : null;\n}\n\nexport function ZauthaFailed(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"failed\" ? props.children : null;\n}\n\n/** Sends a signed-out visitor to sign-in once loaded; renders nothing. */\nexport function RedirectToSignIn(props: { redirectUrl?: string }): ReactNode {\n const zautha = useZautha();\n const { isLoaded, isSignedIn } = useAuth();\n const { redirectUrl } = props;\n useEffect(() => {\n if (zautha !== null && isLoaded && !isSignedIn)\n zautha.redirectToSignIn(redirectUrl === undefined ? {} : { redirectUrl });\n }, [zautha, isLoaded, isSignedIn, redirectUrl]);\n return null;\n}\n\nexport function RedirectToSignUp(props: { redirectUrl?: string }): ReactNode {\n const zautha = useZautha();\n const { isLoaded, isSignedIn } = useAuth();\n const { redirectUrl } = props;\n useEffect(() => {\n if (zautha !== null && isLoaded && !isSignedIn)\n zautha.redirectToSignUp(redirectUrl === undefined ? {} : { redirectUrl });\n }, [zautha, isLoaded, isSignedIn, redirectUrl]);\n return null;\n}\n","import { Children, cloneElement, isValidElement, type MouseEvent, type ReactElement, type ReactNode } from \"react\";\nimport { useZautha } from \"./provider\";\n\ninterface ButtonProps {\n /** `redirect` (default) goes to the sign-in page; `modal` opens the prebuilt component (needs `ui`). */\n mode?: \"redirect\" | \"modal\";\n redirectUrl?: string;\n children?: ReactNode;\n}\n\n/** Wraps its single child (or renders a plain button) and wires the click. Unstyled by design. */\nfunction Trigger(props: { children: ReactNode; label: string; onClick: () => void }): ReactNode {\n const child = Children.count(props.children) === 1 ? Children.only(props.children) : null;\n if (isValidElement<{ onClick?: (event: MouseEvent) => void }>(child)) {\n const original = child.props.onClick;\n return cloneElement(child as ReactElement<{ onClick?: (event: MouseEvent) => void }>, {\n onClick: (event: MouseEvent) => {\n original?.(event);\n if (!event.defaultPrevented) props.onClick();\n },\n });\n }\n return (\n <button type=\"button\" onClick={props.onClick}>\n {props.children ?? props.label}\n </button>\n );\n}\n\nexport function SignInButton(props: ButtonProps): ReactNode {\n const zautha = useZautha();\n const options = props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl };\n return (\n <Trigger\n label=\"Sign in\"\n onClick={() => (props.mode === \"modal\" ? zautha?.openSignIn(options) : zautha?.redirectToSignIn(options))}\n >\n {props.children}\n </Trigger>\n );\n}\n\nexport function SignUpButton(props: ButtonProps): ReactNode {\n const zautha = useZautha();\n const options = props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl };\n return (\n <Trigger\n label=\"Sign up\"\n onClick={() => (props.mode === \"modal\" ? zautha?.openSignUp(options) : zautha?.redirectToSignUp(options))}\n >\n {props.children}\n </Trigger>\n );\n}\n\nexport function SignOutButton(props: { redirectUrl?: string; children?: ReactNode }): ReactNode {\n const zautha = useZautha();\n return (\n <Trigger\n label=\"Sign out\"\n onClick={() => void zautha?.signOut(props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl })}\n >\n {props.children}\n </Trigger>\n );\n}\n","import type { UiComponentName } from \"@zautha/js\";\nimport { useEffect, useRef, type ReactNode } from \"react\";\nimport { useZautha } from \"./provider\";\n\n/**\n * Mounts a @zautha/ui component into a div once the instance exists; later prop changes update it in\n * place. SSR renders only the empty div.\n */\nfunction Mounted(props: { name: UiComponentName; componentProps: object }): ReactNode {\n const zautha = useZautha();\n const ref = useRef<HTMLDivElement>(null);\n const mountedWith = useRef<object | null>(null);\n const { name, componentProps } = props;\n\n useEffect(() => {\n const element = ref.current;\n if (zautha === null || element === null) return;\n zautha.mount(name, element, componentProps);\n mountedWith.current = componentProps;\n return () => {\n mountedWith.current = null;\n zautha.unmount(element);\n };\n // componentProps changes are applied by the effect below without remounting.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [zautha, name]);\n\n useEffect(() => {\n const element = ref.current;\n if (zautha === null || element === null || mountedWith.current === null || mountedWith.current === componentProps)\n return;\n mountedWith.current = componentProps;\n zautha.updateMounted(element, componentProps);\n }, [zautha, componentProps]);\n\n return <div ref={ref} />;\n}\n\n// Prop types live in @zautha/ui; they are structural here so @zautha/react has no runtime dependency on it.\nexport function SignIn(props: import(\"@zautha/ui\").SignInProps): ReactNode {\n return <Mounted name=\"SignIn\" componentProps={props} />;\n}\n\nexport function SignUp(props: import(\"@zautha/ui\").SignUpProps): ReactNode {\n return <Mounted name=\"SignUp\" componentProps={props} />;\n}\n\n/** The page a provider sends the user back to: finishes the social sign-in or sign-up (see @zautha/ui). */\nexport function AuthenticateWithRedirectCallback(\n props: import(\"@zautha/ui\").AuthenticateWithRedirectCallbackProps,\n): ReactNode {\n return <Mounted name=\"AuthenticateWithRedirectCallback\" componentProps={props} />;\n}\n\nexport function UserButton(props: import(\"@zautha/ui\").UserButtonProps): ReactNode {\n return <Mounted name=\"UserButton\" componentProps={props} />;\n}\n\nexport function UserProfile(props: import(\"@zautha/ui\").UserProfileProps): ReactNode {\n return <Mounted name=\"UserProfile\" componentProps={props} />;\n}\n\nexport function OAuthConsent(props: import(\"@zautha/ui\").OAuthConsentProps): ReactNode {\n return <Mounted name=\"OAuthConsent\" componentProps={props} />;\n}\n"],"mappings":";;;;;;AASA,MAAM,iBAAA,GAAgBA,MAAAA,cAAAA,CAA8C,KAAA,CAAS;;;;;;AAY7E,SAAgB,eAAe,EAAE,gBAAgB,UAAU,GAAG,WAA2C;CACvG,MAAM,CAAC,QAAQ,cAAA,GAAaC,MAAAA,SAAAA,CAAwB,IAAI;CACxD,MAAM,EAAE,IAAI,YAAY,cAAc,WAAW,WAAW,UAAU,iBAAiB;CACvF,MAAM,CAAC,YAAA,GAAWA,MAAAA,SAAAA,QAA6B;EAAE,GAAG;EAAU,cAAc,gBAAgB;CAAK,EAAE;CAEnG,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,WAAW,IAAIC,WAAAA,OAAO,gBAAgB;GAC1C,GAAI,OAAO,KAAA,IAAY,CAAC,IAAI,EAAE,GAAG;GACjC,GAAI,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW;GACjD,GAAI,iBAAiB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa;GACrD,GAAI,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU;GAC/C,GAAI,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU;GAC/C,GAAI,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS;GAC7C,GAAI,iBAAiB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa;EACvD,CAAC;EAGD,UAAU,QAAQ;EAClB,SAAc,KAAK;EACnB,aAAa;GACX,SAAS,QAAQ;GACjB,UAAU,IAAI;EAChB;CAGF,GAAG,CAAC,cAAc,CAAC;CAEnB,MAAM,SAAA,GAAQC,MAAAA,QAAAA,QAAe;EAAE;EAAQ;CAAQ,IAAI,CAAC,QAAQ,OAAO,CAAC;CACpE,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,cAAc,UAAf;EAA+B;EAAQ;CAAiC,CAAA;AACjF;;AAGA,SAAgB,YAA2B;CACzC,OAAO,iBAAiB,CAAC,CAAC;AAC5B;AAEA,SAAS,mBAAuC;CAC9C,MAAM,SAAA,GAAQC,MAAAA,WAAAA,CAAW,aAAa;CACtC,IAAI,UAAU,KAAA,GAAW,MAAM,IAAI,MAAM,mEAAmE;CAC5G,OAAO;AACT;AAEA,MAAM,WAAwB;CAC5B,QAAQ;CACR,aAAa;CACb,QAAQ;CACR,SAAS;CACT,MAAM;CACN,cAAc;CACd,cAAc;AAChB;AACA,MAAM,mBAAiC,KAAA;;AAGvC,SAAgB,iBAA8B;CAC5C,MAAM,EAAE,QAAQ,YAAY,iBAAiB;CAC7C,QAAA,GAAOC,MAAAA,qBAAAA,CACL,QAAQ,aAAa,YACf,QAAQ,YAAY,KAAK,eACzB,OACR;AACF;;;ACvCA,MAAM,kBAAkB,WAA4B,WAAW,WAAW,WAAW;;AAGrF,MAAM,iBAAiB,UACrB,MAAM,SAAS,WAAW,WAAW,MAAM,UAAU;AAEvD,SAAgB,UAAyB;CACvC,MAAM,SAAS,UAAU;CACzB,MAAM,QAAQ,eAAe;CAC7B,MAAM,YAAA,GAAWC,MAAAA,YAAAA,EACd,YAAsC,QAAQ,SAAS,OAAO,KAAK,QAAQ,QAAQ,IAAI,GACxF,CAAC,MAAM,CACT;CACA,MAAM,WAAA,GAAUA,MAAAA,YAAAA,EACb,YAAuC,QAAQ,QAAQ,OAAO,KAAK,QAAQ,QAAQ,GACpF,CAAC,MAAM,CACT;CAEA,MAAM,UAAU,MAAM,WAAW,YAAY,MAAM,eAAe;CAClE,MAAM,UAAU,cAAc,KAAK;CACnC,MAAM,SAAS,YAAY,OAAQ,SAAS,UAAU,OAAQ,QAAQ;CACtE,MAAM,YAAY,YAAY,OAAQ,SAAS,MAAM,OAAQ,QAAQ;CACrE,MAAM,WAAW,WAAW;CAC5B,MAAM,eAAe,YAAY,OAAQ,YAAY,OAAO,OAAO,MAAM,eAAgB,QAAQ;CACjG,MAAM,OAAA,GAAMA,MAAAA,YAAAA,EAAkB,YAAA,GAAWC,WAAAA,mBAAAA,CAAmB,cAAc,MAAM,GAAG,CAAC,YAAY,CAAC;CACjG,OAAO;EACL,UAAU,eAAe,MAAM,MAAM,KAAK,YAAY;EACtD,YAAY;EACZ;EACA;EACA,OAAO,cAAc,MAAM;EAC3B,SAAS,cAAc,QAAQ;EAC/B,SAAS,cAAc,QAAQ;EAC/B,gBAAgB,cAAc,eAAe;EAC7C;EACA;EACA;CACF;AACF;;AAGA,SAAgB,UAAiF;CAC/F,MAAM,SAAS,UAAU;CACzB,MAAM,QAAQ,eAAe;CAC7B,MAAM,WAAW,cAAc,KAAK,MAAM;CAE1C,MAAM,OAAO,CAAC,YAAY,MAAM,SAAS,OAAO,OAAQ,QAAQ,QAAQ;CACxE,OAAO;EAAE,UAAU,eAAe,MAAM,MAAM;EAAG,YAAY;EAAU;CAAK;AAC9E;;;;;;;;;AAUA,SAAgB,kBACd,SACoC;CACpC,MAAM,SAAS,UAAU;CACzB,MAAM,UAAA,GAASC,MAAAA,OAAAA,CAAO,OAAO;CAC7B,CAAA,GAAA,MAAA,gBAAA,OAAsB;EACpB,OAAO,UAAU;CACnB,CAAC;CACD,QAAA,GAAOF,MAAAA,YAAAA,EACJ,GAAG,SAAe;EACjB,MAAM,QAAQ,GAAG,aAAoC,OAAO,QAAQ,GAAG,QAAQ;EAE/E,OAAO,WAAW,OAAO,KAAK,GAAG,IAAI,KAAA,GAAIG,WAAAA,mBAAAA,CAAmB,QAAQ,IAAI,CAAC,CAAC,GAAG,IAAI;CACnF,GACA,CAAC,MAAM,CACT;AACF;;AAGA,SAAgB,aAAkF;CAChG,MAAM,QAAQ,eAAe;CAC7B,MAAM,UAAU,cAAc,KAAK;CACnC,OAAO;EAAE,UAAU,eAAe,MAAM,MAAM;EAAG,YAAY,YAAY;EAAM;CAAQ;AACzF;AAEA,MAAM,4BAA0C,KAAA;AAEhD,SAAS,YAAuD,UAAoB;CAMlF,QAAA,GALiBC,MAAAA,qBAAAA,CACf,UAAU,aAAa,qBACjB,UAAU,YAAY,YACtB,IAEM;AAChB;AAUA,MAAM,YAA2B;CAAE,QAAQ,CAAC;CAAG,QAAQ,CAAC;AAAE;AAE1D,SAAgB,YAA6B;CAC3C,MAAM,SAAS,UAAU;CACzB,MAAM,QAAQ,eAAe;CAC7B,MAAM,WAAW,YAAY,QAAQ,UAAU,IAAI;CACnD,OAAO;EACL,UAAU,eAAe,MAAM,MAAM;EACrC,QAAQ,QAAQ,UAAU;EAC1B,QAAQ,UAAU,UAAU;EAC5B,aAAa,UAAU,eAAe;CACxC;AACF;AASA,SAAgB,YAA6B;CAC3C,MAAM,SAAS,UAAU;CACzB,MAAM,QAAQ,eAAe;CAC7B,MAAM,WAAW,YAAY,QAAQ,UAAU,IAAI;CACnD,OAAO;EACL,UAAU,eAAe,MAAM,MAAM;EACrC,QAAQ,QAAQ,UAAU;EAC1B,QAAQ,UAAU,UAAU;EAC5B,aAAa,UAAU,eAAe;CACxC;AACF;;;;;;;ACtKA,SAAgB,KAAK,OAAkF;CACrG,MAAM,EAAE,UAAU,YAAY,QAAQ,QAAQ;CAC9C,IAAI,CAAC,UAAU,OAAO;CACtB,MAAM,EAAE,SAAS;CASjB,QAPE,SAAS,cACL,aACA,SAAS,eACP,CAAC,aACD,OAAO,SAAS,aACd,KAAK,GAAG,IACR,IAAI,IAAI,KACJ,MAAM,WAAY,MAAM,YAAY;AACpD;AAEA,SAAgB,cAAc,OAA4C;CACxE,OAAO,eAAe,CAAC,CAAC,WAAW,YAAY,MAAM,WAAW;AAClE;;AAGA,SAAgB,aAAa,OAA4C;CACvE,MAAM,EAAE,WAAW,eAAe;CAClC,OAAO,WAAW,WAAW,WAAW,aAAa,MAAM,WAAW;AACxE;AAEA,SAAgB,eAAe,OAA4C;CACzE,OAAO,eAAe,CAAC,CAAC,WAAW,aAAa,MAAM,WAAW;AACnE;AAEA,SAAgB,aAAa,OAA4C;CACvE,OAAO,eAAe,CAAC,CAAC,WAAW,WAAW,MAAM,WAAW;AACjE;;AAGA,SAAgB,iBAAiB,OAA4C;CAC3E,MAAM,SAAS,UAAU;CACzB,MAAM,EAAE,UAAU,eAAe,QAAQ;CACzC,MAAM,EAAE,gBAAgB;CACxB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,WAAW,QAAQ,YAAY,CAAC,YAClC,OAAO,iBAAiB,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY,CAAC;CAC5E,GAAG;EAAC;EAAQ;EAAU;EAAY;CAAW,CAAC;CAC9C,OAAO;AACT;AAEA,SAAgB,iBAAiB,OAA4C;CAC3E,MAAM,SAAS,UAAU;CACzB,MAAM,EAAE,UAAU,eAAe,QAAQ;CACzC,MAAM,EAAE,gBAAgB;CACxB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,WAAW,QAAQ,YAAY,CAAC,YAClC,OAAO,iBAAiB,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY,CAAC;CAC5E,GAAG;EAAC;EAAQ;EAAU;EAAY;CAAW,CAAC;CAC9C,OAAO;AACT;;;;ACrDA,SAAS,QAAQ,OAA+E;CAC9F,MAAM,QAAQC,MAAAA,SAAS,MAAM,MAAM,QAAQ,MAAM,IAAIA,MAAAA,SAAS,KAAK,MAAM,QAAQ,IAAI;CACrF,KAAA,GAAIC,MAAAA,eAAAA,CAA0D,KAAK,GAAG;EACpE,MAAM,WAAW,MAAM,MAAM;EAC7B,QAAA,GAAOC,MAAAA,aAAAA,CAAa,OAAkE,EACpF,UAAU,UAAsB;GAC9B,WAAW,KAAK;GAChB,IAAI,CAAC,MAAM,kBAAkB,MAAM,QAAQ;EAC7C,EACF,CAAC;CACH;CACA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;EAAQ,MAAK;EAAS,SAAS,MAAM;EAClC,UAAA,MAAM,YAAY,MAAM;CACnB,CAAA;AAEZ;AAEA,SAAgB,aAAa,OAA+B;CAC1D,MAAM,SAAS,UAAU;CACzB,MAAM,UAAU,MAAM,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,MAAM,YAAY;CACxF,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;EACE,OAAM;EACN,eAAgB,MAAM,SAAS,UAAU,QAAQ,WAAW,OAAO,IAAI,QAAQ,iBAAiB,OAAO;EAEtG,UAAA,MAAM;CACA,CAAA;AAEb;AAEA,SAAgB,aAAa,OAA+B;CAC1D,MAAM,SAAS,UAAU;CACzB,MAAM,UAAU,MAAM,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,MAAM,YAAY;CACxF,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;EACE,OAAM;EACN,eAAgB,MAAM,SAAS,UAAU,QAAQ,WAAW,OAAO,IAAI,QAAQ,iBAAiB,OAAO;EAEtG,UAAA,MAAM;CACA,CAAA;AAEb;AAEA,SAAgB,cAAc,OAAkE;CAC9F,MAAM,SAAS,UAAU;CACzB,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;EACE,OAAM;EACN,eAAe,KAAK,QAAQ,QAAQ,MAAM,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,MAAM,YAAY,CAAC;EAE5G,UAAA,MAAM;CACA,CAAA;AAEb;;;;;;;ACzDA,SAAS,QAAQ,OAAqE;CACpF,MAAM,SAAS,UAAU;CACzB,MAAM,OAAA,GAAMC,MAAAA,OAAAA,CAAuB,IAAI;CACvC,MAAM,eAAA,GAAcA,MAAAA,OAAAA,CAAsB,IAAI;CAC9C,MAAM,EAAE,MAAM,mBAAmB;CAEjC,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,UAAU,IAAI;EACpB,IAAI,WAAW,QAAQ,YAAY,MAAM;EACzC,OAAO,MAAM,MAAM,SAAS,cAAc;EAC1C,YAAY,UAAU;EACtB,aAAa;GACX,YAAY,UAAU;GACtB,OAAO,QAAQ,OAAO;EACxB;CAGF,GAAG,CAAC,QAAQ,IAAI,CAAC;CAEjB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,UAAU,IAAI;EACpB,IAAI,WAAW,QAAQ,YAAY,QAAQ,YAAY,YAAY,QAAQ,YAAY,YAAY,gBACjG;EACF,YAAY,UAAU;EACtB,OAAO,cAAc,SAAS,cAAc;CAC9C,GAAG,CAAC,QAAQ,cAAc,CAAC;CAE3B,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD,EAAU,IAAM,CAAA;AACzB;AAGA,SAAgB,OAAO,OAAoD;CACzE,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;EAAS,MAAK;EAAS,gBAAgB;CAAQ,CAAA;AACxD;AAEA,SAAgB,OAAO,OAAoD;CACzE,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;EAAS,MAAK;EAAS,gBAAgB;CAAQ,CAAA;AACxD;;AAGA,SAAgB,iCACd,OACW;CACX,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;EAAS,MAAK;EAAmC,gBAAgB;CAAQ,CAAA;AAClF;AAEA,SAAgB,WAAW,OAAwD;CACjF,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;EAAS,MAAK;EAAa,gBAAgB;CAAQ,CAAA;AAC5D;AAEA,SAAgB,YAAY,OAAyD;CACnF,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;EAAS,MAAK;EAAc,gBAAgB;CAAQ,CAAA;AAC7D;AAEA,SAAgB,aAAa,OAA0D;CACrF,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;EAAS,MAAK;EAAe,gBAAgB;CAAQ,CAAA;AAC9D"}
1
+ {"version":3,"file":"index.cjs","names":["createContext","useState","Zautha","useMemo","useContext","useSyncExternalStore","useState","useRef","useCallback","useCallback","checkAuthorization","useRef","withReverification","useSyncExternalStore","ZauthaError","Children","isValidElement","cloneElement","useRef"],"sources":["../src/provider.tsx","../src/pagination.ts","../src/hooks.ts","../src/control.tsx","../src/buttons.tsx","../src/prebuilt.tsx"],"sourcesContent":["import { Zautha, type ZauthaOptions, type ZauthaState } from \"@zautha/js\";\nimport { createContext, useContext, useEffect, useMemo, useState, useSyncExternalStore, type ReactNode } from \"react\";\n\ninterface ZauthaContextValue {\n readonly zautha: Zautha | null;\n /** The snapshot before the instance exists and during server rendering (carries `initialState`). */\n readonly pending: ZauthaState;\n}\n\nconst ZauthaContext = createContext<ZauthaContextValue | undefined>(undefined);\n\nexport interface ZauthaProviderProps extends Omit<ZauthaOptions, \"fetch\"> {\n publishableKey: string;\n children?: ReactNode;\n}\n\n/**\n * Creates the Zautha instance after mount (never during render, so StrictMode's double mount and SSR\n * create no timers or channels), loads it, and disposes it on unmount. Until then hooks report\n * `isLoaded: false`, unless `initialState` (the server's view, e.g. from @zautha/nextjs) says who is signed in.\n */\nexport function ZauthaProvider({ publishableKey, children, ...options }: ZauthaProviderProps): ReactNode {\n const [zautha, setZautha] = useState<Zautha | null>(null);\n const { ui, appearance, localization, signInUrl, signUpUrl, navigate, initialState } = options;\n const [pending] = useState<ZauthaState>(() => ({ ...NO_STATE, initialState: initialState ?? null }));\n\n useEffect(() => {\n const instance = new Zautha(publishableKey, {\n ...(ui === undefined ? {} : { ui }),\n ...(appearance === undefined ? {} : { appearance }),\n ...(localization === undefined ? {} : { localization }),\n ...(signInUrl === undefined ? {} : { signInUrl }),\n ...(signUpUrl === undefined ? {} : { signUpUrl }),\n ...(navigate === undefined ? {} : { navigate }),\n ...(initialState === undefined ? {} : { initialState }),\n });\n // The instance is an external system: it is created here, never during render, and published through state.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setZautha(instance);\n void instance.load();\n return () => {\n instance.dispose();\n setZautha(null);\n };\n // Appearance/localization objects are read at mount; changing the key re-creates the instance.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [publishableKey]);\n\n const value = useMemo(() => ({ zautha, pending }), [zautha, pending]);\n return <ZauthaContext.Provider value={value}>{children}</ZauthaContext.Provider>;\n}\n\n/** The Zautha instance, or null before the provider has created it. */\nexport function useZautha(): Zautha | null {\n return useZauthaContext().zautha;\n}\n\nfunction useZauthaContext(): ZauthaContextValue {\n const value = useContext(ZauthaContext);\n if (value === undefined) throw new Error(\"Zautha hooks and components must be used inside <ZauthaProvider>.\");\n return value;\n}\n\nconst NO_STATE: ZauthaState = {\n status: \"loading\",\n environment: null,\n client: null,\n session: null,\n user: null,\n organization: null,\n initialState: null,\n};\nconst noop = (): (() => void) => () => undefined;\n\n/** Reactive snapshot of the instance state (the loading state, with any initial state, before the instance exists). */\nexport function useZauthaState(): ZauthaState {\n const { zautha, pending } = useZauthaContext();\n return useSyncExternalStore(\n zautha?.subscribe ?? noop,\n () => zautha?.getSnapshot() ?? pending,\n () => pending,\n );\n}\n","import type { Paginated } from \"@zautha/js\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n/** A list's page size (default 10, the API's) and the page to start on (default 1). */\nexport interface PaginationParams {\n pageSize?: number;\n initialPage?: number;\n}\n\n/**\n * One page of a list and how to move through it. `isLoading`: the page has no data yet; `isFetching`: a request for it\n * is in flight (also while `revalidate()` reads it again). A failed read leaves `data` empty and sets `error`.\n */\nexport interface PaginatedResult<T> {\n data: T[];\n /** How many there are in all. */\n count: number;\n page: number;\n pageCount: number;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n fetchNext: () => void;\n fetchPrevious: () => void;\n fetchPage: (page: number) => void;\n /** Reads the current page again; resolves once it has been read. */\n revalidate: () => Promise<void>;\n}\n\n/** What a page read gets: 1–100 items after `offset`. */\nexport type PageLoader<T> = (page: { limit: number; offset: number }) => Promise<Paginated<T>>;\n\n/** A list to read: `key` names what is listed (the user, the organization, the filters); `load` reads one page. */\nexport interface PageSource<T> {\n readonly key: string;\n readonly load: PageLoader<T>;\n}\n\ninterface Settled<T> {\n readonly request: string;\n readonly key: string;\n readonly page: number;\n readonly data: T[];\n readonly count: number;\n readonly error: Error | null;\n}\n\n/**\n * The pages of one list. Without a source nothing is read and the list is empty; a source with a new key starts again on\n * the initial page. A response to an older request (another page, key or revalidation) is dropped, so it never\n * overwrites a newer one.\n */\nexport function usePages<T>(\n source: PageSource<T> | null,\n params: PaginationParams | true | undefined,\n): PaginatedResult<T> {\n const key = source?.key ?? null;\n const { pageSize = 10, initialPage = 1 } = params === true || params === undefined ? {} : params;\n const [at, setAt] = useState({ key, page: initialPage, version: 0 });\n const [settled, setSettled] = useState<Settled<T> | null>(null);\n const latest = useRef(0);\n const waiting = useRef<(() => void)[]>([]);\n if (at.key !== key) {\n // Another list (also an earlier one again): start on its initial page with a fresh read, whatever was shown before.\n setAt({ key, page: initialPage, version: 0 });\n setSettled(null);\n }\n const { page, version } = at.key === key ? at : { page: initialPage, version: 0 };\n const request = JSON.stringify([key, page, pageSize, version]);\n const loader = useRef(source?.load);\n useEffect(() => {\n loader.current = source?.load;\n });\n\n useEffect(() => {\n const id = ++latest.current;\n const settle = (data: T[], count: number, error: Error | null): void => {\n if (latest.current !== id) return;\n if (key !== null) setSettled({ request, key, page, data, count, error });\n for (const resolve of waiting.current.splice(0)) resolve();\n };\n if (key === null || loader.current === undefined) return settle([], 0, null);\n loader.current({ limit: pageSize, offset: (page - 1) * pageSize }).then(\n (r) => settle(r.data, r.totalCount, null),\n (error: unknown) => settle([], 0, error instanceof Error ? error : new Error(String(error))),\n );\n // `request` covers key, page, pageSize and version.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [request]);\n\n const shown = settled !== null && settled.key === key && settled.page === page ? settled : null;\n const isFetching = key !== null && settled?.request !== request;\n const count = shown?.count ?? 0;\n const pageCount = Math.ceil(count / pageSize);\n const go = useCallback(\n (to: (page: number) => number) =>\n setAt((a) => {\n const from = a.key === key ? a.page : initialPage;\n return { key, page: Math.max(1, to(from)), version: a.key === key ? a.version : 0 };\n }),\n [key, initialPage],\n );\n const revalidate = useCallback(\n () =>\n new Promise<void>((resolve) => {\n waiting.current.push(resolve);\n setAt((a) => (a.key === key ? { ...a, version: a.version + 1 } : { key, page: initialPage, version: 1 }));\n }),\n [key, initialPage],\n );\n return {\n data: shown?.data ?? [],\n count,\n page,\n pageCount,\n isLoading: isFetching && shown === null,\n isFetching,\n error: shown?.error ?? null,\n hasNextPage: page < pageCount,\n hasPreviousPage: page > 1,\n fetchNext: useCallback(() => go((p) => p + 1), [go]),\n fetchPrevious: useCallback(() => go((p) => p - 1), [go]),\n fetchPage: useCallback((n: number) => go(() => n), [go]),\n revalidate,\n };\n}\n","import {\n checkAuthorization,\n withReverification,\n ZauthaError,\n type AttemptErrors,\n type FetchStatus,\n type OrganizationInvitationResource,\n type OrganizationInvitationStatus,\n type OrganizationMembership,\n type OrganizationMembershipResource,\n type OrganizationResource,\n type Session,\n type SessionActor,\n type SignInResource,\n type SignUpResource,\n type UserOrganizationInvitationResource,\n type UserResource,\n type ZauthaState,\n} from \"@zautha/js\";\nimport { useCallback, useLayoutEffect, useRef, useSyncExternalStore } from \"react\";\nimport { usePages, type PageLoader, type PageSource, type PaginatedResult, type PaginationParams } from \"./pagination\";\nimport { useZautha, useZauthaState } from \"./provider\";\n\n/**\n * What `has` checks in the session's active organization: full keys (`org:admin`, `org:invoices:read`). Every condition\n * given must hold; with none, false.\n */\nexport type HasParams = { role?: string; permission?: string };\nexport type Has = (params: HasParams) => boolean;\n\nexport interface UseAuthResult {\n isLoaded: boolean;\n isSignedIn: boolean;\n userId: string | null;\n sessionId: string | null;\n /** The active organization (`org_…`); null without one, and while signed out. */\n orgId: string | null;\n /** The user's role in it, a full key such as `org:admin`. */\n orgRole: string | null;\n /** Its slug; null without one or while the instance has slugs off. */\n orgSlug: string | null;\n /** The role's custom permissions, full keys such as `org:invoices:read`. */\n orgPermissions: readonly string[] | null;\n /**\n * Who is impersonating the user (an impersonation session; the token's `act` claim); null for the user's own session\n * and while signed out. With `ui` from @zautha/ui the provider shows the impersonation band by itself.\n */\n actor: SessionActor | null;\n getToken: (options?: { skipCache?: boolean }) => Promise<string | null>;\n signOut: (options?: { redirectUrl?: string }) => Promise<void>;\n /**\n * From the session token alone, the same rule as every Zautha SDK and your server: false without an active\n * organization, and always false for a system permission (`org:sys_…`, never in the token).\n */\n has: Has;\n}\n\nconst isLoadedStatus = (status: string): boolean => status === \"ready\" || status === \"degraded\";\n\n/** The signed-in session: a pending one (tasks left, e.g. setting up two-step verification) counts as signed out. */\nconst activeSession = (state: ZauthaState): Session | null =>\n state.session?.status === \"active\" ? state.session : null;\n\nexport function useAuth(): UseAuthResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const getToken = useCallback(\n (options?: { skipCache?: boolean }) => zautha?.getToken(options) ?? Promise.resolve(null),\n [zautha],\n );\n const signOut = useCallback(\n (options?: { redirectUrl?: string }) => zautha?.signOut(options) ?? Promise.resolve(),\n [zautha],\n );\n // Until the first load settles, the server's initial state (if any) answers, so nothing flickers.\n const initial = state.status === \"loading\" ? state.initialState : null;\n const session = activeSession(state);\n const userId = initial === null ? (session?.userId ?? null) : initial.userId;\n const sessionId = initial === null ? (session?.id ?? null) : initial.sessionId;\n const signedIn = userId !== null;\n const organization = initial === null ? (session === null ? null : state.organization) : initial.organization;\n const actor = initial === null ? (session?.actor ?? null) : initial.actor;\n const has = useCallback<Has>((params) => checkAuthorization(organization, params), [organization]);\n return {\n isLoaded: isLoadedStatus(state.status) || initial !== null,\n isSignedIn: signedIn,\n userId,\n sessionId,\n orgId: organization?.id ?? null,\n orgRole: organization?.role ?? null,\n orgSlug: organization?.slug ?? null,\n orgPermissions: organization?.permissions ?? null,\n actor,\n getToken,\n signOut,\n has,\n };\n}\n\n/** The signed-in user with its self-service actions (`user.update`, `user.createEmailAddress`, …). */\nexport function useUser(): { isLoaded: boolean; isSignedIn: boolean; user: UserResource | null } {\n const zautha = useZautha();\n const state = useZauthaState();\n const signedIn = activeSession(state) !== null;\n // zautha.user is rebuilt only when state.user changes, so the resource is stable between renders.\n const user = !signedIn || state.user === null ? null : (zautha?.user ?? null);\n return { isLoaded: isLoadedStatus(state.status), isSignedIn: signedIn, user };\n}\n\n/**\n * Wraps a sensitive action so that it completes after an identity check when it needs one: when `fetcher` throws\n * `ReverificationRequiredError` (e.g. `user.updatePassword`) or resolves to a `Response` with the `403\n * reverification_required` body (your backend with @zautha/backend, @zautha/nextjs or Zautha.AspNetCore), the\n * reverification modal opens and, once the user has verified, `fetcher` runs once more with the same arguments (its\n * token is fresh by then). Closing the modal rejects with `ReverificationCancelledError`. Needs `ui` from @zautha/ui on\n * the provider. The returned function is stable; it always calls the latest `fetcher`.\n */\nexport function useReverification<Args extends unknown[], Result>(\n fetcher: (...args: Args) => Promise<Result>,\n): (...args: Args) => Promise<Result> {\n const zautha = useZautha();\n const latest = useRef(fetcher);\n useLayoutEffect(() => {\n latest.current = fetcher;\n });\n return useCallback(\n (...args: Args) => {\n const call = (...callArgs: Args): Promise<Result> => latest.current(...callArgs);\n // Before the provider has created the instance no modal can open: the action runs as it is.\n return zautha === null ? call(...args) : withReverification(zautha, call)(...args);\n },\n [zautha],\n );\n}\n\n/** The signed-in session; null while signed out or while the session is pending (tasks left). */\nexport function useSession(): { isLoaded: boolean; isSignedIn: boolean; session: Session | null } {\n const state = useZauthaState();\n const session = activeSession(state);\n return { isLoaded: isLoadedStatus(state.status), isSignedIn: session !== null, session };\n}\n\nconst noopSubscribe = (): (() => void) => () => undefined;\n\nfunction useResource<T extends SignInResource | SignUpResource>(resource: T | null) {\n const snapshot = useSyncExternalStore(\n resource?.subscribe ?? noopSubscribe,\n () => resource?.snapshot ?? null,\n () => null,\n );\n return snapshot;\n}\n\nexport interface UseSignInResult {\n isLoaded: boolean;\n /** The sign-in resource; null until the provider has created the instance. */\n signIn: SignInResource | null;\n errors: AttemptErrors;\n fetchStatus: FetchStatus;\n}\n\nconst NO_ERRORS: AttemptErrors = { fields: {}, global: [] };\n\nexport function useSignIn(): UseSignInResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const snapshot = useResource(zautha?.signIn ?? null);\n return {\n isLoaded: isLoadedStatus(state.status),\n signIn: zautha?.signIn ?? null,\n errors: snapshot?.errors ?? NO_ERRORS,\n fetchStatus: snapshot?.fetchStatus ?? \"idle\",\n };\n}\n\nexport interface UseSignUpResult {\n isLoaded: boolean;\n signUp: SignUpResource | null;\n errors: AttemptErrors;\n fetchStatus: FetchStatus;\n}\n\nexport function useSignUp(): UseSignUpResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const snapshot = useResource(zautha?.signUp ?? null);\n return {\n isLoaded: isLoadedStatus(state.status),\n signUp: zautha?.signUp ?? null,\n errors: snapshot?.errors ?? NO_ERRORS,\n fetchStatus: snapshot?.fetchStatus ?? \"idle\",\n };\n}\n\n/** A list a hook reads only when asked: `true` for the defaults, or the page size, the first page and the filters. */\nexport type ListParams<Filters = object> = true | (PaginationParams & Filters);\n\nexport interface UseOrganizationParams {\n /** The active organization's members (needs `org:sys_memberships:read`), filtered by a role key. */\n memberships?: ListParams<{ role?: string }>;\n /** Its invitations, filtered by status; read only for a member with `org:sys_memberships:manage` (else empty). */\n invitations?: ListParams<{ status?: OrganizationInvitationStatus[] }>;\n}\n\nexport interface UseOrganizationResult {\n isLoaded: boolean;\n /** The session's active organization with the member's actions; null without one, while signed out or pending. */\n organization: OrganizationResource | null;\n /** The user's membership of it: role and every permission of the role, system ones included (to show buttons). */\n membership: OrganizationMembershipResource | null;\n /** Only when asked for in the params. */\n memberships?: PaginatedResult<OrganizationMembership>;\n invitations?: PaginatedResult<OrganizationInvitationResource>;\n}\n\nexport interface UseOrganizationListParams {\n /** The user's memberships, newest first. */\n userMemberships?: ListParams;\n /** The invitations to the user's verified addresses; by default the pending ones. */\n userInvitations?: ListParams<{ status?: OrganizationInvitationStatus[] }>;\n}\n\nexport interface UseOrganizationListResult {\n isLoaded: boolean;\n /** Creates an organization with the user in it; it is not made active (`setActive` does that). */\n createOrganization: (params: { name: string; slug?: string }) => Promise<OrganizationResource>;\n /** Makes an organization (id or slug) the session's active one; null is the personal account. */\n setActive: (params: { organization: string | null }) => Promise<void>;\n userMemberships?: PaginatedResult<OrganizationMembershipResource>;\n userInvitations?: PaginatedResult<UserOrganizationInvitationResource>;\n}\n\n/** A list's filters: its params without the page size and the first page. */\nfunction filtersOf<F extends object>(params: ListParams<F>): F {\n const filters = { ...(params === true ? {} : params) } as PaginationParams & F;\n delete filters.pageSize;\n delete filters.initialPage;\n return filters;\n}\n\n/** A list of `owner` read with `load`: its key (`owner` and the params, so new filters start the list again). */\nconst list = <T>(owner: string, params: ListParams<object>, load: PageLoader<T>): PageSource<T> => ({\n key: `${owner}:${JSON.stringify(params)}`,\n load,\n});\n\n/** The signed-in user (an active session's) and whether hooks that read it are loaded. */\nfunction useSignedInUser(): { isLoaded: boolean; state: ZauthaState; user: UserResource | null } {\n const zautha = useZautha();\n const state = useZauthaState();\n const user = activeSession(state) === null ? null : (zautha?.user ?? null);\n // An active session is loaded once its user is.\n return { isLoaded: isLoadedStatus(state.status) && (activeSession(state) === null || user !== null), state, user };\n}\n\n/**\n * The session's active organization and the user's membership of it, from the session token and the user (no request of\n * its own), and on request its members and invitations, page by page. The lists start again on their first page when\n * the active organization changes.\n */\nexport function useOrganization(params: UseOrganizationParams = {}): UseOrganizationResult {\n const { isLoaded, state, user } = useSignedInUser();\n const id = state.organization?.id;\n const membership = user?.organizationMemberships.find((m) => m.organization.id === id) ?? null;\n const organization = membership?.organization ?? null;\n // The user's own membership: its user is the signed-in one.\n const owner = membership === null ? \"\" : `${membership.publicUserData.userId}:${membership.organization.id}`;\n const { memberships, invitations } = params;\n const manages = membership?.permissions.includes(\"org:sys_memberships:manage\") === true;\n const members = usePages(\n organization === null || memberships === undefined\n ? null\n : list(owner, memberships, (page) => organization.getMemberships({ ...filtersOf(memberships), ...page })),\n memberships,\n );\n const invited = usePages(\n organization === null || invitations === undefined || !manages\n ? null\n : list(owner, invitations, (page) => organization.getInvitations({ ...filtersOf(invitations), ...page })),\n invitations,\n );\n return {\n isLoaded,\n organization,\n membership,\n ...(memberships === undefined ? {} : { memberships: members }),\n ...(invitations === undefined ? {} : { invitations: invited }),\n };\n}\n\n/**\n * Creating an organization and choosing the active one, and on request the user's memberships and the invitations to\n * the user, page by page.\n */\nexport function useOrganizationList(params: UseOrganizationListParams = {}): UseOrganizationListResult {\n const zautha = useZautha();\n const { isLoaded, user } = useSignedInUser();\n const { userMemberships, userInvitations } = params;\n const memberships = usePages(\n user === null || userMemberships === undefined\n ? null\n : list(user.id, userMemberships, (page) => user.getOrganizationMemberships(page)),\n userMemberships,\n );\n const invitations = usePages(\n user === null || userInvitations === undefined\n ? null\n : list(user.id, userInvitations, (page) =>\n user.getOrganizationInvitations({ ...filtersOf(userInvitations), ...page }),\n ),\n userInvitations,\n );\n const createOrganization = useCallback(\n (p: { name: string; slug?: string }) => zautha?.createOrganization(p) ?? notLoaded(),\n [zautha],\n );\n const setActive = useCallback((p: { organization: string | null }) => zautha?.setActive(p) ?? notLoaded(), [zautha]);\n return {\n isLoaded,\n createOrganization,\n setActive,\n ...(userMemberships === undefined ? {} : { userMemberships: memberships }),\n ...(userInvitations === undefined ? {} : { userInvitations: invitations }),\n };\n}\n\nconst notLoaded = (): Promise<never> => Promise.reject(new ZauthaError(\"Zautha is not loaded yet.\"));\n","import { useEffect, type ReactNode } from \"react\";\nimport { useAuth, type Has, type HasParams } from \"./hooks\";\nimport { useZautha, useZauthaState } from \"./provider\";\n\nexport type ShowWhen = \"signed-in\" | \"signed-out\" | HasParams | ((has: Has) => boolean);\n\n/**\n * Renders `children` when the condition holds, else `fallback`. Renders nothing until Zautha has\n * loaded, so a signed-in user never sees a signed-out flash.\n */\nexport function Show(props: { when: ShowWhen; fallback?: ReactNode; children?: ReactNode }): ReactNode {\n const { isLoaded, isSignedIn, has } = useAuth();\n if (!isLoaded) return null;\n const { when } = props;\n const pass =\n when === \"signed-in\"\n ? isSignedIn\n : when === \"signed-out\"\n ? !isSignedIn\n : typeof when === \"function\"\n ? when(has)\n : has(when);\n return pass ? props.children : (props.fallback ?? null);\n}\n\nexport function ZauthaLoading(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"loading\" ? props.children : null;\n}\n\n/** Loaded, including degraded (network trouble after load: last known state is shown). */\nexport function ZauthaLoaded(props: { children?: ReactNode }): ReactNode {\n const { status } = useZauthaState();\n return status === \"ready\" || status === \"degraded\" ? props.children : null;\n}\n\nexport function ZauthaDegraded(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"degraded\" ? props.children : null;\n}\n\nexport function ZauthaFailed(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"failed\" ? props.children : null;\n}\n\n/** Sends a signed-out visitor to sign-in once loaded; renders nothing. */\nexport function RedirectToSignIn(props: { redirectUrl?: string }): ReactNode {\n const zautha = useZautha();\n const { isLoaded, isSignedIn } = useAuth();\n const { redirectUrl } = props;\n useEffect(() => {\n if (zautha !== null && isLoaded && !isSignedIn)\n zautha.redirectToSignIn(redirectUrl === undefined ? {} : { redirectUrl });\n }, [zautha, isLoaded, isSignedIn, redirectUrl]);\n return null;\n}\n\nexport function RedirectToSignUp(props: { redirectUrl?: string }): ReactNode {\n const zautha = useZautha();\n const { isLoaded, isSignedIn } = useAuth();\n const { redirectUrl } = props;\n useEffect(() => {\n if (zautha !== null && isLoaded && !isSignedIn)\n zautha.redirectToSignUp(redirectUrl === undefined ? {} : { redirectUrl });\n }, [zautha, isLoaded, isSignedIn, redirectUrl]);\n return null;\n}\n","import { Children, cloneElement, isValidElement, type MouseEvent, type ReactElement, type ReactNode } from \"react\";\nimport { useZautha } from \"./provider\";\n\ninterface ButtonProps {\n /** `redirect` (default) goes to the sign-in page; `modal` opens the prebuilt component (needs `ui`). */\n mode?: \"redirect\" | \"modal\";\n redirectUrl?: string;\n children?: ReactNode;\n}\n\n/** Wraps its single child (or renders a plain button) and wires the click. Unstyled by design. */\nfunction Trigger(props: { children: ReactNode; label: string; onClick: () => void }): ReactNode {\n const child = Children.count(props.children) === 1 ? Children.only(props.children) : null;\n if (isValidElement<{ onClick?: (event: MouseEvent) => void }>(child)) {\n const original = child.props.onClick;\n return cloneElement(child as ReactElement<{ onClick?: (event: MouseEvent) => void }>, {\n onClick: (event: MouseEvent) => {\n original?.(event);\n if (!event.defaultPrevented) props.onClick();\n },\n });\n }\n return (\n <button type=\"button\" onClick={props.onClick}>\n {props.children ?? props.label}\n </button>\n );\n}\n\nexport function SignInButton(props: ButtonProps): ReactNode {\n const zautha = useZautha();\n const options = props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl };\n return (\n <Trigger\n label=\"Sign in\"\n onClick={() => (props.mode === \"modal\" ? zautha?.openSignIn(options) : zautha?.redirectToSignIn(options))}\n >\n {props.children}\n </Trigger>\n );\n}\n\nexport function SignUpButton(props: ButtonProps): ReactNode {\n const zautha = useZautha();\n const options = props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl };\n return (\n <Trigger\n label=\"Sign up\"\n onClick={() => (props.mode === \"modal\" ? zautha?.openSignUp(options) : zautha?.redirectToSignUp(options))}\n >\n {props.children}\n </Trigger>\n );\n}\n\nexport function SignOutButton(props: { redirectUrl?: string; children?: ReactNode }): ReactNode {\n const zautha = useZautha();\n return (\n <Trigger\n label=\"Sign out\"\n onClick={() => void zautha?.signOut(props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl })}\n >\n {props.children}\n </Trigger>\n );\n}\n","import type { UiComponentName } from \"@zautha/js\";\nimport { useEffect, useRef, type ReactNode } from \"react\";\nimport { useZautha } from \"./provider\";\n\n/**\n * Mounts a @zautha/ui component into a div once the instance exists; later prop changes update it in\n * place. SSR renders only the empty div.\n */\nfunction Mounted(props: { name: UiComponentName; componentProps: object }): ReactNode {\n const zautha = useZautha();\n const ref = useRef<HTMLDivElement>(null);\n const mountedWith = useRef<object | null>(null);\n const { name, componentProps } = props;\n\n useEffect(() => {\n const element = ref.current;\n if (zautha === null || element === null) return;\n zautha.mount(name, element, componentProps);\n mountedWith.current = componentProps;\n return () => {\n mountedWith.current = null;\n zautha.unmount(element);\n };\n // componentProps changes are applied by the effect below without remounting.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [zautha, name]);\n\n useEffect(() => {\n const element = ref.current;\n if (zautha === null || element === null || mountedWith.current === null || mountedWith.current === componentProps)\n return;\n mountedWith.current = componentProps;\n zautha.updateMounted(element, componentProps);\n }, [zautha, componentProps]);\n\n return <div ref={ref} />;\n}\n\n// Prop types live in @zautha/ui; they are structural here so @zautha/react has no runtime dependency on it.\nexport function SignIn(props: import(\"@zautha/ui\").SignInProps): ReactNode {\n return <Mounted name=\"SignIn\" componentProps={props} />;\n}\n\nexport function SignUp(props: import(\"@zautha/ui\").SignUpProps): ReactNode {\n return <Mounted name=\"SignUp\" componentProps={props} />;\n}\n\n/** The page a provider sends the user back to: finishes the social sign-in or sign-up (see @zautha/ui). */\nexport function AuthenticateWithRedirectCallback(\n props: import(\"@zautha/ui\").AuthenticateWithRedirectCallbackProps,\n): ReactNode {\n return <Mounted name=\"AuthenticateWithRedirectCallback\" componentProps={props} />;\n}\n\nexport function UserButton(props: import(\"@zautha/ui\").UserButtonProps): ReactNode {\n return <Mounted name=\"UserButton\" componentProps={props} />;\n}\n\nexport function UserProfile(props: import(\"@zautha/ui\").UserProfileProps): ReactNode {\n return <Mounted name=\"UserProfile\" componentProps={props} />;\n}\n\nexport function OAuthConsent(props: import(\"@zautha/ui\").OAuthConsentProps): ReactNode {\n return <Mounted name=\"OAuthConsent\" componentProps={props} />;\n}\n\nexport function CreateOrganization(props: import(\"@zautha/ui\").CreateOrganizationProps): ReactNode {\n return <Mounted name=\"CreateOrganization\" componentProps={props} />;\n}\n\nexport function OrganizationProfile(props: import(\"@zautha/ui\").OrganizationProfileProps): ReactNode {\n return <Mounted name=\"OrganizationProfile\" componentProps={props} />;\n}\n\nexport function OrganizationSwitcher(props: import(\"@zautha/ui\").OrganizationSwitcherProps): ReactNode {\n return <Mounted name=\"OrganizationSwitcher\" componentProps={props} />;\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,7 +1,6 @@
1
1
 
2
- import { AttemptErrors, EmailAddress, Environment, ExternalAccount, ExternalAccountResource, FetchStatus, OAuthStrategy, Passkey, PasskeyCreation, RedirectCallbackResult, ReverificationCancelledError, ReverificationRequiredError, ReverificationRequirement, Session, Session as Session$1, SessionWithActivity, SignInResource, SignInResource as SignInResource$1, SignUpResource, SignUpResource as SignUpResource$1, SocialProvider, User, UserResource, UserResource as UserResource$1, Zautha, ZauthaApiError, ZauthaCaptchaError, ZauthaError, ZauthaErrorCode, ZauthaNetworkError, ZauthaOfflineError, ZauthaOptions, ZauthaPasskeyError, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError } from "@zautha/js";
2
+ import { AttemptErrors, EmailAddress, Environment, ExternalAccount, ExternalAccountResource, FetchStatus, OAuthStrategy, Organization, OrganizationInvitation, OrganizationInvitationResource, OrganizationInvitationResource as OrganizationInvitationResource$1, OrganizationInvitationStatus, OrganizationInvitationStatus as OrganizationInvitationStatus$1, OrganizationMembership, OrganizationMembership as OrganizationMembership$1, OrganizationMembershipResource, OrganizationMembershipResource as OrganizationMembershipResource$1, OrganizationResource, OrganizationResource as OrganizationResource$1, OrganizationRole, Passkey, PasskeyCreation, RedirectCallbackResult, ReverificationCancelledError, ReverificationRequiredError, ReverificationRequirement, Session, Session as Session$1, SessionActor, SessionActor as SessionActor$1, SessionWithActivity, SignInResource, SignInResource as SignInResource$1, SignUpResource, SignUpResource as SignUpResource$1, SocialProvider, User, UserOrganizationInvitationResource, UserOrganizationInvitationResource as UserOrganizationInvitationResource$1, UserResource, UserResource as UserResource$1, Zautha, ZauthaApiError, ZauthaCaptchaError, ZauthaError, ZauthaErrorCode, ZauthaNetworkError, ZauthaOfflineError, ZauthaOptions, ZauthaPasskeyError, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError } from "@zautha/js";
3
3
  import { ReactNode } from "react";
4
- //#region src/provider.d.ts
5
4
  interface ZauthaProviderProps extends Omit<ZauthaOptions, "fetch"> {
6
5
  publishableKey: string;
7
6
  children?: ReactNode;
@@ -14,8 +13,32 @@ interface ZauthaProviderProps extends Omit<ZauthaOptions, "fetch"> {
14
13
  export declare function ZauthaProvider({ publishableKey, children, ...options }: ZauthaProviderProps): ReactNode;
15
14
  /** The Zautha instance, or null before the provider has created it. */
16
15
  export declare function useZautha(): Zautha | null;
17
- //#endregion
18
- //#region src/hooks.d.ts
16
+ /** A list's page size (default 10, the API's) and the page to start on (default 1). */
17
+ interface PaginationParams {
18
+ pageSize?: number;
19
+ initialPage?: number;
20
+ }
21
+ /**
22
+ * One page of a list and how to move through it. `isLoading`: the page has no data yet; `isFetching`: a request for it
23
+ * is in flight (also while `revalidate()` reads it again). A failed read leaves `data` empty and sets `error`.
24
+ */
25
+ interface PaginatedResult<T> {
26
+ data: T[];
27
+ /** How many there are in all. */
28
+ count: number;
29
+ page: number;
30
+ pageCount: number;
31
+ isLoading: boolean;
32
+ isFetching: boolean;
33
+ error: Error | null;
34
+ hasNextPage: boolean;
35
+ hasPreviousPage: boolean;
36
+ fetchNext: () => void;
37
+ fetchPrevious: () => void;
38
+ fetchPage: (page: number) => void;
39
+ /** Reads the current page again; resolves once it has been read. */
40
+ revalidate: () => Promise<void>;
41
+ }
19
42
  /**
20
43
  * What `has` checks in the session's active organization: full keys (`org:admin`, `org:invoices:read`). Every condition
21
44
  * given must hold; with none, false.
@@ -38,6 +61,11 @@ interface UseAuthResult {
38
61
  orgSlug: string | null;
39
62
  /** The role's custom permissions, full keys such as `org:invoices:read`. */
40
63
  orgPermissions: readonly string[] | null;
64
+ /**
65
+ * Who is impersonating the user (an impersonation session; the token's `act` claim); null for the user's own session
66
+ * and while signed out. With `ui` from @zautha/ui the provider shows the impersonation band by itself.
67
+ */
68
+ actor: SessionActor$1 | null;
41
69
  getToken: (options?: {
42
70
  skipCache?: boolean;
43
71
  }) => Promise<string | null>;
@@ -87,8 +115,61 @@ interface UseSignUpResult {
87
115
  fetchStatus: FetchStatus;
88
116
  }
89
117
  export declare function useSignUp(): UseSignUpResult;
90
- //#endregion
91
- //#region src/control.d.ts
118
+ /** A list a hook reads only when asked: `true` for the defaults, or the page size, the first page and the filters. */
119
+ type ListParams<Filters = object> = true | (PaginationParams & Filters);
120
+ interface UseOrganizationParams {
121
+ /** The active organization's members (needs `org:sys_memberships:read`), filtered by a role key. */
122
+ memberships?: ListParams<{
123
+ role?: string;
124
+ }>;
125
+ /** Its invitations, filtered by status; read only for a member with `org:sys_memberships:manage` (else empty). */
126
+ invitations?: ListParams<{
127
+ status?: OrganizationInvitationStatus$1[];
128
+ }>;
129
+ }
130
+ interface UseOrganizationResult {
131
+ isLoaded: boolean;
132
+ /** The session's active organization with the member's actions; null without one, while signed out or pending. */
133
+ organization: OrganizationResource$1 | null;
134
+ /** The user's membership of it: role and every permission of the role, system ones included (to show buttons). */
135
+ membership: OrganizationMembershipResource$1 | null;
136
+ /** Only when asked for in the params. */
137
+ memberships?: PaginatedResult<OrganizationMembership$1>;
138
+ invitations?: PaginatedResult<OrganizationInvitationResource$1>;
139
+ }
140
+ interface UseOrganizationListParams {
141
+ /** The user's memberships, newest first. */
142
+ userMemberships?: ListParams;
143
+ /** The invitations to the user's verified addresses; by default the pending ones. */
144
+ userInvitations?: ListParams<{
145
+ status?: OrganizationInvitationStatus$1[];
146
+ }>;
147
+ }
148
+ interface UseOrganizationListResult {
149
+ isLoaded: boolean;
150
+ /** Creates an organization with the user in it; it is not made active (`setActive` does that). */
151
+ createOrganization: (params: {
152
+ name: string;
153
+ slug?: string;
154
+ }) => Promise<OrganizationResource$1>;
155
+ /** Makes an organization (id or slug) the session's active one; null is the personal account. */
156
+ setActive: (params: {
157
+ organization: string | null;
158
+ }) => Promise<void>;
159
+ userMemberships?: PaginatedResult<OrganizationMembershipResource$1>;
160
+ userInvitations?: PaginatedResult<UserOrganizationInvitationResource$1>;
161
+ }
162
+ /**
163
+ * The session's active organization and the user's membership of it, from the session token and the user (no request of
164
+ * its own), and on request its members and invitations, page by page. The lists start again on their first page when
165
+ * the active organization changes.
166
+ */
167
+ export declare function useOrganization(params?: UseOrganizationParams): UseOrganizationResult;
168
+ /**
169
+ * Creating an organization and choosing the active one, and on request the user's memberships and the invitations to
170
+ * the user, page by page.
171
+ */
172
+ export declare function useOrganizationList(params?: UseOrganizationListParams): UseOrganizationListResult;
92
173
  type ShowWhen = "signed-in" | "signed-out" | HasParams | ((has: Has) => boolean);
93
174
  /**
94
175
  * Renders `children` when the condition holds, else `fallback`. Renders nothing until Zautha has
@@ -119,8 +200,6 @@ export declare function RedirectToSignIn(props: {
119
200
  export declare function RedirectToSignUp(props: {
120
201
  redirectUrl?: string;
121
202
  }): ReactNode;
122
- //#endregion
123
- //#region src/buttons.d.ts
124
203
  interface ButtonProps {
125
204
  /** `redirect` (default) goes to the sign-in page; `modal` opens the prebuilt component (needs `ui`). */
126
205
  mode?: "redirect" | "modal";
@@ -133,8 +212,6 @@ export declare function SignOutButton(props: {
133
212
  redirectUrl?: string;
134
213
  children?: ReactNode;
135
214
  }): ReactNode;
136
- //#endregion
137
- //#region src/prebuilt.d.ts
138
215
  export declare function SignIn(props: import("@zautha/ui").SignInProps): ReactNode;
139
216
  export declare function SignUp(props: import("@zautha/ui").SignUpProps): ReactNode;
140
217
  /** The page a provider sends the user back to: finishes the social sign-in or sign-up (see @zautha/ui). */
@@ -142,6 +219,8 @@ export declare function AuthenticateWithRedirectCallback(props: import("@zautha/
142
219
  export declare function UserButton(props: import("@zautha/ui").UserButtonProps): ReactNode;
143
220
  export declare function UserProfile(props: import("@zautha/ui").UserProfileProps): ReactNode;
144
221
  export declare function OAuthConsent(props: import("@zautha/ui").OAuthConsentProps): ReactNode;
145
- //#endregion
146
- export { type EmailAddress, type Environment, type ExternalAccount, type ExternalAccountResource, type Has, type HasParams, type OAuthStrategy, type Passkey, type PasskeyCreation, type RedirectCallbackResult, ReverificationCancelledError, ReverificationRequiredError, type ReverificationRequirement, type Session, type SessionWithActivity, type ShowWhen, type SignInResource, type SignUpResource, type SocialProvider, type UseAuthResult, type UseSignInResult, type UseSignUpResult, type User, type UserResource, ZauthaApiError, ZauthaCaptchaError, ZauthaError, type ZauthaErrorCode, ZauthaNetworkError, ZauthaOfflineError, ZauthaPasskeyError, type ZauthaProviderProps, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError };
222
+ export declare function CreateOrganization(props: import("@zautha/ui").CreateOrganizationProps): ReactNode;
223
+ export declare function OrganizationProfile(props: import("@zautha/ui").OrganizationProfileProps): ReactNode;
224
+ export declare function OrganizationSwitcher(props: import("@zautha/ui").OrganizationSwitcherProps): ReactNode;
225
+ export { type EmailAddress, type Environment, type ExternalAccount, type ExternalAccountResource, type Has, type HasParams, type ListParams, type OAuthStrategy, type Organization, type OrganizationInvitation, type OrganizationInvitationResource, type OrganizationInvitationStatus, type OrganizationMembership, type OrganizationMembershipResource, type OrganizationResource, type OrganizationRole, type PaginatedResult, type PaginationParams, type Passkey, type PasskeyCreation, type RedirectCallbackResult, ReverificationCancelledError, ReverificationRequiredError, type ReverificationRequirement, type Session, type SessionActor, type SessionWithActivity, type ShowWhen, type SignInResource, type SignUpResource, type SocialProvider, type UseAuthResult, type UseOrganizationListParams, type UseOrganizationListResult, type UseOrganizationParams, type UseOrganizationResult, type UseSignInResult, type UseSignUpResult, type User, type UserOrganizationInvitationResource, type UserResource, ZauthaApiError, ZauthaCaptchaError, ZauthaError, type ZauthaErrorCode, ZauthaNetworkError, ZauthaOfflineError, ZauthaPasskeyError, type ZauthaProviderProps, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError };
147
226
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.mts CHANGED
@@ -1,7 +1,6 @@
1
1
 
2
- import { AttemptErrors, EmailAddress, Environment, ExternalAccount, ExternalAccountResource, FetchStatus, OAuthStrategy, Passkey, PasskeyCreation, RedirectCallbackResult, ReverificationCancelledError, ReverificationRequiredError, ReverificationRequirement, Session, Session as Session$1, SessionWithActivity, SignInResource, SignInResource as SignInResource$1, SignUpResource, SignUpResource as SignUpResource$1, SocialProvider, User, UserResource, UserResource as UserResource$1, Zautha, ZauthaApiError, ZauthaCaptchaError, ZauthaError, ZauthaErrorCode, ZauthaNetworkError, ZauthaOfflineError, ZauthaOptions, ZauthaPasskeyError, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError } from "@zautha/js";
2
+ import { AttemptErrors, EmailAddress, Environment, ExternalAccount, ExternalAccountResource, FetchStatus, OAuthStrategy, Organization, OrganizationInvitation, OrganizationInvitationResource, OrganizationInvitationResource as OrganizationInvitationResource$1, OrganizationInvitationStatus, OrganizationInvitationStatus as OrganizationInvitationStatus$1, OrganizationMembership, OrganizationMembership as OrganizationMembership$1, OrganizationMembershipResource, OrganizationMembershipResource as OrganizationMembershipResource$1, OrganizationResource, OrganizationResource as OrganizationResource$1, OrganizationRole, Passkey, PasskeyCreation, RedirectCallbackResult, ReverificationCancelledError, ReverificationRequiredError, ReverificationRequirement, Session, Session as Session$1, SessionActor, SessionActor as SessionActor$1, SessionWithActivity, SignInResource, SignInResource as SignInResource$1, SignUpResource, SignUpResource as SignUpResource$1, SocialProvider, User, UserOrganizationInvitationResource, UserOrganizationInvitationResource as UserOrganizationInvitationResource$1, UserResource, UserResource as UserResource$1, Zautha, ZauthaApiError, ZauthaCaptchaError, ZauthaError, ZauthaErrorCode, ZauthaNetworkError, ZauthaOfflineError, ZauthaOptions, ZauthaPasskeyError, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError } from "@zautha/js";
3
3
  import { ReactNode } from "react";
4
- //#region src/provider.d.ts
5
4
  interface ZauthaProviderProps extends Omit<ZauthaOptions, "fetch"> {
6
5
  publishableKey: string;
7
6
  children?: ReactNode;
@@ -14,8 +13,32 @@ interface ZauthaProviderProps extends Omit<ZauthaOptions, "fetch"> {
14
13
  export declare function ZauthaProvider({ publishableKey, children, ...options }: ZauthaProviderProps): ReactNode;
15
14
  /** The Zautha instance, or null before the provider has created it. */
16
15
  export declare function useZautha(): Zautha | null;
17
- //#endregion
18
- //#region src/hooks.d.ts
16
+ /** A list's page size (default 10, the API's) and the page to start on (default 1). */
17
+ interface PaginationParams {
18
+ pageSize?: number;
19
+ initialPage?: number;
20
+ }
21
+ /**
22
+ * One page of a list and how to move through it. `isLoading`: the page has no data yet; `isFetching`: a request for it
23
+ * is in flight (also while `revalidate()` reads it again). A failed read leaves `data` empty and sets `error`.
24
+ */
25
+ interface PaginatedResult<T> {
26
+ data: T[];
27
+ /** How many there are in all. */
28
+ count: number;
29
+ page: number;
30
+ pageCount: number;
31
+ isLoading: boolean;
32
+ isFetching: boolean;
33
+ error: Error | null;
34
+ hasNextPage: boolean;
35
+ hasPreviousPage: boolean;
36
+ fetchNext: () => void;
37
+ fetchPrevious: () => void;
38
+ fetchPage: (page: number) => void;
39
+ /** Reads the current page again; resolves once it has been read. */
40
+ revalidate: () => Promise<void>;
41
+ }
19
42
  /**
20
43
  * What `has` checks in the session's active organization: full keys (`org:admin`, `org:invoices:read`). Every condition
21
44
  * given must hold; with none, false.
@@ -38,6 +61,11 @@ interface UseAuthResult {
38
61
  orgSlug: string | null;
39
62
  /** The role's custom permissions, full keys such as `org:invoices:read`. */
40
63
  orgPermissions: readonly string[] | null;
64
+ /**
65
+ * Who is impersonating the user (an impersonation session; the token's `act` claim); null for the user's own session
66
+ * and while signed out. With `ui` from @zautha/ui the provider shows the impersonation band by itself.
67
+ */
68
+ actor: SessionActor$1 | null;
41
69
  getToken: (options?: {
42
70
  skipCache?: boolean;
43
71
  }) => Promise<string | null>;
@@ -87,8 +115,61 @@ interface UseSignUpResult {
87
115
  fetchStatus: FetchStatus;
88
116
  }
89
117
  export declare function useSignUp(): UseSignUpResult;
90
- //#endregion
91
- //#region src/control.d.ts
118
+ /** A list a hook reads only when asked: `true` for the defaults, or the page size, the first page and the filters. */
119
+ type ListParams<Filters = object> = true | (PaginationParams & Filters);
120
+ interface UseOrganizationParams {
121
+ /** The active organization's members (needs `org:sys_memberships:read`), filtered by a role key. */
122
+ memberships?: ListParams<{
123
+ role?: string;
124
+ }>;
125
+ /** Its invitations, filtered by status; read only for a member with `org:sys_memberships:manage` (else empty). */
126
+ invitations?: ListParams<{
127
+ status?: OrganizationInvitationStatus$1[];
128
+ }>;
129
+ }
130
+ interface UseOrganizationResult {
131
+ isLoaded: boolean;
132
+ /** The session's active organization with the member's actions; null without one, while signed out or pending. */
133
+ organization: OrganizationResource$1 | null;
134
+ /** The user's membership of it: role and every permission of the role, system ones included (to show buttons). */
135
+ membership: OrganizationMembershipResource$1 | null;
136
+ /** Only when asked for in the params. */
137
+ memberships?: PaginatedResult<OrganizationMembership$1>;
138
+ invitations?: PaginatedResult<OrganizationInvitationResource$1>;
139
+ }
140
+ interface UseOrganizationListParams {
141
+ /** The user's memberships, newest first. */
142
+ userMemberships?: ListParams;
143
+ /** The invitations to the user's verified addresses; by default the pending ones. */
144
+ userInvitations?: ListParams<{
145
+ status?: OrganizationInvitationStatus$1[];
146
+ }>;
147
+ }
148
+ interface UseOrganizationListResult {
149
+ isLoaded: boolean;
150
+ /** Creates an organization with the user in it; it is not made active (`setActive` does that). */
151
+ createOrganization: (params: {
152
+ name: string;
153
+ slug?: string;
154
+ }) => Promise<OrganizationResource$1>;
155
+ /** Makes an organization (id or slug) the session's active one; null is the personal account. */
156
+ setActive: (params: {
157
+ organization: string | null;
158
+ }) => Promise<void>;
159
+ userMemberships?: PaginatedResult<OrganizationMembershipResource$1>;
160
+ userInvitations?: PaginatedResult<UserOrganizationInvitationResource$1>;
161
+ }
162
+ /**
163
+ * The session's active organization and the user's membership of it, from the session token and the user (no request of
164
+ * its own), and on request its members and invitations, page by page. The lists start again on their first page when
165
+ * the active organization changes.
166
+ */
167
+ export declare function useOrganization(params?: UseOrganizationParams): UseOrganizationResult;
168
+ /**
169
+ * Creating an organization and choosing the active one, and on request the user's memberships and the invitations to
170
+ * the user, page by page.
171
+ */
172
+ export declare function useOrganizationList(params?: UseOrganizationListParams): UseOrganizationListResult;
92
173
  type ShowWhen = "signed-in" | "signed-out" | HasParams | ((has: Has) => boolean);
93
174
  /**
94
175
  * Renders `children` when the condition holds, else `fallback`. Renders nothing until Zautha has
@@ -119,8 +200,6 @@ export declare function RedirectToSignIn(props: {
119
200
  export declare function RedirectToSignUp(props: {
120
201
  redirectUrl?: string;
121
202
  }): ReactNode;
122
- //#endregion
123
- //#region src/buttons.d.ts
124
203
  interface ButtonProps {
125
204
  /** `redirect` (default) goes to the sign-in page; `modal` opens the prebuilt component (needs `ui`). */
126
205
  mode?: "redirect" | "modal";
@@ -133,8 +212,6 @@ export declare function SignOutButton(props: {
133
212
  redirectUrl?: string;
134
213
  children?: ReactNode;
135
214
  }): ReactNode;
136
- //#endregion
137
- //#region src/prebuilt.d.ts
138
215
  export declare function SignIn(props: import("@zautha/ui").SignInProps): ReactNode;
139
216
  export declare function SignUp(props: import("@zautha/ui").SignUpProps): ReactNode;
140
217
  /** The page a provider sends the user back to: finishes the social sign-in or sign-up (see @zautha/ui). */
@@ -142,6 +219,8 @@ export declare function AuthenticateWithRedirectCallback(props: import("@zautha/
142
219
  export declare function UserButton(props: import("@zautha/ui").UserButtonProps): ReactNode;
143
220
  export declare function UserProfile(props: import("@zautha/ui").UserProfileProps): ReactNode;
144
221
  export declare function OAuthConsent(props: import("@zautha/ui").OAuthConsentProps): ReactNode;
145
- //#endregion
146
- export { type EmailAddress, type Environment, type ExternalAccount, type ExternalAccountResource, type Has, type HasParams, type OAuthStrategy, type Passkey, type PasskeyCreation, type RedirectCallbackResult, ReverificationCancelledError, ReverificationRequiredError, type ReverificationRequirement, type Session, type SessionWithActivity, type ShowWhen, type SignInResource, type SignUpResource, type SocialProvider, type UseAuthResult, type UseSignInResult, type UseSignUpResult, type User, type UserResource, ZauthaApiError, ZauthaCaptchaError, ZauthaError, type ZauthaErrorCode, ZauthaNetworkError, ZauthaOfflineError, ZauthaPasskeyError, type ZauthaProviderProps, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError };
222
+ export declare function CreateOrganization(props: import("@zautha/ui").CreateOrganizationProps): ReactNode;
223
+ export declare function OrganizationProfile(props: import("@zautha/ui").OrganizationProfileProps): ReactNode;
224
+ export declare function OrganizationSwitcher(props: import("@zautha/ui").OrganizationSwitcherProps): ReactNode;
225
+ export { type EmailAddress, type Environment, type ExternalAccount, type ExternalAccountResource, type Has, type HasParams, type ListParams, type OAuthStrategy, type Organization, type OrganizationInvitation, type OrganizationInvitationResource, type OrganizationInvitationStatus, type OrganizationMembership, type OrganizationMembershipResource, type OrganizationResource, type OrganizationRole, type PaginatedResult, type PaginationParams, type Passkey, type PasskeyCreation, type RedirectCallbackResult, ReverificationCancelledError, ReverificationRequiredError, type ReverificationRequirement, type Session, type SessionActor, type SessionWithActivity, type ShowWhen, type SignInResource, type SignUpResource, type SocialProvider, type UseAuthResult, type UseOrganizationListParams, type UseOrganizationListResult, type UseOrganizationParams, type UseOrganizationResult, type UseSignInResult, type UseSignUpResult, type User, type UserOrganizationInvitationResource, type UserResource, ZauthaApiError, ZauthaCaptchaError, ZauthaError, type ZauthaErrorCode, ZauthaNetworkError, ZauthaOfflineError, ZauthaPasskeyError, type ZauthaProviderProps, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError };
147
226
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { ReverificationCancelledError, ReverificationRequiredError, Zautha, ZauthaApiError, ZauthaCaptchaError, ZauthaError, ZauthaNetworkError, ZauthaOfflineError, ZauthaPasskeyError, checkAuthorization, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError, withReverification } from "@zautha/js";
2
+ import { ReverificationCancelledError, ReverificationRequiredError, Zautha, ZauthaApiError, ZauthaCaptchaError, ZauthaError, ZauthaError as ZauthaError$1, ZauthaNetworkError, ZauthaOfflineError, ZauthaPasskeyError, checkAuthorization, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError, withReverification } from "@zautha/js";
3
3
  import { Children, cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
4
  import { jsx } from "react/jsx-runtime";
5
- //#region src/provider.tsx
5
+ // src/provider.tsx
6
6
  const ZauthaContext = createContext(void 0);
7
7
  /**
8
8
  * Creates the Zautha instance after mount (never during render, so StrictMode's double mount and SSR
@@ -66,8 +66,105 @@ function useZauthaState() {
66
66
  const { zautha, pending } = useZauthaContext();
67
67
  return useSyncExternalStore(zautha?.subscribe ?? noop, () => zautha?.getSnapshot() ?? pending, () => pending);
68
68
  }
69
- //#endregion
70
- //#region src/hooks.ts
69
+ // src/pagination.ts
70
+ /**
71
+ * The pages of one list. Without a source nothing is read and the list is empty; a source with a new key starts again on
72
+ * the initial page. A response to an older request (another page, key or revalidation) is dropped, so it never
73
+ * overwrites a newer one.
74
+ */
75
+ function usePages(source, params) {
76
+ const key = source?.key ?? null;
77
+ const { pageSize = 10, initialPage = 1 } = params === true || params === void 0 ? {} : params;
78
+ const [at, setAt] = useState({
79
+ key,
80
+ page: initialPage,
81
+ version: 0
82
+ });
83
+ const [settled, setSettled] = useState(null);
84
+ const latest = useRef(0);
85
+ const waiting = useRef([]);
86
+ if (at.key !== key) {
87
+ setAt({
88
+ key,
89
+ page: initialPage,
90
+ version: 0
91
+ });
92
+ setSettled(null);
93
+ }
94
+ const { page, version } = at.key === key ? at : {
95
+ page: initialPage,
96
+ version: 0
97
+ };
98
+ const request = JSON.stringify([
99
+ key,
100
+ page,
101
+ pageSize,
102
+ version
103
+ ]);
104
+ const loader = useRef(source?.load);
105
+ useEffect(() => {
106
+ loader.current = source?.load;
107
+ });
108
+ useEffect(() => {
109
+ const id = ++latest.current;
110
+ const settle = (data, count, error) => {
111
+ if (latest.current !== id) return;
112
+ if (key !== null) setSettled({
113
+ request,
114
+ key,
115
+ page,
116
+ data,
117
+ count,
118
+ error
119
+ });
120
+ for (const resolve of waiting.current.splice(0)) resolve();
121
+ };
122
+ if (key === null || loader.current === void 0) return settle([], 0, null);
123
+ loader.current({
124
+ limit: pageSize,
125
+ offset: (page - 1) * pageSize
126
+ }).then((r) => settle(r.data, r.totalCount, null), (error) => settle([], 0, error instanceof Error ? error : new Error(String(error))));
127
+ }, [request]);
128
+ const shown = settled !== null && settled.key === key && settled.page === page ? settled : null;
129
+ const isFetching = key !== null && settled?.request !== request;
130
+ const count = shown?.count ?? 0;
131
+ const pageCount = Math.ceil(count / pageSize);
132
+ const go = useCallback((to) => setAt((a) => {
133
+ const from = a.key === key ? a.page : initialPage;
134
+ return {
135
+ key,
136
+ page: Math.max(1, to(from)),
137
+ version: a.key === key ? a.version : 0
138
+ };
139
+ }), [key, initialPage]);
140
+ const revalidate = useCallback(() => new Promise((resolve) => {
141
+ waiting.current.push(resolve);
142
+ setAt((a) => a.key === key ? {
143
+ ...a,
144
+ version: a.version + 1
145
+ } : {
146
+ key,
147
+ page: initialPage,
148
+ version: 1
149
+ });
150
+ }), [key, initialPage]);
151
+ return {
152
+ data: shown?.data ?? [],
153
+ count,
154
+ page,
155
+ pageCount,
156
+ isLoading: isFetching && shown === null,
157
+ isFetching,
158
+ error: shown?.error ?? null,
159
+ hasNextPage: page < pageCount,
160
+ hasPreviousPage: page > 1,
161
+ fetchNext: useCallback(() => go((p) => p + 1), [go]),
162
+ fetchPrevious: useCallback(() => go((p) => p - 1), [go]),
163
+ fetchPage: useCallback((n) => go(() => n), [go]),
164
+ revalidate
165
+ };
166
+ }
167
+ // src/hooks.ts
71
168
  const isLoadedStatus = (status) => status === "ready" || status === "degraded";
72
169
  /** The signed-in session: a pending one (tasks left, e.g. setting up two-step verification) counts as signed out. */
73
170
  const activeSession = (state) => state.session?.status === "active" ? state.session : null;
@@ -82,6 +179,7 @@ function useAuth() {
82
179
  const sessionId = initial === null ? session?.id ?? null : initial.sessionId;
83
180
  const signedIn = userId !== null;
84
181
  const organization = initial === null ? session === null ? null : state.organization : initial.organization;
182
+ const actor = initial === null ? session?.actor ?? null : initial.actor;
85
183
  const has = useCallback((params) => checkAuthorization(organization, params), [organization]);
86
184
  return {
87
185
  isLoaded: isLoadedStatus(state.status) || initial !== null,
@@ -92,6 +190,7 @@ function useAuth() {
92
190
  orgRole: organization?.role ?? null,
93
191
  orgSlug: organization?.slug ?? null,
94
192
  orgPermissions: organization?.permissions ?? null,
193
+ actor,
95
194
  getToken,
96
195
  signOut,
97
196
  has
@@ -168,8 +267,81 @@ function useSignUp() {
168
267
  fetchStatus: snapshot?.fetchStatus ?? "idle"
169
268
  };
170
269
  }
171
- //#endregion
172
- //#region src/control.tsx
270
+ /** A list's filters: its params without the page size and the first page. */
271
+ function filtersOf(params) {
272
+ const filters = { ...params === true ? {} : params };
273
+ delete filters.pageSize;
274
+ delete filters.initialPage;
275
+ return filters;
276
+ }
277
+ /** A list of `owner` read with `load`: its key (`owner` and the params, so new filters start the list again). */
278
+ const list = (owner, params, load) => ({
279
+ key: `${owner}:${JSON.stringify(params)}`,
280
+ load
281
+ });
282
+ /** The signed-in user (an active session's) and whether hooks that read it are loaded. */
283
+ function useSignedInUser() {
284
+ const zautha = useZautha();
285
+ const state = useZauthaState();
286
+ const user = activeSession(state) === null ? null : zautha?.user ?? null;
287
+ return {
288
+ isLoaded: isLoadedStatus(state.status) && (activeSession(state) === null || user !== null),
289
+ state,
290
+ user
291
+ };
292
+ }
293
+ /**
294
+ * The session's active organization and the user's membership of it, from the session token and the user (no request of
295
+ * its own), and on request its members and invitations, page by page. The lists start again on their first page when
296
+ * the active organization changes.
297
+ */
298
+ function useOrganization(params = {}) {
299
+ const { isLoaded, state, user } = useSignedInUser();
300
+ const id = state.organization?.id;
301
+ const membership = user?.organizationMemberships.find((m) => m.organization.id === id) ?? null;
302
+ const organization = membership?.organization ?? null;
303
+ const owner = membership === null ? "" : `${membership.publicUserData.userId}:${membership.organization.id}`;
304
+ const { memberships, invitations } = params;
305
+ const manages = membership?.permissions.includes("org:sys_memberships:manage") === true;
306
+ const members = usePages(organization === null || memberships === void 0 ? null : list(owner, memberships, (page) => organization.getMemberships({
307
+ ...filtersOf(memberships),
308
+ ...page
309
+ })), memberships);
310
+ const invited = usePages(organization === null || invitations === void 0 || !manages ? null : list(owner, invitations, (page) => organization.getInvitations({
311
+ ...filtersOf(invitations),
312
+ ...page
313
+ })), invitations);
314
+ return {
315
+ isLoaded,
316
+ organization,
317
+ membership,
318
+ ...memberships === void 0 ? {} : { memberships: members },
319
+ ...invitations === void 0 ? {} : { invitations: invited }
320
+ };
321
+ }
322
+ /**
323
+ * Creating an organization and choosing the active one, and on request the user's memberships and the invitations to
324
+ * the user, page by page.
325
+ */
326
+ function useOrganizationList(params = {}) {
327
+ const zautha = useZautha();
328
+ const { isLoaded, user } = useSignedInUser();
329
+ const { userMemberships, userInvitations } = params;
330
+ const memberships = usePages(user === null || userMemberships === void 0 ? null : list(user.id, userMemberships, (page) => user.getOrganizationMemberships(page)), userMemberships);
331
+ const invitations = usePages(user === null || userInvitations === void 0 ? null : list(user.id, userInvitations, (page) => user.getOrganizationInvitations({
332
+ ...filtersOf(userInvitations),
333
+ ...page
334
+ })), userInvitations);
335
+ return {
336
+ isLoaded,
337
+ createOrganization: useCallback((p) => zautha?.createOrganization(p) ?? notLoaded(), [zautha]),
338
+ setActive: useCallback((p) => zautha?.setActive(p) ?? notLoaded(), [zautha]),
339
+ ...userMemberships === void 0 ? {} : { userMemberships: memberships },
340
+ ...userInvitations === void 0 ? {} : { userInvitations: invitations }
341
+ };
342
+ }
343
+ const notLoaded = () => Promise.reject(new ZauthaError$1("Zautha is not loaded yet."));
344
+ // src/control.tsx
173
345
  /**
174
346
  * Renders `children` when the condition holds, else `fallback`. Renders nothing until Zautha has
175
347
  * loaded, so a signed-in user never sees a signed-out flash.
@@ -223,8 +395,7 @@ function RedirectToSignUp(props) {
223
395
  ]);
224
396
  return null;
225
397
  }
226
- //#endregion
227
- //#region src/buttons.tsx
398
+ // src/buttons.tsx
228
399
  /** Wraps its single child (or renders a plain button) and wires the click. Unstyled by design. */
229
400
  function Trigger(props) {
230
401
  const child = Children.count(props.children) === 1 ? Children.only(props.children) : null;
@@ -267,8 +438,7 @@ function SignOutButton(props) {
267
438
  children: props.children
268
439
  });
269
440
  }
270
- //#endregion
271
- //#region src/prebuilt.tsx
441
+ // src/prebuilt.tsx
272
442
  /**
273
443
  * Mounts a @zautha/ui component into a div once the instance exists; later prop changes update it in
274
444
  * place. SSR renders only the empty div.
@@ -333,7 +503,24 @@ function OAuthConsent(props) {
333
503
  componentProps: props
334
504
  });
335
505
  }
336
- //#endregion
337
- export { AuthenticateWithRedirectCallback, OAuthConsent, RedirectToSignIn, RedirectToSignUp, ReverificationCancelledError, ReverificationRequiredError, Show, SignIn, SignInButton, SignOutButton, SignUp, SignUpButton, UserButton, UserProfile, ZauthaApiError, ZauthaCaptchaError, ZauthaDegraded, ZauthaError, ZauthaFailed, ZauthaLoaded, ZauthaLoading, ZauthaNetworkError, ZauthaOfflineError, ZauthaPasskeyError, ZauthaProvider, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError, useAuth, useReverification, useSession, useSignIn, useSignUp, useUser, useZautha };
506
+ function CreateOrganization(props) {
507
+ return /* @__PURE__ */ jsx(Mounted, {
508
+ name: "CreateOrganization",
509
+ componentProps: props
510
+ });
511
+ }
512
+ function OrganizationProfile(props) {
513
+ return /* @__PURE__ */ jsx(Mounted, {
514
+ name: "OrganizationProfile",
515
+ componentProps: props
516
+ });
517
+ }
518
+ function OrganizationSwitcher(props) {
519
+ return /* @__PURE__ */ jsx(Mounted, {
520
+ name: "OrganizationSwitcher",
521
+ componentProps: props
522
+ });
523
+ }
524
+ export { AuthenticateWithRedirectCallback, CreateOrganization, OAuthConsent, OrganizationProfile, OrganizationSwitcher, RedirectToSignIn, RedirectToSignUp, ReverificationCancelledError, ReverificationRequiredError, Show, SignIn, SignInButton, SignOutButton, SignUp, SignUpButton, UserButton, UserProfile, ZauthaApiError, ZauthaCaptchaError, ZauthaDegraded, ZauthaError, ZauthaFailed, ZauthaLoaded, ZauthaLoading, ZauthaNetworkError, ZauthaOfflineError, ZauthaPasskeyError, ZauthaProvider, isReverificationCancelledError, isReverificationRequiredError, isZauthaApiError, isZauthaCaptchaError, isZauthaError, isZauthaNetworkError, isZauthaOfflineError, isZauthaPasskeyError, useAuth, useOrganization, useOrganizationList, useReverification, useSession, useSignIn, useSignUp, useUser, useZautha };
338
525
 
339
526
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/provider.tsx","../src/hooks.ts","../src/control.tsx","../src/buttons.tsx","../src/prebuilt.tsx"],"sourcesContent":["import { Zautha, type ZauthaOptions, type ZauthaState } from \"@zautha/js\";\nimport { createContext, useContext, useEffect, useMemo, useState, useSyncExternalStore, type ReactNode } from \"react\";\n\ninterface ZauthaContextValue {\n readonly zautha: Zautha | null;\n /** The snapshot before the instance exists and during server rendering (carries `initialState`). */\n readonly pending: ZauthaState;\n}\n\nconst ZauthaContext = createContext<ZauthaContextValue | undefined>(undefined);\n\nexport interface ZauthaProviderProps extends Omit<ZauthaOptions, \"fetch\"> {\n publishableKey: string;\n children?: ReactNode;\n}\n\n/**\n * Creates the Zautha instance after mount (never during render, so StrictMode's double mount and SSR\n * create no timers or channels), loads it, and disposes it on unmount. Until then hooks report\n * `isLoaded: false`, unless `initialState` (the server's view, e.g. from @zautha/nextjs) says who is signed in.\n */\nexport function ZauthaProvider({ publishableKey, children, ...options }: ZauthaProviderProps): ReactNode {\n const [zautha, setZautha] = useState<Zautha | null>(null);\n const { ui, appearance, localization, signInUrl, signUpUrl, navigate, initialState } = options;\n const [pending] = useState<ZauthaState>(() => ({ ...NO_STATE, initialState: initialState ?? null }));\n\n useEffect(() => {\n const instance = new Zautha(publishableKey, {\n ...(ui === undefined ? {} : { ui }),\n ...(appearance === undefined ? {} : { appearance }),\n ...(localization === undefined ? {} : { localization }),\n ...(signInUrl === undefined ? {} : { signInUrl }),\n ...(signUpUrl === undefined ? {} : { signUpUrl }),\n ...(navigate === undefined ? {} : { navigate }),\n ...(initialState === undefined ? {} : { initialState }),\n });\n // The instance is an external system: it is created here, never during render, and published through state.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setZautha(instance);\n void instance.load();\n return () => {\n instance.dispose();\n setZautha(null);\n };\n // Appearance/localization objects are read at mount; changing the key re-creates the instance.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [publishableKey]);\n\n const value = useMemo(() => ({ zautha, pending }), [zautha, pending]);\n return <ZauthaContext.Provider value={value}>{children}</ZauthaContext.Provider>;\n}\n\n/** The Zautha instance, or null before the provider has created it. */\nexport function useZautha(): Zautha | null {\n return useZauthaContext().zautha;\n}\n\nfunction useZauthaContext(): ZauthaContextValue {\n const value = useContext(ZauthaContext);\n if (value === undefined) throw new Error(\"Zautha hooks and components must be used inside <ZauthaProvider>.\");\n return value;\n}\n\nconst NO_STATE: ZauthaState = {\n status: \"loading\",\n environment: null,\n client: null,\n session: null,\n user: null,\n organization: null,\n initialState: null,\n};\nconst noop = (): (() => void) => () => undefined;\n\n/** Reactive snapshot of the instance state (the loading state, with any initial state, before the instance exists). */\nexport function useZauthaState(): ZauthaState {\n const { zautha, pending } = useZauthaContext();\n return useSyncExternalStore(\n zautha?.subscribe ?? noop,\n () => zautha?.getSnapshot() ?? pending,\n () => pending,\n );\n}\n","import {\n checkAuthorization,\n withReverification,\n type AttemptErrors,\n type FetchStatus,\n type Session,\n type SignInResource,\n type SignUpResource,\n type UserResource,\n type ZauthaState,\n} from \"@zautha/js\";\nimport { useCallback, useLayoutEffect, useRef, useSyncExternalStore } from \"react\";\nimport { useZautha, useZauthaState } from \"./provider\";\n\n/**\n * What `has` checks in the session's active organization: full keys (`org:admin`, `org:invoices:read`). Every condition\n * given must hold; with none, false.\n */\nexport type HasParams = { role?: string; permission?: string };\nexport type Has = (params: HasParams) => boolean;\n\nexport interface UseAuthResult {\n isLoaded: boolean;\n isSignedIn: boolean;\n userId: string | null;\n sessionId: string | null;\n /** The active organization (`org_…`); null without one, and while signed out. */\n orgId: string | null;\n /** The user's role in it, a full key such as `org:admin`. */\n orgRole: string | null;\n /** Its slug; null without one or while the instance has slugs off. */\n orgSlug: string | null;\n /** The role's custom permissions, full keys such as `org:invoices:read`. */\n orgPermissions: readonly string[] | null;\n getToken: (options?: { skipCache?: boolean }) => Promise<string | null>;\n signOut: (options?: { redirectUrl?: string }) => Promise<void>;\n /**\n * From the session token alone, the same rule as every Zautha SDK and your server: false without an active\n * organization, and always false for a system permission (`org:sys_…`, never in the token).\n */\n has: Has;\n}\n\nconst isLoadedStatus = (status: string): boolean => status === \"ready\" || status === \"degraded\";\n\n/** The signed-in session: a pending one (tasks left, e.g. setting up two-step verification) counts as signed out. */\nconst activeSession = (state: ZauthaState): Session | null =>\n state.session?.status === \"active\" ? state.session : null;\n\nexport function useAuth(): UseAuthResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const getToken = useCallback(\n (options?: { skipCache?: boolean }) => zautha?.getToken(options) ?? Promise.resolve(null),\n [zautha],\n );\n const signOut = useCallback(\n (options?: { redirectUrl?: string }) => zautha?.signOut(options) ?? Promise.resolve(),\n [zautha],\n );\n // Until the first load settles, the server's initial state (if any) answers, so nothing flickers.\n const initial = state.status === \"loading\" ? state.initialState : null;\n const session = activeSession(state);\n const userId = initial === null ? (session?.userId ?? null) : initial.userId;\n const sessionId = initial === null ? (session?.id ?? null) : initial.sessionId;\n const signedIn = userId !== null;\n const organization = initial === null ? (session === null ? null : state.organization) : initial.organization;\n const has = useCallback<Has>((params) => checkAuthorization(organization, params), [organization]);\n return {\n isLoaded: isLoadedStatus(state.status) || initial !== null,\n isSignedIn: signedIn,\n userId,\n sessionId,\n orgId: organization?.id ?? null,\n orgRole: organization?.role ?? null,\n orgSlug: organization?.slug ?? null,\n orgPermissions: organization?.permissions ?? null,\n getToken,\n signOut,\n has,\n };\n}\n\n/** The signed-in user with its self-service actions (`user.update`, `user.createEmailAddress`, …). */\nexport function useUser(): { isLoaded: boolean; isSignedIn: boolean; user: UserResource | null } {\n const zautha = useZautha();\n const state = useZauthaState();\n const signedIn = activeSession(state) !== null;\n // zautha.user is rebuilt only when state.user changes, so the resource is stable between renders.\n const user = !signedIn || state.user === null ? null : (zautha?.user ?? null);\n return { isLoaded: isLoadedStatus(state.status), isSignedIn: signedIn, user };\n}\n\n/**\n * Wraps a sensitive action so that it completes after an identity check when it needs one: when `fetcher` throws\n * `ReverificationRequiredError` (e.g. `user.updatePassword`) or resolves to a `Response` with the `403\n * reverification_required` body (your backend with @zautha/backend, @zautha/nextjs or Zautha.AspNetCore), the\n * reverification modal opens and, once the user has verified, `fetcher` runs once more with the same arguments (its\n * token is fresh by then). Closing the modal rejects with `ReverificationCancelledError`. Needs `ui` from @zautha/ui on\n * the provider. The returned function is stable; it always calls the latest `fetcher`.\n */\nexport function useReverification<Args extends unknown[], Result>(\n fetcher: (...args: Args) => Promise<Result>,\n): (...args: Args) => Promise<Result> {\n const zautha = useZautha();\n const latest = useRef(fetcher);\n useLayoutEffect(() => {\n latest.current = fetcher;\n });\n return useCallback(\n (...args: Args) => {\n const call = (...callArgs: Args): Promise<Result> => latest.current(...callArgs);\n // Before the provider has created the instance no modal can open: the action runs as it is.\n return zautha === null ? call(...args) : withReverification(zautha, call)(...args);\n },\n [zautha],\n );\n}\n\n/** The signed-in session; null while signed out or while the session is pending (tasks left). */\nexport function useSession(): { isLoaded: boolean; isSignedIn: boolean; session: Session | null } {\n const state = useZauthaState();\n const session = activeSession(state);\n return { isLoaded: isLoadedStatus(state.status), isSignedIn: session !== null, session };\n}\n\nconst noopSubscribe = (): (() => void) => () => undefined;\n\nfunction useResource<T extends SignInResource | SignUpResource>(resource: T | null) {\n const snapshot = useSyncExternalStore(\n resource?.subscribe ?? noopSubscribe,\n () => resource?.snapshot ?? null,\n () => null,\n );\n return snapshot;\n}\n\nexport interface UseSignInResult {\n isLoaded: boolean;\n /** The sign-in resource; null until the provider has created the instance. */\n signIn: SignInResource | null;\n errors: AttemptErrors;\n fetchStatus: FetchStatus;\n}\n\nconst NO_ERRORS: AttemptErrors = { fields: {}, global: [] };\n\nexport function useSignIn(): UseSignInResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const snapshot = useResource(zautha?.signIn ?? null);\n return {\n isLoaded: isLoadedStatus(state.status),\n signIn: zautha?.signIn ?? null,\n errors: snapshot?.errors ?? NO_ERRORS,\n fetchStatus: snapshot?.fetchStatus ?? \"idle\",\n };\n}\n\nexport interface UseSignUpResult {\n isLoaded: boolean;\n signUp: SignUpResource | null;\n errors: AttemptErrors;\n fetchStatus: FetchStatus;\n}\n\nexport function useSignUp(): UseSignUpResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const snapshot = useResource(zautha?.signUp ?? null);\n return {\n isLoaded: isLoadedStatus(state.status),\n signUp: zautha?.signUp ?? null,\n errors: snapshot?.errors ?? NO_ERRORS,\n fetchStatus: snapshot?.fetchStatus ?? \"idle\",\n };\n}\n","import { useEffect, type ReactNode } from \"react\";\nimport { useAuth, type Has, type HasParams } from \"./hooks\";\nimport { useZautha, useZauthaState } from \"./provider\";\n\nexport type ShowWhen = \"signed-in\" | \"signed-out\" | HasParams | ((has: Has) => boolean);\n\n/**\n * Renders `children` when the condition holds, else `fallback`. Renders nothing until Zautha has\n * loaded, so a signed-in user never sees a signed-out flash.\n */\nexport function Show(props: { when: ShowWhen; fallback?: ReactNode; children?: ReactNode }): ReactNode {\n const { isLoaded, isSignedIn, has } = useAuth();\n if (!isLoaded) return null;\n const { when } = props;\n const pass =\n when === \"signed-in\"\n ? isSignedIn\n : when === \"signed-out\"\n ? !isSignedIn\n : typeof when === \"function\"\n ? when(has)\n : has(when);\n return pass ? props.children : (props.fallback ?? null);\n}\n\nexport function ZauthaLoading(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"loading\" ? props.children : null;\n}\n\n/** Loaded, including degraded (network trouble after load: last known state is shown). */\nexport function ZauthaLoaded(props: { children?: ReactNode }): ReactNode {\n const { status } = useZauthaState();\n return status === \"ready\" || status === \"degraded\" ? props.children : null;\n}\n\nexport function ZauthaDegraded(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"degraded\" ? props.children : null;\n}\n\nexport function ZauthaFailed(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"failed\" ? props.children : null;\n}\n\n/** Sends a signed-out visitor to sign-in once loaded; renders nothing. */\nexport function RedirectToSignIn(props: { redirectUrl?: string }): ReactNode {\n const zautha = useZautha();\n const { isLoaded, isSignedIn } = useAuth();\n const { redirectUrl } = props;\n useEffect(() => {\n if (zautha !== null && isLoaded && !isSignedIn)\n zautha.redirectToSignIn(redirectUrl === undefined ? {} : { redirectUrl });\n }, [zautha, isLoaded, isSignedIn, redirectUrl]);\n return null;\n}\n\nexport function RedirectToSignUp(props: { redirectUrl?: string }): ReactNode {\n const zautha = useZautha();\n const { isLoaded, isSignedIn } = useAuth();\n const { redirectUrl } = props;\n useEffect(() => {\n if (zautha !== null && isLoaded && !isSignedIn)\n zautha.redirectToSignUp(redirectUrl === undefined ? {} : { redirectUrl });\n }, [zautha, isLoaded, isSignedIn, redirectUrl]);\n return null;\n}\n","import { Children, cloneElement, isValidElement, type MouseEvent, type ReactElement, type ReactNode } from \"react\";\nimport { useZautha } from \"./provider\";\n\ninterface ButtonProps {\n /** `redirect` (default) goes to the sign-in page; `modal` opens the prebuilt component (needs `ui`). */\n mode?: \"redirect\" | \"modal\";\n redirectUrl?: string;\n children?: ReactNode;\n}\n\n/** Wraps its single child (or renders a plain button) and wires the click. Unstyled by design. */\nfunction Trigger(props: { children: ReactNode; label: string; onClick: () => void }): ReactNode {\n const child = Children.count(props.children) === 1 ? Children.only(props.children) : null;\n if (isValidElement<{ onClick?: (event: MouseEvent) => void }>(child)) {\n const original = child.props.onClick;\n return cloneElement(child as ReactElement<{ onClick?: (event: MouseEvent) => void }>, {\n onClick: (event: MouseEvent) => {\n original?.(event);\n if (!event.defaultPrevented) props.onClick();\n },\n });\n }\n return (\n <button type=\"button\" onClick={props.onClick}>\n {props.children ?? props.label}\n </button>\n );\n}\n\nexport function SignInButton(props: ButtonProps): ReactNode {\n const zautha = useZautha();\n const options = props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl };\n return (\n <Trigger\n label=\"Sign in\"\n onClick={() => (props.mode === \"modal\" ? zautha?.openSignIn(options) : zautha?.redirectToSignIn(options))}\n >\n {props.children}\n </Trigger>\n );\n}\n\nexport function SignUpButton(props: ButtonProps): ReactNode {\n const zautha = useZautha();\n const options = props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl };\n return (\n <Trigger\n label=\"Sign up\"\n onClick={() => (props.mode === \"modal\" ? zautha?.openSignUp(options) : zautha?.redirectToSignUp(options))}\n >\n {props.children}\n </Trigger>\n );\n}\n\nexport function SignOutButton(props: { redirectUrl?: string; children?: ReactNode }): ReactNode {\n const zautha = useZautha();\n return (\n <Trigger\n label=\"Sign out\"\n onClick={() => void zautha?.signOut(props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl })}\n >\n {props.children}\n </Trigger>\n );\n}\n","import type { UiComponentName } from \"@zautha/js\";\nimport { useEffect, useRef, type ReactNode } from \"react\";\nimport { useZautha } from \"./provider\";\n\n/**\n * Mounts a @zautha/ui component into a div once the instance exists; later prop changes update it in\n * place. SSR renders only the empty div.\n */\nfunction Mounted(props: { name: UiComponentName; componentProps: object }): ReactNode {\n const zautha = useZautha();\n const ref = useRef<HTMLDivElement>(null);\n const mountedWith = useRef<object | null>(null);\n const { name, componentProps } = props;\n\n useEffect(() => {\n const element = ref.current;\n if (zautha === null || element === null) return;\n zautha.mount(name, element, componentProps);\n mountedWith.current = componentProps;\n return () => {\n mountedWith.current = null;\n zautha.unmount(element);\n };\n // componentProps changes are applied by the effect below without remounting.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [zautha, name]);\n\n useEffect(() => {\n const element = ref.current;\n if (zautha === null || element === null || mountedWith.current === null || mountedWith.current === componentProps)\n return;\n mountedWith.current = componentProps;\n zautha.updateMounted(element, componentProps);\n }, [zautha, componentProps]);\n\n return <div ref={ref} />;\n}\n\n// Prop types live in @zautha/ui; they are structural here so @zautha/react has no runtime dependency on it.\nexport function SignIn(props: import(\"@zautha/ui\").SignInProps): ReactNode {\n return <Mounted name=\"SignIn\" componentProps={props} />;\n}\n\nexport function SignUp(props: import(\"@zautha/ui\").SignUpProps): ReactNode {\n return <Mounted name=\"SignUp\" componentProps={props} />;\n}\n\n/** The page a provider sends the user back to: finishes the social sign-in or sign-up (see @zautha/ui). */\nexport function AuthenticateWithRedirectCallback(\n props: import(\"@zautha/ui\").AuthenticateWithRedirectCallbackProps,\n): ReactNode {\n return <Mounted name=\"AuthenticateWithRedirectCallback\" componentProps={props} />;\n}\n\nexport function UserButton(props: import(\"@zautha/ui\").UserButtonProps): ReactNode {\n return <Mounted name=\"UserButton\" componentProps={props} />;\n}\n\nexport function UserProfile(props: import(\"@zautha/ui\").UserProfileProps): ReactNode {\n return <Mounted name=\"UserProfile\" componentProps={props} />;\n}\n\nexport function OAuthConsent(props: import(\"@zautha/ui\").OAuthConsentProps): ReactNode {\n return <Mounted name=\"OAuthConsent\" componentProps={props} />;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["ZauthaError"],"sources":["../src/provider.tsx","../src/pagination.ts","../src/hooks.ts","../src/control.tsx","../src/buttons.tsx","../src/prebuilt.tsx"],"sourcesContent":["import { Zautha, type ZauthaOptions, type ZauthaState } from \"@zautha/js\";\nimport { createContext, useContext, useEffect, useMemo, useState, useSyncExternalStore, type ReactNode } from \"react\";\n\ninterface ZauthaContextValue {\n readonly zautha: Zautha | null;\n /** The snapshot before the instance exists and during server rendering (carries `initialState`). */\n readonly pending: ZauthaState;\n}\n\nconst ZauthaContext = createContext<ZauthaContextValue | undefined>(undefined);\n\nexport interface ZauthaProviderProps extends Omit<ZauthaOptions, \"fetch\"> {\n publishableKey: string;\n children?: ReactNode;\n}\n\n/**\n * Creates the Zautha instance after mount (never during render, so StrictMode's double mount and SSR\n * create no timers or channels), loads it, and disposes it on unmount. Until then hooks report\n * `isLoaded: false`, unless `initialState` (the server's view, e.g. from @zautha/nextjs) says who is signed in.\n */\nexport function ZauthaProvider({ publishableKey, children, ...options }: ZauthaProviderProps): ReactNode {\n const [zautha, setZautha] = useState<Zautha | null>(null);\n const { ui, appearance, localization, signInUrl, signUpUrl, navigate, initialState } = options;\n const [pending] = useState<ZauthaState>(() => ({ ...NO_STATE, initialState: initialState ?? null }));\n\n useEffect(() => {\n const instance = new Zautha(publishableKey, {\n ...(ui === undefined ? {} : { ui }),\n ...(appearance === undefined ? {} : { appearance }),\n ...(localization === undefined ? {} : { localization }),\n ...(signInUrl === undefined ? {} : { signInUrl }),\n ...(signUpUrl === undefined ? {} : { signUpUrl }),\n ...(navigate === undefined ? {} : { navigate }),\n ...(initialState === undefined ? {} : { initialState }),\n });\n // The instance is an external system: it is created here, never during render, and published through state.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setZautha(instance);\n void instance.load();\n return () => {\n instance.dispose();\n setZautha(null);\n };\n // Appearance/localization objects are read at mount; changing the key re-creates the instance.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [publishableKey]);\n\n const value = useMemo(() => ({ zautha, pending }), [zautha, pending]);\n return <ZauthaContext.Provider value={value}>{children}</ZauthaContext.Provider>;\n}\n\n/** The Zautha instance, or null before the provider has created it. */\nexport function useZautha(): Zautha | null {\n return useZauthaContext().zautha;\n}\n\nfunction useZauthaContext(): ZauthaContextValue {\n const value = useContext(ZauthaContext);\n if (value === undefined) throw new Error(\"Zautha hooks and components must be used inside <ZauthaProvider>.\");\n return value;\n}\n\nconst NO_STATE: ZauthaState = {\n status: \"loading\",\n environment: null,\n client: null,\n session: null,\n user: null,\n organization: null,\n initialState: null,\n};\nconst noop = (): (() => void) => () => undefined;\n\n/** Reactive snapshot of the instance state (the loading state, with any initial state, before the instance exists). */\nexport function useZauthaState(): ZauthaState {\n const { zautha, pending } = useZauthaContext();\n return useSyncExternalStore(\n zautha?.subscribe ?? noop,\n () => zautha?.getSnapshot() ?? pending,\n () => pending,\n );\n}\n","import type { Paginated } from \"@zautha/js\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n/** A list's page size (default 10, the API's) and the page to start on (default 1). */\nexport interface PaginationParams {\n pageSize?: number;\n initialPage?: number;\n}\n\n/**\n * One page of a list and how to move through it. `isLoading`: the page has no data yet; `isFetching`: a request for it\n * is in flight (also while `revalidate()` reads it again). A failed read leaves `data` empty and sets `error`.\n */\nexport interface PaginatedResult<T> {\n data: T[];\n /** How many there are in all. */\n count: number;\n page: number;\n pageCount: number;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n fetchNext: () => void;\n fetchPrevious: () => void;\n fetchPage: (page: number) => void;\n /** Reads the current page again; resolves once it has been read. */\n revalidate: () => Promise<void>;\n}\n\n/** What a page read gets: 1–100 items after `offset`. */\nexport type PageLoader<T> = (page: { limit: number; offset: number }) => Promise<Paginated<T>>;\n\n/** A list to read: `key` names what is listed (the user, the organization, the filters); `load` reads one page. */\nexport interface PageSource<T> {\n readonly key: string;\n readonly load: PageLoader<T>;\n}\n\ninterface Settled<T> {\n readonly request: string;\n readonly key: string;\n readonly page: number;\n readonly data: T[];\n readonly count: number;\n readonly error: Error | null;\n}\n\n/**\n * The pages of one list. Without a source nothing is read and the list is empty; a source with a new key starts again on\n * the initial page. A response to an older request (another page, key or revalidation) is dropped, so it never\n * overwrites a newer one.\n */\nexport function usePages<T>(\n source: PageSource<T> | null,\n params: PaginationParams | true | undefined,\n): PaginatedResult<T> {\n const key = source?.key ?? null;\n const { pageSize = 10, initialPage = 1 } = params === true || params === undefined ? {} : params;\n const [at, setAt] = useState({ key, page: initialPage, version: 0 });\n const [settled, setSettled] = useState<Settled<T> | null>(null);\n const latest = useRef(0);\n const waiting = useRef<(() => void)[]>([]);\n if (at.key !== key) {\n // Another list (also an earlier one again): start on its initial page with a fresh read, whatever was shown before.\n setAt({ key, page: initialPage, version: 0 });\n setSettled(null);\n }\n const { page, version } = at.key === key ? at : { page: initialPage, version: 0 };\n const request = JSON.stringify([key, page, pageSize, version]);\n const loader = useRef(source?.load);\n useEffect(() => {\n loader.current = source?.load;\n });\n\n useEffect(() => {\n const id = ++latest.current;\n const settle = (data: T[], count: number, error: Error | null): void => {\n if (latest.current !== id) return;\n if (key !== null) setSettled({ request, key, page, data, count, error });\n for (const resolve of waiting.current.splice(0)) resolve();\n };\n if (key === null || loader.current === undefined) return settle([], 0, null);\n loader.current({ limit: pageSize, offset: (page - 1) * pageSize }).then(\n (r) => settle(r.data, r.totalCount, null),\n (error: unknown) => settle([], 0, error instanceof Error ? error : new Error(String(error))),\n );\n // `request` covers key, page, pageSize and version.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [request]);\n\n const shown = settled !== null && settled.key === key && settled.page === page ? settled : null;\n const isFetching = key !== null && settled?.request !== request;\n const count = shown?.count ?? 0;\n const pageCount = Math.ceil(count / pageSize);\n const go = useCallback(\n (to: (page: number) => number) =>\n setAt((a) => {\n const from = a.key === key ? a.page : initialPage;\n return { key, page: Math.max(1, to(from)), version: a.key === key ? a.version : 0 };\n }),\n [key, initialPage],\n );\n const revalidate = useCallback(\n () =>\n new Promise<void>((resolve) => {\n waiting.current.push(resolve);\n setAt((a) => (a.key === key ? { ...a, version: a.version + 1 } : { key, page: initialPage, version: 1 }));\n }),\n [key, initialPage],\n );\n return {\n data: shown?.data ?? [],\n count,\n page,\n pageCount,\n isLoading: isFetching && shown === null,\n isFetching,\n error: shown?.error ?? null,\n hasNextPage: page < pageCount,\n hasPreviousPage: page > 1,\n fetchNext: useCallback(() => go((p) => p + 1), [go]),\n fetchPrevious: useCallback(() => go((p) => p - 1), [go]),\n fetchPage: useCallback((n: number) => go(() => n), [go]),\n revalidate,\n };\n}\n","import {\n checkAuthorization,\n withReverification,\n ZauthaError,\n type AttemptErrors,\n type FetchStatus,\n type OrganizationInvitationResource,\n type OrganizationInvitationStatus,\n type OrganizationMembership,\n type OrganizationMembershipResource,\n type OrganizationResource,\n type Session,\n type SessionActor,\n type SignInResource,\n type SignUpResource,\n type UserOrganizationInvitationResource,\n type UserResource,\n type ZauthaState,\n} from \"@zautha/js\";\nimport { useCallback, useLayoutEffect, useRef, useSyncExternalStore } from \"react\";\nimport { usePages, type PageLoader, type PageSource, type PaginatedResult, type PaginationParams } from \"./pagination\";\nimport { useZautha, useZauthaState } from \"./provider\";\n\n/**\n * What `has` checks in the session's active organization: full keys (`org:admin`, `org:invoices:read`). Every condition\n * given must hold; with none, false.\n */\nexport type HasParams = { role?: string; permission?: string };\nexport type Has = (params: HasParams) => boolean;\n\nexport interface UseAuthResult {\n isLoaded: boolean;\n isSignedIn: boolean;\n userId: string | null;\n sessionId: string | null;\n /** The active organization (`org_…`); null without one, and while signed out. */\n orgId: string | null;\n /** The user's role in it, a full key such as `org:admin`. */\n orgRole: string | null;\n /** Its slug; null without one or while the instance has slugs off. */\n orgSlug: string | null;\n /** The role's custom permissions, full keys such as `org:invoices:read`. */\n orgPermissions: readonly string[] | null;\n /**\n * Who is impersonating the user (an impersonation session; the token's `act` claim); null for the user's own session\n * and while signed out. With `ui` from @zautha/ui the provider shows the impersonation band by itself.\n */\n actor: SessionActor | null;\n getToken: (options?: { skipCache?: boolean }) => Promise<string | null>;\n signOut: (options?: { redirectUrl?: string }) => Promise<void>;\n /**\n * From the session token alone, the same rule as every Zautha SDK and your server: false without an active\n * organization, and always false for a system permission (`org:sys_…`, never in the token).\n */\n has: Has;\n}\n\nconst isLoadedStatus = (status: string): boolean => status === \"ready\" || status === \"degraded\";\n\n/** The signed-in session: a pending one (tasks left, e.g. setting up two-step verification) counts as signed out. */\nconst activeSession = (state: ZauthaState): Session | null =>\n state.session?.status === \"active\" ? state.session : null;\n\nexport function useAuth(): UseAuthResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const getToken = useCallback(\n (options?: { skipCache?: boolean }) => zautha?.getToken(options) ?? Promise.resolve(null),\n [zautha],\n );\n const signOut = useCallback(\n (options?: { redirectUrl?: string }) => zautha?.signOut(options) ?? Promise.resolve(),\n [zautha],\n );\n // Until the first load settles, the server's initial state (if any) answers, so nothing flickers.\n const initial = state.status === \"loading\" ? state.initialState : null;\n const session = activeSession(state);\n const userId = initial === null ? (session?.userId ?? null) : initial.userId;\n const sessionId = initial === null ? (session?.id ?? null) : initial.sessionId;\n const signedIn = userId !== null;\n const organization = initial === null ? (session === null ? null : state.organization) : initial.organization;\n const actor = initial === null ? (session?.actor ?? null) : initial.actor;\n const has = useCallback<Has>((params) => checkAuthorization(organization, params), [organization]);\n return {\n isLoaded: isLoadedStatus(state.status) || initial !== null,\n isSignedIn: signedIn,\n userId,\n sessionId,\n orgId: organization?.id ?? null,\n orgRole: organization?.role ?? null,\n orgSlug: organization?.slug ?? null,\n orgPermissions: organization?.permissions ?? null,\n actor,\n getToken,\n signOut,\n has,\n };\n}\n\n/** The signed-in user with its self-service actions (`user.update`, `user.createEmailAddress`, …). */\nexport function useUser(): { isLoaded: boolean; isSignedIn: boolean; user: UserResource | null } {\n const zautha = useZautha();\n const state = useZauthaState();\n const signedIn = activeSession(state) !== null;\n // zautha.user is rebuilt only when state.user changes, so the resource is stable between renders.\n const user = !signedIn || state.user === null ? null : (zautha?.user ?? null);\n return { isLoaded: isLoadedStatus(state.status), isSignedIn: signedIn, user };\n}\n\n/**\n * Wraps a sensitive action so that it completes after an identity check when it needs one: when `fetcher` throws\n * `ReverificationRequiredError` (e.g. `user.updatePassword`) or resolves to a `Response` with the `403\n * reverification_required` body (your backend with @zautha/backend, @zautha/nextjs or Zautha.AspNetCore), the\n * reverification modal opens and, once the user has verified, `fetcher` runs once more with the same arguments (its\n * token is fresh by then). Closing the modal rejects with `ReverificationCancelledError`. Needs `ui` from @zautha/ui on\n * the provider. The returned function is stable; it always calls the latest `fetcher`.\n */\nexport function useReverification<Args extends unknown[], Result>(\n fetcher: (...args: Args) => Promise<Result>,\n): (...args: Args) => Promise<Result> {\n const zautha = useZautha();\n const latest = useRef(fetcher);\n useLayoutEffect(() => {\n latest.current = fetcher;\n });\n return useCallback(\n (...args: Args) => {\n const call = (...callArgs: Args): Promise<Result> => latest.current(...callArgs);\n // Before the provider has created the instance no modal can open: the action runs as it is.\n return zautha === null ? call(...args) : withReverification(zautha, call)(...args);\n },\n [zautha],\n );\n}\n\n/** The signed-in session; null while signed out or while the session is pending (tasks left). */\nexport function useSession(): { isLoaded: boolean; isSignedIn: boolean; session: Session | null } {\n const state = useZauthaState();\n const session = activeSession(state);\n return { isLoaded: isLoadedStatus(state.status), isSignedIn: session !== null, session };\n}\n\nconst noopSubscribe = (): (() => void) => () => undefined;\n\nfunction useResource<T extends SignInResource | SignUpResource>(resource: T | null) {\n const snapshot = useSyncExternalStore(\n resource?.subscribe ?? noopSubscribe,\n () => resource?.snapshot ?? null,\n () => null,\n );\n return snapshot;\n}\n\nexport interface UseSignInResult {\n isLoaded: boolean;\n /** The sign-in resource; null until the provider has created the instance. */\n signIn: SignInResource | null;\n errors: AttemptErrors;\n fetchStatus: FetchStatus;\n}\n\nconst NO_ERRORS: AttemptErrors = { fields: {}, global: [] };\n\nexport function useSignIn(): UseSignInResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const snapshot = useResource(zautha?.signIn ?? null);\n return {\n isLoaded: isLoadedStatus(state.status),\n signIn: zautha?.signIn ?? null,\n errors: snapshot?.errors ?? NO_ERRORS,\n fetchStatus: snapshot?.fetchStatus ?? \"idle\",\n };\n}\n\nexport interface UseSignUpResult {\n isLoaded: boolean;\n signUp: SignUpResource | null;\n errors: AttemptErrors;\n fetchStatus: FetchStatus;\n}\n\nexport function useSignUp(): UseSignUpResult {\n const zautha = useZautha();\n const state = useZauthaState();\n const snapshot = useResource(zautha?.signUp ?? null);\n return {\n isLoaded: isLoadedStatus(state.status),\n signUp: zautha?.signUp ?? null,\n errors: snapshot?.errors ?? NO_ERRORS,\n fetchStatus: snapshot?.fetchStatus ?? \"idle\",\n };\n}\n\n/** A list a hook reads only when asked: `true` for the defaults, or the page size, the first page and the filters. */\nexport type ListParams<Filters = object> = true | (PaginationParams & Filters);\n\nexport interface UseOrganizationParams {\n /** The active organization's members (needs `org:sys_memberships:read`), filtered by a role key. */\n memberships?: ListParams<{ role?: string }>;\n /** Its invitations, filtered by status; read only for a member with `org:sys_memberships:manage` (else empty). */\n invitations?: ListParams<{ status?: OrganizationInvitationStatus[] }>;\n}\n\nexport interface UseOrganizationResult {\n isLoaded: boolean;\n /** The session's active organization with the member's actions; null without one, while signed out or pending. */\n organization: OrganizationResource | null;\n /** The user's membership of it: role and every permission of the role, system ones included (to show buttons). */\n membership: OrganizationMembershipResource | null;\n /** Only when asked for in the params. */\n memberships?: PaginatedResult<OrganizationMembership>;\n invitations?: PaginatedResult<OrganizationInvitationResource>;\n}\n\nexport interface UseOrganizationListParams {\n /** The user's memberships, newest first. */\n userMemberships?: ListParams;\n /** The invitations to the user's verified addresses; by default the pending ones. */\n userInvitations?: ListParams<{ status?: OrganizationInvitationStatus[] }>;\n}\n\nexport interface UseOrganizationListResult {\n isLoaded: boolean;\n /** Creates an organization with the user in it; it is not made active (`setActive` does that). */\n createOrganization: (params: { name: string; slug?: string }) => Promise<OrganizationResource>;\n /** Makes an organization (id or slug) the session's active one; null is the personal account. */\n setActive: (params: { organization: string | null }) => Promise<void>;\n userMemberships?: PaginatedResult<OrganizationMembershipResource>;\n userInvitations?: PaginatedResult<UserOrganizationInvitationResource>;\n}\n\n/** A list's filters: its params without the page size and the first page. */\nfunction filtersOf<F extends object>(params: ListParams<F>): F {\n const filters = { ...(params === true ? {} : params) } as PaginationParams & F;\n delete filters.pageSize;\n delete filters.initialPage;\n return filters;\n}\n\n/** A list of `owner` read with `load`: its key (`owner` and the params, so new filters start the list again). */\nconst list = <T>(owner: string, params: ListParams<object>, load: PageLoader<T>): PageSource<T> => ({\n key: `${owner}:${JSON.stringify(params)}`,\n load,\n});\n\n/** The signed-in user (an active session's) and whether hooks that read it are loaded. */\nfunction useSignedInUser(): { isLoaded: boolean; state: ZauthaState; user: UserResource | null } {\n const zautha = useZautha();\n const state = useZauthaState();\n const user = activeSession(state) === null ? null : (zautha?.user ?? null);\n // An active session is loaded once its user is.\n return { isLoaded: isLoadedStatus(state.status) && (activeSession(state) === null || user !== null), state, user };\n}\n\n/**\n * The session's active organization and the user's membership of it, from the session token and the user (no request of\n * its own), and on request its members and invitations, page by page. The lists start again on their first page when\n * the active organization changes.\n */\nexport function useOrganization(params: UseOrganizationParams = {}): UseOrganizationResult {\n const { isLoaded, state, user } = useSignedInUser();\n const id = state.organization?.id;\n const membership = user?.organizationMemberships.find((m) => m.organization.id === id) ?? null;\n const organization = membership?.organization ?? null;\n // The user's own membership: its user is the signed-in one.\n const owner = membership === null ? \"\" : `${membership.publicUserData.userId}:${membership.organization.id}`;\n const { memberships, invitations } = params;\n const manages = membership?.permissions.includes(\"org:sys_memberships:manage\") === true;\n const members = usePages(\n organization === null || memberships === undefined\n ? null\n : list(owner, memberships, (page) => organization.getMemberships({ ...filtersOf(memberships), ...page })),\n memberships,\n );\n const invited = usePages(\n organization === null || invitations === undefined || !manages\n ? null\n : list(owner, invitations, (page) => organization.getInvitations({ ...filtersOf(invitations), ...page })),\n invitations,\n );\n return {\n isLoaded,\n organization,\n membership,\n ...(memberships === undefined ? {} : { memberships: members }),\n ...(invitations === undefined ? {} : { invitations: invited }),\n };\n}\n\n/**\n * Creating an organization and choosing the active one, and on request the user's memberships and the invitations to\n * the user, page by page.\n */\nexport function useOrganizationList(params: UseOrganizationListParams = {}): UseOrganizationListResult {\n const zautha = useZautha();\n const { isLoaded, user } = useSignedInUser();\n const { userMemberships, userInvitations } = params;\n const memberships = usePages(\n user === null || userMemberships === undefined\n ? null\n : list(user.id, userMemberships, (page) => user.getOrganizationMemberships(page)),\n userMemberships,\n );\n const invitations = usePages(\n user === null || userInvitations === undefined\n ? null\n : list(user.id, userInvitations, (page) =>\n user.getOrganizationInvitations({ ...filtersOf(userInvitations), ...page }),\n ),\n userInvitations,\n );\n const createOrganization = useCallback(\n (p: { name: string; slug?: string }) => zautha?.createOrganization(p) ?? notLoaded(),\n [zautha],\n );\n const setActive = useCallback((p: { organization: string | null }) => zautha?.setActive(p) ?? notLoaded(), [zautha]);\n return {\n isLoaded,\n createOrganization,\n setActive,\n ...(userMemberships === undefined ? {} : { userMemberships: memberships }),\n ...(userInvitations === undefined ? {} : { userInvitations: invitations }),\n };\n}\n\nconst notLoaded = (): Promise<never> => Promise.reject(new ZauthaError(\"Zautha is not loaded yet.\"));\n","import { useEffect, type ReactNode } from \"react\";\nimport { useAuth, type Has, type HasParams } from \"./hooks\";\nimport { useZautha, useZauthaState } from \"./provider\";\n\nexport type ShowWhen = \"signed-in\" | \"signed-out\" | HasParams | ((has: Has) => boolean);\n\n/**\n * Renders `children` when the condition holds, else `fallback`. Renders nothing until Zautha has\n * loaded, so a signed-in user never sees a signed-out flash.\n */\nexport function Show(props: { when: ShowWhen; fallback?: ReactNode; children?: ReactNode }): ReactNode {\n const { isLoaded, isSignedIn, has } = useAuth();\n if (!isLoaded) return null;\n const { when } = props;\n const pass =\n when === \"signed-in\"\n ? isSignedIn\n : when === \"signed-out\"\n ? !isSignedIn\n : typeof when === \"function\"\n ? when(has)\n : has(when);\n return pass ? props.children : (props.fallback ?? null);\n}\n\nexport function ZauthaLoading(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"loading\" ? props.children : null;\n}\n\n/** Loaded, including degraded (network trouble after load: last known state is shown). */\nexport function ZauthaLoaded(props: { children?: ReactNode }): ReactNode {\n const { status } = useZauthaState();\n return status === \"ready\" || status === \"degraded\" ? props.children : null;\n}\n\nexport function ZauthaDegraded(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"degraded\" ? props.children : null;\n}\n\nexport function ZauthaFailed(props: { children?: ReactNode }): ReactNode {\n return useZauthaState().status === \"failed\" ? props.children : null;\n}\n\n/** Sends a signed-out visitor to sign-in once loaded; renders nothing. */\nexport function RedirectToSignIn(props: { redirectUrl?: string }): ReactNode {\n const zautha = useZautha();\n const { isLoaded, isSignedIn } = useAuth();\n const { redirectUrl } = props;\n useEffect(() => {\n if (zautha !== null && isLoaded && !isSignedIn)\n zautha.redirectToSignIn(redirectUrl === undefined ? {} : { redirectUrl });\n }, [zautha, isLoaded, isSignedIn, redirectUrl]);\n return null;\n}\n\nexport function RedirectToSignUp(props: { redirectUrl?: string }): ReactNode {\n const zautha = useZautha();\n const { isLoaded, isSignedIn } = useAuth();\n const { redirectUrl } = props;\n useEffect(() => {\n if (zautha !== null && isLoaded && !isSignedIn)\n zautha.redirectToSignUp(redirectUrl === undefined ? {} : { redirectUrl });\n }, [zautha, isLoaded, isSignedIn, redirectUrl]);\n return null;\n}\n","import { Children, cloneElement, isValidElement, type MouseEvent, type ReactElement, type ReactNode } from \"react\";\nimport { useZautha } from \"./provider\";\n\ninterface ButtonProps {\n /** `redirect` (default) goes to the sign-in page; `modal` opens the prebuilt component (needs `ui`). */\n mode?: \"redirect\" | \"modal\";\n redirectUrl?: string;\n children?: ReactNode;\n}\n\n/** Wraps its single child (or renders a plain button) and wires the click. Unstyled by design. */\nfunction Trigger(props: { children: ReactNode; label: string; onClick: () => void }): ReactNode {\n const child = Children.count(props.children) === 1 ? Children.only(props.children) : null;\n if (isValidElement<{ onClick?: (event: MouseEvent) => void }>(child)) {\n const original = child.props.onClick;\n return cloneElement(child as ReactElement<{ onClick?: (event: MouseEvent) => void }>, {\n onClick: (event: MouseEvent) => {\n original?.(event);\n if (!event.defaultPrevented) props.onClick();\n },\n });\n }\n return (\n <button type=\"button\" onClick={props.onClick}>\n {props.children ?? props.label}\n </button>\n );\n}\n\nexport function SignInButton(props: ButtonProps): ReactNode {\n const zautha = useZautha();\n const options = props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl };\n return (\n <Trigger\n label=\"Sign in\"\n onClick={() => (props.mode === \"modal\" ? zautha?.openSignIn(options) : zautha?.redirectToSignIn(options))}\n >\n {props.children}\n </Trigger>\n );\n}\n\nexport function SignUpButton(props: ButtonProps): ReactNode {\n const zautha = useZautha();\n const options = props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl };\n return (\n <Trigger\n label=\"Sign up\"\n onClick={() => (props.mode === \"modal\" ? zautha?.openSignUp(options) : zautha?.redirectToSignUp(options))}\n >\n {props.children}\n </Trigger>\n );\n}\n\nexport function SignOutButton(props: { redirectUrl?: string; children?: ReactNode }): ReactNode {\n const zautha = useZautha();\n return (\n <Trigger\n label=\"Sign out\"\n onClick={() => void zautha?.signOut(props.redirectUrl === undefined ? {} : { redirectUrl: props.redirectUrl })}\n >\n {props.children}\n </Trigger>\n );\n}\n","import type { UiComponentName } from \"@zautha/js\";\nimport { useEffect, useRef, type ReactNode } from \"react\";\nimport { useZautha } from \"./provider\";\n\n/**\n * Mounts a @zautha/ui component into a div once the instance exists; later prop changes update it in\n * place. SSR renders only the empty div.\n */\nfunction Mounted(props: { name: UiComponentName; componentProps: object }): ReactNode {\n const zautha = useZautha();\n const ref = useRef<HTMLDivElement>(null);\n const mountedWith = useRef<object | null>(null);\n const { name, componentProps } = props;\n\n useEffect(() => {\n const element = ref.current;\n if (zautha === null || element === null) return;\n zautha.mount(name, element, componentProps);\n mountedWith.current = componentProps;\n return () => {\n mountedWith.current = null;\n zautha.unmount(element);\n };\n // componentProps changes are applied by the effect below without remounting.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [zautha, name]);\n\n useEffect(() => {\n const element = ref.current;\n if (zautha === null || element === null || mountedWith.current === null || mountedWith.current === componentProps)\n return;\n mountedWith.current = componentProps;\n zautha.updateMounted(element, componentProps);\n }, [zautha, componentProps]);\n\n return <div ref={ref} />;\n}\n\n// Prop types live in @zautha/ui; they are structural here so @zautha/react has no runtime dependency on it.\nexport function SignIn(props: import(\"@zautha/ui\").SignInProps): ReactNode {\n return <Mounted name=\"SignIn\" componentProps={props} />;\n}\n\nexport function SignUp(props: import(\"@zautha/ui\").SignUpProps): ReactNode {\n return <Mounted name=\"SignUp\" componentProps={props} />;\n}\n\n/** The page a provider sends the user back to: finishes the social sign-in or sign-up (see @zautha/ui). */\nexport function AuthenticateWithRedirectCallback(\n props: import(\"@zautha/ui\").AuthenticateWithRedirectCallbackProps,\n): ReactNode {\n return <Mounted name=\"AuthenticateWithRedirectCallback\" componentProps={props} />;\n}\n\nexport function UserButton(props: import(\"@zautha/ui\").UserButtonProps): ReactNode {\n return <Mounted name=\"UserButton\" componentProps={props} />;\n}\n\nexport function UserProfile(props: import(\"@zautha/ui\").UserProfileProps): ReactNode {\n return <Mounted name=\"UserProfile\" componentProps={props} />;\n}\n\nexport function OAuthConsent(props: import(\"@zautha/ui\").OAuthConsentProps): ReactNode {\n return <Mounted name=\"OAuthConsent\" componentProps={props} />;\n}\n\nexport function CreateOrganization(props: import(\"@zautha/ui\").CreateOrganizationProps): ReactNode {\n return <Mounted name=\"CreateOrganization\" componentProps={props} />;\n}\n\nexport function OrganizationProfile(props: import(\"@zautha/ui\").OrganizationProfileProps): ReactNode {\n return <Mounted name=\"OrganizationProfile\" componentProps={props} />;\n}\n\nexport function OrganizationSwitcher(props: import(\"@zautha/ui\").OrganizationSwitcherProps): ReactNode {\n return <Mounted name=\"OrganizationSwitcher\" componentProps={props} />;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zautha/react",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "private": false,
5
5
  "description": "React bindings for Zautha: provider, hooks, <Show>, buttons and prebuilt components.",
6
6
  "license": "MIT",
@@ -31,12 +31,12 @@
31
31
  "LICENSE"
32
32
  ],
33
33
  "dependencies": {
34
- "@zautha/js": "^0.10.0"
34
+ "@zautha/js": "^0.12.0"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "react": "^19.0.0",
38
38
  "react-dom": "^19.0.0",
39
- "@zautha/ui": "^0.10.0"
39
+ "@zautha/ui": "^0.12.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@size-limit/preset-small-lib": "14.0.1",
@@ -44,15 +44,15 @@
44
44
  "@testing-library/user-event": "14.6.7",
45
45
  "@types/react": "19.3.0",
46
46
  "@types/react-dom": "19.3.0",
47
- "@zautha/ui": "0.10.0",
48
- "happy-dom": "20.14.5",
47
+ "@zautha/ui": "0.12.0",
48
+ "happy-dom": "21.0.4",
49
49
  "msw": "2.15.0",
50
50
  "react": "19.3.0",
51
51
  "react-dom": "19.3.0",
52
52
  "size-limit": "14.0.1",
53
53
  "tsdown": "0.23.0",
54
54
  "typescript": "6.0.3",
55
- "vitest": "5.0.2"
55
+ "vitest": "5.0.5"
56
56
  },
57
57
  "size-limit": [
58
58
  {