@c15t/react 3.0.0-alpha.6 → 3.0.0-alpha.8

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.
Files changed (40) hide show
  1. package/SKILL.md +1 -1
  2. package/dist/components/iab-prompt/atoms/overlay.js +1 -1
  3. package/dist/components/iab-prompt/atoms/root.js +1 -1
  4. package/dist/components/prompt/atoms/overlay.js +1 -1
  5. package/dist/components/prompt/atoms/root.js +1 -1
  6. package/dist/components/prompt/prompt.js +1 -1
  7. package/dist/components/shared/primitives/legal-links/index.js +1 -1
  8. package/dist/components/shared/streamed-surface.js +2 -0
  9. package/dist/context.js +1 -1
  10. package/dist/hooks/use-late-entry.js +2 -0
  11. package/dist/hooks.js +1 -1
  12. package/dist/iab/styles.tw3.css +2 -2
  13. package/dist/kernel-selector.js +1 -1
  14. package/dist/provider.js +1 -1
  15. package/dist/styles.tw3.css +4 -4
  16. package/dist/version.js +1 -1
  17. package/dist-types/components/prompt/atoms/root.d.ts +4 -0
  18. package/dist-types/components/prompt/prompt.d.ts +4 -0
  19. package/dist-types/components/shared/streamed-surface.d.ts +23 -0
  20. package/dist-types/context.d.ts +17 -1
  21. package/dist-types/hooks/use-late-entry.d.ts +14 -0
  22. package/dist-types/kernel-selector.d.ts +10 -0
  23. package/dist-types/provider.d.ts +28 -6
  24. package/dist-types/version.d.ts +1 -1
  25. package/docs/concepts/choose-your-setup.md +2 -2
  26. package/docs/concepts/consent-state.md +6 -0
  27. package/docs/concepts/data-fetching.md +34 -0
  28. package/docs/customization/motion.md +22 -13
  29. package/docs/customization/tokens.md +1 -0
  30. package/docs/frameworks/react/components/consent-banner.md +7 -2
  31. package/docs/frameworks/react/components/consent-dialog.md +7 -2
  32. package/docs/frameworks/react/components/consent-provider.md +41 -33
  33. package/docs/frameworks/react/components.md +7 -2
  34. package/docs/frameworks/react/quickstart.md +80 -81
  35. package/docs/frameworks/react/rendering.md +19 -9
  36. package/docs/frameworks/react/scripts.md +7 -2
  37. package/docs/frameworks/react/troubleshooting.md +28 -13
  38. package/docs/guides/banner-experiments.md +2 -2
  39. package/docs/upgrade-v3.md +5 -1
  40. package/package.json +7 -7
@@ -25,6 +25,9 @@ explains the difference in general terms.
25
25
 
26
26
  ## Bundle the manifest during Vite builds
27
27
 
28
+ The [quickstart](./quickstart.md) and `examples/react` in
29
+ the c15t repository use this setup.
30
+
28
31
  The build fetches your public policy once and bundles it, so the server never
29
32
  fetches it at runtime.
30
33
 
