@outseta/react 0.0.0 → 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Outseta
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # @outseta/react
2
+
3
+ React hooks and components for the [Outseta](https://www.outseta.com) API. Built on [TanStack Query](https://tanstack.com/query) with auto-generated hooks from the Outseta OpenAPI spec.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @outseta/react
9
+ ```
10
+
11
+ ### Peer dependencies
12
+
13
+ - `react` ^18.0.0 || ^19.0.0
14
+
15
+ ## Usage
16
+
17
+ ```ts
18
+ import { createClient } from "@outseta/react";
19
+
20
+ const client = createClient({
21
+ subdomain: "your-company",
22
+ apiKey: "your-api-key",
23
+ apiSecret: "your-api-secret",
24
+ });
25
+ ```
26
+
27
+ ## License
28
+
29
+ [MIT](../../LICENSE)
package/dist/index.js CHANGED
@@ -1,3 +1,210 @@
1
+ // src/components/OutsetaProvider.tsx
2
+ import {
3
+ createContext,
4
+ useContext,
5
+ useEffect,
6
+ useRef,
7
+ useState
8
+ } from "react";
9
+ import { jsxDEV } from "react/jsx-dev-runtime";
10
+ var OutsetaContext = createContext(null);
11
+ function useOutseta() {
12
+ const context = useContext(OutsetaContext);
13
+ if (!context) {
14
+ throw new Error("useOutseta must be used within an OutsetaProvider");
15
+ }
16
+ return context;
17
+ }
18
+ function getOutseta() {
19
+ if (typeof window !== "undefined" && window.Outseta) {
20
+ return window.Outseta;
21
+ }
22
+ return null;
23
+ }
24
+ function OutsetaProvider({ children }) {
25
+ const [status, setStatus] = useState("init");
26
+ const [user, setUser] = useState(null);
27
+ const outsetaRef = useRef(null);
28
+ useEffect(() => {
29
+ const outseta = getOutseta();
30
+ if (!outseta)
31
+ return;
32
+ outsetaRef.current = outseta;
33
+ const updateUser = async () => {
34
+ try {
35
+ const outsetaUser = await outseta.getUser();
36
+ setUser(outsetaUser);
37
+ } catch {
38
+ setUser(null);
39
+ } finally {
40
+ setStatus("ready");
41
+ }
42
+ };
43
+ outseta.on("subscription.update", updateUser);
44
+ outseta.on("profile.update", updateUser);
45
+ outseta.on("account.update", updateUser);
46
+ const params = new URLSearchParams(window.location.search);
47
+ const accessToken = params.get("access_token");
48
+ if (accessToken) {
49
+ outseta.setAccessToken(accessToken);
50
+ params.delete("access_token");
51
+ const newSearch = params.toString();
52
+ const newUrl = window.location.pathname + (newSearch ? `?${newSearch}` : "") + window.location.hash;
53
+ window.history.replaceState({}, "", newUrl);
54
+ }
55
+ const checkAuth = async () => {
56
+ try {
57
+ const token = await outseta.getAccessToken();
58
+ if (token) {
59
+ await updateUser();
60
+ } else {
61
+ setStatus("ready");
62
+ }
63
+ } catch {
64
+ setStatus("ready");
65
+ }
66
+ };
67
+ checkAuth();
68
+ return () => {
69
+ outseta.on("subscription.update", () => {});
70
+ outseta.on("profile.update", () => {});
71
+ outseta.on("account.update", () => {});
72
+ };
73
+ }, []);
74
+ const logout = () => {
75
+ const outseta = outsetaRef.current;
76
+ if (!outseta)
77
+ return;
78
+ outseta.setAccessToken("");
79
+ setUser(null);
80
+ outseta.logout();
81
+ };
82
+ const openLogin = (options = {}) => {
83
+ outsetaRef.current?.auth.open({
84
+ widgetMode: "login|register",
85
+ authenticationCallbackUrl: window.location.href,
86
+ ...options
87
+ });
88
+ };
89
+ const openSignup = (options = {}) => {
90
+ outsetaRef.current?.auth.open({
91
+ widgetMode: "register",
92
+ authenticationCallbackUrl: window.location.href,
93
+ ...options
94
+ });
95
+ };
96
+ const openProfile = (options = {}) => {
97
+ outsetaRef.current?.profile.open({ tab: "profile", ...options });
98
+ };
99
+ return /* @__PURE__ */ jsxDEV(OutsetaContext.Provider, {
100
+ value: {
101
+ user,
102
+ isLoading: status !== "ready",
103
+ logout,
104
+ openLogin,
105
+ openSignup,
106
+ openProfile
107
+ },
108
+ children
109
+ }, undefined, false, undefined, this);
110
+ }
111
+ // src/components/AuthEmbed.tsx
112
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
113
+ function AuthEmbed({
114
+ widgetMode = "login|register",
115
+ registrationDefaults,
116
+ ...props
117
+ }) {
118
+ const defaults = typeof registrationDefaults === "string" ? registrationDefaults : registrationDefaults ? JSON.stringify(registrationDefaults) : undefined;
119
+ return /* @__PURE__ */ jsxDEV2("div", {
120
+ ...props,
121
+ children: /* @__PURE__ */ jsxDEV2("div", {
122
+ "data-o-auth": "1",
123
+ "data-mode": "embed",
124
+ "data-widget-mode": widgetMode,
125
+ "data-registration-defaults": defaults
126
+ }, undefined, false, undefined, this)
127
+ }, widgetMode, false, undefined, this);
128
+ }
129
+ // src/components/ProfileEmbed.tsx
130
+ import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
131
+ function ProfileEmbed({ tab = "profile", ...props }) {
132
+ return /* @__PURE__ */ jsxDEV3("div", {
133
+ ...props,
134
+ children: /* @__PURE__ */ jsxDEV3("div", {
135
+ "data-o-profile": "1",
136
+ "data-mode": "embed",
137
+ "data-tab": tab
138
+ }, undefined, false, undefined, this)
139
+ }, tab, false, undefined, this);
140
+ }
141
+ // src/components/ProtectedRoute.tsx
142
+ import { jsxDEV as jsxDEV4, Fragment } from "react/jsx-dev-runtime";
143
+ function ProtectedRoute({
144
+ plans,
145
+ children,
146
+ loading = null,
147
+ accessDenied = null,
148
+ unauthenticated = null
149
+ }) {
150
+ const { user, isLoading } = useOutseta();
151
+ if (isLoading)
152
+ return /* @__PURE__ */ jsxDEV4(Fragment, {
153
+ children: loading
154
+ }, undefined, false, undefined, this);
155
+ if (!user)
156
+ return /* @__PURE__ */ jsxDEV4(Fragment, {
157
+ children: unauthenticated
158
+ }, undefined, false, undefined, this);
159
+ const userPlanUid = user.Account?.CurrentSubscription?.Plan?.Uid;
160
+ const hasAccess = userPlanUid ? plans.includes(userPlanUid) : false;
161
+ if (!hasAccess)
162
+ return /* @__PURE__ */ jsxDEV4(Fragment, {
163
+ children: accessDenied
164
+ }, undefined, false, undefined, this);
165
+ return /* @__PURE__ */ jsxDEV4(Fragment, {
166
+ children
167
+ }, undefined, false, undefined, this);
168
+ }
169
+ // src/components/PurchaseAddonButton.tsx
170
+ import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
171
+ function PurchaseAddonButton({
172
+ addonUid,
173
+ billingRenewalTerm = 4,
174
+ children = "Buy Add-on",
175
+ ...props
176
+ }) {
177
+ const { openProfile } = useOutseta();
178
+ return /* @__PURE__ */ jsxDEV5("button", {
179
+ onClick: () => openProfile({
180
+ mode: "popup",
181
+ tab: "purchaseAddOn",
182
+ stateProps: { addOnUid: addonUid, billingRenewalTerm }
183
+ }),
184
+ ...props,
185
+ children
186
+ }, undefined, false, undefined, this);
187
+ }
188
+ // src/components/LogoutButton.tsx
189
+ import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
190
+ function LogoutButton({
191
+ children = "Logout",
192
+ ...props
193
+ }) {
194
+ const { logout } = useOutseta();
195
+ return /* @__PURE__ */ jsxDEV6("button", {
196
+ onClick: logout,
197
+ ...props,
198
+ children
199
+ }, undefined, false, undefined, this);
200
+ }
1
201
  export {
2
- createClient
202
+ useOutseta,
203
+ createClient,
204
+ PurchaseAddonButton,
205
+ ProtectedRoute,
206
+ ProfileEmbed,
207
+ OutsetaProvider,
208
+ LogoutButton,
209
+ AuthEmbed
3
210
  };
package/package.json CHANGED
@@ -1,7 +1,13 @@
1
1
  {
2
2
  "name": "@outseta/react",
3
- "version": "0.0.0",
3
+ "version": "0.2.0",
4
4
  "description": "React hooks and components for the Outseta API",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/outseta/outseta-js.git",
9
+ "directory": "packages/react"
10
+ },
5
11
  "type": "module",
6
12
  "main": "./dist/index.js",
7
13
  "types": "./src/index.ts",
@@ -28,8 +34,12 @@
28
34
  "typescript": "^5.7.0"
29
35
  },
30
36
  "sideEffects": false,
31
- "files": ["dist", "src"],
37
+ "files": [
38
+ "dist",
39
+ "src"
40
+ ],
32
41
  "publishConfig": {
33
- "access": "public"
42
+ "access": "public",
43
+ "provenance": true
34
44
  }
35
45
  }
@@ -0,0 +1,38 @@
1
+ import type { HTMLAttributes } from "react";
2
+
3
+ export interface AuthEmbedProps extends HTMLAttributes<HTMLDivElement> {
4
+ /** Widget mode: "login", "register", or "login|register" */
5
+ widgetMode?: "login" | "register" | "login|register";
6
+ /** Registration defaults as a JSON string or object */
7
+ registrationDefaults?: string | Record<string, unknown>;
8
+ }
9
+
10
+ /**
11
+ * Renders an embedded Outseta auth widget (login/register).
12
+ *
13
+ * Uses `key={widgetMode}` internally so React re-mounts the widget
14
+ * when the mode changes.
15
+ */
16
+ export function AuthEmbed({
17
+ widgetMode = "login|register",
18
+ registrationDefaults,
19
+ ...props
20
+ }: AuthEmbedProps) {
21
+ const defaults =
22
+ typeof registrationDefaults === "string"
23
+ ? registrationDefaults
24
+ : registrationDefaults
25
+ ? JSON.stringify(registrationDefaults)
26
+ : undefined;
27
+
28
+ return (
29
+ <div key={widgetMode} {...props}>
30
+ <div
31
+ data-o-auth="1"
32
+ data-mode="embed"
33
+ data-widget-mode={widgetMode}
34
+ data-registration-defaults={defaults}
35
+ />
36
+ </div>
37
+ );
38
+ }
@@ -0,0 +1,18 @@
1
+ import type { ButtonHTMLAttributes } from "react";
2
+ import { useOutseta } from "./OutsetaProvider.js";
3
+
4
+ /**
5
+ * Button that logs the user out of Outseta.
6
+ */
7
+ export function LogoutButton({
8
+ children = "Logout",
9
+ ...props
10
+ }: ButtonHTMLAttributes<HTMLButtonElement>) {
11
+ const { logout } = useOutseta();
12
+
13
+ return (
14
+ <button onClick={logout} {...props}>
15
+ {children}
16
+ </button>
17
+ );
18
+ }
@@ -0,0 +1,151 @@
1
+ import {
2
+ createContext,
3
+ useContext,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
+ type ReactNode,
8
+ } from "react";
9
+ import type {
10
+ AuthWidgetOptions,
11
+ OutsetaEmbed,
12
+ OutsetaUser,
13
+ ProfileWidgetOptions,
14
+ } from "./types.js";
15
+
16
+ export interface OutsetaContextValue {
17
+ user: OutsetaUser | null;
18
+ isLoading: boolean;
19
+ logout: () => void;
20
+ openLogin: (options?: AuthWidgetOptions) => void;
21
+ openSignup: (options?: AuthWidgetOptions) => void;
22
+ openProfile: (options?: ProfileWidgetOptions) => void;
23
+ }
24
+
25
+ const OutsetaContext = createContext<OutsetaContextValue | null>(null);
26
+
27
+ export function useOutseta(): OutsetaContextValue {
28
+ const context = useContext(OutsetaContext);
29
+ if (!context) {
30
+ throw new Error("useOutseta must be used within an OutsetaProvider");
31
+ }
32
+ return context;
33
+ }
34
+
35
+ function getOutseta(): OutsetaEmbed | null {
36
+ if (typeof window !== "undefined" && window.Outseta) {
37
+ return window.Outseta;
38
+ }
39
+ return null;
40
+ }
41
+
42
+ export function OutsetaProvider({ children }: { children: ReactNode }) {
43
+ const [status, setStatus] = useState<"init" | "ready">("init");
44
+ const [user, setUser] = useState<OutsetaUser | null>(null);
45
+ const outsetaRef = useRef<OutsetaEmbed | null>(null);
46
+
47
+ useEffect(() => {
48
+ const outseta = getOutseta();
49
+ if (!outseta) return;
50
+ outsetaRef.current = outseta;
51
+
52
+ const updateUser = async () => {
53
+ try {
54
+ const outsetaUser = await outseta.getUser();
55
+ setUser(outsetaUser);
56
+ } catch {
57
+ setUser(null);
58
+ } finally {
59
+ setStatus("ready");
60
+ }
61
+ };
62
+
63
+ // Subscribe to user-related events
64
+ outseta.on("subscription.update", updateUser);
65
+ outseta.on("profile.update", updateUser);
66
+ outseta.on("account.update", updateUser);
67
+
68
+ // Handle OAuth callback access_token from URL
69
+ const params = new URLSearchParams(window.location.search);
70
+ const accessToken = params.get("access_token");
71
+
72
+ if (accessToken) {
73
+ outseta.setAccessToken(accessToken);
74
+
75
+ // Clean up URL without triggering navigation
76
+ params.delete("access_token");
77
+ const newSearch = params.toString();
78
+ const newUrl =
79
+ window.location.pathname +
80
+ (newSearch ? `?${newSearch}` : "") +
81
+ window.location.hash;
82
+ window.history.replaceState({}, "", newUrl);
83
+ }
84
+
85
+ // Check existing auth state
86
+ const checkAuth = async () => {
87
+ try {
88
+ const token = await outseta.getAccessToken();
89
+ if (token) {
90
+ await updateUser();
91
+ } else {
92
+ setStatus("ready");
93
+ }
94
+ } catch {
95
+ setStatus("ready");
96
+ }
97
+ };
98
+
99
+ checkAuth();
100
+
101
+ return () => {
102
+ // Replace event handlers with no-ops on cleanup
103
+ outseta.on("subscription.update", () => {});
104
+ outseta.on("profile.update", () => {});
105
+ outseta.on("account.update", () => {});
106
+ };
107
+ }, []);
108
+
109
+ const logout = () => {
110
+ const outseta = outsetaRef.current;
111
+ if (!outseta) return;
112
+ outseta.setAccessToken("");
113
+ setUser(null);
114
+ outseta.logout();
115
+ };
116
+
117
+ const openLogin = (options: AuthWidgetOptions = {}) => {
118
+ outsetaRef.current?.auth.open({
119
+ widgetMode: "login|register",
120
+ authenticationCallbackUrl: window.location.href,
121
+ ...options,
122
+ });
123
+ };
124
+
125
+ const openSignup = (options: AuthWidgetOptions = {}) => {
126
+ outsetaRef.current?.auth.open({
127
+ widgetMode: "register",
128
+ authenticationCallbackUrl: window.location.href,
129
+ ...options,
130
+ });
131
+ };
132
+
133
+ const openProfile = (options: ProfileWidgetOptions = {}) => {
134
+ outsetaRef.current?.profile.open({ tab: "profile", ...options });
135
+ };
136
+
137
+ return (
138
+ <OutsetaContext.Provider
139
+ value={{
140
+ user,
141
+ isLoading: status !== "ready",
142
+ logout,
143
+ openLogin,
144
+ openSignup,
145
+ openProfile,
146
+ }}
147
+ >
148
+ {children}
149
+ </OutsetaContext.Provider>
150
+ );
151
+ }
@@ -0,0 +1,26 @@
1
+ import type { HTMLAttributes } from "react";
2
+
3
+ export interface ProfileEmbedProps extends HTMLAttributes<HTMLDivElement> {
4
+ /** Profile tab to display */
5
+ tab?:
6
+ | "profile"
7
+ | "billing"
8
+ | "planChange"
9
+ | "purchaseAddOn"
10
+ | "passwordChange"
11
+ | "teamMembers";
12
+ }
13
+
14
+ /**
15
+ * Renders an embedded Outseta profile widget.
16
+ *
17
+ * Uses `key={tab}` internally so React re-mounts the widget
18
+ * when the tab changes.
19
+ */
20
+ export function ProfileEmbed({ tab = "profile", ...props }: ProfileEmbedProps) {
21
+ return (
22
+ <div key={tab} {...props}>
23
+ <div data-o-profile="1" data-mode="embed" data-tab={tab} />
24
+ </div>
25
+ );
26
+ }
@@ -0,0 +1,42 @@
1
+ import type { ReactNode } from "react";
2
+ import { useOutseta } from "./OutsetaProvider.js";
3
+
4
+ export interface ProtectedRouteProps {
5
+ /** Plan UIDs that grant access to this route */
6
+ plans: string[];
7
+ /** Content to render when access is granted */
8
+ children: ReactNode;
9
+ /** Rendered while checking auth status (defaults to null) */
10
+ loading?: ReactNode;
11
+ /** Rendered when user is logged in but lacks the right plan */
12
+ accessDenied?: ReactNode;
13
+ /** Rendered when user is not logged in */
14
+ unauthenticated?: ReactNode;
15
+ }
16
+
17
+ /**
18
+ * Protects content behind plan-based access control.
19
+ *
20
+ * Checks the current user's subscription plan UID against the
21
+ * provided list of allowed plan UIDs.
22
+ */
23
+ export function ProtectedRoute({
24
+ plans,
25
+ children,
26
+ loading = null,
27
+ accessDenied = null,
28
+ unauthenticated = null,
29
+ }: ProtectedRouteProps) {
30
+ const { user, isLoading } = useOutseta();
31
+
32
+ if (isLoading) return <>{loading}</>;
33
+
34
+ if (!user) return <>{unauthenticated}</>;
35
+
36
+ const userPlanUid = user.Account?.CurrentSubscription?.Plan?.Uid;
37
+ const hasAccess = userPlanUid ? plans.includes(userPlanUid) : false;
38
+
39
+ if (!hasAccess) return <>{accessDenied}</>;
40
+
41
+ return <>{children}</>;
42
+ }
@@ -0,0 +1,38 @@
1
+ import type { ButtonHTMLAttributes } from "react";
2
+ import { useOutseta } from "./OutsetaProvider.js";
3
+
4
+ export interface PurchaseAddonButtonProps
5
+ extends ButtonHTMLAttributes<HTMLButtonElement> {
6
+ /** The Outseta add-on UID to purchase */
7
+ addonUid: string;
8
+ /** Billing renewal term (4 = one-time purchase by default) */
9
+ billingRenewalTerm?: number;
10
+ }
11
+
12
+ /**
13
+ * Button that opens the Outseta profile widget to the
14
+ * "Purchase Add-on" tab for a specific add-on.
15
+ */
16
+ export function PurchaseAddonButton({
17
+ addonUid,
18
+ billingRenewalTerm = 4,
19
+ children = "Buy Add-on",
20
+ ...props
21
+ }: PurchaseAddonButtonProps) {
22
+ const { openProfile } = useOutseta();
23
+
24
+ return (
25
+ <button
26
+ onClick={() =>
27
+ openProfile({
28
+ mode: "popup",
29
+ tab: "purchaseAddOn",
30
+ stateProps: { addOnUid: addonUid, billingRenewalTerm },
31
+ })
32
+ }
33
+ {...props}
34
+ >
35
+ {children}
36
+ </button>
37
+ );
38
+ }
@@ -0,0 +1,17 @@
1
+ export type {
2
+ OutsetaUser,
3
+ OutsetaEmbed,
4
+ AuthWidgetOptions,
5
+ ProfileWidgetOptions,
6
+ } from "./types.js";
7
+ export { OutsetaProvider, useOutseta } from "./OutsetaProvider.js";
8
+ export type { OutsetaContextValue } from "./OutsetaProvider.js";
9
+ export { AuthEmbed } from "./AuthEmbed.js";
10
+ export type { AuthEmbedProps } from "./AuthEmbed.js";
11
+ export { ProfileEmbed } from "./ProfileEmbed.js";
12
+ export type { ProfileEmbedProps } from "./ProfileEmbed.js";
13
+ export { ProtectedRoute } from "./ProtectedRoute.js";
14
+ export type { ProtectedRouteProps } from "./ProtectedRoute.js";
15
+ export { PurchaseAddonButton } from "./PurchaseAddonButton.js";
16
+ export type { PurchaseAddonButtonProps } from "./PurchaseAddonButton.js";
17
+ export { LogoutButton } from "./LogoutButton.js";
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Type definitions for the Outseta embed script (window.Outseta).
3
+ * These describe the client-side SDK loaded via script tag,
4
+ * NOT the REST API types generated by Orval.
5
+ */
6
+
7
+ export interface OutsetaUser {
8
+ Uid: string;
9
+ Email: string;
10
+ FirstName?: string;
11
+ LastName?: string;
12
+ FullName?: string;
13
+ Account?: {
14
+ Uid?: string;
15
+ Name?: string;
16
+ CurrentSubscription?: {
17
+ Uid?: string;
18
+ Plan?: {
19
+ Uid?: string;
20
+ Name?: string;
21
+ };
22
+ SubscriptionAddOns?: Array<{
23
+ AddOn?: {
24
+ Uid?: string;
25
+ Name?: string;
26
+ };
27
+ }>;
28
+ };
29
+ };
30
+ [key: string]: unknown;
31
+ }
32
+
33
+ export interface AuthWidgetOptions {
34
+ widgetMode?: "login" | "register" | "login|register";
35
+ authenticationCallbackUrl?: string;
36
+ mode?: "popup" | "embed";
37
+ registrationDefaults?: string;
38
+ [key: string]: unknown;
39
+ }
40
+
41
+ export interface ProfileWidgetOptions {
42
+ tab?:
43
+ | "profile"
44
+ | "billing"
45
+ | "planChange"
46
+ | "purchaseAddOn"
47
+ | "passwordChange"
48
+ | "teamMembers";
49
+ mode?: "popup" | "embed";
50
+ stateProps?: Record<string, unknown>;
51
+ [key: string]: unknown;
52
+ }
53
+
54
+ export interface OutsetaEmbed {
55
+ setAccessToken: (token: string) => void;
56
+ getAccessToken: () => Promise<string | null>;
57
+ getUser: () => Promise<OutsetaUser>;
58
+ logout: () => void;
59
+ on: (event: string, callback: () => void) => void;
60
+ auth: {
61
+ open: (options?: AuthWidgetOptions) => void;
62
+ };
63
+ profile: {
64
+ open: (options?: ProfileWidgetOptions) => void;
65
+ };
66
+ }
67
+
68
+ declare global {
69
+ interface Window {
70
+ Outseta?: OutsetaEmbed;
71
+ }
72
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  export { createClient } from "@outseta/api-client";
2
2
  export type { OutsetaCredentials } from "@outseta/api-client";
3
3
 
4
+ // Outseta embed components and hooks
5
+ export * from "./components/index.js";
6
+
4
7
  // Re-export generated React Query hooks once generated
5
8
  // export * from "./generated/index.js";