@accelerated-agency/visual-editor 0.2.1 → 0.2.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/dist/index.js +105 -70
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,6 +5,11 @@ import { persist } from 'zustand/middleware';
|
|
|
5
5
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
6
6
|
import { HexColorPicker } from 'react-colorful';
|
|
7
7
|
|
|
8
|
+
var PERSIST_NAME_PREFIX = "conversion-editor-variations-v3-";
|
|
9
|
+
function variationsPersistStorageName(experimentId) {
|
|
10
|
+
const id = experimentId?.trim();
|
|
11
|
+
return `${PERSIST_NAME_PREFIX}${id && id.length > 0 ? id : "standalone"}`;
|
|
12
|
+
}
|
|
8
13
|
var VARIATION_COLORS = [
|
|
9
14
|
"#0084D1",
|
|
10
15
|
"#F54A00",
|
|
@@ -77,16 +82,12 @@ var useVariationsStore = create()(
|
|
|
77
82
|
}));
|
|
78
83
|
},
|
|
79
84
|
setActiveVariation: (id) => set({ activeVariationId: id }),
|
|
80
|
-
addMutationToActive: (mutation) => set((s) => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// Clear redo stack for active variation on new mutation
|
|
87
|
-
redoStacks: { ...s.redoStacks, [s.activeVariationId]: [] }
|
|
88
|
-
};
|
|
89
|
-
}),
|
|
85
|
+
addMutationToActive: (mutation) => set((s) => ({
|
|
86
|
+
variations: s.variations.map(
|
|
87
|
+
(v) => v.id === s.activeVariationId ? { ...v, mutations: [...v.mutations, mutation] } : v
|
|
88
|
+
),
|
|
89
|
+
redoStacks: { ...s.redoStacks, [s.activeVariationId]: [] }
|
|
90
|
+
})),
|
|
90
91
|
removeLastMutationFromActive: () => set((s) => {
|
|
91
92
|
const active = s.variations.find((v) => v.id === s.activeVariationId);
|
|
92
93
|
const removed = active?.mutations[active.mutations.length - 1];
|
|
@@ -149,7 +150,8 @@ var useVariationsStore = create()(
|
|
|
149
150
|
}
|
|
150
151
|
}),
|
|
151
152
|
{
|
|
152
|
-
name:
|
|
153
|
+
name: variationsPersistStorageName(void 0),
|
|
154
|
+
skipHydration: true,
|
|
153
155
|
partialize: (state) => ({
|
|
154
156
|
variations: state.variations,
|
|
155
157
|
activeVariationId: state.activeVariationId
|
|
@@ -157,6 +159,15 @@ var useVariationsStore = create()(
|
|
|
157
159
|
}
|
|
158
160
|
)
|
|
159
161
|
);
|
|
162
|
+
async function hydrateVariationsFromStorage(experimentId) {
|
|
163
|
+
useVariationsStore.persist.setOptions({
|
|
164
|
+
name: variationsPersistStorageName(experimentId)
|
|
165
|
+
});
|
|
166
|
+
try {
|
|
167
|
+
await useVariationsStore.persist.rehydrate();
|
|
168
|
+
} catch {
|
|
169
|
+
}
|
|
170
|
+
}
|
|
160
171
|
function TopBar({
|
|
161
172
|
connectionStatus,
|
|
162
173
|
onLoadUrl,
|
|
@@ -4078,6 +4089,9 @@ function sendToPlatform(type, payload) {
|
|
|
4078
4089
|
data: { channel: PLATFORM_CHANNEL, type, payload }
|
|
4079
4090
|
}));
|
|
4080
4091
|
}
|
|
4092
|
+
function experimentIframeContextKey(exp) {
|
|
4093
|
+
return [exp.experimentId ?? "", exp.pageUrl ?? "", exp.editorPassword ?? ""].join("");
|
|
4094
|
+
}
|
|
4081
4095
|
function EditorShell({ initialExperiment, embeddedMode, proxyBaseUrl }) {
|
|
4082
4096
|
const [url, setUrl] = useState("");
|
|
4083
4097
|
const [password, setPassword] = useState("");
|
|
@@ -4090,7 +4104,8 @@ function EditorShell({ initialExperiment, embeddedMode, proxyBaseUrl }) {
|
|
|
4090
4104
|
);
|
|
4091
4105
|
const [experimentData, setExperimentData] = useState(null);
|
|
4092
4106
|
const experimentDataRef = useRef(null);
|
|
4093
|
-
const
|
|
4107
|
+
const lastAppliedRunKeyRef = useRef("");
|
|
4108
|
+
const iframeContextKeyRef = useRef("");
|
|
4094
4109
|
useEffect(() => {
|
|
4095
4110
|
experimentDataRef.current = experimentData;
|
|
4096
4111
|
}, [experimentData]);
|
|
@@ -4108,7 +4123,6 @@ function EditorShell({ initialExperiment, embeddedMode, proxyBaseUrl }) {
|
|
|
4108
4123
|
const clearAll = useVariationsStore((s) => s.clearAll);
|
|
4109
4124
|
const setSelectedElement = useMutationsStore((s) => s.setSelectedElement);
|
|
4110
4125
|
const selectedElement = useMutationsStore((s) => s.selectedElement);
|
|
4111
|
-
const activeVariationId = useVariationsStore((s) => s.activeVariationId);
|
|
4112
4126
|
const variations = useVariationsStore((s) => s.variations);
|
|
4113
4127
|
const removeLastMutationFromActive = useVariationsStore((s) => s.removeLastMutationFromActive);
|
|
4114
4128
|
const removeMutationsForSelector = useVariationsStore((s) => s.removeMutationsForSelector);
|
|
@@ -4159,7 +4173,6 @@ function EditorShell({ initialExperiment, embeddedMode, proxyBaseUrl }) {
|
|
|
4159
4173
|
}, [embedded, experimentData, toast, buildPlatformVariations]);
|
|
4160
4174
|
const pingIntervalRef = useRef(null);
|
|
4161
4175
|
const pongTimeoutRef = useRef(null);
|
|
4162
|
-
const syncDebounceRef = useRef(null);
|
|
4163
4176
|
const stopHeartbeat = useCallback(() => {
|
|
4164
4177
|
if (pingIntervalRef.current) {
|
|
4165
4178
|
clearInterval(pingIntervalRef.current);
|
|
@@ -4193,15 +4206,24 @@ function EditorShell({ initialExperiment, embeddedMode, proxyBaseUrl }) {
|
|
|
4193
4206
|
},
|
|
4194
4207
|
[stopHeartbeat, clearAll, setSelectedElement]
|
|
4195
4208
|
);
|
|
4209
|
+
useEffect(() => {
|
|
4210
|
+
if (initialExperiment) return;
|
|
4211
|
+
let cancelled = false;
|
|
4212
|
+
void (async () => {
|
|
4213
|
+
await hydrateVariationsFromStorage(void 0);
|
|
4214
|
+
if (cancelled) return;
|
|
4215
|
+
})();
|
|
4216
|
+
return () => {
|
|
4217
|
+
cancelled = true;
|
|
4218
|
+
};
|
|
4219
|
+
}, [initialExperiment]);
|
|
4196
4220
|
useEffect(() => {
|
|
4197
4221
|
if (!initialExperiment) return;
|
|
4198
|
-
const
|
|
4199
|
-
if (
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
handleLoadUrl(initialExperiment.pageUrl, initialExperiment.editorPassword || void 0);
|
|
4204
|
-
}
|
|
4222
|
+
const runKey = JSON.stringify(initialExperiment);
|
|
4223
|
+
if (lastAppliedRunKeyRef.current === runKey) return;
|
|
4224
|
+
const ctx = experimentIframeContextKey(initialExperiment);
|
|
4225
|
+
const sameIframeContext = iframeContextKeyRef.current !== "" && iframeContextKeyRef.current === ctx;
|
|
4226
|
+
let cancelled = false;
|
|
4205
4227
|
const sourceVariations = Array.isArray(initialExperiment.variations) ? initialExperiment.variations : [];
|
|
4206
4228
|
const editorVariations = sourceVariations.map((v, idx) => {
|
|
4207
4229
|
let mutations = [];
|
|
@@ -4221,7 +4243,31 @@ function EditorShell({ initialExperiment, embeddedMode, proxyBaseUrl }) {
|
|
|
4221
4243
|
mutations
|
|
4222
4244
|
};
|
|
4223
4245
|
});
|
|
4224
|
-
|
|
4246
|
+
setExperimentData(initialExperiment);
|
|
4247
|
+
if (sameIframeContext) {
|
|
4248
|
+
void (async () => {
|
|
4249
|
+
await hydrateVariationsFromStorage(initialExperiment.experimentId);
|
|
4250
|
+
if (cancelled) return;
|
|
4251
|
+
loadExperimentVariations(editorVariations);
|
|
4252
|
+
lastAppliedRunKeyRef.current = runKey;
|
|
4253
|
+
})();
|
|
4254
|
+
return () => {
|
|
4255
|
+
cancelled = true;
|
|
4256
|
+
};
|
|
4257
|
+
}
|
|
4258
|
+
if (initialExperiment.pageUrl) {
|
|
4259
|
+
handleLoadUrl(initialExperiment.pageUrl, initialExperiment.editorPassword || void 0);
|
|
4260
|
+
iframeContextKeyRef.current = ctx;
|
|
4261
|
+
}
|
|
4262
|
+
void (async () => {
|
|
4263
|
+
await hydrateVariationsFromStorage(initialExperiment.experimentId);
|
|
4264
|
+
if (cancelled) return;
|
|
4265
|
+
loadExperimentVariations(editorVariations);
|
|
4266
|
+
lastAppliedRunKeyRef.current = runKey;
|
|
4267
|
+
})();
|
|
4268
|
+
return () => {
|
|
4269
|
+
cancelled = true;
|
|
4270
|
+
};
|
|
4225
4271
|
}, [initialExperiment, handleLoadUrl, loadExperimentVariations]);
|
|
4226
4272
|
const handleBridgeReady = useCallback(() => {
|
|
4227
4273
|
setConnectionStatus("connected");
|
|
@@ -4251,33 +4297,44 @@ function EditorShell({ initialExperiment, embeddedMode, proxyBaseUrl }) {
|
|
|
4251
4297
|
switch (msg.type) {
|
|
4252
4298
|
case "load-experiment": {
|
|
4253
4299
|
const data = msg.payload;
|
|
4254
|
-
setExperimentData(data);
|
|
4255
4300
|
experimentDataRef.current = data;
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
try {
|
|
4263
|
-
const chainSets = JSON.parse(v.changesets || "[]");
|
|
4264
|
-
if (Array.isArray(chainSets) && chainSets.length > 0) {
|
|
4265
|
-
mutations = convertChainSetsToMutations(chainSets);
|
|
4266
|
-
}
|
|
4267
|
-
} catch {
|
|
4301
|
+
const editorVariations = Array.isArray(data.variations) ? data.variations.map((v, idx) => {
|
|
4302
|
+
let mutations = [];
|
|
4303
|
+
try {
|
|
4304
|
+
const chainSets = JSON.parse(v.changesets || "[]");
|
|
4305
|
+
if (Array.isArray(chainSets) && chainSets.length > 0) {
|
|
4306
|
+
mutations = convertChainSetsToMutations(chainSets);
|
|
4268
4307
|
}
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4308
|
+
} catch {
|
|
4309
|
+
}
|
|
4310
|
+
return {
|
|
4311
|
+
id: v._id || `v_${idx}`,
|
|
4312
|
+
platformIid: v.iid,
|
|
4313
|
+
name: v.name,
|
|
4314
|
+
isControl: v.baseline || false,
|
|
4315
|
+
traffic_allocation: v.traffic_allocation,
|
|
4316
|
+
mutations
|
|
4317
|
+
};
|
|
4318
|
+
}) : [];
|
|
4319
|
+
setExperimentData(data);
|
|
4320
|
+
const ctx = experimentIframeContextKey(data);
|
|
4321
|
+
let reloadedIframe = false;
|
|
4322
|
+
if (data.pageUrl && !data.skipUrlReload) {
|
|
4323
|
+
if (iframeContextKeyRef.current !== ctx) {
|
|
4324
|
+
handleLoadUrl(data.pageUrl, data.editorPassword || void 0);
|
|
4325
|
+
iframeContextKeyRef.current = ctx;
|
|
4326
|
+
reloadedIframe = true;
|
|
4327
|
+
}
|
|
4279
4328
|
}
|
|
4280
|
-
|
|
4329
|
+
void (async () => {
|
|
4330
|
+
await hydrateVariationsFromStorage(data.experimentId);
|
|
4331
|
+
if (Array.isArray(data.variations)) {
|
|
4332
|
+
loadExperimentVariations(editorVariations);
|
|
4333
|
+
}
|
|
4334
|
+
if (reloadedIframe) {
|
|
4335
|
+
toast(`Loaded experiment: ${data.name || "Untitled"}`, "info");
|
|
4336
|
+
}
|
|
4337
|
+
})();
|
|
4281
4338
|
break;
|
|
4282
4339
|
}
|
|
4283
4340
|
case "request-save": {
|
|
@@ -4351,27 +4408,6 @@ function EditorShell({ initialExperiment, embeddedMode, proxyBaseUrl }) {
|
|
|
4351
4408
|
useEffect(() => {
|
|
4352
4409
|
sendToBridge({ type: "setMode", mode: interactionMode });
|
|
4353
4410
|
}, [interactionMode]);
|
|
4354
|
-
useEffect(() => {
|
|
4355
|
-
if (syncDebounceRef.current) {
|
|
4356
|
-
clearTimeout(syncDebounceRef.current);
|
|
4357
|
-
syncDebounceRef.current = null;
|
|
4358
|
-
}
|
|
4359
|
-
if (connectionStatus !== "connected") return;
|
|
4360
|
-
syncDebounceRef.current = setTimeout(() => {
|
|
4361
|
-
const currentActiveMutations = useVariationsStore.getState().getActiveMutations();
|
|
4362
|
-
sendToBridge({ type: "clearAllMutations" });
|
|
4363
|
-
if (currentActiveMutations.length > 0) {
|
|
4364
|
-
sendToBridge({ type: "applyMutationBatch", mutations: currentActiveMutations });
|
|
4365
|
-
}
|
|
4366
|
-
syncDebounceRef.current = null;
|
|
4367
|
-
}, 350);
|
|
4368
|
-
return () => {
|
|
4369
|
-
if (syncDebounceRef.current) {
|
|
4370
|
-
clearTimeout(syncDebounceRef.current);
|
|
4371
|
-
syncDebounceRef.current = null;
|
|
4372
|
-
}
|
|
4373
|
-
};
|
|
4374
|
-
}, [connectionStatus, activeVariationId, experimentData?.experimentId]);
|
|
4375
4411
|
useEffect(() => {
|
|
4376
4412
|
const handler = (e) => {
|
|
4377
4413
|
const meta = e.metaKey || e.ctrlKey;
|
|
@@ -4574,7 +4610,7 @@ function PlatformVisualEditor({
|
|
|
4574
4610
|
renderLoading,
|
|
4575
4611
|
renderError
|
|
4576
4612
|
}) {
|
|
4577
|
-
console.log(experiment);
|
|
4613
|
+
console.log("experiment", experiment);
|
|
4578
4614
|
const [editorReady, setEditorReady] = useState(false);
|
|
4579
4615
|
const [dirty, setDirty] = useState(false);
|
|
4580
4616
|
const dirtyRef = useRef(false);
|
|
@@ -4788,7 +4824,6 @@ function PlatformVisualEditorV2({
|
|
|
4788
4824
|
renderLoading,
|
|
4789
4825
|
renderError
|
|
4790
4826
|
}) {
|
|
4791
|
-
console.log(experiment);
|
|
4792
4827
|
const iframeRef = useRef(null);
|
|
4793
4828
|
const [editorReady, setEditorReady] = useState(false);
|
|
4794
4829
|
const [dirty, setDirty] = useState(false);
|
|
@@ -4978,4 +5013,4 @@ function PlatformVisualEditorV2({
|
|
|
4978
5013
|
] });
|
|
4979
5014
|
}
|
|
4980
5015
|
|
|
4981
|
-
export { EditorShell, PlatformVisualEditor, PlatformVisualEditorV2, ToastProvider, useToast };
|
|
5016
|
+
export { EditorShell, PlatformVisualEditor, PlatformVisualEditorV2, ToastProvider, hydrateVariationsFromStorage, useToast, variationsPersistStorageName };
|