@preprio/toolkit 0.1.0-beta.6 → 0.2.0-beta.2
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 +85 -12
- package/dist/astro/index.cjs +37 -15
- package/dist/astro/index.d.cts +38 -8
- package/dist/astro/index.d.ts +38 -8
- package/dist/astro/index.js +37 -15
- package/dist/{chunk-NLQIRN5O.js → chunk-6OOGNVJ4.js} +83 -41
- package/dist/index.cjs +102 -55
- package/dist/index.d.cts +59 -16
- package/dist/index.d.ts +59 -16
- package/dist/index.js +22 -16
- package/dist/nextjs/components.cjs +87 -42
- package/dist/nextjs/components.d.cts +3 -3
- package/dist/nextjs/components.d.ts +3 -3
- package/dist/nextjs/components.js +8 -4
- package/dist/nextjs/index.cjs +37 -15
- package/dist/nextjs/index.d.cts +46 -16
- package/dist/nextjs/index.d.ts +46 -16
- package/dist/nextjs/index.js +37 -15
- package/dist/nuxt/index.cjs +37 -15
- package/dist/nuxt/index.d.cts +62 -32
- package/dist/nuxt/index.d.ts +62 -32
- package/dist/nuxt/index.js +37 -15
- package/dist/{pixel-DVSJQC0K.d.cts → pixel-763p7m6A.d.cts} +64 -1
- package/dist/{pixel-DVSJQC0K.d.ts → pixel-763p7m6A.d.ts} +64 -1
- package/dist/sveltekit/index.cjs +37 -15
- package/dist/sveltekit/index.d.cts +62 -32
- package/dist/sveltekit/index.d.ts +62 -32
- package/dist/sveltekit/index.js +37 -15
- package/package.json +1 -1
- package/src/astro/PreprToolbar.astro +16 -10
- package/src/nuxt/PreprToolbar.vue +10 -8
- package/src/sveltekit/PreprToolbar.svelte +11 -4
package/dist/index.cjs
CHANGED
|
@@ -23,7 +23,7 @@ __export(src_exports, {
|
|
|
23
23
|
PreprError: () => PreprError,
|
|
24
24
|
PreprToolbarElement: () => PreprToolbarElement,
|
|
25
25
|
VERSION: () => VERSION,
|
|
26
|
-
|
|
26
|
+
createPreprPreview: () => createPreprPreview,
|
|
27
27
|
createToolbarStore: () => createToolbarStore,
|
|
28
28
|
definePreprToolbar: () => definePreprToolbar,
|
|
29
29
|
extractAccessToken: () => extractAccessToken,
|
|
@@ -35,6 +35,7 @@ __export(src_exports, {
|
|
|
35
35
|
getToolbarPropsFromHeaders: () => getToolbarPropsFromHeaders,
|
|
36
36
|
loadTrackingPixel: () => loadTrackingPixel,
|
|
37
37
|
processPreprRequest: () => processPreprRequest,
|
|
38
|
+
resolveFeatures: () => resolveFeatures,
|
|
38
39
|
setTrackingParam: () => setTrackingParam,
|
|
39
40
|
stegaClean: () => stegaClean,
|
|
40
41
|
trackEvent: () => trackEvent,
|
|
@@ -43,7 +44,25 @@ __export(src_exports, {
|
|
|
43
44
|
module.exports = __toCommonJS(src_exports);
|
|
44
45
|
|
|
45
46
|
// src/version.ts
|
|
46
|
-
var VERSION = "0.
|
|
47
|
+
var VERSION = "0.2.0-beta.2";
|
|
48
|
+
|
|
49
|
+
// src/core/features.ts
|
|
50
|
+
function isEnabled(config) {
|
|
51
|
+
if (typeof config === "boolean") return config;
|
|
52
|
+
return config?.enabled ?? true;
|
|
53
|
+
}
|
|
54
|
+
function resolveFeatures(features) {
|
|
55
|
+
return {
|
|
56
|
+
segments: isEnabled(features?.segments),
|
|
57
|
+
abTesting: isEnabled(features?.abTesting),
|
|
58
|
+
editMode: isEnabled(features?.editMode)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
var ALL_FEATURES_ENABLED = Object.freeze({
|
|
62
|
+
segments: true,
|
|
63
|
+
abTesting: true,
|
|
64
|
+
editMode: true
|
|
65
|
+
});
|
|
47
66
|
|
|
48
67
|
// src/core/constants.ts
|
|
49
68
|
var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
|
|
@@ -326,7 +345,7 @@ function createIframeBridge(store, options = {}) {
|
|
|
326
345
|
const top = data.scrollPosition;
|
|
327
346
|
setTimeout(() => window.scrollTo(0, top), 1);
|
|
328
347
|
}
|
|
329
|
-
store
|
|
348
|
+
store?.set({ previewMode: true, editMode: data.editMode ?? true });
|
|
330
349
|
}
|
|
331
350
|
if (!parentOrigin || evt.origin !== parentOrigin) return;
|
|
332
351
|
if (data?.event === "prepr:getScrollPosition") {
|
|
@@ -952,7 +971,8 @@ var DEFAULT_STATE = {
|
|
|
952
971
|
editMode: false,
|
|
953
972
|
previewMode: false,
|
|
954
973
|
toolbarOpen: false,
|
|
955
|
-
isIframe: false
|
|
974
|
+
isIframe: false,
|
|
975
|
+
features: ALL_FEATURES_ENABLED
|
|
956
976
|
};
|
|
957
977
|
function createToolbarStore(initial = {}) {
|
|
958
978
|
let state = { ...DEFAULT_STATE, ...initial };
|
|
@@ -987,7 +1007,7 @@ function cookieOpts() {
|
|
|
987
1007
|
};
|
|
988
1008
|
}
|
|
989
1009
|
function createChangeHandler(deps) {
|
|
990
|
-
const { store, stega, syncAutoClean } = deps;
|
|
1010
|
+
const { store, stega, syncAutoClean, features, editingEnabled } = deps;
|
|
991
1011
|
function updateParams(patch) {
|
|
992
1012
|
const [path, existing] = splitPath(deps.currentPath());
|
|
993
1013
|
const params = new URLSearchParams(existing);
|
|
@@ -1003,7 +1023,7 @@ function createChangeHandler(deps) {
|
|
|
1003
1023
|
}
|
|
1004
1024
|
return function handleChange(before, after) {
|
|
1005
1025
|
const paramPatch = {};
|
|
1006
|
-
if (before.selectedSegment !== after.selectedSegment) {
|
|
1026
|
+
if (features.segments && before.selectedSegment !== after.selectedSegment) {
|
|
1007
1027
|
if (after.selectedSegment === null) {
|
|
1008
1028
|
removeCookie(COOKIE_SEGMENT, "/", crossSiteCookieOptions());
|
|
1009
1029
|
} else {
|
|
@@ -1014,7 +1034,7 @@ function createChangeHandler(deps) {
|
|
|
1014
1034
|
segment: after.selectedSegment ?? void 0
|
|
1015
1035
|
});
|
|
1016
1036
|
}
|
|
1017
|
-
if (before.selectedVariant !== after.selectedVariant) {
|
|
1037
|
+
if (features.abTesting && before.selectedVariant !== after.selectedVariant) {
|
|
1018
1038
|
if (after.selectedVariant === null) {
|
|
1019
1039
|
removeCookie(COOKIE_VARIANT, "/", crossSiteCookieOptions());
|
|
1020
1040
|
} else {
|
|
@@ -1029,7 +1049,7 @@ function createChangeHandler(deps) {
|
|
|
1029
1049
|
updateParams(paramPatch);
|
|
1030
1050
|
}
|
|
1031
1051
|
if (before.editMode !== after.editMode) {
|
|
1032
|
-
if (after.editMode) {
|
|
1052
|
+
if (after.editMode && editingEnabled) {
|
|
1033
1053
|
stega.start();
|
|
1034
1054
|
} else {
|
|
1035
1055
|
stega.stop();
|
|
@@ -1600,9 +1620,10 @@ function StatusPill({
|
|
|
1600
1620
|
t: t3,
|
|
1601
1621
|
handlers
|
|
1602
1622
|
}) {
|
|
1623
|
+
const { features } = state;
|
|
1603
1624
|
const defaultSegmentName = state.segments.find((s2) => s2._id === "all_other_users")?.name ?? t3("adaptiveContent.allOtherUsers");
|
|
1604
1625
|
let segmentLabel;
|
|
1605
|
-
if (!state.previewMode) {
|
|
1626
|
+
if (!state.previewMode || !features.segments) {
|
|
1606
1627
|
segmentLabel = t3("common.user");
|
|
1607
1628
|
} else if (state.selectedSegment !== null) {
|
|
1608
1629
|
const seg = state.segments.find((s2) => s2._id === state.selectedSegment);
|
|
@@ -1626,7 +1647,7 @@ function StatusPill({
|
|
|
1626
1647
|
{
|
|
1627
1648
|
class: "prepr-status-variant",
|
|
1628
1649
|
"data-prepr": "status-variant",
|
|
1629
|
-
hidden: !state.previewMode,
|
|
1650
|
+
hidden: !features.abTesting || !state.previewMode,
|
|
1630
1651
|
children: state.selectedVariant === "B" ? "B" : "A"
|
|
1631
1652
|
}
|
|
1632
1653
|
),
|
|
@@ -1635,7 +1656,7 @@ function StatusPill({
|
|
|
1635
1656
|
{
|
|
1636
1657
|
class: "prepr-status-x",
|
|
1637
1658
|
"data-prepr": "status-x",
|
|
1638
|
-
hidden: !state.previewMode || state.selectedSegment === null,
|
|
1659
|
+
hidden: !features.segments || !state.previewMode || state.selectedSegment === null,
|
|
1639
1660
|
children: /* @__PURE__ */ u2(RawSvg, { svg: XMARK_ICON_SVG })
|
|
1640
1661
|
}
|
|
1641
1662
|
)
|
|
@@ -1655,7 +1676,7 @@ function CloseEditPill({
|
|
|
1655
1676
|
class: "prepr-close-edit-pill",
|
|
1656
1677
|
"data-prepr": "close-edit-pill",
|
|
1657
1678
|
"aria-label": t3("editingTools.ariaCloseEditMode"),
|
|
1658
|
-
hidden: !state.editMode || state.isIframe,
|
|
1679
|
+
hidden: !state.features.editMode || !state.editMode || state.isIframe,
|
|
1659
1680
|
onClick: () => handlers.onCloseEditPill(),
|
|
1660
1681
|
children: [
|
|
1661
1682
|
/* @__PURE__ */ u2("span", { "data-prepr": "close-edit-label", children: t3("editingTools.editMode") }),
|
|
@@ -1671,7 +1692,9 @@ function Panel({
|
|
|
1671
1692
|
segmentFilter,
|
|
1672
1693
|
handlers
|
|
1673
1694
|
}) {
|
|
1674
|
-
const
|
|
1695
|
+
const { features } = state;
|
|
1696
|
+
const hasPersonalization = features.segments && state.selectedSegment !== null || features.abTesting && state.selectedVariant !== null;
|
|
1697
|
+
const showAdaptive = features.segments || features.abTesting;
|
|
1675
1698
|
return /* @__PURE__ */ u2(S, { children: [
|
|
1676
1699
|
/* @__PURE__ */ u2(
|
|
1677
1700
|
"style",
|
|
@@ -1714,12 +1737,12 @@ function Panel({
|
|
|
1714
1737
|
children: [
|
|
1715
1738
|
/* @__PURE__ */ u2(Header, { t: t3, onClose: handlers.onClose }),
|
|
1716
1739
|
/* @__PURE__ */ u2("div", { class: "prepr-section", "data-prepr": "section-adaptive", children: [
|
|
1717
|
-
/* @__PURE__ */ u2("span", { class: "prepr-section-label", "data-prepr": "adaptive-label", children: t3("adaptiveContent.adaptiveContent") }),
|
|
1740
|
+
/* @__PURE__ */ u2("span", { class: "prepr-section-label", "data-prepr": "adaptive-label", children: showAdaptive ? t3("adaptiveContent.adaptiveContent") : t3("adaptiveContent.enablePreview") }),
|
|
1718
1741
|
/* @__PURE__ */ u2("div", { class: "prepr-row", children: [
|
|
1719
1742
|
/* @__PURE__ */ u2("h2", { class: "prepr-row-title", "data-prepr": "preview-label", children: t3("adaptiveContent.enablePreview") }),
|
|
1720
1743
|
/* @__PURE__ */ u2(PreviewSelector, { state, t: t3, handlers })
|
|
1721
1744
|
] }),
|
|
1722
|
-
/* @__PURE__ */ u2("div", { class: "prepr-row", children: [
|
|
1745
|
+
features.segments && /* @__PURE__ */ u2("div", { class: "prepr-row", children: [
|
|
1723
1746
|
/* @__PURE__ */ u2("h2", { class: "prepr-row-title", "data-prepr": "segment-label", children: t3("adaptiveContent.segment") }),
|
|
1724
1747
|
/* @__PURE__ */ u2(
|
|
1725
1748
|
SegmentListbox,
|
|
@@ -1732,12 +1755,12 @@ function Panel({
|
|
|
1732
1755
|
}
|
|
1733
1756
|
)
|
|
1734
1757
|
] }),
|
|
1735
|
-
/* @__PURE__ */ u2("div", { class: "prepr-row", children: [
|
|
1758
|
+
features.abTesting && /* @__PURE__ */ u2("div", { class: "prepr-row", children: [
|
|
1736
1759
|
/* @__PURE__ */ u2("h2", { class: "prepr-row-title", "data-prepr": "variant-label", children: t3("adaptiveContent.ABVariant") }),
|
|
1737
1760
|
/* @__PURE__ */ u2(VariantSelector, { state, handlers })
|
|
1738
1761
|
] })
|
|
1739
1762
|
] }),
|
|
1740
|
-
/* @__PURE__ */ u2("div", { class: "prepr-section", "data-prepr": "section-editing", children: [
|
|
1763
|
+
features.editMode && /* @__PURE__ */ u2("div", { class: "prepr-section", "data-prepr": "section-editing", children: [
|
|
1741
1764
|
/* @__PURE__ */ u2("span", { class: "prepr-section-label", "data-prepr": "editing-label", children: t3("editingTools.editingTools") }),
|
|
1742
1765
|
/* @__PURE__ */ u2("div", { class: "prepr-row", children: [
|
|
1743
1766
|
/* @__PURE__ */ u2("h2", { class: "prepr-row-title", "data-prepr": "edit-label", children: t3("editingTools.editMode") }),
|
|
@@ -1790,26 +1813,28 @@ var PreprToolbarElement = class extends HTMLElementBase {
|
|
|
1790
1813
|
onToggle: () => this.set({ toolbarOpen: !this.state.toolbarOpen }),
|
|
1791
1814
|
onClose: () => this.set({ toolbarOpen: false }),
|
|
1792
1815
|
onPreviewMode: (value) => this.set({ previewMode: value }),
|
|
1793
|
-
onEditMode: (value) =>
|
|
1816
|
+
onEditMode: (value) => {
|
|
1817
|
+
if (!this.state.features.editMode) return;
|
|
1818
|
+
this.set({ editMode: value });
|
|
1819
|
+
},
|
|
1794
1820
|
onVariant: (value) => {
|
|
1821
|
+
if (!this.state.features.abTesting) return;
|
|
1795
1822
|
if (!this.state.previewMode) return;
|
|
1796
1823
|
this.set({ selectedVariant: value });
|
|
1797
1824
|
},
|
|
1798
1825
|
// Reset contract: segment to none, variant to 'A' — NOT null, since the
|
|
1799
1826
|
// resulting `variant_changed` must carry 'A' on the wire — edit mode off.
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
editMode: false
|
|
1804
|
-
}),
|
|
1827
|
+
// Disabled features are left untouched: their state is already inert and
|
|
1828
|
+
// writing it would emit events for a feature the consumer turned off.
|
|
1829
|
+
onReset: () => this.set(this.resetPatch({ editMode: false })),
|
|
1805
1830
|
onStatusPill: () => {
|
|
1806
1831
|
if (!this.state.previewMode) {
|
|
1807
1832
|
this.set({ previewMode: true });
|
|
1808
1833
|
return;
|
|
1809
1834
|
}
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1835
|
+
const patch = this.resetPatch();
|
|
1836
|
+
const dirty = "selectedSegment" in patch && this.state.selectedSegment !== null || "selectedVariant" in patch && this.state.selectedVariant !== "A";
|
|
1837
|
+
if (dirty) this.set(patch);
|
|
1813
1838
|
},
|
|
1814
1839
|
onCloseEditPill: () => this.set({ editMode: false }),
|
|
1815
1840
|
onSegmentButtonClick: () => this.toggleListbox(!this.listboxOpen),
|
|
@@ -1859,6 +1884,14 @@ var PreprToolbarElement = class extends HTMLElementBase {
|
|
|
1859
1884
|
set(patch) {
|
|
1860
1885
|
this.store?.set(patch);
|
|
1861
1886
|
}
|
|
1887
|
+
/** Reset patch covering only the enabled personalization features. */
|
|
1888
|
+
resetPatch(base = {}) {
|
|
1889
|
+
const { features } = this.state;
|
|
1890
|
+
const patch = { ...base };
|
|
1891
|
+
if (features.segments) patch.selectedSegment = null;
|
|
1892
|
+
if (features.abTesting) patch.selectedVariant = "A";
|
|
1893
|
+
return patch;
|
|
1894
|
+
}
|
|
1862
1895
|
// Synchronous: Preact's top-level render() mutates the DOM before returning.
|
|
1863
1896
|
renderPanel(state) {
|
|
1864
1897
|
const root = this.shadowRoot;
|
|
@@ -2017,6 +2050,7 @@ var PreprToolbarElement = class extends HTMLElementBase {
|
|
|
2017
2050
|
) ?? null;
|
|
2018
2051
|
}
|
|
2019
2052
|
chooseSegment(id) {
|
|
2053
|
+
if (!this.state.features.segments) return;
|
|
2020
2054
|
this.listboxOpen = false;
|
|
2021
2055
|
this.segmentFilter = "";
|
|
2022
2056
|
this.set({ selectedSegment: id });
|
|
@@ -2031,8 +2065,8 @@ function definePreprToolbar() {
|
|
|
2031
2065
|
}
|
|
2032
2066
|
}
|
|
2033
2067
|
|
|
2034
|
-
// src/core/create-
|
|
2035
|
-
var debug7 = createScopedLogger("create-
|
|
2068
|
+
// src/core/create-preview.ts
|
|
2069
|
+
var debug7 = createScopedLogger("create-preview");
|
|
2036
2070
|
var controllerStores = /* @__PURE__ */ new WeakMap();
|
|
2037
2071
|
function defaultNavigation() {
|
|
2038
2072
|
return {
|
|
@@ -2053,7 +2087,7 @@ function resolveLocale(options) {
|
|
|
2053
2087
|
}
|
|
2054
2088
|
return "en";
|
|
2055
2089
|
}
|
|
2056
|
-
function
|
|
2090
|
+
function createPreprPreview(opts = {}) {
|
|
2057
2091
|
const { props, options } = opts;
|
|
2058
2092
|
const navigation = opts.navigation ?? defaultNavigation();
|
|
2059
2093
|
initDebugLogger(options?.debug ?? false);
|
|
@@ -2066,36 +2100,40 @@ function createPreprToolbar(opts) {
|
|
|
2066
2100
|
const search = new URLSearchParams(window.location.search);
|
|
2067
2101
|
const hideBar = search.get(PARAM_HIDE_BAR) === "true";
|
|
2068
2102
|
if (hideBar) {
|
|
2069
|
-
debug7.log(`${PARAM_HIDE_BAR}=true \u2014
|
|
2070
|
-
return noop();
|
|
2103
|
+
debug7.log(`${PARAM_HIDE_BAR}=true \u2014 no visible toolbar`);
|
|
2071
2104
|
}
|
|
2105
|
+
const mountUi = (options?.ui ?? true) && !isIframe && !hideBar;
|
|
2072
2106
|
const locale = resolveLocale(options);
|
|
2107
|
+
const features = resolveFeatures(options?.features);
|
|
2073
2108
|
const previewMode = getCookie(COOKIE_PREVIEW_MODE) === "true";
|
|
2074
2109
|
const toolbarOpen = getCookie(COOKIE_TOOLBAR_OPEN) === "true";
|
|
2075
|
-
const cookieSegment = getCookie(COOKIE_SEGMENT);
|
|
2076
|
-
const cookieVariant = getCookie(COOKIE_VARIANT);
|
|
2077
|
-
const rawVariant = props
|
|
2110
|
+
const cookieSegment = features.segments ? getCookie(COOKIE_SEGMENT) : null;
|
|
2111
|
+
const cookieVariant = features.abTesting ? getCookie(COOKIE_VARIANT) : null;
|
|
2112
|
+
const rawVariant = features.abTesting ? props?.activeVariant ?? cookieVariant : null;
|
|
2078
2113
|
const selectedVariant = rawVariant === "A" || rawVariant === "B" ? rawVariant : null;
|
|
2079
2114
|
const store = createToolbarStore({
|
|
2080
2115
|
locale,
|
|
2081
|
-
|
|
2082
|
-
|
|
2116
|
+
features,
|
|
2117
|
+
segments: features.segments ? buildSegments(props?.segments ?? props?.data ?? []) : [],
|
|
2118
|
+
selectedSegment: features.segments ? props?.activeSegment ?? cookieSegment ?? null : null,
|
|
2083
2119
|
selectedVariant,
|
|
2084
2120
|
previewMode,
|
|
2085
2121
|
toolbarOpen,
|
|
2086
2122
|
isIframe
|
|
2087
2123
|
});
|
|
2088
2124
|
let el = null;
|
|
2089
|
-
if (
|
|
2125
|
+
if (mountUi) {
|
|
2090
2126
|
definePreprToolbar();
|
|
2091
2127
|
el = document.createElement("prepr-toolbar");
|
|
2092
2128
|
document.body.appendChild(el);
|
|
2093
2129
|
el.connect(store, (key) => t(key, locale));
|
|
2094
2130
|
}
|
|
2131
|
+
const editingEnabled = features.editMode || isIframe;
|
|
2095
2132
|
const stega = createStegaController({
|
|
2096
|
-
// The CMS deep-link tooltip is
|
|
2097
|
-
//
|
|
2098
|
-
|
|
2133
|
+
// The CMS deep-link tooltip is chrome, so it follows the same decision as
|
|
2134
|
+
// the bar: noise inside the editor (clicking the element itself requests
|
|
2135
|
+
// the edit there), and unwanted in a headless preview that asked for no UI.
|
|
2136
|
+
tooltip: mountUi,
|
|
2099
2137
|
// In the editor, ask the parent to focus the field instead of opening a new
|
|
2100
2138
|
// tab. Standalone previews keep the window.open behaviour.
|
|
2101
2139
|
onEdit: ({ href, origin, id, field }) => {
|
|
@@ -2119,6 +2157,8 @@ function createPreprToolbar(opts) {
|
|
|
2119
2157
|
}
|
|
2120
2158
|
const handleChange = createChangeHandler({
|
|
2121
2159
|
store,
|
|
2160
|
+
features,
|
|
2161
|
+
editingEnabled,
|
|
2122
2162
|
navigate: (url) => navigation.navigate(url),
|
|
2123
2163
|
currentPath: () => navigation.currentPath(),
|
|
2124
2164
|
reload: navigation.reload ?? (() => window.location.reload()),
|
|
@@ -2132,7 +2172,9 @@ function createPreprToolbar(opts) {
|
|
|
2132
2172
|
handleChange(before, state);
|
|
2133
2173
|
});
|
|
2134
2174
|
syncAutoClean(store.get().previewMode);
|
|
2135
|
-
const bridge = createIframeBridge(store
|
|
2175
|
+
const bridge = createIframeBridge(store, {
|
|
2176
|
+
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2177
|
+
});
|
|
2136
2178
|
sendPreprEvent("getScrollPosition", { value: 0 }, {
|
|
2137
2179
|
allowUntrustedTarget: true
|
|
2138
2180
|
});
|
|
@@ -2147,7 +2189,7 @@ function createPreprToolbar(opts) {
|
|
|
2147
2189
|
bridge.stop();
|
|
2148
2190
|
}
|
|
2149
2191
|
el?.remove();
|
|
2150
|
-
debug7.log("
|
|
2192
|
+
debug7.log("preview destroyed");
|
|
2151
2193
|
}
|
|
2152
2194
|
const controller = { destroy };
|
|
2153
2195
|
controllerStores.set(controller, store);
|
|
@@ -2290,16 +2332,19 @@ async function getPreprEnvironmentSegments(token) {
|
|
|
2290
2332
|
);
|
|
2291
2333
|
}
|
|
2292
2334
|
}
|
|
2293
|
-
async function getToolbarPropsFromHeaders(headers, token) {
|
|
2335
|
+
async function getToolbarPropsFromHeaders(headers, token, features) {
|
|
2336
|
+
const resolved = resolveFeatures(features);
|
|
2294
2337
|
let segments = [];
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2338
|
+
if (resolved.segments) {
|
|
2339
|
+
try {
|
|
2340
|
+
segments = await getPreprEnvironmentSegments(token);
|
|
2341
|
+
} catch {
|
|
2342
|
+
segments = [];
|
|
2343
|
+
}
|
|
2299
2344
|
}
|
|
2300
2345
|
return {
|
|
2301
|
-
activeSegment: getActiveSegmentFromHeaders(headers),
|
|
2302
|
-
activeVariant: getActiveVariantFromHeaders(headers),
|
|
2346
|
+
activeSegment: resolved.segments ? getActiveSegmentFromHeaders(headers) : null,
|
|
2347
|
+
activeVariant: resolved.abTesting ? getActiveVariantFromHeaders(headers) : null,
|
|
2303
2348
|
segments,
|
|
2304
2349
|
data: segments
|
|
2305
2350
|
};
|
|
@@ -2374,7 +2419,8 @@ function processPreprRequest(request, opts) {
|
|
|
2374
2419
|
if (!opts?.preview) {
|
|
2375
2420
|
return { requestHeaders, responseCookies };
|
|
2376
2421
|
}
|
|
2377
|
-
const
|
|
2422
|
+
const features = resolveFeatures(opts?.features);
|
|
2423
|
+
const hasPreviewParams = features.segments && searchParams.has(PARAM_SEGMENT) || features.abTesting && searchParams.has(PARAM_VARIANT);
|
|
2378
2424
|
if (!hasPreviewParams) {
|
|
2379
2425
|
const previewModeCookie = requestCookies.get(COOKIE_PREVIEW_MODE);
|
|
2380
2426
|
const previewModeEnabled = previewModeCookie !== "false";
|
|
@@ -2394,16 +2440,16 @@ function processPreprRequest(request, opts) {
|
|
|
2394
2440
|
});
|
|
2395
2441
|
}
|
|
2396
2442
|
if (!isLivePreview) {
|
|
2397
|
-
const segmentCookie = requestCookies.get(COOKIE_SEGMENT);
|
|
2443
|
+
const segmentCookie = features.segments ? requestCookies.get(COOKIE_SEGMENT) : void 0;
|
|
2398
2444
|
if (segmentCookie) {
|
|
2399
2445
|
requestHeaders.set("Prepr-Segments", segmentCookie);
|
|
2400
2446
|
}
|
|
2401
|
-
const abCookie = requestCookies.get(COOKIE_VARIANT);
|
|
2447
|
+
const abCookie = features.abTesting ? requestCookies.get(COOKIE_VARIANT) : void 0;
|
|
2402
2448
|
if (abCookie) {
|
|
2403
2449
|
requestHeaders.set("Prepr-ABtesting", abCookie);
|
|
2404
2450
|
}
|
|
2405
2451
|
}
|
|
2406
|
-
const previewAb = searchParams.get(PARAM_VARIANT);
|
|
2452
|
+
const previewAb = features.abTesting ? searchParams.get(PARAM_VARIANT) : null;
|
|
2407
2453
|
if (previewAb !== null) {
|
|
2408
2454
|
requestHeaders.set("Prepr-ABtesting", previewAb);
|
|
2409
2455
|
if (!isLivePreview) {
|
|
@@ -2416,7 +2462,7 @@ function processPreprRequest(request, opts) {
|
|
|
2416
2462
|
});
|
|
2417
2463
|
}
|
|
2418
2464
|
}
|
|
2419
|
-
const previewSegment = searchParams.get(PARAM_SEGMENT);
|
|
2465
|
+
const previewSegment = features.segments ? searchParams.get(PARAM_SEGMENT) : null;
|
|
2420
2466
|
if (previewSegment !== null) {
|
|
2421
2467
|
requestHeaders.set("Prepr-Segments", previewSegment);
|
|
2422
2468
|
if (!isLivePreview) {
|
|
@@ -2500,7 +2546,7 @@ function setTrackingParam(key, value) {
|
|
|
2500
2546
|
PreprError,
|
|
2501
2547
|
PreprToolbarElement,
|
|
2502
2548
|
VERSION,
|
|
2503
|
-
|
|
2549
|
+
createPreprPreview,
|
|
2504
2550
|
createToolbarStore,
|
|
2505
2551
|
definePreprToolbar,
|
|
2506
2552
|
extractAccessToken,
|
|
@@ -2512,6 +2558,7 @@ function setTrackingParam(key, value) {
|
|
|
2512
2558
|
getToolbarPropsFromHeaders,
|
|
2513
2559
|
loadTrackingPixel,
|
|
2514
2560
|
processPreprRequest,
|
|
2561
|
+
resolveFeatures,
|
|
2515
2562
|
setTrackingParam,
|
|
2516
2563
|
stegaClean,
|
|
2517
2564
|
trackEvent,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import { L as Locale,
|
|
2
|
-
export {
|
|
1
|
+
import { P as PreprFeatures, R as ResolvedPreprFeatures, L as Locale, a as PreprSegment, b as PreprVariant, c as PreprToolbarProps, d as PreprPreviewOptions, e as PreprErrorCode, f as PreprHeaders } from './pixel-763p7m6A.cjs';
|
|
2
|
+
export { g as PreprEnvironment, h as PreprEventType, i as PreprFeatureConfig, j as PreprHeaderName, k as PreprPixelConfig, l as PreprToolbarComponentProps, m as PreprToolbarOptions, n as loadTrackingPixel, s as setTrackingParam, t as trackEvent } from './pixel-763p7m6A.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
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.
|
|
8
|
+
declare const VERSION = "0.2.0-beta.2";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
|
|
12
|
+
* to enabled. Shared by the toolbar and the middleware so both sides agree on
|
|
13
|
+
* what a given config means.
|
|
14
|
+
*/
|
|
15
|
+
declare function resolveFeatures(features?: PreprFeatures): ResolvedPreprFeatures;
|
|
9
16
|
|
|
10
17
|
interface ToolbarState {
|
|
11
18
|
locale: Locale;
|
|
@@ -16,6 +23,11 @@ interface ToolbarState {
|
|
|
16
23
|
previewMode: boolean;
|
|
17
24
|
toolbarOpen: boolean;
|
|
18
25
|
isIframe: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Set once at construction, never patched. Lives here so the panel and the
|
|
28
|
+
* element read it the same way they read everything else.
|
|
29
|
+
*/
|
|
30
|
+
features: ResolvedPreprFeatures;
|
|
19
31
|
}
|
|
20
32
|
interface ToolbarStore {
|
|
21
33
|
get(): ToolbarState;
|
|
@@ -25,7 +37,7 @@ interface ToolbarStore {
|
|
|
25
37
|
/**
|
|
26
38
|
* Framework-free store for toolbar state. Deliberately pure: it holds state and
|
|
27
39
|
* notifies subscribers, nothing else. Cookies, postMessage and reloads are side
|
|
28
|
-
* effects owned by the mount controller (create-
|
|
40
|
+
* effects owned by the mount controller (create-preview.ts).
|
|
29
41
|
*/
|
|
30
42
|
declare function createToolbarStore(initial?: Partial<ToolbarState>): ToolbarStore;
|
|
31
43
|
|
|
@@ -45,21 +57,32 @@ interface PreprNavigationAdapter {
|
|
|
45
57
|
*/
|
|
46
58
|
reload?(): void;
|
|
47
59
|
}
|
|
48
|
-
interface
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
interface CreatePreprPreviewOptions {
|
|
61
|
+
/**
|
|
62
|
+
* Toolbar data. Optional: a headless preview (`ui: false`) that only wants
|
|
63
|
+
* click-to-edit or scroll restore has no segment list to pass.
|
|
64
|
+
*/
|
|
65
|
+
props?: PreprToolbarProps;
|
|
66
|
+
options?: PreprPreviewOptions;
|
|
51
67
|
navigation?: PreprNavigationAdapter;
|
|
52
68
|
}
|
|
53
|
-
interface
|
|
69
|
+
interface PreprPreviewController {
|
|
54
70
|
destroy(): void;
|
|
55
71
|
}
|
|
56
72
|
/**
|
|
57
|
-
* Composition root: hydrates state from props +
|
|
58
|
-
* `<prepr-toolbar>`, and wires the collaborators —
|
|
59
|
-
* (toolbar-change-handler.ts), the stega click-to-edit
|
|
60
|
-
* auto-clean pass and the editor bridge (iframe-bridge.ts).
|
|
73
|
+
* Composition root for the Prepr preview runtime: hydrates state from props +
|
|
74
|
+
* cookies, optionally mounts `<prepr-toolbar>`, and wires the collaborators —
|
|
75
|
+
* the change handler (toolbar-change-handler.ts), the stega click-to-edit
|
|
76
|
+
* controller, the auto-clean pass and the editor bridge (iframe-bridge.ts).
|
|
77
|
+
*
|
|
78
|
+
* Two independent axes control what runs:
|
|
79
|
+
* - `options.features` — which features are active at all (segments, A/B,
|
|
80
|
+
* click-to-edit).
|
|
81
|
+
* - `options.ui` — whether the visible toolbar is mounted. `ui: false` keeps
|
|
82
|
+
* every non-visual side effect wired, which is how a headless preview gets
|
|
83
|
+
* click-to-edit or editor scroll restore with no chrome of its own.
|
|
61
84
|
*/
|
|
62
|
-
declare function
|
|
85
|
+
declare function createPreprPreview(opts?: CreatePreprPreviewOptions): PreprPreviewController;
|
|
63
86
|
|
|
64
87
|
type Translate = (key: string) => string;
|
|
65
88
|
declare const HTMLElementBase: typeof HTMLElement;
|
|
@@ -69,7 +92,7 @@ declare const HTMLElementBase: typeof HTMLElement;
|
|
|
69
92
|
*
|
|
70
93
|
* This element is the controller: it owns interaction state (listbox open,
|
|
71
94
|
* keyboard nav, tooltip positioning, outside-click) and writes back ONLY via
|
|
72
|
-
* `store.set(...)`. Cookies/postMessage/navigation belong to create-
|
|
95
|
+
* `store.set(...)`. Cookies/postMessage/navigation belong to create-preview.ts,
|
|
73
96
|
* which subscribes to the same store.
|
|
74
97
|
*
|
|
75
98
|
* State reaches `<Panel>` as a prop rather than internal Preact state, so every
|
|
@@ -87,6 +110,8 @@ declare class PreprToolbarElement extends HTMLElementBase {
|
|
|
87
110
|
disconnectedCallback(): void;
|
|
88
111
|
private get state();
|
|
89
112
|
private set;
|
|
113
|
+
/** Reset patch covering only the enabled personalization features. */
|
|
114
|
+
private resetPatch;
|
|
90
115
|
private renderPanel;
|
|
91
116
|
private tip;
|
|
92
117
|
/**
|
|
@@ -112,6 +137,14 @@ declare class PreprToolbarElement extends HTMLElementBase {
|
|
|
112
137
|
/** Idempotent, including across bundles that each try to define the element. */
|
|
113
138
|
declare function definePreprToolbar(): void;
|
|
114
139
|
|
|
140
|
+
interface IframeBridgeOptions {
|
|
141
|
+
/**
|
|
142
|
+
* Replace the `*.prepr.io` wildcard with an exact origin list. Intended for
|
|
143
|
+
* self-hosted editors; when set, the wildcard no longer applies.
|
|
144
|
+
*/
|
|
145
|
+
allowedEditorOrigins?: string[];
|
|
146
|
+
}
|
|
147
|
+
|
|
115
148
|
/** Error thrown by the token helpers and the segments fetch. */
|
|
116
149
|
declare class PreprError extends Error {
|
|
117
150
|
readonly code: PreprErrorCode;
|
|
@@ -152,8 +185,12 @@ declare function getPreprEnvironmentSegments(token: string): Promise<PreprSegmen
|
|
|
152
185
|
* Never throws: a failed segments fetch yields an empty list so the toolbar
|
|
153
186
|
* still renders. The list is returned under both `segments` and the deprecated
|
|
154
187
|
* `data` alias.
|
|
188
|
+
*
|
|
189
|
+
* Pass the same `features` object you give the toolbar and the middleware: with
|
|
190
|
+
* segments disabled the `_Segments` request is skipped entirely, saving a
|
|
191
|
+
* round-trip per page.
|
|
155
192
|
*/
|
|
156
|
-
declare function getToolbarPropsFromHeaders(headers: Headers, token: string): Promise<PreprToolbarProps>;
|
|
193
|
+
declare function getToolbarPropsFromHeaders(headers: Headers, token: string, features?: PreprFeatures): Promise<PreprToolbarProps>;
|
|
157
194
|
|
|
158
195
|
interface CookieSpec {
|
|
159
196
|
name: string;
|
|
@@ -177,6 +214,12 @@ interface PreprMiddlewareResult {
|
|
|
177
214
|
interface PreprMiddlewareOptions {
|
|
178
215
|
/** Enable preview-mode headers (segment/AB overrides, preview bar). */
|
|
179
216
|
preview?: boolean;
|
|
217
|
+
/**
|
|
218
|
+
* Disable features app-wide. Pass the same object you give the toolbar: a
|
|
219
|
+
* disabled feature injects no header and persists no cookie, whatever the
|
|
220
|
+
* request carries.
|
|
221
|
+
*/
|
|
222
|
+
features?: PreprFeatures;
|
|
180
223
|
/** Override the version reported in Prepr-Package (mainly for tests). */
|
|
181
224
|
version?: string;
|
|
182
225
|
}
|
|
@@ -187,4 +230,4 @@ interface PreprMiddlewareOptions {
|
|
|
187
230
|
*/
|
|
188
231
|
declare function processPreprRequest(request: Request, opts?: PreprMiddlewareOptions): PreprMiddlewareResult;
|
|
189
232
|
|
|
190
|
-
export { type CookieSpec, type
|
|
233
|
+
export { type CookieSpec, type CreatePreprPreviewOptions, type IframeBridgeOptions, PreprError, PreprErrorCode, PreprFeatures, PreprHeaders, type PreprMiddlewareOptions, type PreprMiddlewareResult, type PreprNavigationAdapter, type PreprPreviewController, PreprPreviewOptions, PreprSegment, PreprToolbarElement, PreprToolbarProps, PreprVariant, ResolvedPreprFeatures, type ToolbarState, type ToolbarStore, VERSION, createPreprPreview, createToolbarStore, definePreprToolbar, extractAccessToken, getActiveSegmentFromHeaders, getActiveVariantFromHeaders, getPreprEnvironmentSegments, getPreprHeadersFromHeaders, getPreprUUIDFromHeaders, getToolbarPropsFromHeaders, processPreprRequest, resolveFeatures, stegaClean, validatePreprToken };
|