@probat/react 0.1.2 → 0.1.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/dist/index.d.mts +1 -30
- package/dist/index.d.ts +1 -30
- package/dist/index.js +191 -193
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +193 -191
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -1
- package/src/context/ProbatContext.tsx +1 -12
- package/src/hoc/itrt-frontend.code-workspace +3 -0
- package/src/hoc/withExperiment.tsx +4 -12
- package/src/index.ts +0 -6
- package/src/utils/api.ts +158 -40
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
"use client";
|
|
3
|
-
import React4, { createContext, useMemo,
|
|
3
|
+
import React4, { createContext, useMemo, useContext, useCallback, useState, useEffect } from 'react';
|
|
4
4
|
|
|
5
5
|
// src/utils/environment.ts
|
|
6
6
|
function detectEnvironment() {
|
|
@@ -13,6 +13,41 @@ function detectEnvironment() {
|
|
|
13
13
|
}
|
|
14
14
|
return "prod";
|
|
15
15
|
}
|
|
16
|
+
|
|
17
|
+
// src/context/ProbatContext.tsx
|
|
18
|
+
var ProbatContext = createContext(null);
|
|
19
|
+
function ProbatProvider({
|
|
20
|
+
apiBaseUrl,
|
|
21
|
+
clientKey,
|
|
22
|
+
environment: explicitEnvironment,
|
|
23
|
+
repoFullName: explicitRepoFullName,
|
|
24
|
+
children
|
|
25
|
+
}) {
|
|
26
|
+
const contextValue = useMemo(() => {
|
|
27
|
+
const resolvedApiBaseUrl = apiBaseUrl || typeof import.meta !== "undefined" && import.meta.env?.VITE_PROBAT_API || typeof globalThis !== "undefined" && globalThis.process?.env?.NEXT_PUBLIC_PROBAT_API || typeof window !== "undefined" && window.__PROBAT_API || "https://gushi.onrender.com";
|
|
28
|
+
const environment = explicitEnvironment || detectEnvironment();
|
|
29
|
+
const resolvedRepoFullName = explicitRepoFullName || typeof globalThis !== "undefined" && globalThis.process?.env?.NEXT_PUBLIC_PROBAT_REPO || typeof import.meta !== "undefined" && import.meta.env?.VITE_PROBAT_REPO || typeof window !== "undefined" && window.__PROBAT_REPO || void 0;
|
|
30
|
+
return {
|
|
31
|
+
apiBaseUrl: resolvedApiBaseUrl,
|
|
32
|
+
environment,
|
|
33
|
+
clientKey,
|
|
34
|
+
repoFullName: resolvedRepoFullName
|
|
35
|
+
};
|
|
36
|
+
}, [apiBaseUrl, clientKey, explicitEnvironment, explicitRepoFullName]);
|
|
37
|
+
return /* @__PURE__ */ React4.createElement(ProbatContext.Provider, { value: contextValue }, children);
|
|
38
|
+
}
|
|
39
|
+
function useProbatContext() {
|
|
40
|
+
const context = useContext(ProbatContext);
|
|
41
|
+
if (!context) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
"useProbatContext must be used within a ProbatProvider. Please wrap your app with <ProbatProvider>."
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return context;
|
|
47
|
+
}
|
|
48
|
+
function ProbatProviderClient(props) {
|
|
49
|
+
return React4.createElement(ProbatProvider, props);
|
|
50
|
+
}
|
|
16
51
|
var pendingFetches = /* @__PURE__ */ new Map();
|
|
17
52
|
async function fetchDecision(baseUrl, proposalId) {
|
|
18
53
|
const existingFetch = pendingFetches.get(proposalId);
|
|
@@ -55,7 +90,7 @@ async function sendMetric(baseUrl, proposalId, metricName, variantLabel = "contr
|
|
|
55
90
|
captured_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
56
91
|
};
|
|
57
92
|
try {
|
|
58
|
-
|
|
93
|
+
await fetch(url, {
|
|
59
94
|
method: "POST",
|
|
60
95
|
headers: {
|
|
61
96
|
Accept: "application/json",
|
|
@@ -65,26 +100,7 @@ async function sendMetric(baseUrl, proposalId, metricName, variantLabel = "contr
|
|
|
65
100
|
// CRITICAL: Include cookies to distinguish different users
|
|
66
101
|
body: JSON.stringify(body)
|
|
67
102
|
});
|
|
68
|
-
|
|
69
|
-
console.warn("[PROBAT] Metric send failed:", {
|
|
70
|
-
status: response.status,
|
|
71
|
-
statusText: response.statusText,
|
|
72
|
-
url,
|
|
73
|
-
body
|
|
74
|
-
});
|
|
75
|
-
} else {
|
|
76
|
-
console.log("[PROBAT] Metric sent successfully:", {
|
|
77
|
-
metricName,
|
|
78
|
-
proposalId,
|
|
79
|
-
variantLabel
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error("[PROBAT] Error sending metric:", {
|
|
84
|
-
error: error instanceof Error ? error.message : String(error),
|
|
85
|
-
url,
|
|
86
|
-
body
|
|
87
|
-
});
|
|
103
|
+
} catch {
|
|
88
104
|
}
|
|
89
105
|
}
|
|
90
106
|
function extractClickMeta(event) {
|
|
@@ -145,7 +161,7 @@ if (typeof window !== "undefined") {
|
|
|
145
161
|
window.__probatReact = React4;
|
|
146
162
|
window.React = window.React || React4;
|
|
147
163
|
}
|
|
148
|
-
async function loadVariantComponent(baseUrl, proposalId, experimentId, filePath) {
|
|
164
|
+
async function loadVariantComponent(baseUrl, proposalId, experimentId, filePath, repoFullName, baseRef) {
|
|
149
165
|
if (!filePath) {
|
|
150
166
|
return null;
|
|
151
167
|
}
|
|
@@ -156,16 +172,151 @@ async function loadVariantComponent(baseUrl, proposalId, experimentId, filePath)
|
|
|
156
172
|
}
|
|
157
173
|
const loadPromise = (async () => {
|
|
158
174
|
try {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
175
|
+
try {
|
|
176
|
+
const variantUrl = `/probat/${filePath}`;
|
|
177
|
+
const mod = await import(
|
|
178
|
+
/* @vite-ignore */
|
|
179
|
+
variantUrl
|
|
180
|
+
);
|
|
181
|
+
const VariantComponent2 = mod?.default || mod;
|
|
182
|
+
if (VariantComponent2 && typeof VariantComponent2 === "function") {
|
|
183
|
+
return VariantComponent2;
|
|
184
|
+
}
|
|
185
|
+
} catch {
|
|
186
|
+
}
|
|
187
|
+
let code = "";
|
|
188
|
+
let rawCode = "";
|
|
189
|
+
let rawCodeFetched = false;
|
|
190
|
+
const localUrl = `/probat/${filePath}`;
|
|
191
|
+
try {
|
|
192
|
+
const localRes = await fetch(localUrl, {
|
|
193
|
+
method: "GET",
|
|
194
|
+
headers: { Accept: "text/plain" }
|
|
195
|
+
});
|
|
196
|
+
if (localRes.ok) {
|
|
197
|
+
rawCode = await localRes.text();
|
|
198
|
+
rawCodeFetched = true;
|
|
199
|
+
console.log(`[PROBAT] \u2705 Loaded variant from local (user's repo): ${localUrl}`);
|
|
200
|
+
}
|
|
201
|
+
} catch {
|
|
202
|
+
console.debug(`[PROBAT] Local file not available (${localUrl}), trying GitHub...`);
|
|
203
|
+
}
|
|
204
|
+
if (!rawCodeFetched && repoFullName) {
|
|
205
|
+
const githubPath = `probat/${filePath}`;
|
|
206
|
+
const gitRef = baseRef || "main";
|
|
207
|
+
const githubUrl = `https://raw.githubusercontent.com/${repoFullName}/${gitRef}/${githubPath}`;
|
|
208
|
+
const res = await fetch(githubUrl, { method: "GET", headers: { Accept: "text/plain" } });
|
|
209
|
+
if (res.ok) {
|
|
210
|
+
rawCode = await res.text();
|
|
211
|
+
rawCodeFetched = true;
|
|
212
|
+
console.log(`[PROBAT] \u26A0\uFE0F Loaded variant from GitHub (fallback): ${githubUrl}`);
|
|
213
|
+
} else {
|
|
214
|
+
console.warn(`[PROBAT] \u26A0\uFE0F GitHub fetch failed (${res.status}), falling back to server compilation`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (rawCodeFetched && rawCode) {
|
|
218
|
+
let Babel;
|
|
219
|
+
if (typeof window !== "undefined" && window.Babel) {
|
|
220
|
+
Babel = window.Babel;
|
|
221
|
+
} else {
|
|
222
|
+
try {
|
|
223
|
+
const babelModule = await import('@babel/standalone');
|
|
224
|
+
Babel = babelModule.default || babelModule;
|
|
225
|
+
} catch (importError) {
|
|
226
|
+
try {
|
|
227
|
+
await new Promise((resolve, reject) => {
|
|
228
|
+
if (typeof document === "undefined") {
|
|
229
|
+
reject(new Error("Document not available"));
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (window.Babel) {
|
|
233
|
+
Babel = window.Babel;
|
|
234
|
+
resolve();
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const script = document.createElement("script");
|
|
238
|
+
script.src = "https://unpkg.com/@babel/standalone/babel.min.js";
|
|
239
|
+
script.async = true;
|
|
240
|
+
script.onload = () => {
|
|
241
|
+
Babel = window.Babel;
|
|
242
|
+
if (!Babel) reject(new Error("Babel not found after script load"));
|
|
243
|
+
else resolve();
|
|
244
|
+
};
|
|
245
|
+
script.onerror = () => reject(new Error("Failed to load Babel from CDN"));
|
|
246
|
+
document.head.appendChild(script);
|
|
247
|
+
});
|
|
248
|
+
} catch (babelError) {
|
|
249
|
+
console.error("[PROBAT] Failed to load Babel, falling back to server compilation", babelError);
|
|
250
|
+
rawCodeFetched = false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (rawCodeFetched && rawCode && Babel) {
|
|
255
|
+
const isTSX = filePath.endsWith(".tsx");
|
|
256
|
+
rawCode = rawCode.replace(/^import\s+['"].*\.css['"];?\s*$/gm, "");
|
|
257
|
+
rawCode = rawCode.replace(/^import\s+.*from\s+['"].*\.css['"];?\s*$/gm, "");
|
|
258
|
+
rawCode = rawCode.replace(
|
|
259
|
+
/^import\s+React(?:\s*,\s*\{[^}]*\})?\s+from\s+['"]react['"];?\s*$/m,
|
|
260
|
+
"const React = window.React || globalThis.React;"
|
|
261
|
+
);
|
|
262
|
+
rawCode = rawCode.replace(
|
|
263
|
+
/^import\s+\*\s+as\s+React\s+from\s+['"]react['"];?\s*$/m,
|
|
264
|
+
"const React = window.React || globalThis.React;"
|
|
265
|
+
);
|
|
266
|
+
rawCode = rawCode.replace(
|
|
267
|
+
/^import\s+\{([^}]+)\}\s+from\s+['"]react['"];?\s*$/m,
|
|
268
|
+
(match, imports) => `const {${imports}} = window.React || globalThis.React;`
|
|
269
|
+
);
|
|
270
|
+
rawCode = rawCode.replace(/import\.meta\.env\.[\w$]+/g, "undefined");
|
|
271
|
+
rawCode = rawCode.replace(/\bimport\.meta\b/g, "({})");
|
|
272
|
+
rawCode = rawCode.replace(/^import\s+.*\/@vite\/client.*$/gm, "");
|
|
273
|
+
rawCode = rawCode.replace(/import\.meta\.hot(?:\.[\w$]+)*/g, "undefined");
|
|
274
|
+
const compiled = Babel.transform(rawCode, {
|
|
275
|
+
presets: [
|
|
276
|
+
["react", { runtime: "classic" }],
|
|
277
|
+
["typescript", { allExtensions: true, isTSX }]
|
|
278
|
+
],
|
|
279
|
+
plugins: [["transform-modules-commonjs", { allowTopLevelThis: true }]],
|
|
280
|
+
sourceType: "module",
|
|
281
|
+
filename: filePath
|
|
282
|
+
}).code;
|
|
283
|
+
code = `
|
|
284
|
+
var __probatVariant = (function() {
|
|
285
|
+
var require = function(name) {
|
|
286
|
+
if (name === "react" || name === "react/jsx-runtime") {
|
|
287
|
+
return window.React || globalThis.React;
|
|
288
|
+
}
|
|
289
|
+
if (name.startsWith("/@vite") || name.includes("@vite/client") || name.includes(".vite/deps")) {
|
|
290
|
+
return {};
|
|
291
|
+
}
|
|
292
|
+
if (name === "react/jsx-runtime.js") {
|
|
293
|
+
return window.React || globalThis.React;
|
|
294
|
+
}
|
|
295
|
+
throw new Error("Unsupported module: " + name);
|
|
296
|
+
};
|
|
297
|
+
var module = { exports: {} };
|
|
298
|
+
var exports = module.exports;
|
|
299
|
+
${compiled}
|
|
300
|
+
return module.exports.default || module.exports;
|
|
301
|
+
})();
|
|
302
|
+
`;
|
|
303
|
+
} else {
|
|
304
|
+
rawCodeFetched = false;
|
|
305
|
+
code = "";
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (!rawCodeFetched || code === "") {
|
|
309
|
+
const variantUrl = `${baseUrl.replace(/\/$/, "")}/variants/${filePath}`;
|
|
310
|
+
const serverRes = await fetch(variantUrl, {
|
|
311
|
+
method: "GET",
|
|
312
|
+
headers: { Accept: "text/javascript" },
|
|
313
|
+
credentials: "include"
|
|
314
|
+
});
|
|
315
|
+
if (!serverRes.ok) {
|
|
316
|
+
throw new Error(`HTTP ${serverRes.status}`);
|
|
317
|
+
}
|
|
318
|
+
code = await serverRes.text();
|
|
167
319
|
}
|
|
168
|
-
const code = await res.text();
|
|
169
320
|
if (typeof window !== "undefined") {
|
|
170
321
|
window.React = window.React || React4;
|
|
171
322
|
}
|
|
@@ -192,146 +343,7 @@ async function loadVariantComponent(baseUrl, proposalId, experimentId, filePath)
|
|
|
192
343
|
return loadPromise;
|
|
193
344
|
}
|
|
194
345
|
|
|
195
|
-
// src/
|
|
196
|
-
var proposalCache = /* @__PURE__ */ new Map();
|
|
197
|
-
var isListenerAttached = false;
|
|
198
|
-
var lastClickTime = /* @__PURE__ */ new Map();
|
|
199
|
-
var DEBOUNCE_MS = 100;
|
|
200
|
-
function getProposalMetadata(element) {
|
|
201
|
-
const probatWrapper = element.closest("[data-probat-proposal]");
|
|
202
|
-
if (!probatWrapper) return null;
|
|
203
|
-
const proposalId = probatWrapper.getAttribute("data-probat-proposal");
|
|
204
|
-
if (!proposalId) return null;
|
|
205
|
-
const cacheKey = `${proposalId}`;
|
|
206
|
-
const cached = proposalCache.get(cacheKey);
|
|
207
|
-
if (cached) return cached;
|
|
208
|
-
const experimentId = probatWrapper.getAttribute("data-probat-experiment-id");
|
|
209
|
-
const variantLabel = probatWrapper.getAttribute("data-probat-variant-label") || "control";
|
|
210
|
-
const apiBaseUrl = probatWrapper.getAttribute("data-probat-api-base-url") || typeof window !== "undefined" && window.__PROBAT_API || "https://gushi.onrender.com";
|
|
211
|
-
const metadata = {
|
|
212
|
-
proposalId,
|
|
213
|
-
experimentId: experimentId || null,
|
|
214
|
-
variantLabel,
|
|
215
|
-
apiBaseUrl
|
|
216
|
-
};
|
|
217
|
-
proposalCache.set(cacheKey, metadata);
|
|
218
|
-
return metadata;
|
|
219
|
-
}
|
|
220
|
-
function handleDocumentClick(event) {
|
|
221
|
-
const target = event.target;
|
|
222
|
-
if (!target) return;
|
|
223
|
-
const metadata = getProposalMetadata(target);
|
|
224
|
-
if (!metadata) {
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
const now2 = Date.now();
|
|
228
|
-
const lastClick = lastClickTime.get(metadata.proposalId) || 0;
|
|
229
|
-
if (now2 - lastClick < DEBOUNCE_MS) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
lastClickTime.set(metadata.proposalId, now2);
|
|
233
|
-
const clickMeta = extractClickMeta(event);
|
|
234
|
-
target.hasAttribute("data-probat-track") || target.closest("[data-probat-track]") !== null;
|
|
235
|
-
const finalMeta = clickMeta || {
|
|
236
|
-
target_tag: target.tagName,
|
|
237
|
-
target_class: target.className || "",
|
|
238
|
-
target_id: target.id || "",
|
|
239
|
-
clicked_inside_probat: true
|
|
240
|
-
// Flag to indicate this was tracked via document-level listener
|
|
241
|
-
};
|
|
242
|
-
const experimentId = metadata.variantLabel === "control" ? void 0 : metadata.experimentId && !metadata.experimentId.startsWith("exp_") ? metadata.experimentId : void 0;
|
|
243
|
-
void sendMetric(
|
|
244
|
-
metadata.apiBaseUrl,
|
|
245
|
-
metadata.proposalId,
|
|
246
|
-
"click",
|
|
247
|
-
metadata.variantLabel,
|
|
248
|
-
experimentId,
|
|
249
|
-
finalMeta
|
|
250
|
-
);
|
|
251
|
-
console.log("[PROBAT] Click tracked:", {
|
|
252
|
-
proposalId: metadata.proposalId,
|
|
253
|
-
variantLabel: metadata.variantLabel,
|
|
254
|
-
target: target.tagName,
|
|
255
|
-
targetId: target.id || "none",
|
|
256
|
-
targetClass: target.className || "none",
|
|
257
|
-
meta: finalMeta
|
|
258
|
-
});
|
|
259
|
-
console.log("[PROBAT] Sending metric to:", `${metadata.apiBaseUrl}/send_metrics/${metadata.proposalId}`);
|
|
260
|
-
}
|
|
261
|
-
function initDocumentClickTracking() {
|
|
262
|
-
if (isListenerAttached) {
|
|
263
|
-
console.warn("[PROBAT] Document click listener already attached");
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
if (typeof document === "undefined") {
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
document.addEventListener("click", handleDocumentClick, true);
|
|
270
|
-
isListenerAttached = true;
|
|
271
|
-
console.log("[PROBAT] Document-level click tracking initialized");
|
|
272
|
-
}
|
|
273
|
-
function cleanupDocumentClickTracking() {
|
|
274
|
-
if (!isListenerAttached) return;
|
|
275
|
-
if (typeof document !== "undefined") {
|
|
276
|
-
document.removeEventListener("click", handleDocumentClick, true);
|
|
277
|
-
}
|
|
278
|
-
isListenerAttached = false;
|
|
279
|
-
proposalCache.clear();
|
|
280
|
-
lastClickTime.clear();
|
|
281
|
-
}
|
|
282
|
-
function updateProposalMetadata(proposalId, metadata) {
|
|
283
|
-
const existing = proposalCache.get(proposalId);
|
|
284
|
-
if (existing) {
|
|
285
|
-
proposalCache.set(proposalId, {
|
|
286
|
-
...existing,
|
|
287
|
-
...metadata
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
function clearProposalCache() {
|
|
292
|
-
proposalCache.clear();
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// src/context/ProbatContext.tsx
|
|
296
|
-
var ProbatContext = createContext(null);
|
|
297
|
-
function ProbatProvider({
|
|
298
|
-
apiBaseUrl,
|
|
299
|
-
clientKey,
|
|
300
|
-
environment: explicitEnvironment,
|
|
301
|
-
repoFullName: explicitRepoFullName,
|
|
302
|
-
children
|
|
303
|
-
}) {
|
|
304
|
-
const contextValue = useMemo(() => {
|
|
305
|
-
const resolvedApiBaseUrl = apiBaseUrl || typeof import.meta !== "undefined" && import.meta.env?.VITE_PROBAT_API || typeof globalThis !== "undefined" && globalThis.process?.env?.NEXT_PUBLIC_PROBAT_API || typeof window !== "undefined" && window.__PROBAT_API || "https://gushi.onrender.com";
|
|
306
|
-
const environment = explicitEnvironment || detectEnvironment();
|
|
307
|
-
const resolvedRepoFullName = explicitRepoFullName || typeof globalThis !== "undefined" && globalThis.process?.env?.NEXT_PUBLIC_PROBAT_REPO || typeof import.meta !== "undefined" && import.meta.env?.VITE_PROBAT_REPO || typeof window !== "undefined" && window.__PROBAT_REPO || void 0;
|
|
308
|
-
return {
|
|
309
|
-
apiBaseUrl: resolvedApiBaseUrl,
|
|
310
|
-
environment,
|
|
311
|
-
clientKey,
|
|
312
|
-
repoFullName: resolvedRepoFullName
|
|
313
|
-
};
|
|
314
|
-
}, [apiBaseUrl, clientKey, explicitEnvironment, explicitRepoFullName]);
|
|
315
|
-
useEffect(() => {
|
|
316
|
-
initDocumentClickTracking();
|
|
317
|
-
return () => {
|
|
318
|
-
cleanupDocumentClickTracking();
|
|
319
|
-
};
|
|
320
|
-
}, []);
|
|
321
|
-
return /* @__PURE__ */ React4.createElement(ProbatContext.Provider, { value: contextValue }, children);
|
|
322
|
-
}
|
|
323
|
-
function useProbatContext() {
|
|
324
|
-
const context = useContext(ProbatContext);
|
|
325
|
-
if (!context) {
|
|
326
|
-
throw new Error(
|
|
327
|
-
"useProbatContext must be used within a ProbatProvider. Please wrap your app with <ProbatProvider>."
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
return context;
|
|
331
|
-
}
|
|
332
|
-
function ProbatProviderClient(props) {
|
|
333
|
-
return React4.createElement(ProbatProvider, props);
|
|
334
|
-
}
|
|
346
|
+
// src/hooks/useProbatMetrics.ts
|
|
335
347
|
function useProbatMetrics() {
|
|
336
348
|
const { apiBaseUrl } = useProbatContext();
|
|
337
349
|
const trackClick = useCallback(
|
|
@@ -595,7 +607,9 @@ function withExperiment(Control, options) {
|
|
|
595
607
|
apiBaseUrl,
|
|
596
608
|
componentConfig.proposal_id,
|
|
597
609
|
variantInfo.experiment_id,
|
|
598
|
-
variantInfo.file_path
|
|
610
|
+
variantInfo.file_path,
|
|
611
|
+
componentConfig.repo_full_name,
|
|
612
|
+
componentConfig.base_ref
|
|
599
613
|
);
|
|
600
614
|
if (VariantComp && typeof VariantComp === "function" && alive) {
|
|
601
615
|
variantComponents[label2] = VariantComp;
|
|
@@ -694,28 +708,16 @@ function withExperiment(Control, options) {
|
|
|
694
708
|
}
|
|
695
709
|
const label = choice?.label ?? "control";
|
|
696
710
|
const Variant = registry[label] || registry.control || ControlComponent;
|
|
697
|
-
return /* @__PURE__ */ React4.createElement(
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
},
|
|
703
|
-
"data-probat-proposal": proposalId,
|
|
704
|
-
"data-probat-experiment-id": choice?.experiment_id || "",
|
|
705
|
-
"data-probat-variant-label": label,
|
|
706
|
-
"data-probat-api-base-url": apiBaseUrl
|
|
707
|
-
},
|
|
708
|
-
React4.createElement(Variant, {
|
|
709
|
-
key: `${proposalId}:${label}`,
|
|
710
|
-
...props,
|
|
711
|
-
probat: { trackClick: () => trackClick(null, { force: true }) }
|
|
712
|
-
})
|
|
713
|
-
);
|
|
711
|
+
return /* @__PURE__ */ React4.createElement("div", { onClick: (event) => trackClick(event), "data-probat-proposal": proposalId }, React4.createElement(Variant, {
|
|
712
|
+
key: `${proposalId}:${label}`,
|
|
713
|
+
...props,
|
|
714
|
+
probat: { trackClick: () => trackClick(null, { force: true }) }
|
|
715
|
+
}));
|
|
714
716
|
}
|
|
715
717
|
Wrapped.displayName = `withExperiment(${Control.displayName || Control.name || "Component"})`;
|
|
716
718
|
return Wrapped;
|
|
717
719
|
}
|
|
718
720
|
|
|
719
|
-
export { ProbatProvider, ProbatProviderClient,
|
|
721
|
+
export { ProbatProvider, ProbatProviderClient, detectEnvironment, extractClickMeta, fetchDecision, hasTrackedVisit, markTrackedVisit, readChoice, sendMetric, useExperiment, useProbatContext, useProbatMetrics, withExperiment, writeChoice };
|
|
720
722
|
//# sourceMappingURL=index.mjs.map
|
|
721
723
|
//# sourceMappingURL=index.mjs.map
|