@superwall/paywalls-react 0.1.4 → 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/.turbo/turbo-typecheck.log +4 -39
- package/README.md +41 -2
- package/package.json +6 -3
- package/src/SuperwallPaywall.tsx +94 -0
- package/src/index.ts +5 -0
|
@@ -1,46 +1,11 @@
|
|
|
1
1
|
$ tsc --noEmit
|
|
2
|
-
../paywalls-js/src/internal/audience.ts(32,3): error TS2322: Type 'Promise<typeof import("/Users/ianrumac/Workspace/Superwall/Superwall-Web/node_modules/.bun/@superwall+superscript@0.2.5/node_modules/@superwall/superscript/dist/types/browser")>' is not assignable to type 'Promise<{ evaluateWithContext: (input: ExecutionContext, host: SuperscriptHostContext) => string | boolean; }>'.
|
|
3
|
-
Type 'typeof import("/Users/ianrumac/Workspace/Superwall/Superwall-Web/node_modules/.bun/@superwall+superscript@0.2.5/node_modules/@superwall/superscript/dist/types/browser")' is not assignable to type '{ evaluateWithContext: (input: ExecutionContext, host: SuperscriptHostContext) => string | boolean; }'.
|
|
4
|
-
The types returned by 'evaluateWithContext(...)' are incompatible between these types.
|
|
5
|
-
Type 'Promise<string>' is not assignable to type 'string | boolean'.
|
|
6
|
-
../paywalls-js/src/internal/audience.ts(232,18): error TS18047: 'mod' is possibly 'null'.
|
|
7
|
-
../paywalls-js/src/internal/redemption.ts(133,21): error TS2379: Argument of type '{ deviceId: string; appUserId: string | undefined; aliasId: string; codes: { code: string; firstRedemption?: boolean; }[]; }' is not assignable to parameter of type 'RedeemRequest' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
8
|
-
Types of property 'appUserId' are incompatible.
|
|
9
|
-
Type 'string | undefined' is not assignable to type 'string'.
|
|
10
|
-
Type 'undefined' is not assignable to type 'string'.
|
|
11
|
-
../paywalls-js/src/superwall.ts(947,7): error TS2379: Argument of type 'Effect<void, StorageSetError, StorageService>' is not assignable to parameter of type 'Effect<unknown, unknown, never>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
12
|
-
Type 'StorageService' is not assignable to type 'never'.
|
|
13
|
-
../paywalls-js/src/superwall.ts(1046,38): error TS2551: Property 'activeSubscriptions' does not exist on type 'CustomerInfo'. Did you mean 'subscriptions'?
|
|
14
|
-
../paywalls-js/src/superwall.ts(1050,11): error TS2375: Type '{ publicApiKey: string; aliasId: string; appUserId: string; vendorId: string; deviceId: string; bundleId: string | undefined; appVersion: string | undefined; isSandbox: boolean; isFirstAppOpen: boolean; ... 6 more ...; activeProducts: any; }' is not assignable to type 'DeviceAttributesInput' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
15
|
-
Types of property 'bundleId' are incompatible.
|
|
16
|
-
Type 'string | undefined' is not assignable to type 'string'.
|
|
17
|
-
Type 'undefined' is not assignable to type 'string'.
|
|
18
|
-
../paywalls-js/src/superwall.ts(1208,9): error TS2379: Argument of type 'Effect<void, never, EventBus>' is not assignable to parameter of type 'Effect<unknown, unknown, never>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
19
|
-
Type 'EventBus' is not assignable to type 'never'.
|
|
20
|
-
../paywalls-js/src/superwall.ts(1608,15): error TS2379: Argument of type 'Effect<void, never, EventBus>' is not assignable to parameter of type 'Effect<unknown, unknown, never>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
21
|
-
Type 'EventBus' is not assignable to type 'never'.
|
|
22
|
-
../paywalls-js/src/superwall.ts(1722,17): error TS2379: Argument of type 'Effect<void, never, EventBus>' is not assignable to parameter of type 'Effect<unknown, unknown, never>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
23
|
-
Type 'EventBus' is not assignable to type 'never'.
|
|
24
|
-
../paywalls-js/src/superwall.ts(1737,17): error TS2379: Argument of type 'Effect<void, never, EventBus>' is not assignable to parameter of type 'Effect<unknown, unknown, never>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
25
|
-
Type 'EventBus' is not assignable to type 'never'.
|
|
26
|
-
../paywalls-js/src/superwall.ts(1949,11): error TS2379: Argument of type 'Effect<void, never, EventBus>' is not assignable to parameter of type 'Effect<unknown, unknown, never>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
27
|
-
Type 'EventBus' is not assignable to type 'never'.
|
|
28
|
-
../paywalls-js/src/superwall.ts(1969,13): error TS2379: Argument of type 'Effect<void, never, EventBus>' is not assignable to parameter of type 'Effect<unknown, unknown, never>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
29
|
-
Type 'EventBus' is not assignable to type 'never'.
|
|
30
|
-
../paywalls-js/src/superwall.ts(2050,11): error TS2379: Argument of type 'Effect<void, never, EventBus>' is not assignable to parameter of type 'Effect<unknown, unknown, never>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
31
|
-
Type 'EventBus' is not assignable to type 'never'.
|
|
32
|
-
../paywalls-js/src/superwall.ts(2112,9): error TS2379: Argument of type 'Effect<void, never, EventBus>' is not assignable to parameter of type 'Effect<unknown, unknown, never>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
33
|
-
Type 'EventBus' is not assignable to type 'never'.
|
|
34
|
-
../paywalls-js/src/superwall.ts(2303,9): error TS2379: Argument of type 'Effect<void, never, Logger>' is not assignable to parameter of type 'Effect<unknown, unknown, never>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
35
|
-
Type 'Logger' is not assignable to type 'never'.
|
|
36
|
-
../paywalls-js/src/superwall.ts(2317,9): error TS2379: Argument of type 'Effect<void, never, EventBus>' is not assignable to parameter of type 'Effect<unknown, unknown, never>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
37
|
-
Type 'EventBus' is not assignable to type 'never'.
|
|
38
|
-
../paywalls-js/src/superwall.ts(2392,9): error TS2352: Conversion of type 'Effect<void, never, NetworkService | ConfigService | AssignmentService>' to type 'Effect<void, unknown, never>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
|
|
39
|
-
Type 'NetworkService | ConfigService | AssignmentService' is not comparable to type 'never'.
|
|
40
|
-
Type 'AssignmentService' is not comparable to type 'never'.
|
|
41
2
|
src/hooks.test.tsx(417,26): error TS2345: Argument of type '{ readonly value: string; subscribe: (run: () => void) => () => void; }' is not assignable to parameter of type 'Readable<string>'.
|
|
42
3
|
Types of property 'subscribe' are incompatible.
|
|
43
4
|
Type '(run: () => void) => () => void' is not assignable to type '(run: (value: string) => void) => () => void'.
|
|
44
5
|
Types of parameters 'run' and 'run' are incompatible.
|
|
45
6
|
Target signature provides too few arguments. Expected 1 or more, but got 0.
|
|
46
7
|
src/hooks.ts(185,11): error TS2367: This comparison appears to be unintentional because the types '"error" | "presented" | "skipped"' and '"entitled"' have no overlap.
|
|
8
|
+
src/SuperwallPaywall.tsx(42,17): error TS2379: Argument of type '{ placement: string; params: PlacementParams | undefined; feature: () => void; handler: { onPresent: (info: PaywallInfo) => void | undefined; onDismiss: (info: PaywallInfo, result: PaywallResult) => void | undefined; onSkip: (reason: PaywallSkippedReason) => void | undefined; onError: (error: Error) => void | undefi...' is not assignable to parameter of type 'RegisterPlacementArgs' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
|
|
9
|
+
Types of property 'params' are incompatible.
|
|
10
|
+
Type 'PlacementParams | undefined' is not assignable to type 'PlacementParams'.
|
|
11
|
+
Type 'undefined' is not assignable to type 'PlacementParams'.
|
package/README.md
CHANGED
|
@@ -23,9 +23,29 @@ export function Root() {
|
|
|
23
23
|
}
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
`SuperwallProvider`
|
|
27
|
-
(`apiKey`, `storage`, `delegate`, `identity`, `options`).
|
|
26
|
+
`SuperwallProvider` accepts the following props:
|
|
28
27
|
|
|
28
|
+
| Prop | Type | Description | Example |
|
|
29
|
+
|-----------|---------------------|------------------------------------------------------------------------------------------------------|---------------------------------------------|
|
|
30
|
+
| `apiKey` | `string` | **Required.** Your Superwall public key. | `"pk_your_public_key"` |
|
|
31
|
+
| `storage` | `StorageAdapter?` | Optional. Provide a storage layer to customize persistence behavior (defaults to localStorage). | `myCustomStorage` |
|
|
32
|
+
| `delegate`| `SuperwallDelegate?`| Optional. Receives paywall and subscription events (like callbacks for onPresent, onDismiss, etc). | `myDelegate` |
|
|
33
|
+
| `identity`| `{ appUserId?, aliasId?, vendorId? }?` | Optional. Seed identity on configure, e.g. from cookies on SSR hydration. | `{ appUserId: 'abc123' }` |
|
|
34
|
+
| `options` | `object?` | Optional. Additional options for advanced configuration (see the paywalls-js docs for details). | `{ networkEnvironment: "release" }` |
|
|
35
|
+
|
|
36
|
+
Most apps will only need to provide `apiKey`, but you can pass the optional extras as needed.
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
<SuperwallProvider
|
|
40
|
+
apiKey="pk_your_public_key"
|
|
41
|
+
storage={myCustomStorage}
|
|
42
|
+
delegate={myDelegate}
|
|
43
|
+
identity={{ appUserId: "123" }}
|
|
44
|
+
options={{ networkEnvironment: "release" }}
|
|
45
|
+
>
|
|
46
|
+
<App />
|
|
47
|
+
</SuperwallProvider>
|
|
48
|
+
```
|
|
29
49
|
## Placements
|
|
30
50
|
|
|
31
51
|
```tsx
|
|
@@ -76,6 +96,25 @@ function GoPro() {
|
|
|
76
96
|
- The placement has no audience match / holdout — feature runs without showing a paywall
|
|
77
97
|
- The user completes a purchase or restore through the paywall
|
|
78
98
|
|
|
99
|
+
## SuperwallPaywall component
|
|
100
|
+
|
|
101
|
+
Declarative alternative to `usePlacement`. Calls `register()` on mount and
|
|
102
|
+
renders `children` when the user is entitled — i.e. the feature block fires.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
import { SuperwallPaywall } from "@superwall/paywalls-react";
|
|
106
|
+
|
|
107
|
+
function App() {
|
|
108
|
+
return (
|
|
109
|
+
<SuperwallPaywall placement="campaign_trigger" loading={<LoadingSpinner />}>
|
|
110
|
+
<ProContent />
|
|
111
|
+
</SuperwallPaywall>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`loading` renders while the paywall is loading and is swapped out the moment it presents. `children` render once the user is entitled. Pass `inline` to mount the paywall iframe inside the component instead of as a full-viewport overlay. Optional handler props (`onPresent`, `onDismiss`, `onSkip`, `onError`) work the same as in `usePlacement`.
|
|
117
|
+
|
|
79
118
|
## Subscription status & user
|
|
80
119
|
|
|
81
120
|
```tsx
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superwall/paywalls-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
6
9
|
"exports": {
|
|
7
10
|
".": {
|
|
8
11
|
"types": "./src/index.ts",
|
|
@@ -17,10 +20,10 @@
|
|
|
17
20
|
},
|
|
18
21
|
"peerDependencies": {
|
|
19
22
|
"react": "^19.0.0",
|
|
20
|
-
"@superwall/paywalls-js": "^0.
|
|
23
|
+
"@superwall/paywalls-js": "^0.2.0"
|
|
21
24
|
},
|
|
22
25
|
"dependencies": {
|
|
23
|
-
"@superwall/paywalls-js": "^0.
|
|
26
|
+
"@superwall/paywalls-js": "^0.2.0"
|
|
24
27
|
},
|
|
25
28
|
"devDependencies": {
|
|
26
29
|
"@happy-dom/global-registrator": "^20.0.0",
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { type ReactNode, useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import type { PlacementParams } from "@superwall/paywalls-js";
|
|
3
|
+
import { createBrowserPresenter } from "@superwall/paywalls-js/browser";
|
|
4
|
+
import type { PaywallPresentationHandlerHooks } from "./hooks.ts";
|
|
5
|
+
import { useSuperwall } from "./hooks.ts";
|
|
6
|
+
|
|
7
|
+
export interface SuperwallPaywallProps extends PaywallPresentationHandlerHooks {
|
|
8
|
+
placement: string;
|
|
9
|
+
params?: PlacementParams;
|
|
10
|
+
/** Rendered when the user is entitled — i.e. the feature block fires. */
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
/** Rendered while the paywall is loading. Swapped out the moment the paywall presents. */
|
|
13
|
+
loading?: ReactNode;
|
|
14
|
+
/**
|
|
15
|
+
* When true the paywall iframe is mounted inside this component instead of
|
|
16
|
+
* as a full-viewport overlay. Default: false.
|
|
17
|
+
*/
|
|
18
|
+
inline?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Declarative feature gate. Calls `register()` on mount and renders
|
|
23
|
+
* `children` when the user is entitled (already subscribed, purchased
|
|
24
|
+
* through the paywall, or the placement has no audience match).
|
|
25
|
+
*
|
|
26
|
+
* ```tsx
|
|
27
|
+
* <SuperwallPaywall placement="campaign_trigger" loading={<Spinner />}>
|
|
28
|
+
* <ProContent />
|
|
29
|
+
* </SuperwallPaywall>
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function SuperwallPaywall({
|
|
33
|
+
placement,
|
|
34
|
+
params,
|
|
35
|
+
children,
|
|
36
|
+
loading = null,
|
|
37
|
+
inline = false,
|
|
38
|
+
onPresent,
|
|
39
|
+
onDismiss,
|
|
40
|
+
onSkip,
|
|
41
|
+
onError,
|
|
42
|
+
}: SuperwallPaywallProps) {
|
|
43
|
+
const sw = useSuperwall();
|
|
44
|
+
const [unlocked, setUnlocked] = useState(false);
|
|
45
|
+
const [presenting, setPresenting] = useState(false);
|
|
46
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
47
|
+
|
|
48
|
+
const handlersRef = useRef({ onPresent, onDismiss, onSkip, onError });
|
|
49
|
+
handlersRef.current = { onPresent, onDismiss, onSkip, onError };
|
|
50
|
+
|
|
51
|
+
const presenter = useMemo(
|
|
52
|
+
() =>
|
|
53
|
+
inline
|
|
54
|
+
? createBrowserPresenter({ container: () => containerRef.current ?? document.body, inline: true })
|
|
55
|
+
: undefined,
|
|
56
|
+
[inline],
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
let cancelled = false;
|
|
61
|
+
sw.register({
|
|
62
|
+
placement,
|
|
63
|
+
params,
|
|
64
|
+
feature: () => { if (!cancelled) setUnlocked(true); },
|
|
65
|
+
...(presenter && { presenter }),
|
|
66
|
+
handler: {
|
|
67
|
+
onPresent: (info) => { if (!cancelled) setPresenting(true); handlersRef.current.onPresent?.(info); },
|
|
68
|
+
onDismiss: (info, result) => { handlersRef.current.onDismiss?.(info, result); },
|
|
69
|
+
onSkip: (reason) => { handlersRef.current.onSkip?.(reason); },
|
|
70
|
+
onError: (error) => { handlersRef.current.onError?.(error); },
|
|
71
|
+
},
|
|
72
|
+
}).catch(() => {});
|
|
73
|
+
return () => { cancelled = true; };
|
|
74
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
75
|
+
}, [placement, params, presenter]);
|
|
76
|
+
|
|
77
|
+
if (unlocked) return <>{children}</>;
|
|
78
|
+
|
|
79
|
+
// Container always stays in the DOM so the presenter can append the iframe
|
|
80
|
+
// before onPresent fires. We swap loading ↔ iframe via display:none.
|
|
81
|
+
return (
|
|
82
|
+
<div style={{ position: "relative", width: "100%", height: "100%" }}>
|
|
83
|
+
<div
|
|
84
|
+
ref={containerRef}
|
|
85
|
+
style={{ display: presenting ? "block" : "none", width: "100%", height: "100%" }}
|
|
86
|
+
/>
|
|
87
|
+
{!presenting && (
|
|
88
|
+
<div style={{ position: "absolute", inset: 0 }}>
|
|
89
|
+
{loading}
|
|
90
|
+
</div>
|
|
91
|
+
)}
|
|
92
|
+
</div>
|
|
93
|
+
);
|
|
94
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -26,6 +26,11 @@ export {
|
|
|
26
26
|
type PaywallPresentationHandlerHooks,
|
|
27
27
|
} from "./hooks.ts";
|
|
28
28
|
|
|
29
|
+
export {
|
|
30
|
+
SuperwallPaywall,
|
|
31
|
+
type SuperwallPaywallProps,
|
|
32
|
+
} from "./SuperwallPaywall.tsx";
|
|
33
|
+
|
|
29
34
|
// Re-export everything public from paywalls-js so React consumers don't
|
|
30
35
|
// need to depend on both packages directly. Tree-shakeable per ESM rules.
|
|
31
36
|
export * from "@superwall/paywalls-js";
|