>;
+};
+
+export function withExperiment(
+Control: React.ComponentType
,
+opts: WithExperimentOpts
+): React.ComponentType
void; probat?: { trackClick: () => void } }> {
+const { proposalId, registry } = opts;
+
+function Wrapped(props: P) {
+ const [choice, setChoice] = React.useState<{ experiment_id: string; label: string } | null>(null);
+
+ React.useEffect(() => {
+ let alive = true;
+
+ const cached = readChoice(proposalId);
+ if (cached) {
+ setChoice({ experiment_id: cached.experiment_id, label: cached.label });
+ }
+
+ if (!cached) {
+ (async () => {
+ try {
+ const { experiment_id, label } = await fetchDecision(ENV_BASE, proposalId);
+ if (!alive) return;
+ setChoice({ experiment_id, label });
+ } catch (e) {
+ if (!alive) return;
+ setChoice({ experiment_id: `exp_${proposalId}`, label: "control" });
+ }
+ })();
+ }
+
+ return () => { alive = false; };
+ }, [proposalId]);
+
+ React.useEffect(() => {
+ const exp = choice?.experiment_id;
+ const lbl = choice?.label ?? "control";
+ if (!lbl) return;
+ recordVisit(ENV_BASE, proposalId, exp ?? undefined, lbl);
+ }, [proposalId, choice?.experiment_id, choice?.label]);
+
+ const trackClick = React.useCallback(
+ (event?: React.MouseEvent | null, options?: { force?: boolean }) => {
+ const exp = choice?.experiment_id;
+ const lbl = choice?.label ?? "control";
+ const meta = extractClickMeta(event ?? undefined);
+ if (!options?.force && event && !meta) {
+ return false;
+ }
+ void sendClickMetric(ENV_BASE, proposalId, exp, lbl, meta);
+ return true;
+ },
+ [proposalId, choice?.experiment_id, choice?.label]
+ );
+
+ const label = choice?.label ?? "control";
+ const Variant = registry[label] || Control;
+
+ const key = `${proposalId}:${label}`;
+ return (
+
{
+ try {
+ props.onProbatClick?.();
+ } catch {}
+ trackClick(event);
+ }}
+ data-probat-proposal={proposalId}
+ >
+ {React.createElement(Variant, {
+ key,
+ ...(props as any),
+ onProbatClick: () => trackClick(null, { force: true }),
+ probat: { trackClick: () => trackClick(null, { force: true }) },
+ })}
+
+ );
+}
+
+(Wrapped as any).displayName = `withExperiment(${(Control as any).displayName || Control.name || "Component"})`;
+return Wrapped as any;
+}
From 8a603281c2218c34028c39f3beb92ee5b20349a9 Mon Sep 17 00:00:00 2001
From: "probatai[bot]" <236084945+probatai[bot]@users.noreply.github.com>
Date: Wed, 12 Nov 2025 07:58:54 +0000
Subject: [PATCH 08/11] Add probat/index.tsx
---
probat/index.tsx | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 probat/index.tsx
diff --git a/probat/index.tsx b/probat/index.tsx
new file mode 100644
index 00000000..c5493906
--- /dev/null
+++ b/probat/index.tsx
@@ -0,0 +1,4 @@
+// probat/index.tsx
+export { withExperiment } from "./runtime";
+export { PROBAT_REGISTRIES } from "./registry";
+export { PROBAT_COMPONENTS } from "./config";
From d0c07dc6feabd051a763699be69b6a1196109a62 Mon Sep 17 00:00:00 2001
From: "probatai[bot]" <236084945+probatai[bot]@users.noreply.github.com>
Date: Wed, 12 Nov 2025 07:58:57 +0000
Subject: [PATCH 09/11] Ensure probat/config.tsx entry
---
probat/config.tsx | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 probat/config.tsx
diff --git a/probat/config.tsx b/probat/config.tsx
new file mode 100644
index 00000000..37f7a7f3
--- /dev/null
+++ b/probat/config.tsx
@@ -0,0 +1,4 @@
+// probat/config.tsx
+export const PROBAT_COMPONENTS: Record = {
+ "src/components/Features.tsx": { proposalId: "b67c9b37-e15f-4562-99a2-8fa70af080a1" }
+};
From 4645a873e3098d5a240a11e17003d55f08817e7d Mon Sep 17 00:00:00 2001
From: "probatai[bot]" <236084945+probatai[bot]@users.noreply.github.com>
Date: Wed, 12 Nov 2025 07:59:00 +0000
Subject: [PATCH 10/11] Ensure probat/registry.tsx entry
---
probat/registry.tsx | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 probat/registry.tsx
diff --git a/probat/registry.tsx b/probat/registry.tsx
new file mode 100644
index 00000000..f79a130d
--- /dev/null
+++ b/probat/registry.tsx
@@ -0,0 +1,18 @@
+// probat/registry.tsx
+ import type React from "react";
+ import Exp_0_c from "./b67c9b37-e15f-4562-99a2-8fa70af080a1/d7fb1a9b-0a03-41e5-aa77-657a308ef113";
+import Exp_1_d from "./b67c9b37-e15f-4562-99a2-8fa70af080a1/35864a5f-62ca-48bf-bfe9-f9200590ffd7";
+import Exp_2_e from "./b67c9b37-e15f-4562-99a2-8fa70af080a1/3c390170-1a94-40d8-9d66-fc01f9ffff82";
+import Exp_3_f from "./b67c9b37-e15f-4562-99a2-8fa70af080a1/735f4aa6-0f9b-4f54-a116-2aec55f39e6a";
+import Exp_4_g from "./b67c9b37-e15f-4562-99a2-8fa70af080a1/bc8fd9d7-0daf-4830-8af7-b5e1e4d31847";
+import Exp_5_i from "./b67c9b37-e15f-4562-99a2-8fa70af080a1/fc41a57e-2bae-4c44-8074-899f97f58c76";
+ export const PROBAT_REGISTRIES: Record>> = {
+ "src/components/Features.tsx": {
+ "c": Exp_0_c,
+ "d": Exp_1_d,
+ "e": Exp_2_e,
+ "f": Exp_3_f,
+ "g": Exp_4_g,
+ "i": Exp_5_i,
+ },
+ };
From 6ee9e29a6a8ac3b0fc1b383c12d23ac37d193332 Mon Sep 17 00:00:00 2001
From: "probatai[bot]" <236084945+probatai[bot]@users.noreply.github.com>
Date: Wed, 12 Nov 2025 07:59:08 +0000
Subject: [PATCH 11/11] probat: auto-edit component to integrate Probat at
src/components/Features.tsx
---
src/components/Features.tsx | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/src/components/Features.tsx b/src/components/Features.tsx
index fdf0619f..3486623e 100644
--- a/src/components/Features.tsx
+++ b/src/components/Features.tsx
@@ -1,6 +1,10 @@
import React from 'react'
+import { withExperiment } from "../../probat/runtime";
+import { PROBAT_COMPONENTS, PROBAT_REGISTRIES } from "../../probat/index";
import './Features.css'
+const __PROBAT_KEY__ = "src/components/Features.tsx";
+
interface Feature {
icon: string
title: string
@@ -67,4 +71,11 @@ const Features: React.FC = () => {
)
}
-export default Features
+// Probat Generate Lines.
+export default (() => {
+ const meta = PROBAT_COMPONENTS[__PROBAT_KEY__];
+ const reg = PROBAT_REGISTRIES[__PROBAT_KEY__] as Record> | undefined;
+ return (meta?.proposalId && reg)
+ ? withExperiment(Features as any, { proposalId: meta.proposalId, registry: reg })
+ : Features;
+})();