@@ -43,8 +46,8 @@ export default {
43
46
 
44
47
  Vite writes `src/c15t-manifest.ts` before compiling, including at development
45
48
  startup. Keep the generated file out of Git. Install `@c15t/browser@alpha` for
46
- its browser manifest transport. In the quickstart's `src/consent.tsx`, replace
47
- the `hosted()` mode with this factory:
49
+ its browser manifest transport. In `src/consent.tsx`, create the provider's
50
+ mode with `manifest()` instead of `hosted()`:
48
51
 
49
52
  ```tsx title="src/consent.tsx"
50
53
  import { manifest } from '@c15t/browser/headless';
@@ -77,19 +80,21 @@ The snapshot is fixed at build time:
77
80
  * Consent choices still go to the backend.
78
81
 
79
82
  Run `vite build` or `vite dev` before a standalone `tsc`, `vue-tsc` or
80
- `svelte-check`; the generated file doesn't exist on a fresh checkout.
83
+ `svelte-check`; the generated file doesn't exist on a fresh checkout. Both
84
+ commands fetch the manifest when they start, so both need the backend.
85
+ `vite preview` serves the last build without fetching.
81
86
 
82
- For policy updates without a rebuild, keep the original `hosted()` factory
83
- and omit the build plugin. That setup resolves policy through the backend
84
- `/init` on each page load.
87
+ For policy updates without a rebuild, use `hosted({ url })` from `c15t/react`
88
+ as the mode and omit the build plugin. That setup resolves policy through the
89
+ backend `/init` on each page load.
85
90
 
86
91
  ## Client-rendered apps
87
92
 
88
93
  The recommended [quickstart](./quickstart.md) bundles the
89
94
  manifest and resolves it in the browser. See [build-time manifests](#bundle-the-manifest-during-vite-builds).
90
95
 
91
- For policy updates without rebuilding, keep `hosted({ url })`. That runtime
92
- path works as follows:
96
+ For policy updates without rebuilding, use `hosted({ url })` from
97
+ `c15t/react` as the mode. That runtime path works as follows:
93
98
 
94
99
  1. The page loads with no consent state. Every optional category is denied.
95
100
  2. `ConsentProvider` requests `GET /init` from your backend URL while it first
@@ -182,7 +187,12 @@ With `hosted({ url })`, the browser calls two backend endpoints:
182
187
  | `GET {url}/init` | Once per page load, to resolve the policy |
183
188
  | `POST {url}/subjects` | When the visitor accepts, rejects or saves |
184
189
 
185
- Both go to the backend's origin, so it must list your site as a trusted origin.
190
+ With a bundled manifest, `manifest({ backendURL })` sends the same
191
+ `/subjects` request, and requests `/init` only when the policy depends on a
192
+ country or region the browser does not know.
193
+
194
+ These requests go to the backend's origin, so it must list your site as a
195
+ trusted origin.
186
196
  [Data fetching](../../concepts/data-fetching.md) compares this with proxies and
187
197
  custom transports.
188
198
 
@@ -28,20 +28,25 @@ export const scripts = [
28
28
  The provider in `src/consent.tsx` receives them:
29
29
 
30
30
  ```tsx title="src/consent.tsx"
31
+ import { manifest } from '@c15t/browser/headless';
31
32
  import {
32
33
  ConsentBanner,
33
34
  ConsentDialog,
34
35
  ConsentDialogLink,
35
36
  ConsentProvider,
36
- hosted,
37
37
  } from 'c15t/react';
38
38
  import type { ReactNode } from 'react';
39
39
 
40
+ import { consentManifest } from './c15t-manifest';
40
41
  import { scripts } from './scripts';
41
42
 
42
43
  import 'c15t/react/styles.css';
43
44
 
44
- const mode = hosted({ url: 'https://your-project.inth.app' });
45
+ const mode = manifest({
46
+ backendURL:
47
+ import.meta.env.VITE_C15T_BACKEND_URL ?? 'https://benchmarks-inth.inth.app',
48
+ manifest: consentManifest,
49
+ });
45
50
 
46
51
  export const Consent = ({ children }: { children: ReactNode }) => (
47
52
  <ConsentProvider options={{ mode, scripts }}>
@@ -5,25 +5,40 @@ description: Fix a missing banner, early vendor requests, unstyled components
5
5
  group: frameworks
6
6
  ---
7
7
 
8
- ## The /init request goes to your-project.inth.app
8
+ ## Why does the build fail to download the manifest?
9
9
 
10
- **Check.** In DevTools Network, the `GET` request to `/init` goes to
11
- `your-project.inth.app` and fails.
10
+ **Check.** `vite build` or `vite dev` stops before compiling, with an error
11
+ from `consentManifest` that starts with `@c15t/core/build:`.
12
12
 
13
- **Fix.** Replace the placeholder URL in `hosted({ url })` in `src/consent.tsx`
14
- with the backend URL from your Inth project, exactly as Inth shows it, then
15
- rebuild.
13
+ | Error | Cause | Fix |
14
+ | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
15
+ | `build-time manifests require an absolute upstream URL.` | `backendURL` is empty or relative, such as `/api/c15t` | Pass the absolute backend URL from your Inth project |
16
+ | `build-time manifests require an http(s) upstream URL.` | `backendURL` uses another protocol | Use the `https://` URL Inth shows |
17
+ | `/manifest responded 404` | The URL is not your project's backend, such as the `https://your-project.inth.app` placeholder or a URL missing its path prefix | Copy the backend URL exactly as Inth shows it, or set `VITE_C15T_BACKEND_URL` |
18
+ | `/manifest returned an invalid consent manifest.` | The URL answered with something other than a consent manifest, such as an HTML page | Point `backendURL` at the backend itself, not your site or a dashboard page |
19
+ | `fetch failed` | The build cannot reach the backend | Build where the backend is reachable. A failed download never reuses an old snapshot |
20
+
21
+ ## Why can't TypeScript find ./c15t-manifest?
22
+
23
+ **Check.** `tsc`, `vue-tsc` or your editor reports that it cannot find the
24
+ module `./c15t-manifest`, on a fresh checkout or in CI.
25
+
26
+ **Fix.** `consentManifest` writes `src/c15t-manifest.ts` when `vite build` or
27
+ `vite dev` starts, and the file is not in Git. Run one of them before the type
28
+ check. In CI, run the build first, or cache the generated file with the build
29
+ output.
16
30
 
17
31
  ## There is no banner
18
32
 
19
33
  **Check.** In DevTools Network, find the `GET` request to `/init` on your
20
- backend URL.
21
-
22
- | What you see | Cause | Fix |
23
- | ------------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
24
- | No `/init` request | `ConsentProvider` is not mounted, or an error stopped `src/consent.tsx` from rendering | Check the console for errors and render one provider at the app root, as in the [quickstart](./quickstart.md) |
25
- | `/init` fails with a CORS error | Your site's origin is not trusted | Add the exact origin, including port in development, to the trusted origins in your Inth project |
26
- | `/init` returns 200 | The policy for this visitor asks for no banner, or a stored choice is still valid | Inspect the active policy with the component below, or clear site data |
34
+ backend URL. With the bundled manifest, the browser makes no request before
35
+ the banner unless the policy depends on a country or region it does not know.
36
+
37
+ | What you see | Cause | Fix |
38
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
39
+ | No request and no banner | `ConsentProvider` is not mounted, an error stopped `src/consent.tsx` from rendering, or the bundled policy asks for no banner | Check the console for errors, render one provider at the app root as in the [quickstart](./quickstart.md), and inspect the active policy with the component below |
40
+ | `/init` fails with a CORS error | Your site's origin is not trusted | Add the exact origin, including port in development, to the trusted origins in your Inth project |
41
+ | `/init` returns 200 | The policy for this visitor asks for no banner, or a stored choice is still valid | Inspect the active policy with the component below, or clear site data |
27
42
 
28
43
  A policy with `prompt: 'none'` shows no banner by design, and so does a
29
44
  returning visitor with a valid stored choice. [Policies](../../concepts/policies.md)
@@ -258,7 +258,7 @@ import { resolveConsent } from 'c15t/next/server';
258
258
  import { Suspense } from 'react';
259
259
  import type { ReactNode } from 'react';
260
260
 
261
- import { consentConfig } from '@/c15t.config';
261
+ import { consentOptions } from '@/c15t.server';
262
262
  import { ExperimentConsent } from '@/components/experiment-consent';
263
263
  import { bannerExperiment } from '@/lib/experiment';
264
264
  import { bannerExperimentFlag } from '@/lib/flags';
@@ -268,7 +268,7 @@ import '@/styles/globals.css';
268
268
  const ResolvedConsent = async ({ children }: { children: ReactNode }) => {
269
269
  const arm = await bannerExperimentFlag();
270
270
  const state = await resolveConsent({
271
- config: consentConfig,
271
+ ...consentOptions,
272
272
  // `off` keeps this visitor out of the experiment.
273
273
  experiment: arm === 'off' ? undefined : { ...bannerExperiment, arm },
274
274
  });
@@ -381,7 +381,7 @@ if (result.ok) {
381
381
  | `createSubject(input)` | `subjects.create(input)`. `givenAt` also takes a `Date`. |
382
382
  | `patchSubject(id, input)`, `subjects.patch(id, input)` | `subjects.identify(id, { externalId, identityProvider })` |
383
383
  | `listSubjects({ externalId })`, `subjects.list({ externalId })` | `subjects.list({ externalId })`, on a client with `apiKey` |
384
- | `checkConsent(query)`, `consent.check({ externalId, type: 'a,b' })` | `consents.check({ externalId, types: ['a', 'b'] })` |
384
+ | `checkConsent(query)`, `consent.check({ externalId, type: 'a,b' })` | `consents.check({ externalId, types: ['a', 'b'] })`, on a client with `apiKey` |
385
385
  | `ResponseContext` with `data: T \|null` | `{ ok: true, data } \|{ ok: false, error }`. Check `ok` first. |
386
386
  | `unwrap()`, `expect()` on the response | `unwrap(result)`, imported from `@c15t/node-sdk` |
387
387
  | `unwrapOr()`, `map()` on the response | Check `result.ok` |
@@ -399,6 +399,10 @@ if (result.ok) {
399
399
  responses, such as `givenAt` and `createdAt`, are now `Date` objects rather
400
400
  than strings.
401
401
 
402
+ `consents.check` and `subjects.list` count only verified links. Links made by
403
+ v2 don't count until you relink them with `subjects.identify` on a keyed
404
+ client, or [with an identity token](https://c15t.com/docs/self-host/api/node-sdk#verify-a-link-made-in-the-browser) on the user's next sign-in.
405
+
402
406
  The `node-sdk-to-v3` codemod renames the factory, client options, methods,
403
407
  types and errors in files that create a client. It turns `type` strings into
404
408
  `types` arrays, and leaves a `TODO(c15t v3)` comment at each call, because
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c15t/react",
3
- "version": "3.0.0-alpha.6",
3
+ "version": "3.0.0-alpha.8",
4
4
  "description": "React cookie banner, consent manager, preference center, and headless CMP components with IAB TCF and Consent Mode support.",
5
5
  "keywords": [
6
6
  "ccpa",
@@ -254,16 +254,16 @@
254
254
  "test:watch": "bun prebuild && vitest"
255
255
  },
256
256
  "dependencies": {
257
- "@c15t/core": "3.0.0-alpha.6",
258
- "@c15t/dev-tools": "3.0.0-alpha.6",
259
- "@c15t/iab": "3.0.0-alpha.6",
260
- "@c15t/schema": "3.0.0-alpha.5",
257
+ "@c15t/core": "3.0.0-alpha.8",
258
+ "@c15t/dev-tools": "3.0.0-alpha.8",
259
+ "@c15t/iab": "3.0.0-alpha.8",
260
+ "@c15t/schema": "3.0.0-alpha.7",
261
261
  "@c15t/translations": "3.0.0-alpha.6",
262
- "@c15t/ui": "3.0.0-alpha.6",
262
+ "@c15t/ui": "3.0.0-alpha.8",
263
263
  "@types/google.maps": "3.65.3"
264
264
  },
265
265
  "devDependencies": {
266
- "@c15t/backend": "3.0.0-alpha.6",
266
+ "@c15t/backend": "3.0.0-alpha.8",
267
267
  "@c15t/conformance": "0.0.1",
268
268
  "@c15t/typescript-config": "0.0.1",
269
269
  "@c15t/vitest-config": "1.0.0",