@outseta/react 0.3.7 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -7
- package/dist/index.js +754 -148
- package/package.json +13 -5
- package/src/components/AuthButton.tsx +33 -0
- package/src/components/AuthEmbed.tsx +4 -0
- package/src/components/EmailListButton.tsx +38 -0
- package/src/components/EmailListEmbed.tsx +28 -0
- package/src/components/EmailListForm.tsx +34 -0
- package/src/components/LeadCaptureButton.tsx +38 -0
- package/src/components/LeadCaptureEmbed.tsx +28 -0
- package/src/components/LoginButton.tsx +18 -0
- package/src/components/LogoutButton.tsx +8 -1
- package/src/components/OutsetaProvider.tsx +36 -7
- package/src/components/ProfileButton.tsx +35 -0
- package/src/components/ProfileEmbed.tsx +8 -2
- package/src/components/PurchaseAddonButton.tsx +8 -4
- package/src/components/SignupButton.tsx +18 -0
- package/src/components/SupportButton.tsx +35 -0
- package/src/components/SupportEmbed.tsx +17 -0
- package/src/components/index.ts +27 -0
- package/src/components/types.ts +33 -4
- package/src/components/utils.ts +13 -0
- package/src/generated/activity/activity.ts +2 -2
- package/src/generated/attribute/attribute.ts +2 -2
- package/src/generated/billing/billing.ts +2 -2
- package/src/generated/crm/crm.ts +2 -2
- package/src/generated/email/email.ts +2 -2
- package/src/generated/outsetaAPI.schemas.ts +5149 -60
- package/src/generated/public/public.ts +2 -2
- package/src/generated/support/support.ts +2 -2
- package/src/index.ts +1 -1
- package/src/mutator.ts +3 -3
- package/src/query.test.ts +276 -0
- package/src/query.ts +352 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@outseta/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "React hooks and components for the Outseta API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -18,15 +18,21 @@
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@
|
|
22
|
-
"@outseta/api-client": "0.3.6"
|
|
21
|
+
"@outseta/api-client": "0.3.7"
|
|
23
22
|
},
|
|
24
23
|
"peerDependencies": {
|
|
25
24
|
"react": "^18.0.0 || ^19.0.0"
|
|
26
25
|
},
|
|
27
26
|
"devDependencies": {
|
|
27
|
+
"@testing-library/dom": "^10.4.0",
|
|
28
|
+
"@testing-library/react": "^16.1.0",
|
|
28
29
|
"@types/react": "^19.0.0",
|
|
29
|
-
"
|
|
30
|
+
"@types/react-dom": "^19.0.0",
|
|
31
|
+
"jsdom": "^26.0.0",
|
|
32
|
+
"react": "19.2.7",
|
|
33
|
+
"react-dom": "19.2.7",
|
|
34
|
+
"typescript": "^5.7.0",
|
|
35
|
+
"vitest": "^3.2.0"
|
|
30
36
|
},
|
|
31
37
|
"sideEffects": false,
|
|
32
38
|
"files": [
|
|
@@ -40,6 +46,8 @@
|
|
|
40
46
|
"scripts": {
|
|
41
47
|
"build": "rimraf dist && bun build src/index.ts --outdir dist --target browser --format esm --packages external",
|
|
42
48
|
"typecheck": "tsc --noEmit",
|
|
43
|
-
"lint": "eslint src --ignore-pattern generated"
|
|
49
|
+
"lint": "eslint src --ignore-pattern generated",
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"test:watch": "vitest"
|
|
44
52
|
}
|
|
45
53
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes } from "react";
|
|
2
|
+
import { useOutseta } from "./OutsetaProvider.js";
|
|
3
|
+
import type { AuthWidgetOptions } from "./types.js";
|
|
4
|
+
import { composeButtonClick } from "./utils.js";
|
|
5
|
+
|
|
6
|
+
export interface AuthButtonProps
|
|
7
|
+
extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
8
|
+
/** Options passed to `Outseta.auth.open`. */
|
|
9
|
+
options?: AuthWidgetOptions;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Unstyled button that opens the Outseta auth widget.
|
|
14
|
+
*/
|
|
15
|
+
export function AuthButton({
|
|
16
|
+
children = "Continue",
|
|
17
|
+
options,
|
|
18
|
+
onClick,
|
|
19
|
+
type = "button",
|
|
20
|
+
...props
|
|
21
|
+
}: AuthButtonProps) {
|
|
22
|
+
const { openAuth } = useOutseta();
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<button
|
|
26
|
+
type={type}
|
|
27
|
+
{...props}
|
|
28
|
+
onClick={composeButtonClick(onClick, () => openAuth(options))}
|
|
29
|
+
>
|
|
30
|
+
{children}
|
|
31
|
+
</button>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -5,6 +5,8 @@ export interface AuthEmbedProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
5
5
|
widgetMode?: "login" | "register" | "login|register";
|
|
6
6
|
/** Registration defaults as a JSON string or object */
|
|
7
7
|
registrationDefaults?: string | Record<string, unknown>;
|
|
8
|
+
/** Props applied to the element Outseta mounts into. */
|
|
9
|
+
widgetProps?: HTMLAttributes<HTMLDivElement>;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
/**
|
|
@@ -16,6 +18,7 @@ export interface AuthEmbedProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
16
18
|
export function AuthEmbed({
|
|
17
19
|
widgetMode = "login|register",
|
|
18
20
|
registrationDefaults,
|
|
21
|
+
widgetProps,
|
|
19
22
|
...props
|
|
20
23
|
}: AuthEmbedProps) {
|
|
21
24
|
const defaults =
|
|
@@ -28,6 +31,7 @@ export function AuthEmbed({
|
|
|
28
31
|
return (
|
|
29
32
|
<div key={widgetMode} {...props}>
|
|
30
33
|
<div
|
|
34
|
+
{...widgetProps}
|
|
31
35
|
data-o-auth="1"
|
|
32
36
|
data-mode="embed"
|
|
33
37
|
data-widget-mode={widgetMode}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes } from "react";
|
|
2
|
+
import { useOutseta } from "./OutsetaProvider.js";
|
|
3
|
+
import type { EmailListWidgetOptions } from "./types.js";
|
|
4
|
+
import { composeButtonClick } from "./utils.js";
|
|
5
|
+
|
|
6
|
+
export interface EmailListButtonProps
|
|
7
|
+
extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
8
|
+
/** The Outseta email list UID to subscribe to. */
|
|
9
|
+
emailListUid: string;
|
|
10
|
+
/** Options passed to `Outseta.emailList.open`. */
|
|
11
|
+
options?: Omit<EmailListWidgetOptions, "emailListUid">;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Unstyled button that opens the Outseta email list widget.
|
|
16
|
+
*/
|
|
17
|
+
export function EmailListButton({
|
|
18
|
+
children = "Subscribe",
|
|
19
|
+
emailListUid,
|
|
20
|
+
options,
|
|
21
|
+
onClick,
|
|
22
|
+
type = "button",
|
|
23
|
+
...props
|
|
24
|
+
}: EmailListButtonProps) {
|
|
25
|
+
const { openEmailList } = useOutseta();
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<button
|
|
29
|
+
type={type}
|
|
30
|
+
{...props}
|
|
31
|
+
onClick={composeButtonClick(onClick, () =>
|
|
32
|
+
openEmailList({ mode: "popup", ...options, emailListUid }),
|
|
33
|
+
)}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
</button>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
|
|
3
|
+
export interface EmailListEmbedProps extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
/** The Outseta email list UID to subscribe to. */
|
|
5
|
+
emailListUid: string;
|
|
6
|
+
/** Props applied to the element Outseta mounts into. */
|
|
7
|
+
widgetProps?: HTMLAttributes<HTMLDivElement>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Renders an embedded Outseta email list widget.
|
|
12
|
+
*/
|
|
13
|
+
export function EmailListEmbed({
|
|
14
|
+
emailListUid,
|
|
15
|
+
widgetProps,
|
|
16
|
+
...props
|
|
17
|
+
}: EmailListEmbedProps) {
|
|
18
|
+
return (
|
|
19
|
+
<div key={emailListUid} {...props}>
|
|
20
|
+
<div
|
|
21
|
+
{...widgetProps}
|
|
22
|
+
data-o-email-list="1"
|
|
23
|
+
data-mode="embed"
|
|
24
|
+
data-email-list-uid={emailListUid}
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { FormHTMLAttributes } from "react";
|
|
2
|
+
|
|
3
|
+
export interface EmailListFormProps extends FormHTMLAttributes<HTMLFormElement> {
|
|
4
|
+
/** Your Outseta domain, e.g. "your-company.outseta.com". */
|
|
5
|
+
domain: string;
|
|
6
|
+
/** The Outseta email list UID to subscribe to. */
|
|
7
|
+
emailListUid: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function getSubscribeAction(domain: string, emailListUid: string): string {
|
|
11
|
+
const hasProtocol = domain.startsWith("http://") || domain.startsWith("https://");
|
|
12
|
+
const baseUrl = hasProtocol ? domain : `https://${domain}`;
|
|
13
|
+
return `${baseUrl.replace(/\/$/, "")}/email/lists/${emailListUid}/subscribe`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Headless native form wrapper for Outseta email list subscriptions.
|
|
18
|
+
* Provide your own fields and styling; Outseta expects an `Email` input.
|
|
19
|
+
*/
|
|
20
|
+
export function EmailListForm({
|
|
21
|
+
domain,
|
|
22
|
+
emailListUid,
|
|
23
|
+
action,
|
|
24
|
+
method = "post",
|
|
25
|
+
...props
|
|
26
|
+
}: EmailListFormProps) {
|
|
27
|
+
return (
|
|
28
|
+
<form
|
|
29
|
+
action={action ?? getSubscribeAction(domain, emailListUid)}
|
|
30
|
+
method={method}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes } from "react";
|
|
2
|
+
import { useOutseta } from "./OutsetaProvider.js";
|
|
3
|
+
import type { LeadCaptureWidgetOptions } from "./types.js";
|
|
4
|
+
import { composeButtonClick } from "./utils.js";
|
|
5
|
+
|
|
6
|
+
export interface LeadCaptureButtonProps
|
|
7
|
+
extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
8
|
+
/** The Outseta lead capture form UID to show. */
|
|
9
|
+
formUid: string;
|
|
10
|
+
/** Options passed to `Outseta.leadCapture.open`. */
|
|
11
|
+
options?: Omit<LeadCaptureWidgetOptions, "formUid">;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Unstyled button that opens the Outseta lead capture widget.
|
|
16
|
+
*/
|
|
17
|
+
export function LeadCaptureButton({
|
|
18
|
+
children = "Get in touch",
|
|
19
|
+
formUid,
|
|
20
|
+
options,
|
|
21
|
+
onClick,
|
|
22
|
+
type = "button",
|
|
23
|
+
...props
|
|
24
|
+
}: LeadCaptureButtonProps) {
|
|
25
|
+
const { openLeadCapture } = useOutseta();
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<button
|
|
29
|
+
type={type}
|
|
30
|
+
{...props}
|
|
31
|
+
onClick={composeButtonClick(onClick, () =>
|
|
32
|
+
openLeadCapture({ mode: "popup", ...options, formUid }),
|
|
33
|
+
)}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
</button>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
|
|
3
|
+
export interface LeadCaptureEmbedProps extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
/** The Outseta lead capture form UID to show. */
|
|
5
|
+
formUid: string;
|
|
6
|
+
/** Props applied to the element Outseta mounts into. */
|
|
7
|
+
widgetProps?: HTMLAttributes<HTMLDivElement>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Renders an embedded Outseta lead capture widget.
|
|
12
|
+
*/
|
|
13
|
+
export function LeadCaptureEmbed({
|
|
14
|
+
formUid,
|
|
15
|
+
widgetProps,
|
|
16
|
+
...props
|
|
17
|
+
}: LeadCaptureEmbedProps) {
|
|
18
|
+
return (
|
|
19
|
+
<div key={formUid} {...props}>
|
|
20
|
+
<div
|
|
21
|
+
{...widgetProps}
|
|
22
|
+
data-o-lead-capture="1"
|
|
23
|
+
data-mode="embed"
|
|
24
|
+
data-form-uid={formUid}
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AuthButton, type AuthButtonProps } from "./AuthButton.js";
|
|
2
|
+
|
|
3
|
+
export type LoginButtonProps = AuthButtonProps;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Unstyled button that opens the Outseta auth widget in login mode.
|
|
7
|
+
*/
|
|
8
|
+
export function LoginButton({
|
|
9
|
+
children = "Log in",
|
|
10
|
+
options,
|
|
11
|
+
...props
|
|
12
|
+
}: LoginButtonProps) {
|
|
13
|
+
return (
|
|
14
|
+
<AuthButton options={{ ...options, widgetMode: "login" }} {...props}>
|
|
15
|
+
{children}
|
|
16
|
+
</AuthButton>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import type { ButtonHTMLAttributes } from "react";
|
|
2
2
|
import { useOutseta } from "./OutsetaProvider.js";
|
|
3
|
+
import { composeButtonClick } from "./utils.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Button that logs the user out of Outseta.
|
|
6
7
|
*/
|
|
7
8
|
export function LogoutButton({
|
|
8
9
|
children = "Logout",
|
|
10
|
+
onClick,
|
|
11
|
+
type = "button",
|
|
9
12
|
...props
|
|
10
13
|
}: ButtonHTMLAttributes<HTMLButtonElement>) {
|
|
11
14
|
const { logout } = useOutseta();
|
|
12
15
|
|
|
13
16
|
return (
|
|
14
|
-
<button
|
|
17
|
+
<button
|
|
18
|
+
type={type}
|
|
19
|
+
{...props}
|
|
20
|
+
onClick={composeButtonClick(onClick, logout)}
|
|
21
|
+
>
|
|
15
22
|
{children}
|
|
16
23
|
</button>
|
|
17
24
|
);
|
|
@@ -8,18 +8,25 @@ import {
|
|
|
8
8
|
} from "react";
|
|
9
9
|
import type {
|
|
10
10
|
AuthWidgetOptions,
|
|
11
|
+
EmailListWidgetOptions,
|
|
12
|
+
LeadCaptureWidgetOptions,
|
|
11
13
|
OutsetaEmbed,
|
|
12
14
|
OutsetaUser,
|
|
13
15
|
ProfileWidgetOptions,
|
|
16
|
+
SupportWidgetOptions,
|
|
14
17
|
} from "./types.js";
|
|
15
18
|
|
|
16
19
|
export interface OutsetaContextValue {
|
|
17
20
|
user: OutsetaUser | null;
|
|
18
21
|
isLoading: boolean;
|
|
19
22
|
logout: () => void;
|
|
23
|
+
openAuth: (options?: AuthWidgetOptions) => void;
|
|
20
24
|
openLogin: (options?: AuthWidgetOptions) => void;
|
|
21
25
|
openSignup: (options?: AuthWidgetOptions) => void;
|
|
22
26
|
openProfile: (options?: ProfileWidgetOptions) => void;
|
|
27
|
+
openSupport: (options?: SupportWidgetOptions) => void;
|
|
28
|
+
openEmailList: (options: EmailListWidgetOptions) => void;
|
|
29
|
+
openLeadCapture: (options: LeadCaptureWidgetOptions) => void;
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
const OutsetaContext = createContext<OutsetaContextValue | null>(null);
|
|
@@ -39,6 +46,11 @@ function getOutseta(): OutsetaEmbed | null {
|
|
|
39
46
|
return null;
|
|
40
47
|
}
|
|
41
48
|
|
|
49
|
+
function getCurrentUrl(): string | undefined {
|
|
50
|
+
if (typeof window === "undefined") return undefined;
|
|
51
|
+
return window.location.href;
|
|
52
|
+
}
|
|
53
|
+
|
|
42
54
|
export function OutsetaProvider({ children }: { children: ReactNode }) {
|
|
43
55
|
const [status, setStatus] = useState<"init" | "ready">("init");
|
|
44
56
|
const [user, setUser] = useState<OutsetaUser | null>(null);
|
|
@@ -114,35 +126,52 @@ export function OutsetaProvider({ children }: { children: ReactNode }) {
|
|
|
114
126
|
outseta.logout();
|
|
115
127
|
};
|
|
116
128
|
|
|
117
|
-
const
|
|
129
|
+
const openAuth = (options: AuthWidgetOptions = {}) => {
|
|
118
130
|
outsetaRef.current?.auth.open({
|
|
119
131
|
widgetMode: "login|register",
|
|
120
|
-
|
|
132
|
+
mode: "popup",
|
|
133
|
+
authenticationCallbackUrl: getCurrentUrl(),
|
|
121
134
|
...options,
|
|
122
135
|
});
|
|
123
136
|
};
|
|
124
137
|
|
|
138
|
+
const openLogin = (options: AuthWidgetOptions = {}) => {
|
|
139
|
+
openAuth({ ...options, widgetMode: "login" });
|
|
140
|
+
};
|
|
141
|
+
|
|
125
142
|
const openSignup = (options: AuthWidgetOptions = {}) => {
|
|
126
|
-
|
|
127
|
-
widgetMode: "register",
|
|
128
|
-
authenticationCallbackUrl: window.location.href,
|
|
129
|
-
...options,
|
|
130
|
-
});
|
|
143
|
+
openAuth({ ...options, widgetMode: "register" });
|
|
131
144
|
};
|
|
132
145
|
|
|
133
146
|
const openProfile = (options: ProfileWidgetOptions = {}) => {
|
|
134
147
|
outsetaRef.current?.profile.open({ tab: "profile", ...options });
|
|
135
148
|
};
|
|
136
149
|
|
|
150
|
+
const openSupport = (options: SupportWidgetOptions = {}) => {
|
|
151
|
+
outsetaRef.current?.support?.open({ mode: "popup", ...options });
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const openEmailList = (options: EmailListWidgetOptions) => {
|
|
155
|
+
outsetaRef.current?.emailList?.open({ mode: "popup", ...options });
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const openLeadCapture = (options: LeadCaptureWidgetOptions) => {
|
|
159
|
+
outsetaRef.current?.leadCapture?.open({ mode: "popup", ...options });
|
|
160
|
+
};
|
|
161
|
+
|
|
137
162
|
return (
|
|
138
163
|
<OutsetaContext.Provider
|
|
139
164
|
value={{
|
|
140
165
|
user,
|
|
141
166
|
isLoading: status !== "ready",
|
|
142
167
|
logout,
|
|
168
|
+
openAuth,
|
|
143
169
|
openLogin,
|
|
144
170
|
openSignup,
|
|
145
171
|
openProfile,
|
|
172
|
+
openSupport,
|
|
173
|
+
openEmailList,
|
|
174
|
+
openLeadCapture,
|
|
146
175
|
}}
|
|
147
176
|
>
|
|
148
177
|
{children}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes } from "react";
|
|
2
|
+
import { useOutseta } from "./OutsetaProvider.js";
|
|
3
|
+
import type { ProfileWidgetOptions } from "./types.js";
|
|
4
|
+
import { composeButtonClick } from "./utils.js";
|
|
5
|
+
|
|
6
|
+
export interface ProfileButtonProps
|
|
7
|
+
extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
8
|
+
/** Options passed to `Outseta.profile.open`. */
|
|
9
|
+
options?: ProfileWidgetOptions;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Unstyled button that opens the Outseta profile widget.
|
|
14
|
+
*/
|
|
15
|
+
export function ProfileButton({
|
|
16
|
+
children = "Profile",
|
|
17
|
+
options,
|
|
18
|
+
onClick,
|
|
19
|
+
type = "button",
|
|
20
|
+
...props
|
|
21
|
+
}: ProfileButtonProps) {
|
|
22
|
+
const { openProfile } = useOutseta();
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<button
|
|
26
|
+
type={type}
|
|
27
|
+
{...props}
|
|
28
|
+
onClick={composeButtonClick(onClick, () =>
|
|
29
|
+
openProfile({ mode: "popup", ...options }),
|
|
30
|
+
)}
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
</button>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -9,6 +9,8 @@ export interface ProfileEmbedProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
9
9
|
| "purchaseAddOn"
|
|
10
10
|
| "passwordChange"
|
|
11
11
|
| "teamMembers";
|
|
12
|
+
/** Props applied to the element Outseta mounts into. */
|
|
13
|
+
widgetProps?: HTMLAttributes<HTMLDivElement>;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
/**
|
|
@@ -17,10 +19,14 @@ export interface ProfileEmbedProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
17
19
|
* Uses `key={tab}` internally so React re-mounts the widget
|
|
18
20
|
* when the tab changes.
|
|
19
21
|
*/
|
|
20
|
-
export function ProfileEmbed({
|
|
22
|
+
export function ProfileEmbed({
|
|
23
|
+
tab = "profile",
|
|
24
|
+
widgetProps,
|
|
25
|
+
...props
|
|
26
|
+
}: ProfileEmbedProps) {
|
|
21
27
|
return (
|
|
22
28
|
<div key={tab} {...props}>
|
|
23
|
-
<div data-o-profile="1" data-mode="embed" data-tab={tab} />
|
|
29
|
+
<div {...widgetProps} data-o-profile="1" data-mode="embed" data-tab={tab} />
|
|
24
30
|
</div>
|
|
25
31
|
);
|
|
26
32
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ButtonHTMLAttributes } from "react";
|
|
2
2
|
import { useOutseta } from "./OutsetaProvider.js";
|
|
3
|
+
import { composeButtonClick } from "./utils.js";
|
|
3
4
|
|
|
4
5
|
export interface PurchaseAddonButtonProps
|
|
5
6
|
extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
@@ -17,20 +18,23 @@ export function PurchaseAddonButton({
|
|
|
17
18
|
addonUid,
|
|
18
19
|
billingRenewalTerm = 4,
|
|
19
20
|
children = "Buy Add-on",
|
|
21
|
+
onClick,
|
|
22
|
+
type = "button",
|
|
20
23
|
...props
|
|
21
24
|
}: PurchaseAddonButtonProps) {
|
|
22
25
|
const { openProfile } = useOutseta();
|
|
23
26
|
|
|
24
27
|
return (
|
|
25
28
|
<button
|
|
26
|
-
|
|
29
|
+
type={type}
|
|
30
|
+
{...props}
|
|
31
|
+
onClick={composeButtonClick(onClick, () =>
|
|
27
32
|
openProfile({
|
|
28
33
|
mode: "popup",
|
|
29
34
|
tab: "purchaseAddOn",
|
|
30
35
|
stateProps: { addOnUid: addonUid, billingRenewalTerm },
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
{...props}
|
|
36
|
+
}),
|
|
37
|
+
)}
|
|
34
38
|
>
|
|
35
39
|
{children}
|
|
36
40
|
</button>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AuthButton, type AuthButtonProps } from "./AuthButton.js";
|
|
2
|
+
|
|
3
|
+
export type SignupButtonProps = AuthButtonProps;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Unstyled button that opens the Outseta auth widget in registration mode.
|
|
7
|
+
*/
|
|
8
|
+
export function SignupButton({
|
|
9
|
+
children = "Sign up",
|
|
10
|
+
options,
|
|
11
|
+
...props
|
|
12
|
+
}: SignupButtonProps) {
|
|
13
|
+
return (
|
|
14
|
+
<AuthButton options={{ ...options, widgetMode: "register" }} {...props}>
|
|
15
|
+
{children}
|
|
16
|
+
</AuthButton>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes } from "react";
|
|
2
|
+
import { useOutseta } from "./OutsetaProvider.js";
|
|
3
|
+
import type { SupportWidgetOptions } from "./types.js";
|
|
4
|
+
import { composeButtonClick } from "./utils.js";
|
|
5
|
+
|
|
6
|
+
export interface SupportButtonProps
|
|
7
|
+
extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
8
|
+
/** Options passed to `Outseta.support.open`. */
|
|
9
|
+
options?: SupportWidgetOptions;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Unstyled button that opens the Outseta support widget.
|
|
14
|
+
*/
|
|
15
|
+
export function SupportButton({
|
|
16
|
+
children = "Contact support",
|
|
17
|
+
options,
|
|
18
|
+
onClick,
|
|
19
|
+
type = "button",
|
|
20
|
+
...props
|
|
21
|
+
}: SupportButtonProps) {
|
|
22
|
+
const { openSupport } = useOutseta();
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<button
|
|
26
|
+
type={type}
|
|
27
|
+
{...props}
|
|
28
|
+
onClick={composeButtonClick(onClick, () =>
|
|
29
|
+
openSupport({ mode: "popup", ...options }),
|
|
30
|
+
)}
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
</button>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
|
|
3
|
+
export interface SupportEmbedProps extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
/** Props applied to the element Outseta mounts into. */
|
|
5
|
+
widgetProps?: HTMLAttributes<HTMLDivElement>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Renders an embedded Outseta support widget.
|
|
10
|
+
*/
|
|
11
|
+
export function SupportEmbed({ widgetProps, ...props }: SupportEmbedProps) {
|
|
12
|
+
return (
|
|
13
|
+
<div {...props}>
|
|
14
|
+
<div {...widgetProps} data-o-support="1" data-mode="embed" />
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -1,15 +1,42 @@
|
|
|
1
1
|
export type {
|
|
2
2
|
OutsetaUser,
|
|
3
3
|
OutsetaEmbed,
|
|
4
|
+
OutsetaWidgetMode,
|
|
5
|
+
AuthWidgetMode,
|
|
4
6
|
AuthWidgetOptions,
|
|
5
7
|
ProfileWidgetOptions,
|
|
8
|
+
SupportWidgetOptions,
|
|
9
|
+
EmailListWidgetOptions,
|
|
10
|
+
LeadCaptureWidgetOptions,
|
|
6
11
|
} from "./types.js";
|
|
7
12
|
export { OutsetaProvider, useOutseta } from "./OutsetaProvider.js";
|
|
8
13
|
export type { OutsetaContextValue } from "./OutsetaProvider.js";
|
|
9
14
|
export { AuthEmbed } from "./AuthEmbed.js";
|
|
10
15
|
export type { AuthEmbedProps } from "./AuthEmbed.js";
|
|
16
|
+
export { AuthButton } from "./AuthButton.js";
|
|
17
|
+
export type { AuthButtonProps } from "./AuthButton.js";
|
|
18
|
+
export { LoginButton } from "./LoginButton.js";
|
|
19
|
+
export type { LoginButtonProps } from "./LoginButton.js";
|
|
20
|
+
export { SignupButton } from "./SignupButton.js";
|
|
21
|
+
export type { SignupButtonProps } from "./SignupButton.js";
|
|
11
22
|
export { ProfileEmbed } from "./ProfileEmbed.js";
|
|
12
23
|
export type { ProfileEmbedProps } from "./ProfileEmbed.js";
|
|
24
|
+
export { ProfileButton } from "./ProfileButton.js";
|
|
25
|
+
export type { ProfileButtonProps } from "./ProfileButton.js";
|
|
26
|
+
export { SupportEmbed } from "./SupportEmbed.js";
|
|
27
|
+
export type { SupportEmbedProps } from "./SupportEmbed.js";
|
|
28
|
+
export { SupportButton } from "./SupportButton.js";
|
|
29
|
+
export type { SupportButtonProps } from "./SupportButton.js";
|
|
30
|
+
export { EmailListEmbed } from "./EmailListEmbed.js";
|
|
31
|
+
export type { EmailListEmbedProps } from "./EmailListEmbed.js";
|
|
32
|
+
export { EmailListButton } from "./EmailListButton.js";
|
|
33
|
+
export type { EmailListButtonProps } from "./EmailListButton.js";
|
|
34
|
+
export { EmailListForm } from "./EmailListForm.js";
|
|
35
|
+
export type { EmailListFormProps } from "./EmailListForm.js";
|
|
36
|
+
export { LeadCaptureEmbed } from "./LeadCaptureEmbed.js";
|
|
37
|
+
export type { LeadCaptureEmbedProps } from "./LeadCaptureEmbed.js";
|
|
38
|
+
export { LeadCaptureButton } from "./LeadCaptureButton.js";
|
|
39
|
+
export type { LeadCaptureButtonProps } from "./LeadCaptureButton.js";
|
|
13
40
|
export { ProtectedRoute } from "./ProtectedRoute.js";
|
|
14
41
|
export type { ProtectedRouteProps } from "./ProtectedRoute.js";
|
|
15
42
|
export { AuthCta } from "./AuthCta.js";
|