@preprio/toolkit 0.2.0-beta.2 → 0.2.0-beta.3
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 +93 -1
- package/dist/astro/index.cjs +1 -1
- package/dist/astro/index.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/nextjs/components.cjs +16 -8
- package/dist/nextjs/components.d.cts +15 -8
- package/dist/nextjs/components.d.ts +15 -8
- package/dist/nextjs/components.js +15 -7
- package/dist/nextjs/index.cjs +1 -1
- package/dist/nextjs/index.js +1 -1
- package/dist/nuxt/index.cjs +1 -1
- package/dist/nuxt/index.js +1 -1
- package/dist/react/components.cjs +2237 -0
- package/dist/react/components.d.cts +167 -0
- package/dist/react/components.d.ts +167 -0
- package/dist/react/components.js +2212 -0
- package/dist/react/index.cjs +32 -0
- package/dist/react/index.d.cts +1 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +9 -0
- package/dist/sveltekit/index.cjs +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/package.json +13 -2
package/README.md
CHANGED
|
@@ -80,6 +80,7 @@ Per-framework requirements:
|
|
|
80
80
|
| Entry point | Peer dependencies |
|
|
81
81
|
| --- | --- |
|
|
82
82
|
| `@preprio/toolkit` (vanilla core) | none |
|
|
83
|
+
| `@preprio/toolkit/react` | `react` >= 17, `react-dom` >= 17 |
|
|
83
84
|
| `@preprio/toolkit/nextjs` | `next` >= 13, `react` >= 17, `react-dom` >= 17 |
|
|
84
85
|
| `@preprio/toolkit/astro` | none (`.astro` components compile in your own pipeline) |
|
|
85
86
|
| `@preprio/toolkit/sveltekit` | `svelte` (only for the `.svelte` components) |
|
|
@@ -535,6 +536,81 @@ const preprHeaders = getPreprHeadersFromEvent(event);
|
|
|
535
536
|
|
|
536
537
|
See the runnable example at `examples/nuxt` for the full source of truth.
|
|
537
538
|
|
|
539
|
+
## React (no framework)
|
|
540
|
+
|
|
541
|
+
`@preprio/toolkit/react` carries the two components that need nothing but React — for Vite + React Router, TanStack Router, Remix SPA mode, or Create React App. Next.js users want the [Next.js section](#nextjs) instead; its `PreprToolbar` binds the App Router for you.
|
|
542
|
+
|
|
543
|
+
```tsx
|
|
544
|
+
import { PreprPreview, PreprTrackingPixel } from '@preprio/toolkit/react';
|
|
545
|
+
|
|
546
|
+
export function App() {
|
|
547
|
+
return (
|
|
548
|
+
<>
|
|
549
|
+
<YourRoutes />
|
|
550
|
+
{import.meta.env.DEV && <PreprPreview />}
|
|
551
|
+
<PreprTrackingPixel id={import.meta.env.VITE_PREPR_TRACKING_ID} />
|
|
552
|
+
</>
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
Mount `PreprPreview` once per page — two copies start two editor bridges.
|
|
558
|
+
|
|
559
|
+
### Without personalization
|
|
560
|
+
|
|
561
|
+
A client-rendered app with no segments and no A/B testing needs **no middleware and no server helpers at all**. The middleware exists to resolve segment and variant cookies into request headers; with both features off there are no headers to resolve. What remains is click-to-edit and the editor's scroll restore, which are pure client concerns:
|
|
562
|
+
|
|
563
|
+
```tsx
|
|
564
|
+
<PreprPreview options={{ features: { segments: false, abTesting: false } }} />
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
No `navigation` prop is needed here. The default adapter drives `window.location`, and with both features off the only reachable path is the preview-mode refresh — a full reload either way. `PreprPreview` also needs no router context in this configuration, so it can mount anywhere in the tree.
|
|
568
|
+
|
|
569
|
+
### With personalization
|
|
570
|
+
|
|
571
|
+
Segments and A/B testing need request headers, which need a server. A static SPA has none — so this requires either a framework with a server (React Router in framework mode, Next.js) or your own backend using the [vanilla core](#any-other-framework).
|
|
572
|
+
|
|
573
|
+
Once there is a server, pass a `navigation` adapter so segment and variant switches route softly instead of reloading:
|
|
574
|
+
|
|
575
|
+
```tsx
|
|
576
|
+
import { useNavigate, useLocation } from 'react-router';
|
|
577
|
+
|
|
578
|
+
const navigate = useNavigate();
|
|
579
|
+
const location = useLocation();
|
|
580
|
+
|
|
581
|
+
<PreprPreview
|
|
582
|
+
{...toolbarProps}
|
|
583
|
+
navigation={{
|
|
584
|
+
navigate: url => navigate(url),
|
|
585
|
+
currentPath: () => location.pathname + location.search,
|
|
586
|
+
}}
|
|
587
|
+
/>;
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
`navigation.reload` is optional and defaults to `window.location.reload()`. React Router has no soft-refresh equivalent, so leaving it unset is usually right.
|
|
591
|
+
|
|
592
|
+
### Tracking pageviews
|
|
593
|
+
|
|
594
|
+
`loadTrackingPixel` queues one `pageload` event when it installs. Client-side route changes emit nothing on their own, so a SPA records a single pageview per session unless you fire them yourself:
|
|
595
|
+
|
|
596
|
+
```tsx
|
|
597
|
+
import { useEffect } from 'react';
|
|
598
|
+
import { useLocation } from 'react-router';
|
|
599
|
+
import { trackEvent } from '@preprio/toolkit';
|
|
600
|
+
|
|
601
|
+
function usePreprPageviews() {
|
|
602
|
+
const { pathname } = useLocation();
|
|
603
|
+
|
|
604
|
+
useEffect(() => {
|
|
605
|
+
trackEvent('pageload');
|
|
606
|
+
}, [pathname]);
|
|
607
|
+
}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
This double-counts the first pageview, since the pixel's own install event fires too. Skip the initial run with a ref if the exact count matters.
|
|
611
|
+
|
|
612
|
+
The `id` is your access token, and in a client-rendered app it is public — bundled into JS and visible in devtools. Use a tracking-only token; do not derive it from a browser-exposed GraphQL URL, which would also expose content read access.
|
|
613
|
+
|
|
538
614
|
## Any other framework
|
|
539
615
|
|
|
540
616
|
The core is runtime-neutral: it works off a WHATWG `Request` and hands back the headers to forward to Prepr plus the cookies to persist. Adapting it to Express, Hono, Fastify, or a plain server is roughly twenty lines.
|
|
@@ -680,9 +756,25 @@ The toolbar. Takes the props returned by `getToolbarProps`, and renders nothing
|
|
|
680
756
|
|
|
681
757
|
There is no provider to wrap your tree in; state lives in the toolbar's own store.
|
|
682
758
|
|
|
759
|
+
#### `PreprPreview`
|
|
760
|
+
|
|
761
|
+
From `@preprio/toolkit/react`. The framework-free equivalent of `PreprToolbar`: same preview runtime, with the router binding left to you. Renders nothing.
|
|
762
|
+
|
|
763
|
+
```tsx
|
|
764
|
+
<PreprPreview {...toolbarProps} navigation={adapter} />
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
| Prop | Type | Description |
|
|
768
|
+
| --- | --- | --- |
|
|
769
|
+
| `activeSegment` / `activeVariant` / `segments` | — | Toolbar data, as returned by `getToolbarProps`. Optional for a headless preview. |
|
|
770
|
+
| `options` | `PreprPreviewOptions` | Feature flags, `ui`, locale, debug (see [Preview Options](#preview-options)). |
|
|
771
|
+
| `navigation` | `PreprNavigationAdapter` | Optional router binding. Defaults to `window.location`, which is correct for any router that keeps the URL bar in sync. |
|
|
772
|
+
|
|
773
|
+
Every prop is read once on mount; changing one afterwards has no effect, since a live update would have to tear down the editor bridge and re-announce the preview. Remount to change configuration.
|
|
774
|
+
|
|
683
775
|
#### `PreprTrackingPixel`
|
|
684
776
|
|
|
685
|
-
Loads Prepr's CDN tracking pixel on mount. Renders nothing.
|
|
777
|
+
Loads Prepr's CDN tracking pixel on mount. Renders nothing. Exported from both `@preprio/toolkit/react` and `@preprio/toolkit/nextjs` — the same component, with nothing Next-specific about it.
|
|
686
778
|
|
|
687
779
|
```tsx
|
|
688
780
|
<PreprTrackingPixel id={accessToken} config={{ destinations: { googleTagManager: true } }} />
|
package/dist/astro/index.cjs
CHANGED
package/dist/astro/index.js
CHANGED
package/dist/index.cjs
CHANGED
package/dist/index.d.cts
CHANGED
|
@@ -5,7 +5,7 @@ export { g as PreprEnvironment, h as PreprEventType, i as PreprFeatureConfig, j
|
|
|
5
5
|
* Package version; must match package.json. Lives in its own leaf module so
|
|
6
6
|
* core can import it without cycling through the barrel.
|
|
7
7
|
*/
|
|
8
|
-
declare const VERSION = "0.2.0-beta.
|
|
8
|
+
declare const VERSION = "0.2.0-beta.3";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { g as PreprEnvironment, h as PreprEventType, i as PreprFeatureConfig, j
|
|
|
5
5
|
* Package version; must match package.json. Lives in its own leaf module so
|
|
6
6
|
* core can import it without cycling through the barrel.
|
|
7
7
|
*/
|
|
8
|
-
declare const VERSION = "0.2.0-beta.
|
|
8
|
+
declare const VERSION = "0.2.0-beta.3";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,7 @@ __export(components_exports, {
|
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(components_exports);
|
|
28
28
|
var import_navigation = require("next/navigation");
|
|
29
|
-
var
|
|
29
|
+
var import_react2 = require("react");
|
|
30
30
|
|
|
31
31
|
// src/core/constants.ts
|
|
32
32
|
var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
|
|
@@ -2172,6 +2172,9 @@ function createPreprPreview(opts = {}) {
|
|
|
2172
2172
|
return controller;
|
|
2173
2173
|
}
|
|
2174
2174
|
|
|
2175
|
+
// src/react/components.ts
|
|
2176
|
+
var import_react = require("react");
|
|
2177
|
+
|
|
2175
2178
|
// src/core/pixel.ts
|
|
2176
2179
|
var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr-v2.min.js";
|
|
2177
2180
|
var CACHE_BUST_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -2210,6 +2213,17 @@ function loadTrackingPixel(trackingId, config) {
|
|
|
2210
2213
|
queueFn("event", "pageload");
|
|
2211
2214
|
}
|
|
2212
2215
|
|
|
2216
|
+
// src/react/components.ts
|
|
2217
|
+
function PreprTrackingPixel({
|
|
2218
|
+
id,
|
|
2219
|
+
config
|
|
2220
|
+
}) {
|
|
2221
|
+
(0, import_react.useEffect)(() => {
|
|
2222
|
+
loadTrackingPixel(id, config);
|
|
2223
|
+
}, []);
|
|
2224
|
+
return null;
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2213
2227
|
// src/nextjs/components.ts
|
|
2214
2228
|
function PreprToolbar({
|
|
2215
2229
|
options,
|
|
@@ -2217,7 +2231,7 @@ function PreprToolbar({
|
|
|
2217
2231
|
}) {
|
|
2218
2232
|
const router = (0, import_navigation.useRouter)();
|
|
2219
2233
|
const pathname = (0, import_navigation.usePathname)();
|
|
2220
|
-
(0,
|
|
2234
|
+
(0, import_react2.useEffect)(() => {
|
|
2221
2235
|
const toolbar = createPreprPreview({
|
|
2222
2236
|
props,
|
|
2223
2237
|
options,
|
|
@@ -2230,12 +2244,6 @@ function PreprToolbar({
|
|
|
2230
2244
|
}, []);
|
|
2231
2245
|
return null;
|
|
2232
2246
|
}
|
|
2233
|
-
function PreprTrackingPixel({ id, config }) {
|
|
2234
|
-
(0, import_react.useEffect)(() => {
|
|
2235
|
-
loadTrackingPixel(id, config);
|
|
2236
|
-
}, []);
|
|
2237
|
-
return null;
|
|
2238
|
-
}
|
|
2239
2247
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2240
2248
|
0 && (module.exports = {
|
|
2241
2249
|
PreprToolbar,
|
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { k as PreprPixelConfig, l as PreprToolbarComponentProps } from '../pixel-763p7m6A.cjs';
|
|
2
|
+
|
|
3
|
+
interface PreprTrackingPixelProps {
|
|
4
|
+
/** Prepr tracking/access token. */
|
|
5
|
+
id: string;
|
|
6
|
+
config?: PreprPixelConfig;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Loads Prepr's CDN tracking pixel on mount. Renders nothing.
|
|
10
|
+
*
|
|
11
|
+
* The pixel queues a single `pageload` event when it installs. Client-side
|
|
12
|
+
* route changes emit nothing on their own — call `trackEvent('pageload')` from
|
|
13
|
+
* the router to count them.
|
|
14
|
+
*/
|
|
15
|
+
declare function PreprTrackingPixel({ id, config, }: PreprTrackingPixelProps): null;
|
|
2
16
|
|
|
3
17
|
/**
|
|
4
18
|
* Mounts the Prepr toolbar and wires it to the Next.js router so segment/variant
|
|
@@ -6,12 +20,5 @@ import { l as PreprToolbarComponentProps, k as PreprPixelConfig } from '../pixel
|
|
|
6
20
|
* `createPreprPreview` mounts imperatively.
|
|
7
21
|
*/
|
|
8
22
|
declare function PreprToolbar({ options, ...props }: PreprToolbarComponentProps): null;
|
|
9
|
-
interface PreprTrackingPixelProps {
|
|
10
|
-
/** Prepr tracking/access token. */
|
|
11
|
-
id: string;
|
|
12
|
-
config?: PreprPixelConfig;
|
|
13
|
-
}
|
|
14
|
-
/** Loads Prepr's CDN tracking pixel on mount. Renders nothing. */
|
|
15
|
-
declare function PreprTrackingPixel({ id, config }: PreprTrackingPixelProps): null;
|
|
16
23
|
|
|
17
24
|
export { PreprToolbar, PreprTrackingPixel, type PreprTrackingPixelProps };
|
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { k as PreprPixelConfig, l as PreprToolbarComponentProps } from '../pixel-763p7m6A.js';
|
|
2
|
+
|
|
3
|
+
interface PreprTrackingPixelProps {
|
|
4
|
+
/** Prepr tracking/access token. */
|
|
5
|
+
id: string;
|
|
6
|
+
config?: PreprPixelConfig;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Loads Prepr's CDN tracking pixel on mount. Renders nothing.
|
|
10
|
+
*
|
|
11
|
+
* The pixel queues a single `pageload` event when it installs. Client-side
|
|
12
|
+
* route changes emit nothing on their own — call `trackEvent('pageload')` from
|
|
13
|
+
* the router to count them.
|
|
14
|
+
*/
|
|
15
|
+
declare function PreprTrackingPixel({ id, config, }: PreprTrackingPixelProps): null;
|
|
2
16
|
|
|
3
17
|
/**
|
|
4
18
|
* Mounts the Prepr toolbar and wires it to the Next.js router so segment/variant
|
|
@@ -6,12 +20,5 @@ import { l as PreprToolbarComponentProps, k as PreprPixelConfig } from '../pixel
|
|
|
6
20
|
* `createPreprPreview` mounts imperatively.
|
|
7
21
|
*/
|
|
8
22
|
declare function PreprToolbar({ options, ...props }: PreprToolbarComponentProps): null;
|
|
9
|
-
interface PreprTrackingPixelProps {
|
|
10
|
-
/** Prepr tracking/access token. */
|
|
11
|
-
id: string;
|
|
12
|
-
config?: PreprPixelConfig;
|
|
13
|
-
}
|
|
14
|
-
/** Loads Prepr's CDN tracking pixel on mount. Renders nothing. */
|
|
15
|
-
declare function PreprTrackingPixel({ id, config }: PreprTrackingPixelProps): null;
|
|
16
23
|
|
|
17
24
|
export { PreprToolbar, PreprTrackingPixel, type PreprTrackingPixelProps };
|
|
@@ -6,14 +6,28 @@ import {
|
|
|
6
6
|
|
|
7
7
|
// src/nextjs/components.ts
|
|
8
8
|
import { usePathname, useRouter } from "next/navigation";
|
|
9
|
+
import { useEffect as useEffect2 } from "react";
|
|
10
|
+
|
|
11
|
+
// src/react/components.ts
|
|
9
12
|
import { useEffect } from "react";
|
|
13
|
+
function PreprTrackingPixel({
|
|
14
|
+
id,
|
|
15
|
+
config
|
|
16
|
+
}) {
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
loadTrackingPixel(id, config);
|
|
19
|
+
}, []);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/nextjs/components.ts
|
|
10
24
|
function PreprToolbar({
|
|
11
25
|
options,
|
|
12
26
|
...props
|
|
13
27
|
}) {
|
|
14
28
|
const router = useRouter();
|
|
15
29
|
const pathname = usePathname();
|
|
16
|
-
|
|
30
|
+
useEffect2(() => {
|
|
17
31
|
const toolbar = createPreprPreview({
|
|
18
32
|
props,
|
|
19
33
|
options,
|
|
@@ -26,12 +40,6 @@ function PreprToolbar({
|
|
|
26
40
|
}, []);
|
|
27
41
|
return null;
|
|
28
42
|
}
|
|
29
|
-
function PreprTrackingPixel({ id, config }) {
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
loadTrackingPixel(id, config);
|
|
32
|
-
}, []);
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
43
|
export {
|
|
36
44
|
PreprToolbar,
|
|
37
45
|
PreprTrackingPixel
|
package/dist/nextjs/index.cjs
CHANGED
|
@@ -38,7 +38,7 @@ module.exports = __toCommonJS(nextjs_exports);
|
|
|
38
38
|
var import_server = require("next/server");
|
|
39
39
|
|
|
40
40
|
// src/version.ts
|
|
41
|
-
var VERSION = "0.2.0-beta.
|
|
41
|
+
var VERSION = "0.2.0-beta.3";
|
|
42
42
|
|
|
43
43
|
// src/core/constants.ts
|
|
44
44
|
var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
|
package/dist/nextjs/index.js
CHANGED
package/dist/nuxt/index.cjs
CHANGED
package/dist/nuxt/index.js
CHANGED