@contentcredits/sdk 2.12.0 → 2.13.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 +0 -0
- package/README.md +138 -8
- package/dist/api/client.d.ts +0 -0
- package/dist/api/comments.d.ts +0 -0
- package/dist/api/credits.d.ts +0 -0
- package/dist/auth/popup.d.ts +0 -0
- package/dist/auth/session.d.ts +0 -0
- package/dist/auth/storage.d.ts +0 -0
- package/dist/auth/token.d.ts +0 -0
- package/dist/comments/index.d.ts +0 -0
- package/dist/comments/panel.d.ts +0 -0
- package/dist/comments/widget.d.ts +0 -0
- package/dist/content-credits.cjs.js +4 -2
- package/dist/content-credits.cjs.js.map +1 -1
- package/dist/content-credits.d.ts +0 -0
- package/dist/content-credits.esm.js +4 -2
- package/dist/content-credits.esm.js.map +1 -1
- package/dist/content-credits.umd.min.js +1 -1
- package/dist/content-credits.umd.min.js.map +1 -1
- package/dist/core/config.d.ts +0 -0
- package/dist/core/events.d.ts +0 -0
- package/dist/core/state.d.ts +0 -0
- package/dist/extension/bridge.d.ts +0 -0
- package/dist/extension/detector.d.ts +0 -0
- package/dist/index.d.ts +0 -0
- package/dist/paywall/gate.d.ts +0 -0
- package/dist/paywall/index.d.ts +0 -0
- package/dist/paywall/renderer.d.ts +0 -0
- package/dist/types/index.d.ts +0 -0
- package/dist/ui/sanitize.d.ts +0 -0
- package/dist/ui/shadow.d.ts +0 -0
- package/dist/ui/styles.d.ts +0 -0
- package/package.json +1 -1
package/LICENSE
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
@@ -13,9 +13,10 @@ Drop-in paywall and threaded comment system for any website. Add credit-based ar
|
|
|
13
13
|
## What it does
|
|
14
14
|
|
|
15
15
|
- **Paywall** — hides premium content behind a credit gate using a CSS selector. Reveals it instantly when the reader pays. No server-side content splitting needed.
|
|
16
|
+
- **Customisable top slot** — inject your own content (React widget, donation banner, structured items) above the SDK's unlock button.
|
|
16
17
|
- **Comments** — threaded comment panel with likes, edit, delete, and sorting. Rendered in a Shadow DOM so it never conflicts with your CSS.
|
|
17
18
|
- **Auth** — popup-based login on desktop, redirect flow on mobile. Tokens stored in memory (never cookies).
|
|
18
|
-
- **Extension support** — detects the Content Credits Chrome extension for a one-click experience.
|
|
19
|
+
- **Extension support** — detects the Content Credits Chrome extension for a one-click experience, with automatic fallback if the extension service worker is unresponsive.
|
|
19
20
|
|
|
20
21
|
---
|
|
21
22
|
|
|
@@ -28,7 +29,7 @@ npm install @contentcredits/sdk
|
|
|
28
29
|
Or via CDN (no build step):
|
|
29
30
|
|
|
30
31
|
```html
|
|
31
|
-
<script src="https://cdn.jsdelivr.net/npm/@contentcredits/sdk@2.
|
|
32
|
+
<script src="https://cdn.jsdelivr.net/npm/@contentcredits/sdk@2.12.0/dist/content-credits.umd.min.js"></script>
|
|
32
33
|
```
|
|
33
34
|
|
|
34
35
|
---
|
|
@@ -44,7 +45,7 @@ Or via CDN (no build step):
|
|
|
44
45
|
</div>
|
|
45
46
|
|
|
46
47
|
<!-- Load and initialise the SDK -->
|
|
47
|
-
<script src="https://cdn.jsdelivr.net/npm/@contentcredits/sdk@2.
|
|
48
|
+
<script src="https://cdn.jsdelivr.net/npm/@contentcredits/sdk@2.12.0/dist/content-credits.umd.min.js"></script>
|
|
48
49
|
<script>
|
|
49
50
|
ContentCreditsSDK.ContentCredits.init({
|
|
50
51
|
apiKey: 'pub_YOUR_API_KEY',
|
|
@@ -59,7 +60,7 @@ Or via CDN (no build step):
|
|
|
59
60
|
|
|
60
61
|
```html
|
|
61
62
|
<script
|
|
62
|
-
src="https://cdn.jsdelivr.net/npm/@contentcredits/sdk@2.
|
|
63
|
+
src="https://cdn.jsdelivr.net/npm/@contentcredits/sdk@2.12.0/dist/content-credits.umd.min.js"
|
|
63
64
|
data-api-key="pub_YOUR_API_KEY"
|
|
64
65
|
data-content-selector="#premium-content"
|
|
65
66
|
data-teaser-paragraphs="2"
|
|
@@ -94,13 +95,90 @@ cc.on('paywall:hidden', () => {
|
|
|
94
95
|
| `teaserParagraphs` | `number` | `2` | Paragraphs to show before the paywall |
|
|
95
96
|
| `enableComments` | `boolean` | `true` | Show the comment widget |
|
|
96
97
|
| `articleUrl` | `string` | `location.href` | Canonical URL of the article |
|
|
98
|
+
| `paywallMode` | `'overlay' \| 'inline'` | `'overlay'` | Paywall layout — overlay sits directly below the teaser; inline is the legacy flow-based panel |
|
|
99
|
+
| `paywallTopSlot` | see below | — | Content rendered above the SDK's unlock button — accepts a React element, structured items, `HTMLElement`, or factory function |
|
|
100
|
+
| `reactDOM` | `ReactDOMAdapter` | — | Your `ReactDOM` instance — required when `paywallTopSlot` is a React element |
|
|
97
101
|
| `theme.primaryColor` | `string` | `'#44C678'` | Brand colour for buttons |
|
|
98
102
|
| `theme.fontFamily` | `string` | system UI | Font for all SDK UI |
|
|
103
|
+
| `headless` | `boolean` | `false` | Disable all built-in DOM/UI — manage everything yourself via state and callbacks |
|
|
99
104
|
| `onAccessGranted` | `() => void` | — | Fires when content is unlocked |
|
|
100
105
|
| `debug` | `boolean` | `false` | Verbose console logging |
|
|
101
106
|
|
|
102
107
|
---
|
|
103
108
|
|
|
109
|
+
## Paywall top slot
|
|
110
|
+
|
|
111
|
+
The `paywallTopSlot` lets you inject custom content — a donation widget, promo banner, or anything else — above the SDK's own unlock button. The slot sits inside the SDK's Shadow DOM so your styles are isolated from the host page.
|
|
112
|
+
|
|
113
|
+
### React widget (recommended for React apps)
|
|
114
|
+
|
|
115
|
+
Pass your ReactDOM instance alongside the JSX element. Works with React 18 (`createRoot`) and React 16/17 (`render`).
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import ReactDOM from 'react-dom/client'; // React 18
|
|
119
|
+
import { ContentCredits } from '@contentcredits/sdk';
|
|
120
|
+
import { DonationWidget } from './DonationWidget';
|
|
121
|
+
|
|
122
|
+
ContentCredits.init({
|
|
123
|
+
apiKey: 'pub_YOUR_API_KEY',
|
|
124
|
+
reactDOM,
|
|
125
|
+
paywallTopSlot: <DonationWidget />,
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Structured items
|
|
130
|
+
|
|
131
|
+
The SDK renders and styles these consistently inside its Shadow DOM:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
ContentCredits.init({
|
|
135
|
+
apiKey: 'pub_YOUR_API_KEY',
|
|
136
|
+
paywallTopSlot: [
|
|
137
|
+
{ type: 'heading', content: 'Donate to access this story.' },
|
|
138
|
+
{ type: 'text', content: 'Donate now for unlimited stories. Cancel anytime.' },
|
|
139
|
+
{ type: 'button', content: 'See Donation Options', variant: 'primary', onClick: () => openDonateFlow() },
|
|
140
|
+
],
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Available item types:
|
|
145
|
+
|
|
146
|
+
| `type` | Description | Extra props |
|
|
147
|
+
|--------|-------------|-------------|
|
|
148
|
+
| `heading` | Large bold heading | `content` |
|
|
149
|
+
| `subheading` | Medium bold text | `content` |
|
|
150
|
+
| `text` | Body copy | `content` |
|
|
151
|
+
| `button` | Styled button | `content`, `variant` (`primary` \| `secondary` \| `outline`), `onClick` |
|
|
152
|
+
| `divider` | Horizontal rule with optional label | `content` |
|
|
153
|
+
|
|
154
|
+
### HTMLElement
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
const banner = document.createElement('div');
|
|
158
|
+
banner.innerHTML = '<strong>Support independent journalism</strong>';
|
|
159
|
+
|
|
160
|
+
ContentCredits.init({
|
|
161
|
+
apiKey: 'pub_YOUR_API_KEY',
|
|
162
|
+
paywallTopSlot: banner,
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Factory function
|
|
167
|
+
|
|
168
|
+
Full control — receives the slot container element and mounts whatever you need:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
ContentCredits.init({
|
|
172
|
+
apiKey: 'pub_YOUR_API_KEY',
|
|
173
|
+
paywallTopSlot: (container) => {
|
|
174
|
+
// vanilla JS, Vue, Svelte — anything goes
|
|
175
|
+
container.innerHTML = `<p>Support us to keep reading.</p>`;
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
104
182
|
## Events
|
|
105
183
|
|
|
106
184
|
```ts
|
|
@@ -128,39 +206,91 @@ const cc = ContentCredits.init(config);
|
|
|
128
206
|
|
|
129
207
|
cc.on(event, handler) // subscribe — returns unsubscribe fn
|
|
130
208
|
cc.off(event, handler) // unsubscribe
|
|
209
|
+
cc.subscribe(fn) // reactive state changes — returns unsubscribe fn
|
|
131
210
|
cc.getState() // → SDKState snapshot
|
|
132
211
|
cc.checkAccess() // trigger access check manually
|
|
212
|
+
cc.login() // open login flow programmatically
|
|
213
|
+
cc.purchase() // trigger article purchase
|
|
214
|
+
cc.buyMoreCredits() // open dashboard to top up balance
|
|
133
215
|
cc.openComments() // open comment panel
|
|
134
216
|
cc.closeComments() // close comment panel
|
|
135
217
|
cc.isLoggedIn() // → boolean
|
|
218
|
+
cc.getToken() // → access token string | null
|
|
219
|
+
cc.logout() // revoke session and clear local auth state
|
|
136
220
|
cc.destroy() // tear down SDK, restore hidden content
|
|
137
221
|
|
|
138
|
-
ContentCredits.version // → "2.
|
|
222
|
+
ContentCredits.version // → "2.12.0"
|
|
139
223
|
```
|
|
140
224
|
|
|
141
225
|
---
|
|
142
226
|
|
|
143
227
|
## React / Next.js
|
|
144
228
|
|
|
229
|
+
### Default UI with a React top slot
|
|
230
|
+
|
|
231
|
+
The simplest integration — the SDK handles all paywall rendering; you only supply the top section:
|
|
232
|
+
|
|
145
233
|
```tsx
|
|
146
|
-
'use client';
|
|
234
|
+
'use client';
|
|
147
235
|
|
|
148
236
|
import { useEffect } from 'react';
|
|
237
|
+
import ReactDOM from 'react-dom/client';
|
|
149
238
|
import { ContentCredits } from '@contentcredits/sdk';
|
|
239
|
+
import { DonationWidget } from './DonationWidget';
|
|
150
240
|
|
|
151
|
-
export function PremiumGate({ apiKey
|
|
241
|
+
export function PremiumGate({ apiKey }: { apiKey: string }) {
|
|
152
242
|
useEffect(() => {
|
|
153
243
|
const cc = ContentCredits.init({
|
|
154
244
|
apiKey,
|
|
155
245
|
contentSelector: '#premium-content',
|
|
246
|
+
reactDOM,
|
|
247
|
+
paywallTopSlot: <DonationWidget />,
|
|
248
|
+
});
|
|
249
|
+
return () => cc.destroy();
|
|
250
|
+
}, [apiKey]);
|
|
251
|
+
|
|
252
|
+
return <div id="premium-content">{/* article content */}</div>;
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Headless mode (full custom UI)
|
|
257
|
+
|
|
258
|
+
Use `headless: true` when you want to build the entire paywall UI yourself in React. The SDK manages auth and access checks but renders no DOM of its own.
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
'use client';
|
|
262
|
+
|
|
263
|
+
import { useEffect, useRef, useState } from 'react';
|
|
264
|
+
import { ContentCredits } from '@contentcredits/sdk';
|
|
265
|
+
import type { SDKState } from '@contentcredits/sdk';
|
|
266
|
+
|
|
267
|
+
export function PremiumGate({ apiKey, children }: { apiKey: string; children: React.ReactNode }) {
|
|
268
|
+
const ccRef = useRef<ContentCredits | null>(null);
|
|
269
|
+
const [state, setState] = useState<SDKState | null>(null);
|
|
270
|
+
|
|
271
|
+
useEffect(() => {
|
|
272
|
+
const cc = ContentCredits.init({
|
|
273
|
+
apiKey,
|
|
274
|
+
headless: true,
|
|
275
|
+
onStateChange: setState,
|
|
156
276
|
});
|
|
277
|
+
ccRef.current = cc;
|
|
157
278
|
return () => cc.destroy();
|
|
158
279
|
}, [apiKey]);
|
|
159
280
|
|
|
160
|
-
return
|
|
281
|
+
if (state?.hasAccess) return <>{children}</>;
|
|
282
|
+
|
|
283
|
+
return (
|
|
284
|
+
<div>
|
|
285
|
+
{/* your teaser content */}
|
|
286
|
+
<button onClick={() => ccRef.current?.purchase()}>Unlock article</button>
|
|
287
|
+
</div>
|
|
288
|
+
);
|
|
161
289
|
}
|
|
162
290
|
```
|
|
163
291
|
|
|
292
|
+
See [`examples/nextjs-blog`](./examples/nextjs-blog) for a full working Next.js 14 (App Router) implementation.
|
|
293
|
+
|
|
164
294
|
---
|
|
165
295
|
|
|
166
296
|
## Requirements
|
package/dist/api/client.d.ts
CHANGED
|
File without changes
|
package/dist/api/comments.d.ts
CHANGED
|
File without changes
|
package/dist/api/credits.d.ts
CHANGED
|
File without changes
|
package/dist/auth/popup.d.ts
CHANGED
|
File without changes
|
package/dist/auth/session.d.ts
CHANGED
|
File without changes
|
package/dist/auth/storage.d.ts
CHANGED
|
File without changes
|
package/dist/auth/token.d.ts
CHANGED
|
File without changes
|
package/dist/comments/index.d.ts
CHANGED
|
File without changes
|
package/dist/comments/panel.d.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
@@ -676,7 +676,9 @@ function getPaywallStyles(primaryColor, fontFamily) {
|
|
|
676
676
|
|
|
677
677
|
/* ── Overlay paywall panel — full-width white panel below gated content ── */
|
|
678
678
|
.cc-paywall-overlay {
|
|
679
|
-
width
|
|
679
|
+
/* Break out of any max-width container to span the full viewport */
|
|
680
|
+
width: 100vw;
|
|
681
|
+
margin-left: calc(50% - 50vw);
|
|
680
682
|
background: #fff;
|
|
681
683
|
font-family: ${fontFamily};
|
|
682
684
|
}
|
|
@@ -3207,7 +3209,7 @@ class ContentCredits {
|
|
|
3207
3209
|
}
|
|
3208
3210
|
/** SDK version string. */
|
|
3209
3211
|
static get version() {
|
|
3210
|
-
return "2.
|
|
3212
|
+
return "2.13.0";
|
|
3211
3213
|
}
|
|
3212
3214
|
}
|
|
3213
3215
|
// ── Auto-init from script data attributes (CDN usage) ────────────────────────
|