@accelerated-agency/visual-editor 0.3.0 → 0.3.1
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 +342 -1
- package/dist/vite.cjs +95 -0
- package/dist/vite.js +95 -0
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { create } from 'zustand';
|
|
|
4
4
|
import { persist } from 'zustand/middleware';
|
|
5
5
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
6
6
|
import { HexColorPicker } from 'react-colorful';
|
|
7
|
+
import 'bootstrap-icons/font/bootstrap-icons.css';
|
|
7
8
|
|
|
8
9
|
var PERSIST_NAME_PREFIX = "conversion-editor-variations-v3-";
|
|
9
10
|
function variationsPersistStorageName(experimentId) {
|
|
@@ -4833,6 +4834,7 @@ function PlatformVisualEditorV2({
|
|
|
4833
4834
|
}) {
|
|
4834
4835
|
const iframeRef = useRef(null);
|
|
4835
4836
|
const [editorReady, setEditorReady] = useState(false);
|
|
4837
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
4836
4838
|
const [dirty, setDirty] = useState(false);
|
|
4837
4839
|
const dirtyRef = useRef(false);
|
|
4838
4840
|
const mutationSkipCountRef = useRef(0);
|
|
@@ -5020,5 +5022,344 @@ function PlatformVisualEditorV2({
|
|
|
5020
5022
|
) })
|
|
5021
5023
|
] });
|
|
5022
5024
|
}
|
|
5025
|
+
var AI_EDITOR_CHANNEL = "ve-ai-editor";
|
|
5026
|
+
var AI_VIEWPORT_WIDTH = {
|
|
5027
|
+
desktop: "100%",
|
|
5028
|
+
tablet: "768px",
|
|
5029
|
+
mobile: "390px"
|
|
5030
|
+
};
|
|
5031
|
+
var AI_VIEWPORT_LABEL = {
|
|
5032
|
+
desktop: "1440px",
|
|
5033
|
+
tablet: "768px",
|
|
5034
|
+
mobile: "390px"
|
|
5035
|
+
};
|
|
5036
|
+
function fingerprint(value) {
|
|
5037
|
+
let hash = 5381;
|
|
5038
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
5039
|
+
hash = hash * 33 ^ value.charCodeAt(index);
|
|
5040
|
+
}
|
|
5041
|
+
return (hash >>> 0).toString(36);
|
|
5042
|
+
}
|
|
5043
|
+
function PlatformAiEditor({
|
|
5044
|
+
embeddedGlobalKey = "__CONVERSION_EMBEDDED__",
|
|
5045
|
+
proxyBaseUrl = "",
|
|
5046
|
+
chatComponent,
|
|
5047
|
+
className = "fixed inset-0 z-[9999] flex flex-col bg-white",
|
|
5048
|
+
editorClassName = "flex-1 min-h-0",
|
|
5049
|
+
showHeader = true,
|
|
5050
|
+
title,
|
|
5051
|
+
status,
|
|
5052
|
+
tabs = [],
|
|
5053
|
+
activeTab = "AI Editor",
|
|
5054
|
+
error = null,
|
|
5055
|
+
showCloseButton = true,
|
|
5056
|
+
closeLabel = "Close",
|
|
5057
|
+
experiment,
|
|
5058
|
+
activeVariationId: controlledActiveVariationId,
|
|
5059
|
+
onClose,
|
|
5060
|
+
onTabChange,
|
|
5061
|
+
onDirtyChange,
|
|
5062
|
+
onEditorReady,
|
|
5063
|
+
onEditorUrlChanged,
|
|
5064
|
+
onSaveSuccess,
|
|
5065
|
+
onSaveError,
|
|
5066
|
+
onRequestSave,
|
|
5067
|
+
renderHeader,
|
|
5068
|
+
renderError,
|
|
5069
|
+
setActiveVariationId: controlledSetActiveVariationId
|
|
5070
|
+
}) {
|
|
5071
|
+
const iframeRef = useRef(null);
|
|
5072
|
+
const [localActiveVariationId, setLocalActiveVariationId] = useState(null);
|
|
5073
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
5074
|
+
const [isIframeLoading, setIsIframeLoading] = useState(false);
|
|
5075
|
+
const [viewport, setViewport] = useState("desktop");
|
|
5076
|
+
useEffect(() => {
|
|
5077
|
+
window[embeddedGlobalKey] = true;
|
|
5078
|
+
return () => {
|
|
5079
|
+
delete window[embeddedGlobalKey];
|
|
5080
|
+
};
|
|
5081
|
+
}, [embeddedGlobalKey]);
|
|
5082
|
+
useEffect(() => {
|
|
5083
|
+
onDirtyChange?.(false);
|
|
5084
|
+
}, [onDirtyChange]);
|
|
5085
|
+
const variations = experiment?.variations ?? [];
|
|
5086
|
+
const activeVariationId = controlledActiveVariationId ?? localActiveVariationId;
|
|
5087
|
+
const setActiveVariationId = controlledSetActiveVariationId ?? setLocalActiveVariationId;
|
|
5088
|
+
useEffect(() => {
|
|
5089
|
+
if (!variations.length) {
|
|
5090
|
+
setActiveVariationId(null);
|
|
5091
|
+
return;
|
|
5092
|
+
}
|
|
5093
|
+
setActiveVariationId((current) => {
|
|
5094
|
+
if (current && variations.some((variation) => variation._id === current)) return current;
|
|
5095
|
+
const baseline = variations.find((variation) => variation.baseline);
|
|
5096
|
+
return baseline?._id ?? variations[0]._id;
|
|
5097
|
+
});
|
|
5098
|
+
}, [variations]);
|
|
5099
|
+
const activeVariation = useMemo(
|
|
5100
|
+
() => variations.find((variation) => variation._id === activeVariationId) ?? null,
|
|
5101
|
+
[variations, activeVariationId]
|
|
5102
|
+
);
|
|
5103
|
+
const effectiveCssCode = useMemo(() => {
|
|
5104
|
+
return (activeVariation?.csscode ?? "").trim();
|
|
5105
|
+
}, [activeVariation?.csscode]);
|
|
5106
|
+
const effectiveJsCode = useMemo(() => {
|
|
5107
|
+
return (activeVariation?.jscode ?? "").trim();
|
|
5108
|
+
}, [activeVariation?.jscode]);
|
|
5109
|
+
const cssFingerprint = useMemo(() => fingerprint(effectiveCssCode), [effectiveCssCode]);
|
|
5110
|
+
const jsFingerprint = useMemo(() => fingerprint(effectiveJsCode), [effectiveJsCode]);
|
|
5111
|
+
const hasAiCode = useMemo(
|
|
5112
|
+
() => Boolean(effectiveCssCode.trim() || effectiveJsCode.trim()),
|
|
5113
|
+
[effectiveCssCode, effectiveJsCode]
|
|
5114
|
+
);
|
|
5115
|
+
const iframeKey = useMemo(
|
|
5116
|
+
() => `ai-iframe-${activeVariationId ?? "default"}-${cssFingerprint}-${jsFingerprint}`,
|
|
5117
|
+
[activeVariationId, cssFingerprint, jsFingerprint]
|
|
5118
|
+
);
|
|
5119
|
+
const iframeWidth = AI_VIEWPORT_WIDTH[viewport];
|
|
5120
|
+
const editorSrc = useMemo(() => {
|
|
5121
|
+
const pageUrl = experiment?.pageUrl;
|
|
5122
|
+
if (!pageUrl) return "about:blank";
|
|
5123
|
+
const safeBaseUrl = normalizeProxyBaseUrl(proxyBaseUrl);
|
|
5124
|
+
const query = new URLSearchParams({
|
|
5125
|
+
password: experiment?.editorPassword ?? "",
|
|
5126
|
+
url: pageUrl
|
|
5127
|
+
}).toString();
|
|
5128
|
+
const previewPath = `/api/conversion-proxy?${query}`;
|
|
5129
|
+
return safeBaseUrl ? `${safeBaseUrl}${previewPath}` : previewPath;
|
|
5130
|
+
}, [proxyBaseUrl, experiment?.pageUrl, experiment?.editorPassword]);
|
|
5131
|
+
const postAiCodeToIframe = useCallback(() => {
|
|
5132
|
+
const targetWindow = iframeRef.current?.contentWindow;
|
|
5133
|
+
if (!targetWindow) return;
|
|
5134
|
+
targetWindow.postMessage(
|
|
5135
|
+
{
|
|
5136
|
+
channel: AI_EDITOR_CHANNEL,
|
|
5137
|
+
type: "apply-ai-code",
|
|
5138
|
+
payload: {
|
|
5139
|
+
cssCode: effectiveCssCode,
|
|
5140
|
+
jsCode: effectiveJsCode
|
|
5141
|
+
}
|
|
5142
|
+
},
|
|
5143
|
+
"*"
|
|
5144
|
+
);
|
|
5145
|
+
}, [effectiveCssCode, effectiveJsCode]);
|
|
5146
|
+
const parseProxyPayloadFromUrl = useCallback((rawUrl) => {
|
|
5147
|
+
if (!rawUrl) return null;
|
|
5148
|
+
try {
|
|
5149
|
+
const parsed = new URL(rawUrl, window.location.href);
|
|
5150
|
+
const url = parsed.searchParams.get("url") ?? void 0;
|
|
5151
|
+
const password = parsed.searchParams.get("password") ?? void 0;
|
|
5152
|
+
return { url, password };
|
|
5153
|
+
} catch {
|
|
5154
|
+
return null;
|
|
5155
|
+
}
|
|
5156
|
+
}, []);
|
|
5157
|
+
const applyAiCodeInIframe = useCallback(() => {
|
|
5158
|
+
postAiCodeToIframe();
|
|
5159
|
+
}, [postAiCodeToIframe]);
|
|
5160
|
+
useEffect(() => {
|
|
5161
|
+
applyAiCodeInIframe();
|
|
5162
|
+
}, [applyAiCodeInIframe]);
|
|
5163
|
+
useEffect(() => {
|
|
5164
|
+
if (!hasAiCode) {
|
|
5165
|
+
setIsIframeLoading(false);
|
|
5166
|
+
return;
|
|
5167
|
+
}
|
|
5168
|
+
setIsIframeLoading(true);
|
|
5169
|
+
const timeoutId = window.setTimeout(() => {
|
|
5170
|
+
setIsIframeLoading(false);
|
|
5171
|
+
}, 5e3);
|
|
5172
|
+
return () => window.clearTimeout(timeoutId);
|
|
5173
|
+
}, [hasAiCode, cssFingerprint, jsFingerprint, activeVariationId]);
|
|
5174
|
+
const handleIframeLoad = useCallback(() => {
|
|
5175
|
+
applyAiCodeInIframe();
|
|
5176
|
+
postAiCodeToIframe();
|
|
5177
|
+
const currentSrc = iframeRef.current?.src ?? null;
|
|
5178
|
+
const proxiedPayload = parseProxyPayloadFromUrl(currentSrc);
|
|
5179
|
+
if (proxiedPayload?.url || proxiedPayload?.password) {
|
|
5180
|
+
void onEditorUrlChanged?.(proxiedPayload);
|
|
5181
|
+
}
|
|
5182
|
+
onEditorReady?.();
|
|
5183
|
+
}, [
|
|
5184
|
+
applyAiCodeInIframe,
|
|
5185
|
+
postAiCodeToIframe,
|
|
5186
|
+
onEditorReady,
|
|
5187
|
+
onEditorUrlChanged,
|
|
5188
|
+
parseProxyPayloadFromUrl
|
|
5189
|
+
]);
|
|
5190
|
+
useEffect(() => {
|
|
5191
|
+
const onMessage = (event) => {
|
|
5192
|
+
const msg = event.data;
|
|
5193
|
+
if (!msg || msg.channel !== AI_EDITOR_CHANNEL) return;
|
|
5194
|
+
if (msg.type === "ai-code-ready") {
|
|
5195
|
+
postAiCodeToIframe();
|
|
5196
|
+
return;
|
|
5197
|
+
}
|
|
5198
|
+
if (msg.type === "ai-url-changed") {
|
|
5199
|
+
const payload = msg.payload ?? {};
|
|
5200
|
+
void onEditorUrlChanged?.({
|
|
5201
|
+
url: payload.url,
|
|
5202
|
+
password: payload.password
|
|
5203
|
+
});
|
|
5204
|
+
return;
|
|
5205
|
+
}
|
|
5206
|
+
if (msg.type === "ai-code-applied") {
|
|
5207
|
+
setIsIframeLoading(false);
|
|
5208
|
+
}
|
|
5209
|
+
};
|
|
5210
|
+
window.addEventListener("message", onMessage);
|
|
5211
|
+
return () => window.removeEventListener("message", onMessage);
|
|
5212
|
+
}, [postAiCodeToIframe, onEditorUrlChanged]);
|
|
5213
|
+
const onTabClick = useCallback(
|
|
5214
|
+
(tab) => onTabChange?.(tab),
|
|
5215
|
+
[onTabChange]
|
|
5216
|
+
);
|
|
5217
|
+
const handleSave = useCallback(async () => {
|
|
5218
|
+
if (!onRequestSave || isSaving) return;
|
|
5219
|
+
const payload = {
|
|
5220
|
+
experimentId: experiment?.experimentId,
|
|
5221
|
+
variations,
|
|
5222
|
+
cssCode: effectiveCssCode,
|
|
5223
|
+
jsCode: effectiveJsCode,
|
|
5224
|
+
selectedVariationId: activeVariation?._id,
|
|
5225
|
+
selectedVariation: activeVariation ?? void 0
|
|
5226
|
+
};
|
|
5227
|
+
setIsSaving(true);
|
|
5228
|
+
try {
|
|
5229
|
+
await onRequestSave(payload);
|
|
5230
|
+
onSaveSuccess?.(payload);
|
|
5231
|
+
} catch (error2) {
|
|
5232
|
+
onSaveError?.(error2);
|
|
5233
|
+
} finally {
|
|
5234
|
+
setIsSaving(false);
|
|
5235
|
+
}
|
|
5236
|
+
}, [
|
|
5237
|
+
onRequestSave,
|
|
5238
|
+
isSaving,
|
|
5239
|
+
experiment?.experimentId,
|
|
5240
|
+
variations,
|
|
5241
|
+
effectiveCssCode,
|
|
5242
|
+
effectiveJsCode,
|
|
5243
|
+
activeVariation,
|
|
5244
|
+
onSaveSuccess,
|
|
5245
|
+
onSaveError
|
|
5246
|
+
]);
|
|
5247
|
+
if (error) {
|
|
5248
|
+
if (renderError) return renderError(error);
|
|
5249
|
+
return /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center bg-slate-50", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 text-center px-8", children: [
|
|
5250
|
+
/* @__PURE__ */ jsx("div", { className: "text-2xl text-red-300", children: "\u26A0" }),
|
|
5251
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-slate-700", children: "Something went wrong" }),
|
|
5252
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-red-400", children: error })
|
|
5253
|
+
] }) });
|
|
5254
|
+
}
|
|
5255
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
5256
|
+
showHeader ? renderHeader?.({
|
|
5257
|
+
title: title ?? experiment?.name,
|
|
5258
|
+
status: status ?? experiment?.status,
|
|
5259
|
+
tabs,
|
|
5260
|
+
activeTab,
|
|
5261
|
+
onTabClick,
|
|
5262
|
+
onClose
|
|
5263
|
+
}) ?? /* @__PURE__ */ jsxs("div", { className: "h-12 border-b border-slate-200 bg-white flex items-center justify-between px-4 shadow-[0_1px_3px_rgba(0,0,0,0.04)] shrink-0", children: [
|
|
5264
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 min-w-0", children: [
|
|
5265
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold tracking-wide px-1.5 py-0.5 rounded bg-indigo-50 text-indigo-600 border border-indigo-100 shrink-0", children: "AI" }),
|
|
5266
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-sm text-slate-800 truncate", children: title ?? experiment?.name ?? "AI Editor" }),
|
|
5267
|
+
status ? /* @__PURE__ */ jsx("span", { className: "hidden sm:inline-flex text-[10px] px-2 py-0.5 rounded-full border border-slate-200 text-slate-500 font-medium bg-slate-50 capitalize", children: status }) : null
|
|
5268
|
+
] }),
|
|
5269
|
+
tabs.length > 0 ? /* @__PURE__ */ jsx("div", { className: "hidden md:flex items-center gap-1 absolute left-1/2 -translate-x-1/2", children: tabs.map((tab) => /* @__PURE__ */ jsx(
|
|
5270
|
+
"button",
|
|
5271
|
+
{
|
|
5272
|
+
type: "button",
|
|
5273
|
+
onClick: () => onTabClick(tab),
|
|
5274
|
+
className: `text-[11px] font-semibold px-3 py-1 rounded-full border transition-all ${tab.label === activeTab ? "bg-indigo-600 text-white border-indigo-600 shadow-sm" : "bg-white text-slate-500 border-slate-200 hover:border-slate-300 hover:text-slate-700"}`,
|
|
5275
|
+
children: tab.label
|
|
5276
|
+
},
|
|
5277
|
+
tab.hash
|
|
5278
|
+
)) }) : null,
|
|
5279
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
5280
|
+
/* @__PURE__ */ jsxs("div", { className: "h-8 px-3 rounded-md border border-slate-200 bg-white flex items-center gap-2 text-xs font-medium text-slate-700", children: [
|
|
5281
|
+
/* @__PURE__ */ jsx("span", { children: AI_VIEWPORT_LABEL[viewport] }),
|
|
5282
|
+
/* @__PURE__ */ jsx("i", { className: "bi bi-chevron-down text-[10px] text-slate-500" })
|
|
5283
|
+
] }),
|
|
5284
|
+
/* @__PURE__ */ jsx("div", { className: "h-8 rounded-lg bg-slate-100 px-1 flex items-center gap-1", style: { backgroundColor: "#F0F0F0" }, children: [
|
|
5285
|
+
{ key: "desktop", icon: "bi-display", title: "Desktop \u2014 full width" },
|
|
5286
|
+
{ key: "tablet", icon: "bi-tablet", title: "Tablet \u2014 768px" },
|
|
5287
|
+
{ key: "mobile", icon: "bi-phone", title: "Mobile \u2014 390px" }
|
|
5288
|
+
].map((vp) => /* @__PURE__ */ jsx(
|
|
5289
|
+
"button",
|
|
5290
|
+
{
|
|
5291
|
+
type: "button",
|
|
5292
|
+
onClick: () => setViewport(vp.key),
|
|
5293
|
+
title: vp.title,
|
|
5294
|
+
className: `w-7 h-7 rounded-md border flex items-center justify-center transition-all ${viewport === vp.key ? "bg-white border-slate-300 text-slate-700 shadow-sm" : "bg-transparent border-transparent text-slate-500 hover:text-slate-700 hover:bg-white/70"}`,
|
|
5295
|
+
children: /* @__PURE__ */ jsx("i", { className: `bi ${vp.icon} text-[12px]` })
|
|
5296
|
+
},
|
|
5297
|
+
vp.key
|
|
5298
|
+
)) })
|
|
5299
|
+
] }),
|
|
5300
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
5301
|
+
variations.length > 0 ? /* @__PURE__ */ jsx(
|
|
5302
|
+
"select",
|
|
5303
|
+
{
|
|
5304
|
+
className: "h-8 max-w-[220px] rounded-md border border-slate-200 bg-white px-2 text-xs text-slate-700",
|
|
5305
|
+
value: activeVariationId ?? "",
|
|
5306
|
+
onChange: (event) => setActiveVariationId(event.target.value || null),
|
|
5307
|
+
"aria-label": "Select variation",
|
|
5308
|
+
children: variations.map((variation) => /* @__PURE__ */ jsx("option", { value: variation._id, children: variation.name }, variation._id))
|
|
5309
|
+
}
|
|
5310
|
+
) : null,
|
|
5311
|
+
onRequestSave ? /* @__PURE__ */ jsx(
|
|
5312
|
+
"button",
|
|
5313
|
+
{
|
|
5314
|
+
type: "button",
|
|
5315
|
+
className: "text-[11px] font-medium px-3 py-1.5 rounded-md border border-indigo-200 text-indigo-700 bg-indigo-50 hover:bg-indigo-100 hover:border-indigo-300 transition-all disabled:opacity-60 disabled:cursor-not-allowed",
|
|
5316
|
+
onClick: () => void handleSave(),
|
|
5317
|
+
disabled: isSaving,
|
|
5318
|
+
children: isSaving ? "Saving..." : "Save"
|
|
5319
|
+
}
|
|
5320
|
+
) : null,
|
|
5321
|
+
showCloseButton ? /* @__PURE__ */ jsx(
|
|
5322
|
+
"button",
|
|
5323
|
+
{
|
|
5324
|
+
type: "button",
|
|
5325
|
+
className: "text-[11px] font-medium px-3 py-1.5 rounded-md border border-slate-200 text-slate-600 hover:bg-slate-50 hover:border-slate-300 transition-all",
|
|
5326
|
+
onClick: () => onClose?.(),
|
|
5327
|
+
children: closeLabel
|
|
5328
|
+
}
|
|
5329
|
+
) : null
|
|
5330
|
+
] })
|
|
5331
|
+
] }) : null,
|
|
5332
|
+
/* @__PURE__ */ jsxs("div", { className: `${editorClassName} relative`, children: [
|
|
5333
|
+
/* @__PURE__ */ jsx("div", { className: "w-full h-full bg-slate-100 overflow-auto flex justify-center items-start p-3", children: /* @__PURE__ */ jsx(
|
|
5334
|
+
"div",
|
|
5335
|
+
{
|
|
5336
|
+
className: "h-full bg-white border border-slate-200 shadow-sm overflow-hidden",
|
|
5337
|
+
style: {
|
|
5338
|
+
width: iframeWidth,
|
|
5339
|
+
minWidth: iframeWidth,
|
|
5340
|
+
maxWidth: "100%"
|
|
5341
|
+
},
|
|
5342
|
+
children: /* @__PURE__ */ jsx(
|
|
5343
|
+
"iframe",
|
|
5344
|
+
{
|
|
5345
|
+
ref: iframeRef,
|
|
5346
|
+
src: editorSrc,
|
|
5347
|
+
onLoad: handleIframeLoad,
|
|
5348
|
+
className: "w-full h-full border-0",
|
|
5349
|
+
title: "AI Editor Preview",
|
|
5350
|
+
allow: "same-origin"
|
|
5351
|
+
},
|
|
5352
|
+
iframeKey
|
|
5353
|
+
)
|
|
5354
|
+
}
|
|
5355
|
+
) }),
|
|
5356
|
+
isIframeLoading ? /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-slate-100/95 backdrop-blur-[1px]", children: /* @__PURE__ */ jsxs("div", { className: "w-[560px] max-w-[88vw]", children: [
|
|
5357
|
+
/* @__PURE__ */ jsx("p", { className: "mb-3 text-center text-base font-semibold text-slate-700", children: "Loading changes..." }),
|
|
5358
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 w-full rounded-full border border-slate-300 bg-white/90 p-1 shadow-sm", children: /* @__PURE__ */ jsx("div", { className: "h-full w-full overflow-hidden rounded-full bg-slate-200", children: /* @__PURE__ */ jsx("div", { className: "h-full w-1/3 rounded-full bg-gradient-to-r from-emerald-300 via-sky-500 to-indigo-600 animate-pulse" }) }) })
|
|
5359
|
+
] }) }) : null,
|
|
5360
|
+
chatComponent ?? null
|
|
5361
|
+
] })
|
|
5362
|
+
] });
|
|
5363
|
+
}
|
|
5023
5364
|
|
|
5024
|
-
export { EditorShell, PlatformVisualEditor, PlatformVisualEditorV2, ToastProvider, hydrateVariationsFromStorage, useToast, variationsPersistStorageName };
|
|
5365
|
+
export { EditorShell, PlatformAiEditor, PlatformVisualEditor, PlatformVisualEditorV2, ToastProvider, hydrateVariationsFromStorage, useToast, variationsPersistStorageName };
|
package/dist/vite.cjs
CHANGED
|
@@ -4694,6 +4694,101 @@ if(window.navigator&&window.navigator.serviceWorker&&typeof window.navigator.ser
|
|
|
4694
4694
|
} else {
|
|
4695
4695
|
html = runtimeProxyScript + html;
|
|
4696
4696
|
}
|
|
4697
|
+
const aiBridgeRuntimeScript = `<script>(function(){try{
|
|
4698
|
+
var AI_CHANNEL="ve-ai-editor";
|
|
4699
|
+
var lastJs="";
|
|
4700
|
+
var aiSheet=null;
|
|
4701
|
+
var lastAiContainerIds=[];
|
|
4702
|
+
function extractAiContainerIds(source){
|
|
4703
|
+
try{
|
|
4704
|
+
var re=/ai-generated-container-[a-zA-Z0-9_-]+/g;
|
|
4705
|
+
var found=String(source||"").match(re)||[];
|
|
4706
|
+
var uniq=[];
|
|
4707
|
+
for(var i=0;i<found.length;i++){
|
|
4708
|
+
if(uniq.indexOf(found[i])===-1) uniq.push(found[i]);
|
|
4709
|
+
}
|
|
4710
|
+
return uniq;
|
|
4711
|
+
}catch(_){
|
|
4712
|
+
return [];
|
|
4713
|
+
}
|
|
4714
|
+
}
|
|
4715
|
+
function cleanupRemovedAiContainers(nextIds){
|
|
4716
|
+
try{
|
|
4717
|
+
for(var i=0;i<lastAiContainerIds.length;i++){
|
|
4718
|
+
var prevId=lastAiContainerIds[i];
|
|
4719
|
+
if(nextIds.indexOf(prevId)!==-1) continue;
|
|
4720
|
+
var el=document.getElementById(prevId);
|
|
4721
|
+
if(!el) continue;
|
|
4722
|
+
var marker=(el.getAttribute("data-ai-generated")||"").toLowerCase();
|
|
4723
|
+
if(marker==="true"||prevId.indexOf("ai-generated-container-")===0){
|
|
4724
|
+
if(el.parentNode) el.parentNode.removeChild(el);
|
|
4725
|
+
}
|
|
4726
|
+
}
|
|
4727
|
+
}catch(_){}
|
|
4728
|
+
}
|
|
4729
|
+
function getProxyPayload(){
|
|
4730
|
+
try{
|
|
4731
|
+
var u=new URL(window.location.href);
|
|
4732
|
+
return {
|
|
4733
|
+
url:u.searchParams.get("url")||undefined,
|
|
4734
|
+
password:u.searchParams.get("password")||undefined
|
|
4735
|
+
};
|
|
4736
|
+
}catch(_){
|
|
4737
|
+
return {};
|
|
4738
|
+
}
|
|
4739
|
+
}
|
|
4740
|
+
function applyAiCode(payload){
|
|
4741
|
+
try{
|
|
4742
|
+
var p=payload||{};
|
|
4743
|
+
var css=typeof p.cssCode==="string"?p.cssCode:"";
|
|
4744
|
+
var js=typeof p.jsCode==="string"?p.jsCode:"";
|
|
4745
|
+
var doc=document;
|
|
4746
|
+
if(typeof CSSStyleSheet!=="undefined"&&"adoptedStyleSheets" in doc){
|
|
4747
|
+
var sheets=doc.adoptedStyleSheets||[];
|
|
4748
|
+
if(css){
|
|
4749
|
+
if(!aiSheet) aiSheet=new CSSStyleSheet();
|
|
4750
|
+
aiSheet.replaceSync(css);
|
|
4751
|
+
if(sheets.indexOf(aiSheet)===-1){
|
|
4752
|
+
doc.adoptedStyleSheets=sheets.concat(aiSheet);
|
|
4753
|
+
}
|
|
4754
|
+
}else if(aiSheet&&sheets.indexOf(aiSheet)!==-1){
|
|
4755
|
+
doc.adoptedStyleSheets=sheets.filter(function(s){return s!==aiSheet;});
|
|
4756
|
+
}
|
|
4757
|
+
}
|
|
4758
|
+
if(js!==lastJs){
|
|
4759
|
+
var nextIds=extractAiContainerIds(js);
|
|
4760
|
+
cleanupRemovedAiContainers(nextIds);
|
|
4761
|
+
if(js) (new Function(js)).call(window);
|
|
4762
|
+
lastJs=js;
|
|
4763
|
+
lastAiContainerIds=nextIds;
|
|
4764
|
+
}
|
|
4765
|
+
try{
|
|
4766
|
+
doc.documentElement.setAttribute("data-ve-ai-applied","1");
|
|
4767
|
+
window.parent&&window.parent.postMessage({
|
|
4768
|
+
channel:AI_CHANNEL,
|
|
4769
|
+
type:"ai-code-applied",
|
|
4770
|
+
payload:{cssLen:css.length,jsLen:js.length}
|
|
4771
|
+
},"*");
|
|
4772
|
+
}catch(_){}
|
|
4773
|
+
}catch(_){}
|
|
4774
|
+
}
|
|
4775
|
+
window.addEventListener("message",function(ev){
|
|
4776
|
+
try{
|
|
4777
|
+
var d=ev&&ev.data;
|
|
4778
|
+
if(!d||d.channel!==AI_CHANNEL||d.type!=="apply-ai-code") return;
|
|
4779
|
+
applyAiCode(d.payload||{});
|
|
4780
|
+
}catch(_){}
|
|
4781
|
+
});
|
|
4782
|
+
try{
|
|
4783
|
+
if(window.parent){
|
|
4784
|
+
window.parent.postMessage({channel:AI_CHANNEL,type:"ai-code-ready"},"*");
|
|
4785
|
+
window.parent.postMessage({channel:AI_CHANNEL,type:"ai-url-changed",payload:getProxyPayload()},"*");
|
|
4786
|
+
}
|
|
4787
|
+
}catch(_){}
|
|
4788
|
+
}catch(_){}})();</script>`;
|
|
4789
|
+
html = html.includes("</head>") ? html.replace("</head>", `${aiBridgeRuntimeScript}
|
|
4790
|
+
</head>`) : `${aiBridgeRuntimeScript}
|
|
4791
|
+
${html}`;
|
|
4697
4792
|
const bridgeScript = `<script src="/bridge.js"></script>`;
|
|
4698
4793
|
html = html.includes("</body>") ? html.replace("</body>", `${bridgeScript}
|
|
4699
4794
|
</body>`) : html + bridgeScript;
|
package/dist/vite.js
CHANGED
|
@@ -4686,6 +4686,101 @@ if(window.navigator&&window.navigator.serviceWorker&&typeof window.navigator.ser
|
|
|
4686
4686
|
} else {
|
|
4687
4687
|
html = runtimeProxyScript + html;
|
|
4688
4688
|
}
|
|
4689
|
+
const aiBridgeRuntimeScript = `<script>(function(){try{
|
|
4690
|
+
var AI_CHANNEL="ve-ai-editor";
|
|
4691
|
+
var lastJs="";
|
|
4692
|
+
var aiSheet=null;
|
|
4693
|
+
var lastAiContainerIds=[];
|
|
4694
|
+
function extractAiContainerIds(source){
|
|
4695
|
+
try{
|
|
4696
|
+
var re=/ai-generated-container-[a-zA-Z0-9_-]+/g;
|
|
4697
|
+
var found=String(source||"").match(re)||[];
|
|
4698
|
+
var uniq=[];
|
|
4699
|
+
for(var i=0;i<found.length;i++){
|
|
4700
|
+
if(uniq.indexOf(found[i])===-1) uniq.push(found[i]);
|
|
4701
|
+
}
|
|
4702
|
+
return uniq;
|
|
4703
|
+
}catch(_){
|
|
4704
|
+
return [];
|
|
4705
|
+
}
|
|
4706
|
+
}
|
|
4707
|
+
function cleanupRemovedAiContainers(nextIds){
|
|
4708
|
+
try{
|
|
4709
|
+
for(var i=0;i<lastAiContainerIds.length;i++){
|
|
4710
|
+
var prevId=lastAiContainerIds[i];
|
|
4711
|
+
if(nextIds.indexOf(prevId)!==-1) continue;
|
|
4712
|
+
var el=document.getElementById(prevId);
|
|
4713
|
+
if(!el) continue;
|
|
4714
|
+
var marker=(el.getAttribute("data-ai-generated")||"").toLowerCase();
|
|
4715
|
+
if(marker==="true"||prevId.indexOf("ai-generated-container-")===0){
|
|
4716
|
+
if(el.parentNode) el.parentNode.removeChild(el);
|
|
4717
|
+
}
|
|
4718
|
+
}
|
|
4719
|
+
}catch(_){}
|
|
4720
|
+
}
|
|
4721
|
+
function getProxyPayload(){
|
|
4722
|
+
try{
|
|
4723
|
+
var u=new URL(window.location.href);
|
|
4724
|
+
return {
|
|
4725
|
+
url:u.searchParams.get("url")||undefined,
|
|
4726
|
+
password:u.searchParams.get("password")||undefined
|
|
4727
|
+
};
|
|
4728
|
+
}catch(_){
|
|
4729
|
+
return {};
|
|
4730
|
+
}
|
|
4731
|
+
}
|
|
4732
|
+
function applyAiCode(payload){
|
|
4733
|
+
try{
|
|
4734
|
+
var p=payload||{};
|
|
4735
|
+
var css=typeof p.cssCode==="string"?p.cssCode:"";
|
|
4736
|
+
var js=typeof p.jsCode==="string"?p.jsCode:"";
|
|
4737
|
+
var doc=document;
|
|
4738
|
+
if(typeof CSSStyleSheet!=="undefined"&&"adoptedStyleSheets" in doc){
|
|
4739
|
+
var sheets=doc.adoptedStyleSheets||[];
|
|
4740
|
+
if(css){
|
|
4741
|
+
if(!aiSheet) aiSheet=new CSSStyleSheet();
|
|
4742
|
+
aiSheet.replaceSync(css);
|
|
4743
|
+
if(sheets.indexOf(aiSheet)===-1){
|
|
4744
|
+
doc.adoptedStyleSheets=sheets.concat(aiSheet);
|
|
4745
|
+
}
|
|
4746
|
+
}else if(aiSheet&&sheets.indexOf(aiSheet)!==-1){
|
|
4747
|
+
doc.adoptedStyleSheets=sheets.filter(function(s){return s!==aiSheet;});
|
|
4748
|
+
}
|
|
4749
|
+
}
|
|
4750
|
+
if(js!==lastJs){
|
|
4751
|
+
var nextIds=extractAiContainerIds(js);
|
|
4752
|
+
cleanupRemovedAiContainers(nextIds);
|
|
4753
|
+
if(js) (new Function(js)).call(window);
|
|
4754
|
+
lastJs=js;
|
|
4755
|
+
lastAiContainerIds=nextIds;
|
|
4756
|
+
}
|
|
4757
|
+
try{
|
|
4758
|
+
doc.documentElement.setAttribute("data-ve-ai-applied","1");
|
|
4759
|
+
window.parent&&window.parent.postMessage({
|
|
4760
|
+
channel:AI_CHANNEL,
|
|
4761
|
+
type:"ai-code-applied",
|
|
4762
|
+
payload:{cssLen:css.length,jsLen:js.length}
|
|
4763
|
+
},"*");
|
|
4764
|
+
}catch(_){}
|
|
4765
|
+
}catch(_){}
|
|
4766
|
+
}
|
|
4767
|
+
window.addEventListener("message",function(ev){
|
|
4768
|
+
try{
|
|
4769
|
+
var d=ev&&ev.data;
|
|
4770
|
+
if(!d||d.channel!==AI_CHANNEL||d.type!=="apply-ai-code") return;
|
|
4771
|
+
applyAiCode(d.payload||{});
|
|
4772
|
+
}catch(_){}
|
|
4773
|
+
});
|
|
4774
|
+
try{
|
|
4775
|
+
if(window.parent){
|
|
4776
|
+
window.parent.postMessage({channel:AI_CHANNEL,type:"ai-code-ready"},"*");
|
|
4777
|
+
window.parent.postMessage({channel:AI_CHANNEL,type:"ai-url-changed",payload:getProxyPayload()},"*");
|
|
4778
|
+
}
|
|
4779
|
+
}catch(_){}
|
|
4780
|
+
}catch(_){}})();</script>`;
|
|
4781
|
+
html = html.includes("</head>") ? html.replace("</head>", `${aiBridgeRuntimeScript}
|
|
4782
|
+
</head>`) : `${aiBridgeRuntimeScript}
|
|
4783
|
+
${html}`;
|
|
4689
4784
|
const bridgeScript = `<script src="/bridge.js"></script>`;
|
|
4690
4785
|
html = html.includes("</body>") ? html.replace("</body>", `${bridgeScript}
|
|
4691
4786
|
</body>`) : html + bridgeScript;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@accelerated-agency/visual-editor",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Conversion visual editor as a reusable React package",
|
|
6
6
|
"type": "module",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"react-dom": ">=18"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
+
"bootstrap-icons": "^1.13.1",
|
|
35
36
|
"lucide-react": "^0.562.0",
|
|
36
37
|
"react-colorful": "^5.6.1",
|
|
37
38
|
"zustand": "^5.0.7"
|