@preprio/toolkit 0.2.0-beta.2 → 0.2.0-beta.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/README.md +93 -1
- package/dist/astro/index.cjs +1 -1
- package/dist/astro/index.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/nextjs/components.cjs +16 -8
- package/dist/nextjs/components.d.cts +15 -8
- package/dist/nextjs/components.d.ts +15 -8
- package/dist/nextjs/components.js +15 -7
- package/dist/nextjs/index.cjs +1 -1
- package/dist/nextjs/index.js +1 -1
- package/dist/nuxt/index.cjs +1 -1
- package/dist/nuxt/index.js +1 -1
- package/dist/react/components.cjs +2237 -0
- package/dist/react/components.d.cts +167 -0
- package/dist/react/components.d.ts +167 -0
- package/dist/react/components.js +2212 -0
- package/dist/react/index.cjs +32 -0
- package/dist/react/index.d.cts +1 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +9 -0
- package/dist/sveltekit/index.cjs +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/package.json +13 -2
|
@@ -0,0 +1,2237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/react/components.ts
|
|
22
|
+
var components_exports = {};
|
|
23
|
+
__export(components_exports, {
|
|
24
|
+
PreprPreview: () => PreprPreview,
|
|
25
|
+
PreprTrackingPixel: () => PreprTrackingPixel
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(components_exports);
|
|
28
|
+
var import_react = require("react");
|
|
29
|
+
|
|
30
|
+
// src/core/constants.ts
|
|
31
|
+
var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
|
|
32
|
+
var COOKIE_TOOLBAR_OPEN = "Prepr-Toolbar-Open";
|
|
33
|
+
var COOKIE_SEGMENT = "Prepr-Segments";
|
|
34
|
+
var COOKIE_VARIANT = "Prepr-ABtesting";
|
|
35
|
+
var PARAM_SEGMENT = "prepr_preview_segment";
|
|
36
|
+
var PARAM_VARIANT = "prepr_preview_ab";
|
|
37
|
+
var PARAM_HIDE_BAR = "prepr_hide_bar";
|
|
38
|
+
var ONE_YEAR_SECONDS = 60 * 60 * 24 * 365;
|
|
39
|
+
|
|
40
|
+
// src/core/cookies.ts
|
|
41
|
+
function getCookie(name) {
|
|
42
|
+
if (typeof document === "undefined") return null;
|
|
43
|
+
const match = document.cookie.split("; ").find((row) => row.startsWith(`${name}=`));
|
|
44
|
+
if (!match) return null;
|
|
45
|
+
const value = match.slice(name.length + 1);
|
|
46
|
+
return decodeURIComponent(value);
|
|
47
|
+
}
|
|
48
|
+
function setCookie(name, value, options = {}) {
|
|
49
|
+
if (typeof document === "undefined") return;
|
|
50
|
+
const { maxAge, path = "/", sameSite, secure } = options;
|
|
51
|
+
let cookie = `${name}=${encodeURIComponent(value)};path=${path}`;
|
|
52
|
+
if (typeof maxAge === "number") {
|
|
53
|
+
cookie += `;max-age=${maxAge}`;
|
|
54
|
+
}
|
|
55
|
+
if (sameSite) {
|
|
56
|
+
cookie += `;samesite=${sameSite}`;
|
|
57
|
+
}
|
|
58
|
+
if (secure) {
|
|
59
|
+
cookie += ";secure";
|
|
60
|
+
}
|
|
61
|
+
document.cookie = cookie;
|
|
62
|
+
}
|
|
63
|
+
function removeCookie(name, path = "/", options = {}) {
|
|
64
|
+
if (typeof document === "undefined") return;
|
|
65
|
+
const { sameSite, secure } = options;
|
|
66
|
+
let cookie = `${name}=;path=${path};expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
67
|
+
if (sameSite) {
|
|
68
|
+
cookie += `;samesite=${sameSite}`;
|
|
69
|
+
}
|
|
70
|
+
if (secure) {
|
|
71
|
+
cookie += ";secure";
|
|
72
|
+
}
|
|
73
|
+
document.cookie = cookie;
|
|
74
|
+
}
|
|
75
|
+
function crossSiteCookieOptions() {
|
|
76
|
+
if (typeof window === "undefined" || !window.isSecureContext) return {};
|
|
77
|
+
return { sameSite: "None", secure: true };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/core/features.ts
|
|
81
|
+
function isEnabled(config) {
|
|
82
|
+
if (typeof config === "boolean") return config;
|
|
83
|
+
return config?.enabled ?? true;
|
|
84
|
+
}
|
|
85
|
+
function resolveFeatures(features) {
|
|
86
|
+
return {
|
|
87
|
+
segments: isEnabled(features?.segments),
|
|
88
|
+
abTesting: isEnabled(features?.abTesting),
|
|
89
|
+
editMode: isEnabled(features?.editMode)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
var ALL_FEATURES_ENABLED = Object.freeze({
|
|
93
|
+
segments: true,
|
|
94
|
+
abTesting: true,
|
|
95
|
+
editMode: true
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// src/core/locales/en.json
|
|
99
|
+
var en_default = {
|
|
100
|
+
common: {
|
|
101
|
+
viewingAs: "Viewing as:",
|
|
102
|
+
user: "User",
|
|
103
|
+
off: "Off",
|
|
104
|
+
on: "On",
|
|
105
|
+
reset: "Reset",
|
|
106
|
+
toolbar: "Toolbar"
|
|
107
|
+
},
|
|
108
|
+
adaptiveContent: {
|
|
109
|
+
adaptiveContent: "Adaptive content",
|
|
110
|
+
enablePreview: "Preview mode",
|
|
111
|
+
segment: "Segment",
|
|
112
|
+
ABVariant: "A/B variant",
|
|
113
|
+
chooseSegment: "Choose segment",
|
|
114
|
+
searchSegments: "Search segments",
|
|
115
|
+
none: "No segments",
|
|
116
|
+
allOtherUsers: "All other users",
|
|
117
|
+
offDescription: "View the site as a real user (use cookies)",
|
|
118
|
+
onDescription: "Use the toolbar to simulate segments and A/B variants"
|
|
119
|
+
},
|
|
120
|
+
editingTools: {
|
|
121
|
+
editingTools: "Editing tools",
|
|
122
|
+
editMode: "Edit mode",
|
|
123
|
+
ariaCloseEditMode: "Close edit mode"
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// src/core/locales/nl.json
|
|
128
|
+
var nl_default = {
|
|
129
|
+
common: {
|
|
130
|
+
viewingAs: "Bekijken als:",
|
|
131
|
+
user: "Gebruiker",
|
|
132
|
+
off: "Uit",
|
|
133
|
+
on: "Aan",
|
|
134
|
+
reset: "Resetten",
|
|
135
|
+
toolbar: "Toolbar"
|
|
136
|
+
},
|
|
137
|
+
adaptiveContent: {
|
|
138
|
+
adaptiveContent: "Adaptieve inhoud",
|
|
139
|
+
enablePreview: "Preview modus",
|
|
140
|
+
segment: "Segment",
|
|
141
|
+
ABVariant: "A/B-variant",
|
|
142
|
+
chooseSegment: "Kies segment",
|
|
143
|
+
searchSegments: "Zoek segmenten",
|
|
144
|
+
none: "Geen segmenten",
|
|
145
|
+
allOtherUsers: "Alle andere gebruikers",
|
|
146
|
+
offDescription: "Bekijk de site als een echte gebruiker (gebruik cookies)",
|
|
147
|
+
onDescription: "Gebruik de werkbalk om segmenten en A/B-varianten te simuleren"
|
|
148
|
+
},
|
|
149
|
+
editingTools: {
|
|
150
|
+
editingTools: "Editing Tools",
|
|
151
|
+
editMode: "Edit mode",
|
|
152
|
+
ariaCloseEditMode: "Edit mode sluiten"
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// src/core/i18n.ts
|
|
157
|
+
var dictionaries = {
|
|
158
|
+
en: en_default,
|
|
159
|
+
nl: nl_default
|
|
160
|
+
};
|
|
161
|
+
var LOCALES = Object.keys(dictionaries);
|
|
162
|
+
function isLocale(value) {
|
|
163
|
+
return typeof value === "string" && value in dictionaries;
|
|
164
|
+
}
|
|
165
|
+
function getDict(locale) {
|
|
166
|
+
return isLocale(locale) ? dictionaries[locale] : dictionaries.en;
|
|
167
|
+
}
|
|
168
|
+
function getFromPath(obj, path) {
|
|
169
|
+
return path.split(".").reduce(
|
|
170
|
+
(acc, key) => acc && typeof acc === "object" ? acc[key] : void 0,
|
|
171
|
+
obj
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
function format(message, vars) {
|
|
175
|
+
if (!vars) return message;
|
|
176
|
+
return Object.keys(vars).reduce(
|
|
177
|
+
(acc, k2) => acc.replace(new RegExp(`\\{${k2}\\}`, "g"), String(vars[k2])),
|
|
178
|
+
message
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
function t(key, locale, vars) {
|
|
182
|
+
const dict = getDict(locale);
|
|
183
|
+
const msg = getFromPath(dict, key);
|
|
184
|
+
if (typeof msg === "string") return format(msg, vars);
|
|
185
|
+
return key;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/core/utils.ts
|
|
189
|
+
var trustedParentOrigin = null;
|
|
190
|
+
function setTrustedParentOrigin(origin) {
|
|
191
|
+
trustedParentOrigin = origin;
|
|
192
|
+
}
|
|
193
|
+
function sendPreprEvent(event, data, options) {
|
|
194
|
+
if (typeof window !== "undefined") {
|
|
195
|
+
const message = {
|
|
196
|
+
name: "prepr_preview_bar",
|
|
197
|
+
event,
|
|
198
|
+
...data
|
|
199
|
+
};
|
|
200
|
+
window.dispatchEvent(
|
|
201
|
+
new CustomEvent("prepr_preview_bar", { detail: message })
|
|
202
|
+
);
|
|
203
|
+
if (window.parent && window.parent !== window) {
|
|
204
|
+
if (trustedParentOrigin) {
|
|
205
|
+
window.parent.postMessage(message, trustedParentOrigin);
|
|
206
|
+
} else if (options?.allowUntrustedTarget) {
|
|
207
|
+
window.parent.postMessage(message, "*");
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
var DebugLogger = class {
|
|
213
|
+
constructor(options) {
|
|
214
|
+
this.options = {
|
|
215
|
+
prefix: "[Prepr]",
|
|
216
|
+
...options
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
// A local `enabled` wins; otherwise defer to the global logger so scoped
|
|
220
|
+
// loggers created before initDebugLogger() still pick up the setting.
|
|
221
|
+
isEnabled() {
|
|
222
|
+
if (this.options.enabled !== void 0) {
|
|
223
|
+
return this.options.enabled;
|
|
224
|
+
}
|
|
225
|
+
return globalDebugLogger?.options?.enabled ?? false;
|
|
226
|
+
}
|
|
227
|
+
log(message, ...args) {
|
|
228
|
+
if (!this.isEnabled()) return;
|
|
229
|
+
const prefix = this.options.prefix;
|
|
230
|
+
console.log(`${prefix} ${message}`, ...args);
|
|
231
|
+
}
|
|
232
|
+
warn(message, ...args) {
|
|
233
|
+
if (!this.isEnabled()) return;
|
|
234
|
+
const prefix = this.options.prefix;
|
|
235
|
+
console.warn(`${prefix} ${message}`, ...args);
|
|
236
|
+
}
|
|
237
|
+
error(message, ...args) {
|
|
238
|
+
if (!this.isEnabled()) return;
|
|
239
|
+
const prefix = this.options.prefix;
|
|
240
|
+
console.error(`${prefix} ${message}`, ...args);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
var globalDebugLogger = null;
|
|
244
|
+
function initDebugLogger(enabled = false) {
|
|
245
|
+
globalDebugLogger = new DebugLogger({ enabled });
|
|
246
|
+
}
|
|
247
|
+
function createScopedLogger(scopeName) {
|
|
248
|
+
return new DebugLogger({
|
|
249
|
+
prefix: `[Prepr][${scopeName}]`
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
function throttle(func, delay) {
|
|
253
|
+
let timeoutId = null;
|
|
254
|
+
let lastExecTime = 0;
|
|
255
|
+
const throttledFunc = ((...args) => {
|
|
256
|
+
const currentTime = Date.now();
|
|
257
|
+
const timeSinceLastExec = currentTime - lastExecTime;
|
|
258
|
+
if (timeSinceLastExec >= delay) {
|
|
259
|
+
func(...args);
|
|
260
|
+
lastExecTime = currentTime;
|
|
261
|
+
} else {
|
|
262
|
+
if (timeoutId) {
|
|
263
|
+
clearTimeout(timeoutId);
|
|
264
|
+
}
|
|
265
|
+
timeoutId = setTimeout(() => {
|
|
266
|
+
func(...args);
|
|
267
|
+
lastExecTime = Date.now();
|
|
268
|
+
timeoutId = null;
|
|
269
|
+
}, delay - timeSinceLastExec);
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
throttledFunc.cancel = () => {
|
|
273
|
+
if (timeoutId) {
|
|
274
|
+
clearTimeout(timeoutId);
|
|
275
|
+
timeoutId = null;
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
return throttledFunc;
|
|
279
|
+
}
|
|
280
|
+
function createElementCache(query, ttl = 1e3) {
|
|
281
|
+
let cache = null;
|
|
282
|
+
let lastCacheTime = 0;
|
|
283
|
+
return () => {
|
|
284
|
+
const now = Date.now();
|
|
285
|
+
if (!cache || now - lastCacheTime > ttl) {
|
|
286
|
+
cache = document.querySelectorAll(query);
|
|
287
|
+
lastCacheTime = now;
|
|
288
|
+
}
|
|
289
|
+
return cache;
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/core/iframe-bridge.ts
|
|
294
|
+
var EDITOR_BASE_DOMAIN = "prepr.io";
|
|
295
|
+
function isAllowedEditorOrigin(origin, allowed) {
|
|
296
|
+
if (allowed) return allowed.includes(origin);
|
|
297
|
+
let url;
|
|
298
|
+
try {
|
|
299
|
+
url = new URL(origin);
|
|
300
|
+
} catch {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
if (url.protocol !== "https:" || url.port !== "") return false;
|
|
304
|
+
const suffix = `.${EDITOR_BASE_DOMAIN}`;
|
|
305
|
+
if (!url.hostname.endsWith(suffix)) return false;
|
|
306
|
+
const label = url.hostname.slice(0, -suffix.length);
|
|
307
|
+
return label.length > 0 && !label.includes(".");
|
|
308
|
+
}
|
|
309
|
+
function createIframeBridge(store, options = {}) {
|
|
310
|
+
const allowedOrigins = options.allowedEditorOrigins;
|
|
311
|
+
let parentOrigin = null;
|
|
312
|
+
const onKeyDown = (event) => {
|
|
313
|
+
const key = event.key.toLowerCase();
|
|
314
|
+
const blocked = (event.ctrlKey || event.metaKey) && ["s", "p", "l"].includes(key);
|
|
315
|
+
if (blocked) event.preventDefault();
|
|
316
|
+
};
|
|
317
|
+
const onMessage = (evt) => {
|
|
318
|
+
const data = evt?.data;
|
|
319
|
+
if (data?.event === "prepr:initVE" && !parentOrigin) {
|
|
320
|
+
if (!isAllowedEditorOrigin(evt.origin, allowedOrigins)) return;
|
|
321
|
+
parentOrigin = evt.origin;
|
|
322
|
+
setTrustedParentOrigin(parentOrigin);
|
|
323
|
+
if (data.scrollPosition != null) {
|
|
324
|
+
const top = data.scrollPosition;
|
|
325
|
+
setTimeout(() => window.scrollTo(0, top), 1);
|
|
326
|
+
}
|
|
327
|
+
store?.set({ previewMode: true, editMode: data.editMode ?? true });
|
|
328
|
+
}
|
|
329
|
+
if (!parentOrigin || evt.origin !== parentOrigin) return;
|
|
330
|
+
if (data?.event === "prepr:getScrollPosition") {
|
|
331
|
+
const currentScrollY = window.scrollY || document.documentElement.scrollTop;
|
|
332
|
+
sendPreprEvent("getScrollPosition", { value: currentScrollY });
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
return {
|
|
336
|
+
start() {
|
|
337
|
+
sendPreprEvent("loaded", void 0, { allowUntrustedTarget: true });
|
|
338
|
+
window.addEventListener("keydown", onKeyDown);
|
|
339
|
+
window.addEventListener("message", onMessage);
|
|
340
|
+
},
|
|
341
|
+
stop() {
|
|
342
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
343
|
+
window.removeEventListener("message", onMessage);
|
|
344
|
+
parentOrigin = null;
|
|
345
|
+
setTrustedParentOrigin(null);
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// src/core/stega/auto-clean.ts
|
|
351
|
+
var import_stega2 = require("@vercel/stega");
|
|
352
|
+
|
|
353
|
+
// src/core/stega/clean.ts
|
|
354
|
+
var import_stega = require("@vercel/stega");
|
|
355
|
+
var debug = createScopedLogger("stega:clean");
|
|
356
|
+
function decodeStega(str) {
|
|
357
|
+
if (!str) return null;
|
|
358
|
+
try {
|
|
359
|
+
const decoded = (0, import_stega.vercelStegaDecode)(str);
|
|
360
|
+
if (decoded?.href) {
|
|
361
|
+
return decoded;
|
|
362
|
+
}
|
|
363
|
+
} catch (error) {
|
|
364
|
+
debug.log("error decoding stega data", error);
|
|
365
|
+
const match = str.match(/{"origin.*?}/);
|
|
366
|
+
if (match) {
|
|
367
|
+
try {
|
|
368
|
+
const decodedMatch = (0, import_stega.vercelStegaDecode)(
|
|
369
|
+
match[0]
|
|
370
|
+
);
|
|
371
|
+
if (decodedMatch?.href) {
|
|
372
|
+
return decodedMatch;
|
|
373
|
+
}
|
|
374
|
+
} catch (innerError) {
|
|
375
|
+
debug.log("error decoding stega regex match", innerError);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// src/core/stega/dom.ts
|
|
383
|
+
var IGNORED_ANCESTORS = "script, style, noscript";
|
|
384
|
+
function isIgnoredTextNode(node) {
|
|
385
|
+
if (node.parentElement?.closest(IGNORED_ANCESTORS)) return true;
|
|
386
|
+
return !node.textContent?.trim();
|
|
387
|
+
}
|
|
388
|
+
function walkTextNodes(root, visit) {
|
|
389
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
|
|
390
|
+
acceptNode: (node2) => isIgnoredTextNode(node2) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT
|
|
391
|
+
});
|
|
392
|
+
let node;
|
|
393
|
+
while (node = walker.nextNode()) {
|
|
394
|
+
visit(node);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
function tagEncodedElement(element, decoded) {
|
|
398
|
+
element.setAttribute("data-prepr-encoded", "");
|
|
399
|
+
element.setAttribute("data-prepr-href", decoded.href);
|
|
400
|
+
element.setAttribute("data-prepr-origin", decoded.origin);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// src/core/stega/auto-clean.ts
|
|
404
|
+
var debug2 = createScopedLogger("stega:auto-clean");
|
|
405
|
+
function createStegaAutoClean() {
|
|
406
|
+
let observer = null;
|
|
407
|
+
let processing = false;
|
|
408
|
+
let cleaned = /* @__PURE__ */ new WeakMap();
|
|
409
|
+
let debounceTimeout = null;
|
|
410
|
+
function cleanTextNode(textNode) {
|
|
411
|
+
if (isIgnoredTextNode(textNode)) return false;
|
|
412
|
+
const textContent = textNode.textContent;
|
|
413
|
+
const info = cleaned.get(textNode);
|
|
414
|
+
if (info && textContent === info.cleaned) return false;
|
|
415
|
+
try {
|
|
416
|
+
const { cleaned: stripped, encoded } = (0, import_stega2.vercelStegaSplit)(textContent);
|
|
417
|
+
if (!encoded || stripped === textContent) return false;
|
|
418
|
+
const decoded = decodeStega(textContent);
|
|
419
|
+
if (!decoded?.href) return false;
|
|
420
|
+
cleaned.set(textNode, { original: textContent, cleaned: stripped });
|
|
421
|
+
textNode.textContent = stripped;
|
|
422
|
+
let target = textNode.parentElement;
|
|
423
|
+
const editTargetParent = textNode.parentElement?.closest(
|
|
424
|
+
"[data-prepr-edit-target]"
|
|
425
|
+
);
|
|
426
|
+
if (editTargetParent) target = editTargetParent;
|
|
427
|
+
if (target) {
|
|
428
|
+
tagEncodedElement(target, decoded);
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
431
|
+
} catch (error) {
|
|
432
|
+
debug2.log("error cleaning text node", error);
|
|
433
|
+
}
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
function scanAndClean() {
|
|
437
|
+
processing = true;
|
|
438
|
+
walkTextNodes(document.body, cleanTextNode);
|
|
439
|
+
processing = false;
|
|
440
|
+
}
|
|
441
|
+
function collectAffected(mutations) {
|
|
442
|
+
const affected = /* @__PURE__ */ new Set();
|
|
443
|
+
mutations.forEach((mutation) => {
|
|
444
|
+
if (mutation.type === "childList") {
|
|
445
|
+
mutation.addedNodes.forEach((node) => {
|
|
446
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
447
|
+
affected.add(node);
|
|
448
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
449
|
+
walkTextNodes(node, (textNode) => affected.add(textNode));
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
if (mutation.type === "characterData" && mutation.target.nodeType === Node.TEXT_NODE) {
|
|
454
|
+
const textNode = mutation.target;
|
|
455
|
+
const info = cleaned.get(textNode);
|
|
456
|
+
if (info && textNode.textContent === info.original) {
|
|
457
|
+
affected.add(textNode);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
return affected;
|
|
462
|
+
}
|
|
463
|
+
function handleMutations(mutations) {
|
|
464
|
+
if (processing) return;
|
|
465
|
+
const affected = collectAffected(mutations);
|
|
466
|
+
if (affected.size === 0) return;
|
|
467
|
+
if (debounceTimeout) clearTimeout(debounceTimeout);
|
|
468
|
+
debounceTimeout = setTimeout(() => {
|
|
469
|
+
processing = true;
|
|
470
|
+
affected.forEach((textNode) => cleanTextNode(textNode));
|
|
471
|
+
processing = false;
|
|
472
|
+
}, 50);
|
|
473
|
+
}
|
|
474
|
+
function setupObserver() {
|
|
475
|
+
observer = new MutationObserver(handleMutations);
|
|
476
|
+
observer.observe(document.body, {
|
|
477
|
+
childList: true,
|
|
478
|
+
subtree: true,
|
|
479
|
+
characterData: true
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
function start() {
|
|
483
|
+
if (observer || typeof window === "undefined") return;
|
|
484
|
+
const run = () => {
|
|
485
|
+
scanAndClean();
|
|
486
|
+
setupObserver();
|
|
487
|
+
};
|
|
488
|
+
if ("requestIdleCallback" in window) {
|
|
489
|
+
window.requestIdleCallback(run);
|
|
490
|
+
} else {
|
|
491
|
+
setTimeout(run, 0);
|
|
492
|
+
}
|
|
493
|
+
debug2.log("stega auto-clean started");
|
|
494
|
+
}
|
|
495
|
+
function stop() {
|
|
496
|
+
if (debounceTimeout) {
|
|
497
|
+
clearTimeout(debounceTimeout);
|
|
498
|
+
debounceTimeout = null;
|
|
499
|
+
}
|
|
500
|
+
if (observer) {
|
|
501
|
+
observer.disconnect();
|
|
502
|
+
observer = null;
|
|
503
|
+
}
|
|
504
|
+
cleaned = /* @__PURE__ */ new WeakMap();
|
|
505
|
+
debug2.log("stega auto-clean stopped");
|
|
506
|
+
}
|
|
507
|
+
return { start, stop };
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// src/core/stega/elements.ts
|
|
511
|
+
var debug3 = createScopedLogger("stega:elements");
|
|
512
|
+
var StegaElements = class {
|
|
513
|
+
constructor(decode = decodeStega) {
|
|
514
|
+
this.observer = null;
|
|
515
|
+
this.decode = decode;
|
|
516
|
+
}
|
|
517
|
+
getElements() {
|
|
518
|
+
if (!this.elements) {
|
|
519
|
+
this.elements = document.querySelectorAll("[data-prepr-encoded]");
|
|
520
|
+
}
|
|
521
|
+
return this.elements;
|
|
522
|
+
}
|
|
523
|
+
/** Returns true only when this tags an element that wasn't tagged before. */
|
|
524
|
+
tagFromTextNode(node) {
|
|
525
|
+
const decoded = this.decode(node.textContent);
|
|
526
|
+
if (!decoded?.href) return false;
|
|
527
|
+
const target = node.parentElement;
|
|
528
|
+
if (!target || target.hasAttribute("data-prepr-encoded")) return false;
|
|
529
|
+
tagEncodedElement(target, decoded);
|
|
530
|
+
return true;
|
|
531
|
+
}
|
|
532
|
+
scanNode(node) {
|
|
533
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
534
|
+
if (isIgnoredTextNode(node)) return;
|
|
535
|
+
this.tagFromTextNode(node);
|
|
536
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
537
|
+
node.childNodes.forEach((child) => this.scanNode(child));
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* `skipIfTagged` reuses whatever the auto-clean pass already tagged instead
|
|
542
|
+
* of re-walking the body.
|
|
543
|
+
*/
|
|
544
|
+
scanDocument(skipIfTagged = false) {
|
|
545
|
+
if (skipIfTagged) {
|
|
546
|
+
const existing = document.querySelectorAll("[data-prepr-encoded]");
|
|
547
|
+
if (existing.length > 0) {
|
|
548
|
+
this.elements = existing;
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
let encodedCount = 0;
|
|
553
|
+
walkTextNodes(document.body, (textNode) => {
|
|
554
|
+
if (this.tagFromTextNode(textNode)) encodedCount++;
|
|
555
|
+
});
|
|
556
|
+
debug3.log("document scan complete, encoded", encodedCount, "elements");
|
|
557
|
+
this.elements = document.querySelectorAll("[data-prepr-encoded]");
|
|
558
|
+
}
|
|
559
|
+
/** `onUpdate` fires after each debounced batch, for refreshing derived state. */
|
|
560
|
+
setupMutationObserver(onUpdate) {
|
|
561
|
+
if (this.observer) {
|
|
562
|
+
this.observer.disconnect();
|
|
563
|
+
}
|
|
564
|
+
let pending = [];
|
|
565
|
+
let debounceTimeout = null;
|
|
566
|
+
const processMutations = () => {
|
|
567
|
+
const addedNodes = /* @__PURE__ */ new Set();
|
|
568
|
+
pending.forEach((mutation) => {
|
|
569
|
+
mutation.addedNodes.forEach((node) => addedNodes.add(node));
|
|
570
|
+
if (mutation.type === "characterData") {
|
|
571
|
+
addedNodes.add(mutation.target);
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
addedNodes.forEach((node) => this.scanNode(node));
|
|
575
|
+
pending = [];
|
|
576
|
+
this.elements = document.querySelectorAll("[data-prepr-encoded]");
|
|
577
|
+
onUpdate?.();
|
|
578
|
+
};
|
|
579
|
+
this.observer = new MutationObserver((mutations) => {
|
|
580
|
+
pending.push(...mutations);
|
|
581
|
+
if (debounceTimeout) clearTimeout(debounceTimeout);
|
|
582
|
+
debounceTimeout = setTimeout(processMutations, 100);
|
|
583
|
+
});
|
|
584
|
+
this.observer.observe(document.body, {
|
|
585
|
+
childList: true,
|
|
586
|
+
subtree: true,
|
|
587
|
+
characterData: true
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
/** Drops the active class but keeps the data attributes, unlike cleanup(). */
|
|
591
|
+
cleanupVisuals() {
|
|
592
|
+
document.querySelectorAll(".prepr-overlay-active").forEach((element) => element.classList.remove("prepr-overlay-active"));
|
|
593
|
+
}
|
|
594
|
+
cleanup() {
|
|
595
|
+
if (this.observer) {
|
|
596
|
+
this.observer.disconnect();
|
|
597
|
+
this.observer = null;
|
|
598
|
+
}
|
|
599
|
+
document.querySelectorAll("[data-prepr-encoded]").forEach((element) => {
|
|
600
|
+
element.removeAttribute("data-prepr-encoded");
|
|
601
|
+
element.removeAttribute("data-prepr-href");
|
|
602
|
+
element.removeAttribute("data-prepr-origin");
|
|
603
|
+
element.classList.remove("prepr-overlay-active");
|
|
604
|
+
});
|
|
605
|
+
this.elements = void 0;
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
// src/core/stega/overlay.ts
|
|
610
|
+
var debug4 = createScopedLogger("stega:overlay");
|
|
611
|
+
var StegaOverlay = class {
|
|
612
|
+
constructor(onEdit) {
|
|
613
|
+
this.overlay = null;
|
|
614
|
+
this.tooltip = null;
|
|
615
|
+
this.hideTimeout = null;
|
|
616
|
+
this.currentElement = null;
|
|
617
|
+
this.onEdit = onEdit;
|
|
618
|
+
}
|
|
619
|
+
create() {
|
|
620
|
+
const overlay = document.createElement("div");
|
|
621
|
+
overlay.className = "prepr-overlay";
|
|
622
|
+
overlay.style.display = "none";
|
|
623
|
+
const tooltip = document.createElement("div");
|
|
624
|
+
tooltip.className = "prepr-tooltip";
|
|
625
|
+
tooltip.style.display = "none";
|
|
626
|
+
document.body.appendChild(overlay);
|
|
627
|
+
document.body.appendChild(tooltip);
|
|
628
|
+
this.overlay = overlay;
|
|
629
|
+
this.tooltip = tooltip;
|
|
630
|
+
return { overlay, tooltip };
|
|
631
|
+
}
|
|
632
|
+
getTooltip() {
|
|
633
|
+
return this.tooltip;
|
|
634
|
+
}
|
|
635
|
+
hasCurrentElement() {
|
|
636
|
+
return this.currentElement !== null;
|
|
637
|
+
}
|
|
638
|
+
clearHideTimeout() {
|
|
639
|
+
if (this.hideTimeout) {
|
|
640
|
+
clearTimeout(this.hideTimeout);
|
|
641
|
+
this.hideTimeout = null;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
show(element) {
|
|
645
|
+
if (!this.overlay || !this.tooltip) return;
|
|
646
|
+
this.clearHideTimeout();
|
|
647
|
+
if (this.currentElement && this.currentElement !== element) {
|
|
648
|
+
this.currentElement.classList.remove("prepr-overlay-active");
|
|
649
|
+
}
|
|
650
|
+
const rect = element.getBoundingClientRect();
|
|
651
|
+
const href = element.getAttribute("data-prepr-href");
|
|
652
|
+
const origin = element.getAttribute("data-prepr-origin");
|
|
653
|
+
const id = element.getAttribute("data-prepr-id") ?? void 0;
|
|
654
|
+
const field = element.getAttribute("data-prepr-field") ?? void 0;
|
|
655
|
+
debug4.log("showing overlay", { href, origin });
|
|
656
|
+
const overlay = this.overlay;
|
|
657
|
+
overlay.style.display = "block";
|
|
658
|
+
overlay.style.top = `${rect.top + window.scrollY - 2}px`;
|
|
659
|
+
overlay.style.left = `${rect.left + window.scrollX - 4}px`;
|
|
660
|
+
overlay.style.width = `${rect.width + 8}px`;
|
|
661
|
+
overlay.style.height = `${rect.height + 4}px`;
|
|
662
|
+
const tooltip = this.tooltip;
|
|
663
|
+
if (href && origin) {
|
|
664
|
+
const MIN_WIDTH_FOR_TEXT = 80;
|
|
665
|
+
const isCompact = rect.width < MIN_WIDTH_FOR_TEXT;
|
|
666
|
+
tooltip.textContent = isCompact ? "\u2197" : `${origin} \u2197`;
|
|
667
|
+
tooltip.style.display = "block";
|
|
668
|
+
tooltip.style.minWidth = isCompact ? "auto" : "80px";
|
|
669
|
+
requestAnimationFrame(() => {
|
|
670
|
+
let top = rect.top + window.scrollY - tooltip.clientHeight - 2;
|
|
671
|
+
let left = rect.right + 4 - tooltip.clientWidth;
|
|
672
|
+
const minTop = window.scrollY + 4;
|
|
673
|
+
const maxTop = window.scrollY + window.innerHeight - tooltip.clientHeight - 4;
|
|
674
|
+
const minLeft = window.scrollX + 4;
|
|
675
|
+
const maxLeft = window.scrollX + window.innerWidth - tooltip.clientWidth - 4;
|
|
676
|
+
if (top < minTop) {
|
|
677
|
+
top = rect.bottom + window.scrollY + 2;
|
|
678
|
+
}
|
|
679
|
+
top = Math.max(minTop, Math.min(top, maxTop));
|
|
680
|
+
left = Math.max(minLeft, Math.min(left, maxLeft));
|
|
681
|
+
tooltip.style.top = `${top}px`;
|
|
682
|
+
tooltip.style.left = `${left}px`;
|
|
683
|
+
});
|
|
684
|
+
tooltip.onclick = () => {
|
|
685
|
+
this.onEdit({ href, origin, id, field });
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
this.currentElement = element;
|
|
689
|
+
element.classList.add("prepr-overlay-active");
|
|
690
|
+
}
|
|
691
|
+
hideImmediate() {
|
|
692
|
+
this.clearHideTimeout();
|
|
693
|
+
if (this.overlay) this.overlay.style.display = "none";
|
|
694
|
+
if (this.tooltip) this.tooltip.style.display = "none";
|
|
695
|
+
if (this.currentElement) {
|
|
696
|
+
this.currentElement.classList.remove("prepr-overlay-active");
|
|
697
|
+
this.currentElement = null;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
hide() {
|
|
701
|
+
if (!this.overlay || !this.tooltip) return;
|
|
702
|
+
this.clearHideTimeout();
|
|
703
|
+
this.hideTimeout = setTimeout(() => this.hideImmediate(), 100);
|
|
704
|
+
}
|
|
705
|
+
cleanup() {
|
|
706
|
+
this.clearHideTimeout();
|
|
707
|
+
if (this.overlay) {
|
|
708
|
+
this.overlay.style.display = "none";
|
|
709
|
+
this.overlay.parentNode?.removeChild(this.overlay);
|
|
710
|
+
this.overlay = null;
|
|
711
|
+
}
|
|
712
|
+
if (this.tooltip) {
|
|
713
|
+
this.tooltip.style.display = "none";
|
|
714
|
+
this.tooltip.parentNode?.removeChild(this.tooltip);
|
|
715
|
+
this.tooltip = null;
|
|
716
|
+
}
|
|
717
|
+
if (this.currentElement) {
|
|
718
|
+
this.currentElement.classList.remove("prepr-overlay-active");
|
|
719
|
+
this.currentElement = null;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
// src/core/stega/proximity.ts
|
|
725
|
+
var debug5 = createScopedLogger("stega:proximity");
|
|
726
|
+
var StegaProximity = class {
|
|
727
|
+
constructor() {
|
|
728
|
+
this.highlighted = /* @__PURE__ */ new Set();
|
|
729
|
+
this.visible = /* @__PURE__ */ new Set();
|
|
730
|
+
this.observer = null;
|
|
731
|
+
this.getEncodedElements = createElementCache(
|
|
732
|
+
"[data-prepr-encoded]",
|
|
733
|
+
200
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
/** Call after the encoded element set changes — rebuilds the observer. */
|
|
737
|
+
refreshObserving() {
|
|
738
|
+
try {
|
|
739
|
+
if (typeof IntersectionObserver === "undefined") return;
|
|
740
|
+
if (this.observer) {
|
|
741
|
+
this.observer.disconnect();
|
|
742
|
+
this.observer = null;
|
|
743
|
+
}
|
|
744
|
+
this.visible = /* @__PURE__ */ new Set();
|
|
745
|
+
this.observer = new IntersectionObserver(
|
|
746
|
+
(entries) => {
|
|
747
|
+
entries.forEach((entry) => {
|
|
748
|
+
const el = entry.target;
|
|
749
|
+
if (entry.isIntersecting) {
|
|
750
|
+
this.visible.add(el);
|
|
751
|
+
} else {
|
|
752
|
+
this.visible.delete(el);
|
|
753
|
+
}
|
|
754
|
+
});
|
|
755
|
+
},
|
|
756
|
+
{ root: null, rootMargin: "0px", threshold: 0 }
|
|
757
|
+
);
|
|
758
|
+
const nodes = this.getEncodedElements();
|
|
759
|
+
nodes.forEach((el) => this.observer.observe(el));
|
|
760
|
+
debug5.log("observing", nodes.length, "encoded elements");
|
|
761
|
+
} catch (error) {
|
|
762
|
+
debug5.log("error setting up IntersectionObserver", error);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
stopObserving() {
|
|
766
|
+
if (this.observer) {
|
|
767
|
+
this.observer.disconnect();
|
|
768
|
+
this.observer = null;
|
|
769
|
+
this.visible.clear();
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
updateElementGradients(cursorX, cursorY) {
|
|
773
|
+
const candidates = this.visible.size > 0 ? Array.from(this.visible) : Array.from(this.getEncodedElements());
|
|
774
|
+
const newHighlighted = /* @__PURE__ */ new Set();
|
|
775
|
+
candidates.forEach((element) => {
|
|
776
|
+
const rect = element.getBoundingClientRect();
|
|
777
|
+
const distance = Math.min(
|
|
778
|
+
Math.abs(cursorX - rect.left),
|
|
779
|
+
Math.abs(cursorX - rect.right),
|
|
780
|
+
Math.abs(cursorY - rect.top),
|
|
781
|
+
Math.abs(cursorY - rect.bottom)
|
|
782
|
+
);
|
|
783
|
+
if (distance < 150) {
|
|
784
|
+
const relativeX = cursorX - rect.left;
|
|
785
|
+
const relativeY = cursorY - rect.top;
|
|
786
|
+
element.style.setProperty("--cursor-x", `${relativeX}px`);
|
|
787
|
+
element.style.setProperty("--cursor-y", `${relativeY}px`);
|
|
788
|
+
const baseGradientSize = Math.max(
|
|
789
|
+
150,
|
|
790
|
+
Math.max(rect.width, rect.height) * 1.1
|
|
791
|
+
);
|
|
792
|
+
const distanceScale = Math.max(0, (400 - distance) / 400);
|
|
793
|
+
const gradientSize = baseGradientSize * distanceScale;
|
|
794
|
+
element.style.setProperty("--gradient-size", `${gradientSize}px`);
|
|
795
|
+
element.classList.add("prepr-proximity-highlight");
|
|
796
|
+
newHighlighted.add(element);
|
|
797
|
+
} else {
|
|
798
|
+
element.classList.remove("prepr-proximity-highlight");
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
this.highlighted = newHighlighted;
|
|
802
|
+
}
|
|
803
|
+
clearAllHighlights() {
|
|
804
|
+
this.highlighted.forEach(
|
|
805
|
+
(element) => element.classList.remove("prepr-proximity-highlight")
|
|
806
|
+
);
|
|
807
|
+
this.highlighted.clear();
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
// src/core/stega/stega.generated.ts
|
|
812
|
+
var STEGA_STYLES = '[data-prepr-encoded]{position:relative}.prepr-overlay{pointer-events:none;z-index:10000;border:2px solid #4f46e5;border-radius:4px 0 4px 4px;transition:all .2s ease-in-out;position:absolute}.prepr-tooltip{color:#fff;white-space:nowrap;z-index:10001;text-align:center;pointer-events:auto;cursor:pointer;background-color:#4f46e5;border-radius:4px 4px 0 0;min-width:80px;padding:4px 8px;font-size:12px;line-height:1;transition:opacity .2s ease-in-out;position:absolute}.prepr-tooltip:hover{background-color:#4338ca}.prepr-proximity-highlight{z-index:1;position:relative}.prepr-proximity-highlight,.prepr-proximity-highlight *{overflow:visible!important}.prepr-proximity-highlight:before{content:"";pointer-events:none;background:radial-gradient(circle var(--gradient-size) at var(--cursor-x) var(--cursor-y), #4f46e526 0%, #2563eb00 70%);z-index:9999;border:2px solid #4f46e526;border-radius:4px;transition:all .2s;position:absolute;top:-2px;bottom:-2px;left:-4px;right:-4px;overflow:visible}';
|
|
813
|
+
|
|
814
|
+
// src/core/stega/styles.ts
|
|
815
|
+
var STEGA_STYLE_MARKER = "data-prepr-stega";
|
|
816
|
+
function injectStegaStyles(css = STEGA_STYLES) {
|
|
817
|
+
const existing = document.querySelector(
|
|
818
|
+
`style[${STEGA_STYLE_MARKER}]`
|
|
819
|
+
);
|
|
820
|
+
if (existing) return existing;
|
|
821
|
+
const style = document.createElement("style");
|
|
822
|
+
style.setAttribute(STEGA_STYLE_MARKER, "");
|
|
823
|
+
style.textContent = css;
|
|
824
|
+
document.head.appendChild(style);
|
|
825
|
+
return style;
|
|
826
|
+
}
|
|
827
|
+
function removeStegaStyles() {
|
|
828
|
+
document.querySelectorAll(`style[${STEGA_STYLE_MARKER}]`).forEach((node) => node.parentNode?.removeChild(node));
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
// src/core/stega/scan.ts
|
|
832
|
+
var debug6 = createScopedLogger("stega:scan");
|
|
833
|
+
var EDITOR_MODE_STYLES = "[data-prepr-encoded]{cursor:pointer}";
|
|
834
|
+
function createStegaController(opts) {
|
|
835
|
+
const tooltipEnabled = opts.tooltip ?? true;
|
|
836
|
+
const overlay = new StegaOverlay(opts.onEdit);
|
|
837
|
+
const proximity = new StegaProximity();
|
|
838
|
+
const elements = new StegaElements();
|
|
839
|
+
let initialized = false;
|
|
840
|
+
let throttledMouseMove = null;
|
|
841
|
+
const handleTooltipMouseEnter = () => {
|
|
842
|
+
overlay.clearHideTimeout();
|
|
843
|
+
};
|
|
844
|
+
const handleTooltipMouseLeave = () => {
|
|
845
|
+
if (!overlay.hasCurrentElement()) {
|
|
846
|
+
overlay.hide();
|
|
847
|
+
}
|
|
848
|
+
};
|
|
849
|
+
const handleScroll = () => {
|
|
850
|
+
overlay.hideImmediate();
|
|
851
|
+
proximity.clearAllHighlights();
|
|
852
|
+
};
|
|
853
|
+
const handleClick = (e2) => {
|
|
854
|
+
const target = e2.target;
|
|
855
|
+
const encoded = target?.closest(
|
|
856
|
+
"[data-prepr-encoded]"
|
|
857
|
+
);
|
|
858
|
+
if (!encoded) return;
|
|
859
|
+
e2.preventDefault();
|
|
860
|
+
e2.stopPropagation();
|
|
861
|
+
opts.onEdit({
|
|
862
|
+
href: encoded.getAttribute("data-prepr-href") ?? "",
|
|
863
|
+
origin: encoded.getAttribute("data-prepr-origin") ?? "",
|
|
864
|
+
id: encoded.getAttribute("data-prepr-id") ?? void 0,
|
|
865
|
+
field: encoded.getAttribute("data-prepr-field") ?? void 0
|
|
866
|
+
});
|
|
867
|
+
};
|
|
868
|
+
const start = () => {
|
|
869
|
+
if (initialized) {
|
|
870
|
+
debug6.log("already initialized, skipping setup");
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
if (!tooltipEnabled) {
|
|
874
|
+
injectStegaStyles(EDITOR_MODE_STYLES);
|
|
875
|
+
elements.scanDocument(true);
|
|
876
|
+
elements.setupMutationObserver(() => {
|
|
877
|
+
});
|
|
878
|
+
document.addEventListener("click", handleClick, { capture: true });
|
|
879
|
+
initialized = true;
|
|
880
|
+
debug6.log("stega controller started (editor mode)");
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
injectStegaStyles();
|
|
884
|
+
const { tooltip } = overlay.create();
|
|
885
|
+
tooltip.addEventListener("mouseenter", handleTooltipMouseEnter);
|
|
886
|
+
tooltip.addEventListener("mouseleave", handleTooltipMouseLeave);
|
|
887
|
+
elements.scanDocument(true);
|
|
888
|
+
proximity.refreshObserving();
|
|
889
|
+
elements.setupMutationObserver(() => proximity.refreshObserving());
|
|
890
|
+
throttledMouseMove = throttle((e2) => {
|
|
891
|
+
const mouseEvent = e2;
|
|
892
|
+
const target = mouseEvent.target;
|
|
893
|
+
if (!target) return;
|
|
894
|
+
if (target.closest(".prepr-tooltip")) return;
|
|
895
|
+
proximity.updateElementGradients(mouseEvent.clientX, mouseEvent.clientY);
|
|
896
|
+
const encoded = target.closest("[data-prepr-encoded]");
|
|
897
|
+
if (encoded) {
|
|
898
|
+
overlay.show(encoded);
|
|
899
|
+
} else {
|
|
900
|
+
overlay.hide();
|
|
901
|
+
}
|
|
902
|
+
}, 16);
|
|
903
|
+
document.addEventListener("mousemove", throttledMouseMove);
|
|
904
|
+
window.addEventListener("scroll", handleScroll, { capture: true });
|
|
905
|
+
initialized = true;
|
|
906
|
+
debug6.log("stega controller started");
|
|
907
|
+
};
|
|
908
|
+
const stop = () => {
|
|
909
|
+
if (!initialized) return;
|
|
910
|
+
if (!tooltipEnabled) {
|
|
911
|
+
document.removeEventListener("click", handleClick, { capture: true });
|
|
912
|
+
elements.cleanup();
|
|
913
|
+
removeStegaStyles();
|
|
914
|
+
initialized = false;
|
|
915
|
+
debug6.log("stega controller stopped (editor mode)");
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
918
|
+
if (throttledMouseMove) {
|
|
919
|
+
document.removeEventListener("mousemove", throttledMouseMove);
|
|
920
|
+
throttledMouseMove.cancel();
|
|
921
|
+
throttledMouseMove = null;
|
|
922
|
+
}
|
|
923
|
+
window.removeEventListener("scroll", handleScroll, { capture: true });
|
|
924
|
+
const tooltip = overlay.getTooltip();
|
|
925
|
+
if (tooltip) {
|
|
926
|
+
tooltip.removeEventListener("mouseenter", handleTooltipMouseEnter);
|
|
927
|
+
tooltip.removeEventListener("mouseleave", handleTooltipMouseLeave);
|
|
928
|
+
}
|
|
929
|
+
overlay.cleanup();
|
|
930
|
+
proximity.clearAllHighlights();
|
|
931
|
+
proximity.stopObserving();
|
|
932
|
+
elements.cleanup();
|
|
933
|
+
removeStegaStyles();
|
|
934
|
+
initialized = false;
|
|
935
|
+
debug6.log("stega controller stopped");
|
|
936
|
+
};
|
|
937
|
+
return { start, stop };
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
// src/core/store.ts
|
|
941
|
+
var DEFAULT_STATE = {
|
|
942
|
+
locale: "en",
|
|
943
|
+
segments: [],
|
|
944
|
+
selectedSegment: null,
|
|
945
|
+
selectedVariant: null,
|
|
946
|
+
editMode: false,
|
|
947
|
+
previewMode: false,
|
|
948
|
+
toolbarOpen: false,
|
|
949
|
+
isIframe: false,
|
|
950
|
+
features: ALL_FEATURES_ENABLED
|
|
951
|
+
};
|
|
952
|
+
function createToolbarStore(initial = {}) {
|
|
953
|
+
let state = { ...DEFAULT_STATE, ...initial };
|
|
954
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
955
|
+
function get() {
|
|
956
|
+
return state;
|
|
957
|
+
}
|
|
958
|
+
function set(patch) {
|
|
959
|
+
const keys = Object.keys(patch);
|
|
960
|
+
const hasChange = keys.some((key) => patch[key] !== state[key]);
|
|
961
|
+
if (!hasChange) return;
|
|
962
|
+
state = { ...state, ...patch };
|
|
963
|
+
for (const listener of listeners) {
|
|
964
|
+
listener(state);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
function subscribe(fn) {
|
|
968
|
+
listeners.add(fn);
|
|
969
|
+
return () => {
|
|
970
|
+
listeners.delete(fn);
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
return { get, set, subscribe };
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// src/core/toolbar-change-handler.ts
|
|
977
|
+
function cookieOpts() {
|
|
978
|
+
return {
|
|
979
|
+
maxAge: ONE_YEAR_SECONDS,
|
|
980
|
+
path: "/",
|
|
981
|
+
...crossSiteCookieOptions()
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
function createChangeHandler(deps) {
|
|
985
|
+
const { store, stega, syncAutoClean, features, editingEnabled } = deps;
|
|
986
|
+
function updateParams(patch) {
|
|
987
|
+
const [path, existing] = splitPath(deps.currentPath());
|
|
988
|
+
const params = new URLSearchParams(existing);
|
|
989
|
+
for (const [name, value] of Object.entries(patch)) {
|
|
990
|
+
if (value === null) {
|
|
991
|
+
params.delete(name);
|
|
992
|
+
} else {
|
|
993
|
+
params.set(name, value);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
const query = params.toString();
|
|
997
|
+
deps.navigate(query ? `${path}?${query}` : path);
|
|
998
|
+
}
|
|
999
|
+
return function handleChange(before, after) {
|
|
1000
|
+
const paramPatch = {};
|
|
1001
|
+
if (features.segments && before.selectedSegment !== after.selectedSegment) {
|
|
1002
|
+
if (after.selectedSegment === null) {
|
|
1003
|
+
removeCookie(COOKIE_SEGMENT, "/", crossSiteCookieOptions());
|
|
1004
|
+
} else {
|
|
1005
|
+
setCookie(COOKIE_SEGMENT, after.selectedSegment, cookieOpts());
|
|
1006
|
+
}
|
|
1007
|
+
paramPatch[PARAM_SEGMENT] = after.selectedSegment;
|
|
1008
|
+
sendPreprEvent("segment_changed", {
|
|
1009
|
+
segment: after.selectedSegment ?? void 0
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
if (features.abTesting && before.selectedVariant !== after.selectedVariant) {
|
|
1013
|
+
if (after.selectedVariant === null) {
|
|
1014
|
+
removeCookie(COOKIE_VARIANT, "/", crossSiteCookieOptions());
|
|
1015
|
+
} else {
|
|
1016
|
+
setCookie(COOKIE_VARIANT, after.selectedVariant, cookieOpts());
|
|
1017
|
+
}
|
|
1018
|
+
paramPatch[PARAM_VARIANT] = after.selectedVariant;
|
|
1019
|
+
sendPreprEvent("variant_changed", {
|
|
1020
|
+
variant: after.selectedVariant ?? void 0
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
if (Object.keys(paramPatch).length > 0) {
|
|
1024
|
+
updateParams(paramPatch);
|
|
1025
|
+
}
|
|
1026
|
+
if (before.editMode !== after.editMode) {
|
|
1027
|
+
if (after.editMode && editingEnabled) {
|
|
1028
|
+
stega.start();
|
|
1029
|
+
} else {
|
|
1030
|
+
stega.stop();
|
|
1031
|
+
}
|
|
1032
|
+
sendPreprEvent("edit_mode_toggled", { editMode: after.editMode });
|
|
1033
|
+
}
|
|
1034
|
+
if (before.previewMode !== after.previewMode) {
|
|
1035
|
+
const coupled = {};
|
|
1036
|
+
if (!after.previewMode && after.editMode) {
|
|
1037
|
+
coupled.editMode = false;
|
|
1038
|
+
}
|
|
1039
|
+
if (after.toolbarOpen) {
|
|
1040
|
+
coupled.toolbarOpen = false;
|
|
1041
|
+
}
|
|
1042
|
+
if (Object.keys(coupled).length > 0) {
|
|
1043
|
+
store.set(coupled);
|
|
1044
|
+
}
|
|
1045
|
+
setCookie(COOKIE_PREVIEW_MODE, String(after.previewMode), cookieOpts());
|
|
1046
|
+
setCookie(COOKIE_TOOLBAR_OPEN, "false", cookieOpts());
|
|
1047
|
+
sendPreprEvent("preview_mode_toggled", { previewMode: after.previewMode });
|
|
1048
|
+
syncAutoClean(after.previewMode);
|
|
1049
|
+
const [path, existing] = splitPath(deps.currentPath());
|
|
1050
|
+
const params = new URLSearchParams(existing);
|
|
1051
|
+
if (params.has(PARAM_SEGMENT) || params.has(PARAM_VARIANT)) {
|
|
1052
|
+
params.delete(PARAM_SEGMENT);
|
|
1053
|
+
params.delete(PARAM_VARIANT);
|
|
1054
|
+
const query = params.toString();
|
|
1055
|
+
deps.navigate(query ? `${path}?${query}` : path);
|
|
1056
|
+
} else {
|
|
1057
|
+
deps.reload();
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
if (before.toolbarOpen !== after.toolbarOpen) {
|
|
1061
|
+
setCookie(COOKIE_TOOLBAR_OPEN, String(after.toolbarOpen), cookieOpts());
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
function splitPath(full) {
|
|
1066
|
+
const index = full.indexOf("?");
|
|
1067
|
+
if (index === -1) return [full, ""];
|
|
1068
|
+
return [full.slice(0, index), full.slice(index + 1)];
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// ../../node_modules/.pnpm/preact@10.29.7/node_modules/preact/dist/preact.mjs
|
|
1072
|
+
var n;
|
|
1073
|
+
var l;
|
|
1074
|
+
var u;
|
|
1075
|
+
var t2;
|
|
1076
|
+
var i;
|
|
1077
|
+
var r;
|
|
1078
|
+
var o;
|
|
1079
|
+
var e;
|
|
1080
|
+
var f;
|
|
1081
|
+
var c;
|
|
1082
|
+
var a;
|
|
1083
|
+
var s;
|
|
1084
|
+
var h;
|
|
1085
|
+
var p;
|
|
1086
|
+
var v;
|
|
1087
|
+
var y;
|
|
1088
|
+
var d = {};
|
|
1089
|
+
var w = [];
|
|
1090
|
+
var _ = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;
|
|
1091
|
+
var g = Array.isArray;
|
|
1092
|
+
function m(n2, l2) {
|
|
1093
|
+
for (var u3 in l2) n2[u3] = l2[u3];
|
|
1094
|
+
return n2;
|
|
1095
|
+
}
|
|
1096
|
+
function b(n2) {
|
|
1097
|
+
n2 && n2.parentNode && n2.parentNode.removeChild(n2);
|
|
1098
|
+
}
|
|
1099
|
+
function k(l2, u3, t3) {
|
|
1100
|
+
var i2, r2, o2, e2 = {};
|
|
1101
|
+
for (o2 in u3) "key" == o2 ? i2 = u3[o2] : "ref" == o2 ? r2 = u3[o2] : e2[o2] = u3[o2];
|
|
1102
|
+
if (arguments.length > 2 && (e2.children = arguments.length > 3 ? n.call(arguments, 2) : t3), "function" == typeof l2 && null != l2.defaultProps) for (o2 in l2.defaultProps) void 0 === e2[o2] && (e2[o2] = l2.defaultProps[o2]);
|
|
1103
|
+
return x(l2, e2, i2, r2, null);
|
|
1104
|
+
}
|
|
1105
|
+
function x(n2, t3, i2, r2, o2) {
|
|
1106
|
+
var e2 = { type: n2, props: t3, key: i2, ref: r2, __k: null, __: null, __b: 0, __e: null, __c: null, constructor: void 0, __v: null == o2 ? ++u : o2, __i: -1, __u: 0 };
|
|
1107
|
+
return null == o2 && null != l.vnode && l.vnode(e2), e2;
|
|
1108
|
+
}
|
|
1109
|
+
function S(n2) {
|
|
1110
|
+
return n2.children;
|
|
1111
|
+
}
|
|
1112
|
+
function C(n2, l2) {
|
|
1113
|
+
this.props = n2, this.context = l2;
|
|
1114
|
+
}
|
|
1115
|
+
function $(n2, l2) {
|
|
1116
|
+
if (null == l2) return n2.__ ? $(n2.__, n2.__i + 1) : null;
|
|
1117
|
+
for (var u3; l2 < n2.__k.length; l2++) if (null != (u3 = n2.__k[l2]) && null != u3.__e) return u3.__e;
|
|
1118
|
+
return "function" == typeof n2.type ? $(n2) : null;
|
|
1119
|
+
}
|
|
1120
|
+
function I(n2) {
|
|
1121
|
+
if (n2.__P && n2.__d) {
|
|
1122
|
+
var u3 = n2.__v, t3 = u3.__e, i2 = [], r2 = [], o2 = m({}, u3);
|
|
1123
|
+
o2.__v = u3.__v + 1, l.vnode && l.vnode(o2), q(n2.__P, o2, u3, n2.__n, n2.__P.namespaceURI, 32 & u3.__u ? [t3] : null, i2, null == t3 ? $(u3) : t3, !!(32 & u3.__u), r2), o2.__v = u3.__v, o2.__.__k[o2.__i] = o2, D(i2, o2, r2), u3.__e = u3.__ = null, o2.__e != t3 && P(o2);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
function P(n2) {
|
|
1127
|
+
if (null != (n2 = n2.__) && null != n2.__c) return n2.__e = n2.__c.base = null, n2.__k.some(function(l2) {
|
|
1128
|
+
if (null != l2 && null != l2.__e) return n2.__e = n2.__c.base = l2.__e;
|
|
1129
|
+
}), P(n2);
|
|
1130
|
+
}
|
|
1131
|
+
function A(n2) {
|
|
1132
|
+
(!n2.__d && (n2.__d = true) && i.push(n2) && !H.__r++ || r != l.debounceRendering) && ((r = l.debounceRendering) || o)(H);
|
|
1133
|
+
}
|
|
1134
|
+
function H() {
|
|
1135
|
+
try {
|
|
1136
|
+
for (var n2, l2 = 1; i.length; ) i.length > l2 && i.sort(e), n2 = i.shift(), l2 = i.length, I(n2);
|
|
1137
|
+
} finally {
|
|
1138
|
+
i.length = H.__r = 0;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
function L(n2, l2, u3, t3, i2, r2, o2, e2, f3, c2, a2) {
|
|
1142
|
+
var s2, h2, p2, v2, y2, _2, g2, m2 = t3 && t3.__k || w, b2 = l2.length;
|
|
1143
|
+
for (f3 = T(u3, l2, m2, f3, b2), s2 = 0; s2 < b2; s2++) null != (p2 = u3.__k[s2]) && (h2 = -1 != p2.__i && m2[p2.__i] || d, p2.__i = s2, _2 = q(n2, p2, h2, i2, r2, o2, e2, f3, c2, a2), v2 = p2.__e, p2.ref && h2.ref != p2.ref && (h2.ref && J(h2.ref, null, p2), a2.push(p2.ref, p2.__c || v2, p2)), null == y2 && null != v2 && (y2 = v2), (g2 = !!(4 & p2.__u)) || h2.__k === p2.__k ? (f3 = j(p2, f3, n2, g2), g2 && h2.__e && (h2.__e = null)) : "function" == typeof p2.type && void 0 !== _2 ? f3 = _2 : v2 && (f3 = v2.nextSibling), p2.__u &= -7);
|
|
1144
|
+
return u3.__e = y2, f3;
|
|
1145
|
+
}
|
|
1146
|
+
function T(n2, l2, u3, t3, i2) {
|
|
1147
|
+
var r2, o2, e2, f3, c2, a2 = u3.length, s2 = a2, h2 = 0;
|
|
1148
|
+
for (n2.__k = new Array(i2), r2 = 0; r2 < i2; r2++) null != (o2 = l2[r2]) && "boolean" != typeof o2 && "function" != typeof o2 ? ("string" == typeof o2 || "number" == typeof o2 || "bigint" == typeof o2 || o2.constructor == String ? o2 = n2.__k[r2] = x(null, o2, null, null, null) : g(o2) ? o2 = n2.__k[r2] = x(S, { children: o2 }, null, null, null) : void 0 === o2.constructor && o2.__b > 0 ? o2 = n2.__k[r2] = x(o2.type, o2.props, o2.key, o2.ref ? o2.ref : null, o2.__v) : n2.__k[r2] = o2, f3 = r2 + h2, o2.__ = n2, o2.__b = n2.__b + 1, e2 = null, -1 != (c2 = o2.__i = O(o2, u3, f3, s2)) && (s2--, (e2 = u3[c2]) && (e2.__u |= 2)), null == e2 || null == e2.__v ? (-1 == c2 && (i2 > a2 ? h2-- : i2 < a2 && h2++), "function" != typeof o2.type && (o2.__u |= 4)) : c2 != f3 && (c2 == f3 - 1 ? h2-- : c2 == f3 + 1 ? h2++ : (c2 > f3 ? h2-- : h2++, o2.__u |= 4))) : n2.__k[r2] = null;
|
|
1149
|
+
if (s2) for (r2 = 0; r2 < a2; r2++) null != (e2 = u3[r2]) && 0 == (2 & e2.__u) && (e2.__e == t3 && (t3 = $(e2)), K(e2, e2));
|
|
1150
|
+
return t3;
|
|
1151
|
+
}
|
|
1152
|
+
function j(n2, l2, u3, t3) {
|
|
1153
|
+
var i2, r2;
|
|
1154
|
+
if ("function" == typeof n2.type) {
|
|
1155
|
+
for (i2 = n2.__k, r2 = 0; i2 && r2 < i2.length; r2++) i2[r2] && (i2[r2].__ = n2, l2 = j(i2[r2], l2, u3, t3));
|
|
1156
|
+
return l2;
|
|
1157
|
+
}
|
|
1158
|
+
n2.__e != l2 && (t3 && (l2 && n2.type && !l2.parentNode && (l2 = $(n2)), u3.insertBefore(n2.__e, l2 || null)), l2 = n2.__e);
|
|
1159
|
+
do {
|
|
1160
|
+
l2 = l2 && l2.nextSibling;
|
|
1161
|
+
} while (null != l2 && 8 == l2.nodeType);
|
|
1162
|
+
return l2;
|
|
1163
|
+
}
|
|
1164
|
+
function O(n2, l2, u3, t3) {
|
|
1165
|
+
var i2, r2, o2, e2 = n2.key, f3 = n2.type, c2 = l2[u3], a2 = null != c2 && 0 == (2 & c2.__u);
|
|
1166
|
+
if (null === c2 && null == e2 || a2 && e2 == c2.key && f3 == c2.type) return u3;
|
|
1167
|
+
if (t3 > (a2 ? 1 : 0)) {
|
|
1168
|
+
for (i2 = u3 - 1, r2 = u3 + 1; i2 >= 0 || r2 < l2.length; ) if (null != (c2 = l2[o2 = i2 >= 0 ? i2-- : r2++]) && 0 == (2 & c2.__u) && e2 == c2.key && f3 == c2.type) return o2;
|
|
1169
|
+
}
|
|
1170
|
+
return -1;
|
|
1171
|
+
}
|
|
1172
|
+
function z(n2, l2, u3) {
|
|
1173
|
+
"-" == l2[0] ? n2.setProperty(l2, null == u3 ? "" : u3) : n2[l2] = null == u3 ? "" : "number" != typeof u3 || _.test(l2) ? u3 : u3 + "px";
|
|
1174
|
+
}
|
|
1175
|
+
function N(n2, l2, u3, t3, i2) {
|
|
1176
|
+
var r2, o2;
|
|
1177
|
+
n: if ("style" == l2) if ("string" == typeof u3) n2.style.cssText = u3;
|
|
1178
|
+
else {
|
|
1179
|
+
if ("string" == typeof t3 && (n2.style.cssText = t3 = ""), t3) for (l2 in t3) u3 && l2 in u3 || z(n2.style, l2, "");
|
|
1180
|
+
if (u3) for (l2 in u3) t3 && u3[l2] == t3[l2] || z(n2.style, l2, u3[l2]);
|
|
1181
|
+
}
|
|
1182
|
+
else if ("o" == l2[0] && "n" == l2[1]) r2 = l2 != (l2 = l2.replace(s, "$1")), o2 = l2.toLowerCase(), l2 = o2 in n2 || "onFocusOut" == l2 || "onFocusIn" == l2 ? o2.slice(2) : l2.slice(2), n2.l || (n2.l = {}), n2.l[l2 + r2] = u3, u3 ? t3 ? u3[a] = t3[a] : (u3[a] = h, n2.addEventListener(l2, r2 ? v : p, r2)) : n2.removeEventListener(l2, r2 ? v : p, r2);
|
|
1183
|
+
else {
|
|
1184
|
+
if ("http://www.w3.org/2000/svg" == i2) l2 = l2.replace(/xlink(H|:h)/, "h").replace(/sName$/, "s");
|
|
1185
|
+
else if ("width" != l2 && "height" != l2 && "href" != l2 && "list" != l2 && "form" != l2 && "tabIndex" != l2 && "download" != l2 && "rowSpan" != l2 && "colSpan" != l2 && "role" != l2 && "popover" != l2 && l2 in n2) try {
|
|
1186
|
+
n2[l2] = null == u3 ? "" : u3;
|
|
1187
|
+
break n;
|
|
1188
|
+
} catch (n3) {
|
|
1189
|
+
}
|
|
1190
|
+
"function" == typeof u3 || (null == u3 || false === u3 && "-" != l2[4] ? n2.removeAttribute(l2) : n2.setAttribute(l2, "popover" == l2 && 1 == u3 ? "" : u3));
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
function V(n2) {
|
|
1194
|
+
return function(u3) {
|
|
1195
|
+
if (this.l) {
|
|
1196
|
+
var t3 = this.l[u3.type + n2];
|
|
1197
|
+
if (null == u3[c]) u3[c] = h++;
|
|
1198
|
+
else if (u3[c] < t3[a]) return;
|
|
1199
|
+
return t3(l.event ? l.event(u3) : u3);
|
|
1200
|
+
}
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
function q(n2, u3, t3, i2, r2, o2, e2, f3, c2, a2) {
|
|
1204
|
+
var s2, h2, p2, v2, y2, d2, _2, k2, x2, M, $2, I2, P2, A2, H2, T2, j2 = u3.type;
|
|
1205
|
+
if (void 0 !== u3.constructor) return null;
|
|
1206
|
+
128 & t3.__u && (c2 = !!(32 & t3.__u), o2 = [f3 = u3.__e = t3.__e]), (s2 = l.__b) && s2(u3);
|
|
1207
|
+
n: if ("function" == typeof j2) {
|
|
1208
|
+
h2 = e2.length;
|
|
1209
|
+
try {
|
|
1210
|
+
if (x2 = u3.props, M = j2.prototype && j2.prototype.render, $2 = (s2 = j2.contextType) && i2[s2.__c], I2 = s2 ? $2 ? $2.props.value : s2.__ : i2, t3.__c ? k2 = (p2 = u3.__c = t3.__c).__ = p2.__E : (M ? u3.__c = p2 = new j2(x2, I2) : (u3.__c = p2 = new C(x2, I2), p2.constructor = j2, p2.render = Q), $2 && $2.sub(p2), p2.state || (p2.state = {}), p2.__n = i2, v2 = p2.__d = true, p2.__h = [], p2._sb = []), M && null == p2.__s && (p2.__s = p2.state), M && null != j2.getDerivedStateFromProps && (p2.__s == p2.state && (p2.__s = m({}, p2.__s)), m(p2.__s, j2.getDerivedStateFromProps(x2, p2.__s))), y2 = p2.props, d2 = p2.state, p2.__v = u3, v2) M && null == j2.getDerivedStateFromProps && null != p2.componentWillMount && p2.componentWillMount(), M && null != p2.componentDidMount && p2.__h.push(p2.componentDidMount);
|
|
1211
|
+
else {
|
|
1212
|
+
if (M && null == j2.getDerivedStateFromProps && x2 !== y2 && null != p2.componentWillReceiveProps && p2.componentWillReceiveProps(x2, I2), u3.__v == t3.__v || !p2.__e && null != p2.shouldComponentUpdate && false === p2.shouldComponentUpdate(x2, p2.__s, I2)) {
|
|
1213
|
+
u3.__v != t3.__v && (p2.props = x2, p2.state = p2.__s, p2.__d = false), u3.__e = t3.__e, u3.__k = t3.__k, u3.__k.some(function(n3) {
|
|
1214
|
+
n3 && (n3.__ = u3);
|
|
1215
|
+
}), w.push.apply(p2.__h, p2._sb), p2._sb = [], p2.__h.length && e2.push(p2);
|
|
1216
|
+
break n;
|
|
1217
|
+
}
|
|
1218
|
+
null != p2.componentWillUpdate && p2.componentWillUpdate(x2, p2.__s, I2), M && null != p2.componentDidUpdate && p2.__h.push(function() {
|
|
1219
|
+
p2.componentDidUpdate(y2, d2, _2);
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
if (p2.context = I2, p2.props = x2, p2.__P = n2, p2.__e = false, P2 = l.__r, A2 = 0, M) p2.state = p2.__s, p2.__d = false, P2 && P2(u3), s2 = p2.render(p2.props, p2.state, p2.context), w.push.apply(p2.__h, p2._sb), p2._sb = [];
|
|
1223
|
+
else do {
|
|
1224
|
+
p2.__d = false, P2 && P2(u3), s2 = p2.render(p2.props, p2.state, p2.context), p2.state = p2.__s;
|
|
1225
|
+
} while (p2.__d && ++A2 < 25);
|
|
1226
|
+
p2.state = p2.__s, null != p2.getChildContext && (i2 = m(m({}, i2), p2.getChildContext())), M && !v2 && null != p2.getSnapshotBeforeUpdate && (_2 = p2.getSnapshotBeforeUpdate(y2, d2)), H2 = null != s2 && s2.type === S && null == s2.key ? E(s2.props.children) : s2, f3 = L(n2, g(H2) ? H2 : [H2], u3, t3, i2, r2, o2, e2, f3, c2, a2), p2.base = u3.__e, u3.__u &= -161, p2.__h.length && e2.push(p2), k2 && (p2.__E = p2.__ = null);
|
|
1227
|
+
} catch (n3) {
|
|
1228
|
+
if (e2.length = h2, u3.__v = null, c2 || null != o2) {
|
|
1229
|
+
if (n3.then) {
|
|
1230
|
+
for (u3.__u |= c2 ? 160 : 128; f3 && 8 == f3.nodeType && f3.nextSibling; ) f3 = f3.nextSibling;
|
|
1231
|
+
null != o2 && (o2[o2.indexOf(f3)] = null), u3.__e = f3;
|
|
1232
|
+
} else if (null != o2) for (T2 = o2.length; T2--; ) b(o2[T2]);
|
|
1233
|
+
} else u3.__e = t3.__e;
|
|
1234
|
+
null == u3.__k && (u3.__k = t3.__k || []), n3.then || B(u3), l.__e(n3, u3, t3);
|
|
1235
|
+
}
|
|
1236
|
+
} else null == o2 && u3.__v == t3.__v ? (u3.__k = t3.__k, u3.__e = t3.__e) : f3 = u3.__e = G(t3.__e, u3, t3, i2, r2, o2, e2, c2, a2);
|
|
1237
|
+
return (s2 = l.diffed) && s2(u3), 128 & u3.__u ? void 0 : f3;
|
|
1238
|
+
}
|
|
1239
|
+
function B(n2) {
|
|
1240
|
+
n2 && (n2.__c && (n2.__c.__e = true), n2.__k && n2.__k.some(B));
|
|
1241
|
+
}
|
|
1242
|
+
function D(n2, u3, t3) {
|
|
1243
|
+
for (var i2 = 0; i2 < t3.length; i2++) J(t3[i2], t3[++i2], t3[++i2]);
|
|
1244
|
+
l.__c && l.__c(u3, n2), n2.some(function(u4) {
|
|
1245
|
+
try {
|
|
1246
|
+
n2 = u4.__h, u4.__h = [], n2.some(function(n3) {
|
|
1247
|
+
n3.call(u4);
|
|
1248
|
+
});
|
|
1249
|
+
} catch (n3) {
|
|
1250
|
+
l.__e(n3, u4.__v);
|
|
1251
|
+
}
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
function E(n2) {
|
|
1255
|
+
return "object" != typeof n2 || null == n2 || n2.__b > 0 ? n2 : g(n2) ? n2.map(E) : void 0 !== n2.constructor ? null : m({}, n2);
|
|
1256
|
+
}
|
|
1257
|
+
function G(u3, t3, i2, r2, o2, e2, f3, c2, a2) {
|
|
1258
|
+
var s2, h2, p2, v2, y2, w2, _2, m2 = i2.props || d, k2 = t3.props, x2 = t3.type;
|
|
1259
|
+
if ("svg" == x2 ? o2 = "http://www.w3.org/2000/svg" : "math" == x2 ? o2 = "http://www.w3.org/1998/Math/MathML" : o2 || (o2 = "http://www.w3.org/1999/xhtml"), null != e2) {
|
|
1260
|
+
for (s2 = 0; s2 < e2.length; s2++) if ((y2 = e2[s2]) && "setAttribute" in y2 == !!x2 && (x2 ? y2.localName == x2 : 3 == y2.nodeType)) {
|
|
1261
|
+
u3 = y2, e2[s2] = null;
|
|
1262
|
+
break;
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
if (null == u3) {
|
|
1266
|
+
if (null == x2) return document.createTextNode(k2);
|
|
1267
|
+
u3 = document.createElementNS(o2, x2, k2.is && k2), c2 && (l.__m && l.__m(t3, e2), c2 = false), e2 = null;
|
|
1268
|
+
}
|
|
1269
|
+
if (null == x2) m2 === k2 || c2 && u3.data == k2 || (u3.data = k2);
|
|
1270
|
+
else {
|
|
1271
|
+
if (e2 = "textarea" == x2 && null != k2.defaultValue ? null : e2 && n.call(u3.childNodes), !c2 && null != e2) for (m2 = {}, s2 = 0; s2 < u3.attributes.length; s2++) m2[(y2 = u3.attributes[s2]).name] = y2.value;
|
|
1272
|
+
for (s2 in m2) y2 = m2[s2], "dangerouslySetInnerHTML" == s2 ? p2 = y2 : "children" == s2 || s2 in k2 || "value" == s2 && "defaultValue" in k2 || "checked" == s2 && "defaultChecked" in k2 || N(u3, s2, null, y2, o2);
|
|
1273
|
+
for (s2 in k2) y2 = k2[s2], "children" == s2 ? v2 = y2 : "dangerouslySetInnerHTML" == s2 ? h2 = y2 : "value" == s2 ? w2 = y2 : "checked" == s2 ? _2 = y2 : c2 && "function" != typeof y2 || m2[s2] === y2 || N(u3, s2, y2, m2[s2], o2);
|
|
1274
|
+
if (h2) c2 || p2 && (h2.__html == p2.__html || h2.__html == u3.innerHTML) || (u3.innerHTML = h2.__html), t3.__k = [];
|
|
1275
|
+
else if (p2 && (u3.innerHTML = ""), L("template" == t3.type ? u3.content : u3, g(v2) ? v2 : [v2], t3, i2, r2, "foreignObject" == x2 ? "http://www.w3.org/1999/xhtml" : o2, e2, f3, e2 ? e2[0] : i2.__k && $(i2, 0), c2, a2), null != e2) for (s2 = e2.length; s2--; ) b(e2[s2]);
|
|
1276
|
+
c2 && "textarea" != x2 || (s2 = "value", "progress" == x2 && null == w2 ? u3.removeAttribute("value") : null != w2 && (w2 !== u3[s2] || "progress" == x2 && !w2 || "option" == x2 && w2 != m2[s2]) && N(u3, s2, w2, m2[s2], o2), s2 = "checked", null != _2 && _2 != u3[s2] && N(u3, s2, _2, m2[s2], o2));
|
|
1277
|
+
}
|
|
1278
|
+
return u3;
|
|
1279
|
+
}
|
|
1280
|
+
function J(n2, u3, t3) {
|
|
1281
|
+
try {
|
|
1282
|
+
if ("function" == typeof n2) {
|
|
1283
|
+
var i2 = "function" == typeof n2.__u;
|
|
1284
|
+
i2 && n2.__u(), i2 && null == u3 || (n2.__u = n2(u3));
|
|
1285
|
+
} else n2.current = u3;
|
|
1286
|
+
} catch (n3) {
|
|
1287
|
+
l.__e(n3, t3);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
function K(n2, u3, t3) {
|
|
1291
|
+
var i2, r2;
|
|
1292
|
+
if (l.unmount && l.unmount(n2), (i2 = n2.ref) && (i2.current && i2.current != n2.__e || J(i2, null, u3)), null != (i2 = n2.__c)) {
|
|
1293
|
+
if (i2.componentWillUnmount) try {
|
|
1294
|
+
i2.componentWillUnmount();
|
|
1295
|
+
} catch (n3) {
|
|
1296
|
+
l.__e(n3, u3);
|
|
1297
|
+
}
|
|
1298
|
+
i2.base = i2.__P = i2.__n = null;
|
|
1299
|
+
}
|
|
1300
|
+
if (i2 = n2.__k) for (r2 = 0; r2 < i2.length; r2++) i2[r2] && K(i2[r2], u3, t3 || "function" != typeof n2.type);
|
|
1301
|
+
t3 || b(n2.__e), n2.__c = n2.__ = n2.__e = void 0;
|
|
1302
|
+
}
|
|
1303
|
+
function Q(n2, l2, u3) {
|
|
1304
|
+
return this.constructor(n2, u3);
|
|
1305
|
+
}
|
|
1306
|
+
function R(u3, t3, i2) {
|
|
1307
|
+
var r2, o2, e2, f3;
|
|
1308
|
+
t3 == document && (t3 = document.documentElement), l.__ && l.__(u3, t3), o2 = (r2 = "function" == typeof i2) ? null : i2 && i2.__k || t3.__k, e2 = [], f3 = [], q(t3, u3 = (!r2 && i2 || t3).__k = k(S, null, [u3]), o2 || d, d, t3.namespaceURI, !r2 && i2 ? [i2] : o2 ? null : t3.firstChild ? n.call(t3.childNodes) : null, e2, !r2 && i2 ? i2 : o2 ? o2.__e : t3.firstChild, r2, f3), D(e2, u3, f3), u3.props.children = null;
|
|
1309
|
+
}
|
|
1310
|
+
n = w.slice, l = { __e: function(n2, l2, u3, t3) {
|
|
1311
|
+
for (var i2, r2, o2; l2 = l2.__; ) if ((i2 = l2.__c) && !i2.__) try {
|
|
1312
|
+
if ((r2 = i2.constructor) && null != r2.getDerivedStateFromError && (i2.setState(r2.getDerivedStateFromError(n2)), o2 = i2.__d), null != i2.componentDidCatch && (i2.componentDidCatch(n2, t3 || {}), o2 = i2.__d), o2) return i2.__E = i2;
|
|
1313
|
+
} catch (l3) {
|
|
1314
|
+
n2 = l3;
|
|
1315
|
+
}
|
|
1316
|
+
throw n2;
|
|
1317
|
+
} }, u = 0, t2 = function(n2) {
|
|
1318
|
+
return null != n2 && void 0 === n2.constructor;
|
|
1319
|
+
}, C.prototype.setState = function(n2, l2) {
|
|
1320
|
+
var u3;
|
|
1321
|
+
u3 = null != this.__s && this.__s != this.state ? this.__s : this.__s = m({}, this.state), "function" == typeof n2 && (n2 = n2(m({}, u3), this.props)), n2 && m(u3, n2), null != n2 && this.__v && (l2 && this._sb.push(l2), A(this));
|
|
1322
|
+
}, C.prototype.forceUpdate = function(n2) {
|
|
1323
|
+
this.__v && (this.__e = true, n2 && this.__h.push(n2), A(this));
|
|
1324
|
+
}, C.prototype.render = S, i = [], o = "function" == typeof Promise ? Promise.prototype.then.bind(Promise.resolve()) : setTimeout, e = function(n2, l2) {
|
|
1325
|
+
return n2.__v.__b - l2.__v.__b;
|
|
1326
|
+
}, H.__r = 0, f = Math.random().toString(8), c = "__d" + f, a = "__a" + f, s = /(PointerCapture)$|Capture$/i, h = 0, p = V(false), v = V(true), y = 0;
|
|
1327
|
+
|
|
1328
|
+
// src/core/ui/icons.ts
|
|
1329
|
+
var LOGO_SVG = `<svg width="102" height="28" viewBox="0 0 102 28" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
1330
|
+
<path d="M39.2674 2.19699C39.2757 2.18321 39.2839 2.16943 39.291 2.15528L39.2939 2.15057L39.2935 2.1502C39.3379 2.06208 39.3633 1.96308 39.3633 1.85754C39.3633 1.62109 39.2374 1.41474 39.0507 1.30231C39.0485 1.30014 39.0467 1.29651 39.0446 1.29578C35.1089 -0.88088 29.8537 -0.36627 26.3741 3.2632C24.4207 5.3006 23.4231 7.92116 23.3716 10.5544H23.3684V20.893C23.3684 21.2495 23.6538 21.5389 24.0058 21.5389H26.98C27.332 21.5389 27.6174 21.2495 27.6174 20.893V10.7698H27.6192C27.6192 9.14658 28.2169 7.52187 29.4209 6.26599C31.5699 4.02478 34.7423 3.8565 36.9299 5.03659C36.9367 5.04058 36.9439 5.04384 36.9507 5.04747C36.9557 5.05001 36.9607 5.05254 36.9657 5.05508H36.9664C37.0494 5.09497 37.1417 5.11782 37.2393 5.11782C37.4879 5.11782 37.7032 4.97276 37.808 4.76206L39.2674 2.19699Z" fill="#4338CA"/>
|
|
1331
|
+
<path d="M10.6216 0.000244141C4.75551 0.000244141 0 4.82177 0 10.7693V27.3543C0 27.7108 0.285079 28.0002 0.637405 28.0002H3.61161C3.96358 28.0002 4.24902 27.7108 4.24902 27.3543V19.3853C6.02424 20.7373 8.23084 21.5388 10.622 21.5388C16.4878 21.5388 21.244 16.7173 21.244 10.7697C21.2437 4.82177 16.4878 0.000244141 10.6216 0.000244141ZM10.6216 17.2311C7.10196 17.2311 4.24866 14.3382 4.24866 10.7693C4.24866 7.20079 7.10196 4.30788 10.6216 4.30788C14.1413 4.30788 16.995 7.20079 16.995 10.7693C16.995 14.3379 14.1413 17.2311 10.6216 17.2311Z" fill="#4338CA"/>
|
|
1332
|
+
<path d="M73.259 0C67.3932 0 62.6373 4.82152 62.6373 10.7691V27.3541C62.6373 27.7106 62.9228 28 63.2747 28H66.2489C66.6009 28 66.8863 27.7106 66.8863 27.3541V19.3854C68.6616 20.7374 70.8682 21.5389 73.2593 21.5389C79.1251 21.5389 83.8813 16.7174 83.8813 10.7698C83.881 4.82152 79.1248 0 73.259 0ZM73.259 17.2309C69.7393 17.2309 66.886 14.338 66.886 10.7691C66.886 7.20055 69.7393 4.30764 73.259 4.30764C76.7783 4.30764 79.632 7.20055 79.632 10.7691C79.632 14.3376 76.7783 17.2309 73.259 17.2309Z" fill="#4338CA"/>
|
|
1333
|
+
<path d="M60.439 10.9845C60.439 5.03657 55.6827 0 49.817 0C43.9508 0 39.1953 4.82152 39.1953 10.7691C39.1953 16.7167 43.9508 21.5382 49.817 21.5382C53.1374 21.5382 55.8763 19.9954 57.5939 18.1031C57.5939 18.1031 57.5942 18.1027 57.5946 18.1024C57.596 18.1009 57.5975 18.0995 57.5985 18.098C57.7112 17.9812 57.7806 17.822 57.7806 17.6461C57.7806 17.4601 57.7026 17.2929 57.5785 17.1751V17.1743L57.5696 17.1671C57.5535 17.1522 57.5367 17.1384 57.5188 17.1254L55.2464 15.2501C55.1344 15.1503 54.9877 15.0891 54.8264 15.0891C54.6261 15.0891 54.4476 15.183 54.331 15.3291C53.3216 16.3707 51.7256 17.2309 49.8166 17.2309C46.2969 17.2309 43.4436 14.338 43.4436 10.7691C43.4436 7.20055 46.2969 4.30764 49.8166 4.30764C52.5909 4.30764 54.9505 6.10605 55.8255 8.61527H50.3474C49.9954 8.61527 49.71 8.90467 49.71 9.26152V12.277C49.71 12.6339 49.9954 12.9233 50.3474 12.9233H59.5884C59.6059 12.9233 59.6227 12.9218 59.6399 12.9207C59.6571 12.9222 59.6742 12.9233 59.6914 12.9233C59.9743 12.9233 60.214 12.7361 60.2973 12.4772L60.3045 12.4783C60.308 12.4551 60.3116 12.4326 60.3152 12.4097C60.3199 12.3876 60.3234 12.3655 60.3256 12.3427C60.4003 11.861 60.439 11.5172 60.439 10.9845Z" fill="#4338CA"/>
|
|
1334
|
+
<path d="M101.928 2.15406L101.931 2.14934L101.93 2.14898C101.974 2.06085 102 1.96185 102 1.85632C102 1.61987 101.874 1.41351 101.687 1.30109C101.685 1.29891 101.683 1.29529 101.681 1.29456C97.7455 -0.882101 92.4903 -0.367491 89.0107 3.26198C87.0573 5.29938 86.0597 7.91993 86.0082 10.5532H86.005V20.8918C86.005 21.2483 86.2904 21.5377 86.6424 21.5377H89.6166C89.9686 21.5377 90.254 21.2483 90.254 20.8918V10.7686H90.2555C90.2555 9.14535 90.8532 7.52065 92.0571 6.26477C94.2062 4.02355 97.3785 3.85528 99.5662 5.03537C99.573 5.03936 99.5801 5.04262 99.5869 5.04624C99.5919 5.04878 99.5969 5.05132 99.6019 5.05386H99.6027C99.6856 5.09375 99.7779 5.11696 99.8756 5.11696C100.124 5.11696 100.339 4.9719 100.444 4.7612L101.905 2.19685C101.913 2.18235 101.92 2.16856 101.928 2.15406Z" fill="#4338CA"/>
|
|
1335
|
+
</svg>`;
|
|
1336
|
+
var TOGGLE_ICON_SVG = `<svg width="16" height="16" viewBox="1.05 0 16 16" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
1337
|
+
<path d="M9.05365 0C5.71033 0 3 2.75516 3 6.15377V15.6309C3 15.8346 3.16248 16 3.36328 16H5.05838C5.25898 16 5.42166 15.8346 5.42166 15.6309V11.0772C6.43342 11.8498 7.69104 12.3077 9.05385 12.3077C12.397 12.3077 15.1077 9.55259 15.1077 6.15397C15.1075 2.75516 12.397 0 9.05365 0ZM9.05365 9.84623C7.04766 9.84623 5.42146 8.19314 5.42146 6.15377C5.42146 4.1146 7.04766 2.46151 9.05365 2.46151C11.0596 2.46151 12.686 4.1146 12.686 6.15377C12.686 8.19293 11.0596 9.84623 9.05365 9.84623Z" fill="currentColor"/>
|
|
1338
|
+
</svg>`;
|
|
1339
|
+
var ROTATE_ICON_SVG = `<svg width="15" height="14" viewBox="0 0 15 14" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
1340
|
+
<path d="M3.37109 5.80078C3.20703 6.26562 2.6875 6.51172 2.25 6.34766C1.78516 6.18359 1.53906 5.69141 1.70312 5.22656C2.00391 4.37891 2.49609 3.58594 3.15234 2.92969C5.55859 0.550781 9.41406 0.550781 11.8203 2.92969L12.2852 3.42188V2C12.2852 1.53516 12.6953 1.125 13.1602 1.125C13.6523 1.125 14.0352 1.53516 14.0352 2V5.5C14.0352 5.99219 13.6523 6.375 13.1602 6.375H9.6875C9.19531 6.375 8.8125 5.99219 8.8125 5.5C8.8125 5.03516 9.19531 4.625 9.6875 4.625H11.0547L10.5898 4.16016C8.86719 2.46484 6.10547 2.46484 4.38281 4.16016C3.91797 4.65234 3.5625 5.19922 3.37109 5.80078ZM1.56641 8.17969C1.59375 8.15234 1.64844 8.15234 1.67578 8.15234C1.73047 8.15234 1.75781 8.125 1.8125 8.125H5.3125C5.77734 8.125 6.1875 8.53516 6.1875 9C6.1875 9.49219 5.77734 9.875 5.3125 9.875H3.91797L4.38281 10.3672C6.10547 12.0625 8.86719 12.0625 10.5898 10.3672C11.0547 9.875 11.4102 9.32812 11.6016 8.72656C11.7656 8.26172 12.2852 8.01562 12.7227 8.17969C13.1875 8.34375 13.4336 8.83594 13.2695 9.30078C12.9688 10.1484 12.4766 10.9141 11.8203 11.5977C9.41406 13.9766 5.55859 13.9766 3.15234 11.5977L2.6875 11.1055V12.5C2.6875 12.9922 2.27734 13.375 1.8125 13.375C1.32031 13.375 0.9375 12.9922 0.9375 12.5V9.02734C0.9375 8.97266 0.9375 8.91797 0.9375 8.89062C0.9375 8.83594 0.9375 8.80859 0.964844 8.78125C0.992188 8.64453 1.07422 8.50781 1.18359 8.39844C1.29297 8.28906 1.42969 8.20703 1.56641 8.17969Z" fill="currentColor"/>
|
|
1341
|
+
</svg>`;
|
|
1342
|
+
var SORT_DOWN_ICON_SVG = `<svg width="9" height="6" viewBox="0 0 9 6" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
1343
|
+
<path d="M5.24274 5.36865C4.91462 5.72412 4.3404 5.72412 4.01227 5.36865L0.512273 1.86865C0.266179 1.62256 0.184148 1.23975 0.320867 0.911621C0.457586 0.583496 0.785711 0.364746 1.14118 0.364746H8.14118C8.46931 0.364746 8.79743 0.583496 8.93415 0.911621C9.07087 1.23975 8.98884 1.62256 8.74274 1.86865L5.24274 5.36865Z" fill="currentColor"/>
|
|
1344
|
+
</svg>`;
|
|
1345
|
+
var XMARK_ICON_SVG = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
1346
|
+
<path d="M4.22 4.22a.75.75 0 0 1 1.06 0L8 6.94l2.72-2.72a.75.75 0 1 1 1.06 1.06L9.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L8 9.06l-2.72 2.72a.75.75 0 1 1-1.06-1.06L6.94 8 4.22 5.28a.75.75 0 0 1 0-1.06z" fill="currentColor"/>
|
|
1347
|
+
</svg>`;
|
|
1348
|
+
var CLOSE_ICON_SVG = `<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
1349
|
+
<path d="M8.17578 1.07031C8.41016 0.816406 8.82031 0.816406 9.05469 1.07031C9.30859 1.30469 9.30859 1.71484 9.05469 1.94922L5.75391 5.25L9.05469 8.57031C9.30859 8.80469 9.30859 9.21484 9.05469 9.44922C8.82031 9.70312 8.41016 9.70312 8.17578 9.44922L4.875 6.14844L1.55469 9.44922C1.32031 9.70312 0.910156 9.70312 0.675781 9.44922C0.421875 9.21484 0.421875 8.80469 0.675781 8.57031L3.97656 5.25L0.675781 1.94922C0.421875 1.71484 0.421875 1.30469 0.675781 1.07031C0.910156 0.816406 1.32031 0.816406 1.55469 1.07031L4.875 4.37109L8.17578 1.07031Z" fill="currentColor"/>
|
|
1350
|
+
</svg>`;
|
|
1351
|
+
|
|
1352
|
+
// src/core/ui/toolbar.generated.ts
|
|
1353
|
+
var TOOLBAR_CSS = ":host{--prepr-primary:#4338ca;--prepr-bg:#eef2ff;--prepr-text:#1f2937;--prepr-radius:8px;--prepr-shadow:0px 0px 40px 0px #1f29373d;--prepr-z-index:10000;--prepr-primary-50:#eef2ff;--prepr-primary-100:#e0e7ff;--prepr-primary-800:#3730a3;--prepr-indigo-600:#4f46e5;--prepr-indigo-50:#eef2ff;--prepr-indigo-700:#4338ca;--prepr-secondary-400:#fb923c;--prepr-secondary-500:#f97316;--prepr-gray-100:#f3f4f6;--prepr-gray-200:#e5e7eb;--prepr-gray-300:#d1d5db;--prepr-gray-400:#9ca3af;--prepr-gray-500:#6b7280;--prepr-gray-700:#374151;--prepr-gray-800:#1f2937;--prepr-gray-900:#111827;--prepr-shadow-sm:0px 0px 12px 0px #c3c3c3cc;color:var(--prepr-text);box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.5}:host *,:host :before,:host :after,*,:before,:after{box-sizing:border-box}button{font-family:inherit;font-size:inherit;margin:0}.prepr-regular-text{font-size:.875rem;font-weight:500;line-height:1.5}.prepr-backdrop{z-index:calc(var(--prepr-z-index) - 1);opacity:0;pointer-events:none;background:#0000001a;transition:opacity .2s ease-in-out;position:fixed;top:0;bottom:0;left:0;right:0}.prepr-backdrop[data-open=true]{opacity:1;pointer-events:auto;animation:.2s ease-in-out prepr-fade-in}.prepr-container{z-index:var(--prepr-z-index);justify-content:flex-end;align-items:center;display:flex;position:fixed;top:calc(50% - 64px);right:0}.prepr-toggle-holder{padding:.5rem}.prepr-toggle{cursor:pointer;background:var(--prepr-primary);color:#fff;border:none;border-radius:9999px;justify-content:center;align-items:center;width:2.25rem;height:2.25rem;display:flex}.prepr-toggle svg{color:#fff}.prepr-panel{z-index:var(--prepr-z-index);opacity:0;pointer-events:none;justify-content:flex-end;padding:.75rem;transition:opacity .2s ease-in-out;display:flex;position:fixed;top:50%;right:0;transform:translateY(-50%)}.prepr-panel[data-open=true]{opacity:1;pointer-events:auto;animation:.2s ease-in-out prepr-fade-in}.prepr-content{box-shadow:var(--prepr-shadow);border-radius:var(--prepr-radius);background:var(--prepr-bg);flex-direction:column;gap:2.5rem;width:100%;padding:1.5rem;display:flex}@media (min-width:640px){.prepr-panel{margin-right:4rem;padding:0}.prepr-content{width:502px;padding:2.5rem}}.prepr-header{justify-content:space-between;align-items:center;gap:.5rem;display:flex}.prepr-header-left{align-items:flex-start;gap:.75rem;display:flex}.prepr-badge{background:var(--prepr-primary-100);height:1.5rem;color:var(--prepr-primary);border-radius:4px;align-items:center;padding:.25rem .75rem;font-size:.875rem;display:flex}.prepr-header-close{cursor:pointer;background:var(--prepr-primary-100);width:2rem;height:2rem;color:var(--prepr-gray-700);border:none;border-radius:6px;justify-content:center;align-items:center;display:flex}.prepr-section{flex-direction:column;gap:.5rem;display:flex}.prepr-section-label{color:var(--prepr-gray-400);font-size:.875rem}.prepr-row{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:.5rem 1.5rem;display:flex}.prepr-row-title{color:var(--prepr-gray-800);margin:0;font-size:1rem;font-weight:600}.prepr-radiogroup{border-radius:var(--prepr-radius);border:1px solid var(--prepr-gray-300);background:#fff;align-items:center;gap:.25rem;height:2.5rem;padding:.25rem;display:flex}.prepr-radiogroup[data-disabled=true]{cursor:not-allowed;opacity:.5}.prepr-radiogroup[data-disabled=true] .prepr-radio{pointer-events:none}.prepr-radio{cursor:pointer;white-space:nowrap;text-align:center;height:2rem;color:var(--prepr-gray-900);background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:.5rem 1.125rem;font-size:.875rem;font-weight:500;transition:all .2s ease-in-out;display:flex}.prepr-radio[data-checked=true]{background:var(--prepr-indigo-600);color:#fff;box-shadow:var(--prepr-shadow-sm)}.prepr-radio[data-checked=true][data-off=true]{background:var(--prepr-gray-800);color:#fff}.prepr-radio-variant{width:82px}.prepr-listbox{position:relative}.prepr-segment-button{border-radius:var(--prepr-radius);border:1px solid var(--prepr-gray-300);width:240px;height:2.5rem;color:var(--prepr-gray-500);cursor:pointer;background:#fff;flex-shrink:0;align-items:center;gap:.5rem;padding:0 .5rem;font-size:.875rem;font-weight:500;display:flex;overflow:hidden}@media (min-width:768px){.prepr-segment-button{padding:0 1rem}}.prepr-segment-button:disabled{cursor:not-allowed;background:var(--prepr-gray-200);color:var(--prepr-gray-400)}.prepr-segment-button[aria-expanded=true]{border-bottom-color:#fff;border-bottom-right-radius:0;border-bottom-left-radius:0}.prepr-segment-label{white-space:nowrap;text-overflow:ellipsis;text-align:left;width:100%;margin-right:auto;overflow:hidden}.prepr-segment-caret{color:var(--prepr-gray-800);display:flex}.prepr-options{z-index:calc(var(--prepr-z-index) + 1);border-left:1px solid var(--prepr-gray-300);border-right:1px solid var(--prepr-gray-300);border-bottom:1px solid var(--prepr-gray-300);-ms-overflow-style:none;scrollbar-width:none;background:#fff;border-radius:0 0 6px 6px;width:240px;max-height:300px;margin:0;padding:0;list-style:none;position:absolute;top:100%;left:0;overflow-y:auto;box-shadow:0 20px 25px -5px #0000001a,0 8px 10px -6px #0000001a}.prepr-options::-webkit-scrollbar{display:none}.prepr-options[hidden]{display:none}.prepr-option-search{background:#fff;padding:.5rem;position:-webkit-sticky;position:sticky;top:0}.prepr-segment-search{border:1px solid var(--prepr-gray-300);border-radius:var(--prepr-radius);width:100%;height:2rem;font:inherit;color:var(--prepr-gray-900);box-sizing:border-box;background:#fff;padding:0 .5rem;font-size:.875rem}.prepr-segment-search::placeholder{color:var(--prepr-gray-400)}.prepr-segment-search:focus{border-color:var(--prepr-gray-400);outline:none}.prepr-option{cursor:pointer;width:100%;color:var(--prepr-gray-900);background:#fff;align-items:center;padding:.5rem 1rem;font-size:.875rem;font-weight:500;display:flex}.prepr-option:hover{background:var(--prepr-gray-100)}.prepr-option[aria-selected=true]{background:var(--prepr-indigo-50);color:var(--prepr-indigo-700)}.prepr-option-label{white-space:nowrap;text-overflow:ellipsis;text-align:left;width:100%;margin-right:auto;overflow:hidden}.prepr-reset{background:var(--prepr-secondary-400);color:#fff;cursor:pointer;border:none;border-radius:6px;justify-content:center;align-items:center;gap:.5rem;width:100%;height:2.5rem;padding:.5rem .75rem;font-size:.875rem;font-weight:500;display:flex}.prepr-reset:hover:not(:disabled){background:var(--prepr-secondary-500)}.prepr-reset:disabled{background:var(--prepr-gray-400);color:var(--prepr-gray-500);cursor:not-allowed}@media (min-width:768px){.prepr-reset{width:108px}}.prepr-indicators{z-index:var(--prepr-z-index);gap:.75rem;display:flex;position:fixed;bottom:1.5rem;right:1.5rem}.prepr-status-pill{background:var(--prepr-primary);color:#fff;cursor:pointer;border:none;border-radius:9999px;align-items:center;gap:.5rem;padding:.5rem 1rem;font-size:.75rem;font-weight:500;transition:background-color .15s;display:flex;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a}.prepr-status-pill:hover{background:var(--prepr-primary-800)}.prepr-status-pill[hidden]{display:none}.prepr-status-viewing{color:#fff9;font-size:10px}.prepr-status-segment{text-overflow:ellipsis;white-space:nowrap;max-width:120px;display:inline-block;overflow:hidden}.prepr-status-variant{text-overflow:ellipsis;white-space:nowrap;background:#fff3;border-radius:4px;max-width:80px;padding:0 .5rem;display:inline-block;overflow:hidden}.prepr-status-x{color:#fff;width:.75rem;height:.75rem}.prepr-close-edit-pill{background:var(--prepr-primary-50);color:var(--prepr-gray-800);cursor:pointer;border:none;border-radius:9999px;align-items:center;gap:.5rem;padding:.5rem 1rem;font-size:.75rem;font-weight:500;transition:background-color .15s;display:flex;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a}.prepr-close-edit-pill:hover{background:var(--prepr-primary-100)}.prepr-close-edit-pill[hidden]{display:none}.prepr-close-edit-x{width:1rem;height:1rem;color:var(--prepr-gray-500);transition:color .15s}.prepr-close-edit-pill:hover .prepr-close-edit-x{color:var(--prepr-gray-700)}.prepr-tip{z-index:calc(var(--prepr-z-index) + 2);overflow-wrap:break-word;background:var(--prepr-gray-900);color:#fff;pointer-events:none;border-radius:6px;width:auto;max-width:min(420px,100vw - 16px);padding:.5rem .75rem;font-size:.75rem;font-weight:500;position:fixed;box-shadow:0 20px 25px -5px #0000001a,0 8px 10px -6px #0000001a}.prepr-tip-arrow{border-left:6px solid #0000;border-right:6px solid #0000;border-top:6px solid var(--prepr-gray-900);width:0;height:0;position:absolute;top:100%;transform:translate(-50%)}[hidden]{display:none!important}@keyframes prepr-fade-in{0%{opacity:0}to{opacity:1}}";
|
|
1354
|
+
|
|
1355
|
+
// ../../node_modules/.pnpm/preact@10.29.7/node_modules/preact/jsx-runtime/dist/jsxRuntime.mjs
|
|
1356
|
+
var f2 = 0;
|
|
1357
|
+
function u2(e2, t3, n2, o2, i2, u3) {
|
|
1358
|
+
t3 || (t3 = {});
|
|
1359
|
+
var a2, c2, p2 = t3;
|
|
1360
|
+
if ("ref" in p2) for (c2 in p2 = {}, t3) "ref" == c2 ? a2 = t3[c2] : p2[c2] = t3[c2];
|
|
1361
|
+
var l2 = { type: e2, props: p2, key: n2, ref: a2, __k: null, __: null, __b: 0, __e: null, __c: null, constructor: void 0, __v: --f2, __i: -1, __u: 0, __source: i2, __self: u3 };
|
|
1362
|
+
if ("function" == typeof e2 && (a2 = e2.defaultProps)) for (c2 in a2) void 0 === p2[c2] && (p2[c2] = a2[c2]);
|
|
1363
|
+
return l.vnode && l.vnode(l2), l2;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// src/core/ui/panel.tsx
|
|
1367
|
+
function RawSvg({ svg, className }) {
|
|
1368
|
+
return /* @__PURE__ */ u2(
|
|
1369
|
+
"span",
|
|
1370
|
+
{
|
|
1371
|
+
className,
|
|
1372
|
+
dangerouslySetInnerHTML: { __html: svg }
|
|
1373
|
+
}
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1376
|
+
function Header({ t: t3, onClose }) {
|
|
1377
|
+
return /* @__PURE__ */ u2("div", { class: "prepr-header", children: [
|
|
1378
|
+
/* @__PURE__ */ u2("div", { class: "prepr-header-left", children: [
|
|
1379
|
+
/* @__PURE__ */ u2(RawSvg, { svg: LOGO_SVG }),
|
|
1380
|
+
/* @__PURE__ */ u2("div", { class: "prepr-badge", "data-prepr": "badge", children: t3("common.toolbar") })
|
|
1381
|
+
] }),
|
|
1382
|
+
/* @__PURE__ */ u2(
|
|
1383
|
+
"button",
|
|
1384
|
+
{
|
|
1385
|
+
type: "button",
|
|
1386
|
+
class: "prepr-header-close",
|
|
1387
|
+
"data-prepr": "close",
|
|
1388
|
+
"aria-label": t3("common.toolbar"),
|
|
1389
|
+
onClick: onClose,
|
|
1390
|
+
children: /* @__PURE__ */ u2(RawSvg, { svg: CLOSE_ICON_SVG })
|
|
1391
|
+
}
|
|
1392
|
+
)
|
|
1393
|
+
] });
|
|
1394
|
+
}
|
|
1395
|
+
function PreviewSelector({
|
|
1396
|
+
state,
|
|
1397
|
+
t: t3,
|
|
1398
|
+
handlers
|
|
1399
|
+
}) {
|
|
1400
|
+
const value = String(state.previewMode);
|
|
1401
|
+
const options = [
|
|
1402
|
+
{
|
|
1403
|
+
v: false,
|
|
1404
|
+
label: t3("common.off"),
|
|
1405
|
+
off: true,
|
|
1406
|
+
tooltipKey: "adaptiveContent.offDescription"
|
|
1407
|
+
},
|
|
1408
|
+
{
|
|
1409
|
+
v: true,
|
|
1410
|
+
label: t3("common.on"),
|
|
1411
|
+
tooltipKey: "adaptiveContent.onDescription"
|
|
1412
|
+
}
|
|
1413
|
+
];
|
|
1414
|
+
return /* @__PURE__ */ u2("div", { class: "prepr-radiogroup", role: "radiogroup", "data-prepr": "preview-group", children: options.map((opt) => {
|
|
1415
|
+
const checked = value === String(opt.v);
|
|
1416
|
+
return /* @__PURE__ */ u2(
|
|
1417
|
+
"button",
|
|
1418
|
+
{
|
|
1419
|
+
type: "button",
|
|
1420
|
+
class: "prepr-radio",
|
|
1421
|
+
"data-prepr": "preview-mode",
|
|
1422
|
+
"data-value": String(opt.v),
|
|
1423
|
+
"data-off": opt.off ? "true" : void 0,
|
|
1424
|
+
role: "radio",
|
|
1425
|
+
"data-checked": String(checked),
|
|
1426
|
+
"aria-checked": checked,
|
|
1427
|
+
"data-tooltip-key": opt.tooltipKey,
|
|
1428
|
+
onClick: () => handlers.onPreviewMode(opt.v),
|
|
1429
|
+
onMouseEnter: (e2) => handlers.onPreviewTooltipEnter(e2.currentTarget),
|
|
1430
|
+
onMouseLeave: () => handlers.onPreviewTooltipLeave(),
|
|
1431
|
+
onFocus: (e2) => handlers.onPreviewTooltipEnter(e2.currentTarget),
|
|
1432
|
+
onBlur: () => handlers.onPreviewTooltipLeave(),
|
|
1433
|
+
children: opt.label
|
|
1434
|
+
}
|
|
1435
|
+
);
|
|
1436
|
+
}) });
|
|
1437
|
+
}
|
|
1438
|
+
function SegmentListbox({
|
|
1439
|
+
state,
|
|
1440
|
+
t: t3,
|
|
1441
|
+
listboxOpen,
|
|
1442
|
+
segmentFilter,
|
|
1443
|
+
handlers
|
|
1444
|
+
}) {
|
|
1445
|
+
const segments = state.segments;
|
|
1446
|
+
const hasSegments = segments.length > 0;
|
|
1447
|
+
const filter = segmentFilter.trim().toLowerCase();
|
|
1448
|
+
const visibleSegments = filter ? segments.filter((s2) => s2.name.toLowerCase().includes(filter)) : segments;
|
|
1449
|
+
let label;
|
|
1450
|
+
if (!hasSegments) {
|
|
1451
|
+
label = t3("adaptiveContent.none");
|
|
1452
|
+
} else if (state.selectedSegment === null) {
|
|
1453
|
+
label = t3("adaptiveContent.chooseSegment");
|
|
1454
|
+
} else {
|
|
1455
|
+
const seg = segments.find((s2) => s2._id === state.selectedSegment);
|
|
1456
|
+
label = seg ? seg.name : t3("adaptiveContent.chooseSegment");
|
|
1457
|
+
}
|
|
1458
|
+
const disabled = !hasSegments || !state.previewMode;
|
|
1459
|
+
return /* @__PURE__ */ u2("div", { class: "prepr-listbox", children: [
|
|
1460
|
+
/* @__PURE__ */ u2(
|
|
1461
|
+
"button",
|
|
1462
|
+
{
|
|
1463
|
+
type: "button",
|
|
1464
|
+
class: "prepr-segment-button",
|
|
1465
|
+
"data-prepr": "segment-button",
|
|
1466
|
+
"aria-haspopup": "listbox",
|
|
1467
|
+
"aria-expanded": listboxOpen,
|
|
1468
|
+
disabled,
|
|
1469
|
+
onClick: () => handlers.onSegmentButtonClick(),
|
|
1470
|
+
onKeyDown: (e2) => handlers.onSegmentButtonKeydown(e2),
|
|
1471
|
+
children: [
|
|
1472
|
+
/* @__PURE__ */ u2("span", { class: "prepr-segment-label", "data-prepr": "segment-button-label", children: label }),
|
|
1473
|
+
/* @__PURE__ */ u2("span", { class: "prepr-segment-caret", children: /* @__PURE__ */ u2(RawSvg, { svg: SORT_DOWN_ICON_SVG }) })
|
|
1474
|
+
]
|
|
1475
|
+
}
|
|
1476
|
+
),
|
|
1477
|
+
/* @__PURE__ */ u2(
|
|
1478
|
+
"ul",
|
|
1479
|
+
{
|
|
1480
|
+
class: "prepr-options",
|
|
1481
|
+
"data-prepr": "options",
|
|
1482
|
+
role: "listbox",
|
|
1483
|
+
hidden: !listboxOpen,
|
|
1484
|
+
onKeyDown: (e2) => handlers.onOptionsKeydown(e2),
|
|
1485
|
+
children: [
|
|
1486
|
+
/* @__PURE__ */ u2("li", { class: "prepr-option-search", role: "none", children: /* @__PURE__ */ u2(
|
|
1487
|
+
"input",
|
|
1488
|
+
{
|
|
1489
|
+
type: "text",
|
|
1490
|
+
class: "prepr-segment-search",
|
|
1491
|
+
"data-prepr": "segment-search",
|
|
1492
|
+
placeholder: t3("adaptiveContent.searchSegments"),
|
|
1493
|
+
value: segmentFilter,
|
|
1494
|
+
onInput: (e2) => handlers.onSegmentFilterInput(
|
|
1495
|
+
e2.currentTarget.value
|
|
1496
|
+
)
|
|
1497
|
+
}
|
|
1498
|
+
) }),
|
|
1499
|
+
visibleSegments.map((seg) => /* @__PURE__ */ u2(
|
|
1500
|
+
SegmentOption,
|
|
1501
|
+
{
|
|
1502
|
+
seg,
|
|
1503
|
+
selected: seg._id === state.selectedSegment,
|
|
1504
|
+
onChoose: handlers.onChooseSegment
|
|
1505
|
+
},
|
|
1506
|
+
seg._id
|
|
1507
|
+
))
|
|
1508
|
+
]
|
|
1509
|
+
}
|
|
1510
|
+
)
|
|
1511
|
+
] });
|
|
1512
|
+
}
|
|
1513
|
+
function SegmentOption({
|
|
1514
|
+
seg,
|
|
1515
|
+
selected,
|
|
1516
|
+
onChoose
|
|
1517
|
+
}) {
|
|
1518
|
+
return /* @__PURE__ */ u2(
|
|
1519
|
+
"li",
|
|
1520
|
+
{
|
|
1521
|
+
class: "prepr-option",
|
|
1522
|
+
role: "option",
|
|
1523
|
+
"data-value": seg._id,
|
|
1524
|
+
tabIndex: -1,
|
|
1525
|
+
"aria-selected": selected,
|
|
1526
|
+
onClick: () => onChoose(seg._id),
|
|
1527
|
+
children: /* @__PURE__ */ u2("span", { class: "prepr-option-label", children: seg.name })
|
|
1528
|
+
}
|
|
1529
|
+
);
|
|
1530
|
+
}
|
|
1531
|
+
function VariantSelector({
|
|
1532
|
+
state,
|
|
1533
|
+
handlers
|
|
1534
|
+
}) {
|
|
1535
|
+
const variantValue = state.selectedVariant === "B" ? "B" : "A";
|
|
1536
|
+
const values = ["A", "B"];
|
|
1537
|
+
return /* @__PURE__ */ u2(
|
|
1538
|
+
"div",
|
|
1539
|
+
{
|
|
1540
|
+
class: "prepr-radiogroup",
|
|
1541
|
+
role: "radiogroup",
|
|
1542
|
+
"data-prepr": "variant-group",
|
|
1543
|
+
"data-disabled": String(!state.previewMode),
|
|
1544
|
+
children: values.map((v2) => {
|
|
1545
|
+
const checked = variantValue === v2;
|
|
1546
|
+
return /* @__PURE__ */ u2(
|
|
1547
|
+
"button",
|
|
1548
|
+
{
|
|
1549
|
+
type: "button",
|
|
1550
|
+
class: "prepr-radio prepr-radio-variant",
|
|
1551
|
+
"data-prepr": "variant",
|
|
1552
|
+
"data-value": v2,
|
|
1553
|
+
role: "radio",
|
|
1554
|
+
"data-checked": String(checked),
|
|
1555
|
+
"aria-checked": checked,
|
|
1556
|
+
onClick: () => handlers.onVariant(v2),
|
|
1557
|
+
children: v2
|
|
1558
|
+
}
|
|
1559
|
+
);
|
|
1560
|
+
})
|
|
1561
|
+
}
|
|
1562
|
+
);
|
|
1563
|
+
}
|
|
1564
|
+
function EditModeSelector({
|
|
1565
|
+
state,
|
|
1566
|
+
t: t3,
|
|
1567
|
+
handlers
|
|
1568
|
+
}) {
|
|
1569
|
+
const value = String(state.editMode);
|
|
1570
|
+
const options = [
|
|
1571
|
+
{ v: false, label: t3("common.off"), off: true },
|
|
1572
|
+
{ v: true, label: t3("common.on") }
|
|
1573
|
+
];
|
|
1574
|
+
return /* @__PURE__ */ u2("div", { class: "prepr-radiogroup", role: "radiogroup", "data-prepr": "edit-group", children: options.map((opt) => {
|
|
1575
|
+
const checked = value === String(opt.v);
|
|
1576
|
+
return /* @__PURE__ */ u2(
|
|
1577
|
+
"button",
|
|
1578
|
+
{
|
|
1579
|
+
type: "button",
|
|
1580
|
+
class: "prepr-radio",
|
|
1581
|
+
"data-prepr": "edit-mode",
|
|
1582
|
+
"data-value": String(opt.v),
|
|
1583
|
+
"data-off": opt.off ? "true" : void 0,
|
|
1584
|
+
role: "radio",
|
|
1585
|
+
"data-checked": String(checked),
|
|
1586
|
+
"aria-checked": checked,
|
|
1587
|
+
onClick: () => handlers.onEditMode(opt.v),
|
|
1588
|
+
children: opt.label
|
|
1589
|
+
}
|
|
1590
|
+
);
|
|
1591
|
+
}) });
|
|
1592
|
+
}
|
|
1593
|
+
function StatusPill({
|
|
1594
|
+
state,
|
|
1595
|
+
t: t3,
|
|
1596
|
+
handlers
|
|
1597
|
+
}) {
|
|
1598
|
+
const { features } = state;
|
|
1599
|
+
const defaultSegmentName = state.segments.find((s2) => s2._id === "all_other_users")?.name ?? t3("adaptiveContent.allOtherUsers");
|
|
1600
|
+
let segmentLabel;
|
|
1601
|
+
if (!state.previewMode || !features.segments) {
|
|
1602
|
+
segmentLabel = t3("common.user");
|
|
1603
|
+
} else if (state.selectedSegment !== null) {
|
|
1604
|
+
const seg = state.segments.find((s2) => s2._id === state.selectedSegment);
|
|
1605
|
+
segmentLabel = seg ? seg.name : defaultSegmentName;
|
|
1606
|
+
} else {
|
|
1607
|
+
segmentLabel = defaultSegmentName;
|
|
1608
|
+
}
|
|
1609
|
+
return /* @__PURE__ */ u2(
|
|
1610
|
+
"button",
|
|
1611
|
+
{
|
|
1612
|
+
type: "button",
|
|
1613
|
+
class: "prepr-status-pill",
|
|
1614
|
+
"data-prepr": "status-pill",
|
|
1615
|
+
hidden: state.isIframe,
|
|
1616
|
+
onClick: () => handlers.onStatusPill(),
|
|
1617
|
+
children: [
|
|
1618
|
+
/* @__PURE__ */ u2("span", { class: "prepr-status-viewing", "data-prepr": "status-viewing", children: t3("common.viewingAs") }),
|
|
1619
|
+
/* @__PURE__ */ u2("span", { class: "prepr-status-segment", "data-prepr": "status-segment", children: segmentLabel }),
|
|
1620
|
+
/* @__PURE__ */ u2(
|
|
1621
|
+
"span",
|
|
1622
|
+
{
|
|
1623
|
+
class: "prepr-status-variant",
|
|
1624
|
+
"data-prepr": "status-variant",
|
|
1625
|
+
hidden: !features.abTesting || !state.previewMode,
|
|
1626
|
+
children: state.selectedVariant === "B" ? "B" : "A"
|
|
1627
|
+
}
|
|
1628
|
+
),
|
|
1629
|
+
/* @__PURE__ */ u2(
|
|
1630
|
+
"span",
|
|
1631
|
+
{
|
|
1632
|
+
class: "prepr-status-x",
|
|
1633
|
+
"data-prepr": "status-x",
|
|
1634
|
+
hidden: !features.segments || !state.previewMode || state.selectedSegment === null,
|
|
1635
|
+
children: /* @__PURE__ */ u2(RawSvg, { svg: XMARK_ICON_SVG })
|
|
1636
|
+
}
|
|
1637
|
+
)
|
|
1638
|
+
]
|
|
1639
|
+
}
|
|
1640
|
+
);
|
|
1641
|
+
}
|
|
1642
|
+
function CloseEditPill({
|
|
1643
|
+
state,
|
|
1644
|
+
t: t3,
|
|
1645
|
+
handlers
|
|
1646
|
+
}) {
|
|
1647
|
+
return /* @__PURE__ */ u2(
|
|
1648
|
+
"button",
|
|
1649
|
+
{
|
|
1650
|
+
type: "button",
|
|
1651
|
+
class: "prepr-close-edit-pill",
|
|
1652
|
+
"data-prepr": "close-edit-pill",
|
|
1653
|
+
"aria-label": t3("editingTools.ariaCloseEditMode"),
|
|
1654
|
+
hidden: !state.features.editMode || !state.editMode || state.isIframe,
|
|
1655
|
+
onClick: () => handlers.onCloseEditPill(),
|
|
1656
|
+
children: [
|
|
1657
|
+
/* @__PURE__ */ u2("span", { "data-prepr": "close-edit-label", children: t3("editingTools.editMode") }),
|
|
1658
|
+
/* @__PURE__ */ u2("span", { class: "prepr-close-edit-x", children: /* @__PURE__ */ u2(RawSvg, { svg: XMARK_ICON_SVG }) })
|
|
1659
|
+
]
|
|
1660
|
+
}
|
|
1661
|
+
);
|
|
1662
|
+
}
|
|
1663
|
+
function Panel({
|
|
1664
|
+
state,
|
|
1665
|
+
t: t3,
|
|
1666
|
+
listboxOpen,
|
|
1667
|
+
segmentFilter,
|
|
1668
|
+
handlers
|
|
1669
|
+
}) {
|
|
1670
|
+
const { features } = state;
|
|
1671
|
+
const hasPersonalization = features.segments && state.selectedSegment !== null || features.abTesting && state.selectedVariant !== null;
|
|
1672
|
+
const showAdaptive = features.segments || features.abTesting;
|
|
1673
|
+
return /* @__PURE__ */ u2(S, { children: [
|
|
1674
|
+
/* @__PURE__ */ u2(
|
|
1675
|
+
"style",
|
|
1676
|
+
{
|
|
1677
|
+
dangerouslySetInnerHTML: { __html: TOOLBAR_CSS }
|
|
1678
|
+
}
|
|
1679
|
+
),
|
|
1680
|
+
/* @__PURE__ */ u2(
|
|
1681
|
+
"div",
|
|
1682
|
+
{
|
|
1683
|
+
class: "prepr-backdrop",
|
|
1684
|
+
"data-prepr": "backdrop",
|
|
1685
|
+
"data-open": String(state.toolbarOpen)
|
|
1686
|
+
}
|
|
1687
|
+
),
|
|
1688
|
+
/* @__PURE__ */ u2("div", { class: "prepr-container", children: /* @__PURE__ */ u2("div", { class: "prepr-toggle-holder", children: /* @__PURE__ */ u2(
|
|
1689
|
+
"button",
|
|
1690
|
+
{
|
|
1691
|
+
type: "button",
|
|
1692
|
+
class: "prepr-toggle",
|
|
1693
|
+
"data-prepr": "toggle",
|
|
1694
|
+
"aria-label": t3("common.toolbar"),
|
|
1695
|
+
onClick: () => handlers.onToggle(),
|
|
1696
|
+
children: /* @__PURE__ */ u2(RawSvg, { svg: TOGGLE_ICON_SVG })
|
|
1697
|
+
}
|
|
1698
|
+
) }) }),
|
|
1699
|
+
/* @__PURE__ */ u2(
|
|
1700
|
+
"div",
|
|
1701
|
+
{
|
|
1702
|
+
class: "prepr-panel",
|
|
1703
|
+
"data-prepr": "panel",
|
|
1704
|
+
"data-open": String(state.toolbarOpen),
|
|
1705
|
+
children: /* @__PURE__ */ u2(
|
|
1706
|
+
"div",
|
|
1707
|
+
{
|
|
1708
|
+
class: "prepr-content",
|
|
1709
|
+
"data-prepr": "content",
|
|
1710
|
+
role: "dialog",
|
|
1711
|
+
"aria-label": t3("common.toolbar"),
|
|
1712
|
+
children: [
|
|
1713
|
+
/* @__PURE__ */ u2(Header, { t: t3, onClose: handlers.onClose }),
|
|
1714
|
+
/* @__PURE__ */ u2("div", { class: "prepr-section", "data-prepr": "section-adaptive", children: [
|
|
1715
|
+
/* @__PURE__ */ u2("span", { class: "prepr-section-label", "data-prepr": "adaptive-label", children: showAdaptive ? t3("adaptiveContent.adaptiveContent") : t3("adaptiveContent.enablePreview") }),
|
|
1716
|
+
/* @__PURE__ */ u2("div", { class: "prepr-row", children: [
|
|
1717
|
+
/* @__PURE__ */ u2("h2", { class: "prepr-row-title", "data-prepr": "preview-label", children: t3("adaptiveContent.enablePreview") }),
|
|
1718
|
+
/* @__PURE__ */ u2(PreviewSelector, { state, t: t3, handlers })
|
|
1719
|
+
] }),
|
|
1720
|
+
features.segments && /* @__PURE__ */ u2("div", { class: "prepr-row", children: [
|
|
1721
|
+
/* @__PURE__ */ u2("h2", { class: "prepr-row-title", "data-prepr": "segment-label", children: t3("adaptiveContent.segment") }),
|
|
1722
|
+
/* @__PURE__ */ u2(
|
|
1723
|
+
SegmentListbox,
|
|
1724
|
+
{
|
|
1725
|
+
state,
|
|
1726
|
+
t: t3,
|
|
1727
|
+
listboxOpen,
|
|
1728
|
+
segmentFilter,
|
|
1729
|
+
handlers
|
|
1730
|
+
}
|
|
1731
|
+
)
|
|
1732
|
+
] }),
|
|
1733
|
+
features.abTesting && /* @__PURE__ */ u2("div", { class: "prepr-row", children: [
|
|
1734
|
+
/* @__PURE__ */ u2("h2", { class: "prepr-row-title", "data-prepr": "variant-label", children: t3("adaptiveContent.ABVariant") }),
|
|
1735
|
+
/* @__PURE__ */ u2(VariantSelector, { state, handlers })
|
|
1736
|
+
] })
|
|
1737
|
+
] }),
|
|
1738
|
+
features.editMode && /* @__PURE__ */ u2("div", { class: "prepr-section", "data-prepr": "section-editing", children: [
|
|
1739
|
+
/* @__PURE__ */ u2("span", { class: "prepr-section-label", "data-prepr": "editing-label", children: t3("editingTools.editingTools") }),
|
|
1740
|
+
/* @__PURE__ */ u2("div", { class: "prepr-row", children: [
|
|
1741
|
+
/* @__PURE__ */ u2("h2", { class: "prepr-row-title", "data-prepr": "edit-label", children: t3("editingTools.editMode") }),
|
|
1742
|
+
/* @__PURE__ */ u2(EditModeSelector, { state, t: t3, handlers })
|
|
1743
|
+
] })
|
|
1744
|
+
] }),
|
|
1745
|
+
/* @__PURE__ */ u2(
|
|
1746
|
+
"button",
|
|
1747
|
+
{
|
|
1748
|
+
type: "button",
|
|
1749
|
+
class: "prepr-reset",
|
|
1750
|
+
"data-prepr": "reset",
|
|
1751
|
+
disabled: !hasPersonalization,
|
|
1752
|
+
onClick: () => handlers.onReset(),
|
|
1753
|
+
children: [
|
|
1754
|
+
/* @__PURE__ */ u2(RawSvg, { svg: ROTATE_ICON_SVG }),
|
|
1755
|
+
/* @__PURE__ */ u2("span", { "data-prepr": "reset-label", children: t3("common.reset") })
|
|
1756
|
+
]
|
|
1757
|
+
}
|
|
1758
|
+
)
|
|
1759
|
+
]
|
|
1760
|
+
}
|
|
1761
|
+
)
|
|
1762
|
+
}
|
|
1763
|
+
),
|
|
1764
|
+
/* @__PURE__ */ u2("div", { class: "prepr-indicators", children: [
|
|
1765
|
+
/* @__PURE__ */ u2(StatusPill, { state, t: t3, handlers }),
|
|
1766
|
+
/* @__PURE__ */ u2(CloseEditPill, { state, t: t3, handlers })
|
|
1767
|
+
] }),
|
|
1768
|
+
/* @__PURE__ */ u2("div", { class: "prepr-tip", "data-prepr": "tooltip", role: "tooltip", hidden: true, children: [
|
|
1769
|
+
/* @__PURE__ */ u2("span", { "data-prepr": "tooltip-text" }),
|
|
1770
|
+
/* @__PURE__ */ u2("span", { class: "prepr-tip-arrow", "data-prepr": "tooltip-arrow" })
|
|
1771
|
+
] })
|
|
1772
|
+
] });
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
// src/core/ui/toolbar-element.ts
|
|
1776
|
+
var TAG_NAME = "prepr-toolbar";
|
|
1777
|
+
var HTMLElementBase = typeof HTMLElement === "undefined" ? class {
|
|
1778
|
+
} : HTMLElement;
|
|
1779
|
+
var PreprToolbarElement = class extends HTMLElementBase {
|
|
1780
|
+
constructor() {
|
|
1781
|
+
super(...arguments);
|
|
1782
|
+
this.store = null;
|
|
1783
|
+
this.t = (key) => key;
|
|
1784
|
+
this.unsubscribe = null;
|
|
1785
|
+
this.listboxOpen = false;
|
|
1786
|
+
this.segmentFilter = "";
|
|
1787
|
+
this.handlers = {
|
|
1788
|
+
onToggle: () => this.set({ toolbarOpen: !this.state.toolbarOpen }),
|
|
1789
|
+
onClose: () => this.set({ toolbarOpen: false }),
|
|
1790
|
+
onPreviewMode: (value) => this.set({ previewMode: value }),
|
|
1791
|
+
onEditMode: (value) => {
|
|
1792
|
+
if (!this.state.features.editMode) return;
|
|
1793
|
+
this.set({ editMode: value });
|
|
1794
|
+
},
|
|
1795
|
+
onVariant: (value) => {
|
|
1796
|
+
if (!this.state.features.abTesting) return;
|
|
1797
|
+
if (!this.state.previewMode) return;
|
|
1798
|
+
this.set({ selectedVariant: value });
|
|
1799
|
+
},
|
|
1800
|
+
// Reset contract: segment to none, variant to 'A' — NOT null, since the
|
|
1801
|
+
// resulting `variant_changed` must carry 'A' on the wire — edit mode off.
|
|
1802
|
+
// Disabled features are left untouched: their state is already inert and
|
|
1803
|
+
// writing it would emit events for a feature the consumer turned off.
|
|
1804
|
+
onReset: () => this.set(this.resetPatch({ editMode: false })),
|
|
1805
|
+
onStatusPill: () => {
|
|
1806
|
+
if (!this.state.previewMode) {
|
|
1807
|
+
this.set({ previewMode: true });
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
const patch = this.resetPatch();
|
|
1811
|
+
const dirty = "selectedSegment" in patch && this.state.selectedSegment !== null || "selectedVariant" in patch && this.state.selectedVariant !== "A";
|
|
1812
|
+
if (dirty) this.set(patch);
|
|
1813
|
+
},
|
|
1814
|
+
onCloseEditPill: () => this.set({ editMode: false }),
|
|
1815
|
+
onSegmentButtonClick: () => this.toggleListbox(!this.listboxOpen),
|
|
1816
|
+
onSegmentButtonKeydown: (e2) => this.onListboxKeydown(e2),
|
|
1817
|
+
onOptionsKeydown: (e2) => this.onListboxKeydown(e2),
|
|
1818
|
+
onChooseSegment: (id) => this.chooseSegment(id),
|
|
1819
|
+
onSegmentFilterInput: (value) => {
|
|
1820
|
+
this.segmentFilter = value;
|
|
1821
|
+
this.renderPanel(this.state);
|
|
1822
|
+
},
|
|
1823
|
+
onPreviewTooltipEnter: (el) => this.showTooltip(el),
|
|
1824
|
+
onPreviewTooltipLeave: () => this.hideTooltip()
|
|
1825
|
+
};
|
|
1826
|
+
this.onDocumentMouseDown = (event) => {
|
|
1827
|
+
if (!this.listboxOpen) return;
|
|
1828
|
+
const button = this.segmentButton();
|
|
1829
|
+
const options = this.optionsList();
|
|
1830
|
+
if (!button || !options) return;
|
|
1831
|
+
const path = event.composedPath();
|
|
1832
|
+
if (!path.includes(button) && !path.includes(options)) {
|
|
1833
|
+
this.toggleListbox(false);
|
|
1834
|
+
}
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
/** Idempotent: calling connect twice re-wires to the (possibly new) store. */
|
|
1838
|
+
connect(store, t3) {
|
|
1839
|
+
this.store = store;
|
|
1840
|
+
this.t = t3;
|
|
1841
|
+
if (!this.shadowRoot) {
|
|
1842
|
+
this.attachShadow({ mode: "open" });
|
|
1843
|
+
}
|
|
1844
|
+
this.unsubscribe?.();
|
|
1845
|
+
this.unsubscribe = store.subscribe((state) => this.renderPanel(state));
|
|
1846
|
+
document.removeEventListener("mousedown", this.onDocumentMouseDown);
|
|
1847
|
+
document.addEventListener("mousedown", this.onDocumentMouseDown);
|
|
1848
|
+
this.renderPanel(store.get());
|
|
1849
|
+
}
|
|
1850
|
+
disconnectedCallback() {
|
|
1851
|
+
this.unsubscribe?.();
|
|
1852
|
+
this.unsubscribe = null;
|
|
1853
|
+
document.removeEventListener("mousedown", this.onDocumentMouseDown);
|
|
1854
|
+
}
|
|
1855
|
+
// --------------------------------------------------------------- rendering
|
|
1856
|
+
get state() {
|
|
1857
|
+
return this.store.get();
|
|
1858
|
+
}
|
|
1859
|
+
set(patch) {
|
|
1860
|
+
this.store?.set(patch);
|
|
1861
|
+
}
|
|
1862
|
+
/** Reset patch covering only the enabled personalization features. */
|
|
1863
|
+
resetPatch(base = {}) {
|
|
1864
|
+
const { features } = this.state;
|
|
1865
|
+
const patch = { ...base };
|
|
1866
|
+
if (features.segments) patch.selectedSegment = null;
|
|
1867
|
+
if (features.abTesting) patch.selectedVariant = "A";
|
|
1868
|
+
return patch;
|
|
1869
|
+
}
|
|
1870
|
+
// Synchronous: Preact's top-level render() mutates the DOM before returning.
|
|
1871
|
+
renderPanel(state) {
|
|
1872
|
+
const root = this.shadowRoot;
|
|
1873
|
+
if (!root) return;
|
|
1874
|
+
R(
|
|
1875
|
+
k(Panel, {
|
|
1876
|
+
state,
|
|
1877
|
+
t: this.t,
|
|
1878
|
+
listboxOpen: this.listboxOpen,
|
|
1879
|
+
segmentFilter: this.segmentFilter,
|
|
1880
|
+
handlers: this.handlers
|
|
1881
|
+
}),
|
|
1882
|
+
root
|
|
1883
|
+
);
|
|
1884
|
+
}
|
|
1885
|
+
// ---------------------------------------------------------------- tooltip
|
|
1886
|
+
tip() {
|
|
1887
|
+
return this.shadowRoot?.querySelector('[data-prepr="tooltip"]') ?? null;
|
|
1888
|
+
}
|
|
1889
|
+
/**
|
|
1890
|
+
* Show the tooltip for a trigger carrying `data-tooltip-key`. Applied
|
|
1891
|
+
* imperatively rather than through the Preact tree: hover/focus never write
|
|
1892
|
+
* to the store, so no re-render can clobber it in between. Positioning is
|
|
1893
|
+
* centered above the trigger, clamped to the viewport with 8px padding,
|
|
1894
|
+
* arrow tracking the trigger center.
|
|
1895
|
+
*/
|
|
1896
|
+
showTooltip(trigger) {
|
|
1897
|
+
const tooltip = this.tip();
|
|
1898
|
+
if (!tooltip) return;
|
|
1899
|
+
const textEl = tooltip.querySelector(
|
|
1900
|
+
'[data-prepr="tooltip-text"]'
|
|
1901
|
+
);
|
|
1902
|
+
const arrowEl = tooltip.querySelector(
|
|
1903
|
+
'[data-prepr="tooltip-arrow"]'
|
|
1904
|
+
);
|
|
1905
|
+
const key = trigger.getAttribute("data-tooltip-key");
|
|
1906
|
+
if (!key || !textEl || !arrowEl) return;
|
|
1907
|
+
textEl.textContent = this.t(key);
|
|
1908
|
+
tooltip.hidden = false;
|
|
1909
|
+
const padding = 8;
|
|
1910
|
+
const tip = tooltip.getBoundingClientRect();
|
|
1911
|
+
const tri = trigger.getBoundingClientRect();
|
|
1912
|
+
const centerX = tri.left + tri.width / 2;
|
|
1913
|
+
const spaceAbove = tri.top - padding;
|
|
1914
|
+
const spaceBelow = window.innerHeight - tri.bottom - padding;
|
|
1915
|
+
const placeTop = tip.height + padding <= spaceAbove || tip.height + padding > spaceBelow;
|
|
1916
|
+
const top = placeTop ? tri.top - tip.height - 8 : tri.bottom + 8;
|
|
1917
|
+
let left = centerX - tip.width / 2;
|
|
1918
|
+
if (left < padding) left = padding;
|
|
1919
|
+
if (left + tip.width > window.innerWidth - padding) {
|
|
1920
|
+
left = window.innerWidth - padding - tip.width;
|
|
1921
|
+
}
|
|
1922
|
+
const arrowX = Math.max(10, Math.min(centerX - left, tip.width - 10));
|
|
1923
|
+
tooltip.style.top = `${top}px`;
|
|
1924
|
+
tooltip.style.left = `${left}px`;
|
|
1925
|
+
arrowEl.style.left = `${arrowX}px`;
|
|
1926
|
+
}
|
|
1927
|
+
hideTooltip() {
|
|
1928
|
+
const tooltip = this.tip();
|
|
1929
|
+
if (tooltip) tooltip.hidden = true;
|
|
1930
|
+
}
|
|
1931
|
+
// ------------------------------------------------------- listbox controller
|
|
1932
|
+
segmentButton() {
|
|
1933
|
+
return this.shadowRoot?.querySelector(
|
|
1934
|
+
'[data-prepr="segment-button"]'
|
|
1935
|
+
) ?? null;
|
|
1936
|
+
}
|
|
1937
|
+
optionsList() {
|
|
1938
|
+
return this.shadowRoot?.querySelector(
|
|
1939
|
+
'[data-prepr="options"]'
|
|
1940
|
+
) ?? null;
|
|
1941
|
+
}
|
|
1942
|
+
onListboxKeydown(event) {
|
|
1943
|
+
const e2 = event;
|
|
1944
|
+
const options = this.optionEls();
|
|
1945
|
+
const inSearch = e2.target?.getAttribute?.("data-prepr") === "segment-search";
|
|
1946
|
+
if (inSearch && e2.key === " ") return;
|
|
1947
|
+
if (options.length === 0 && e2.key !== "Escape") return;
|
|
1948
|
+
switch (e2.key) {
|
|
1949
|
+
case "Enter":
|
|
1950
|
+
case " ": {
|
|
1951
|
+
e2.preventDefault();
|
|
1952
|
+
if (!this.listboxOpen) {
|
|
1953
|
+
this.toggleListbox(true);
|
|
1954
|
+
} else {
|
|
1955
|
+
const active = this.activeOptionIndex();
|
|
1956
|
+
if (active >= 0) this.chooseSegment(options[active].dataset.value);
|
|
1957
|
+
}
|
|
1958
|
+
break;
|
|
1959
|
+
}
|
|
1960
|
+
case "Escape": {
|
|
1961
|
+
e2.preventDefault();
|
|
1962
|
+
this.toggleListbox(false);
|
|
1963
|
+
this.segmentButton()?.focus();
|
|
1964
|
+
break;
|
|
1965
|
+
}
|
|
1966
|
+
case "ArrowDown": {
|
|
1967
|
+
e2.preventDefault();
|
|
1968
|
+
if (!this.listboxOpen) this.toggleListbox(true);
|
|
1969
|
+
this.moveActiveOption(1);
|
|
1970
|
+
break;
|
|
1971
|
+
}
|
|
1972
|
+
case "ArrowUp": {
|
|
1973
|
+
e2.preventDefault();
|
|
1974
|
+
if (!this.listboxOpen) this.toggleListbox(true);
|
|
1975
|
+
this.moveActiveOption(-1);
|
|
1976
|
+
break;
|
|
1977
|
+
}
|
|
1978
|
+
default:
|
|
1979
|
+
break;
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
optionEls() {
|
|
1983
|
+
const options = this.optionsList();
|
|
1984
|
+
if (!options) return [];
|
|
1985
|
+
return Array.from(options.querySelectorAll('[role="option"]'));
|
|
1986
|
+
}
|
|
1987
|
+
activeOptionIndex() {
|
|
1988
|
+
return this.optionEls().findIndex(
|
|
1989
|
+
(el) => el.getAttribute("data-active") === "true"
|
|
1990
|
+
);
|
|
1991
|
+
}
|
|
1992
|
+
moveActiveOption(delta) {
|
|
1993
|
+
const options = this.optionEls();
|
|
1994
|
+
if (options.length === 0) return;
|
|
1995
|
+
let index = this.activeOptionIndex();
|
|
1996
|
+
index = index < 0 ? 0 : (index + delta + options.length) % options.length;
|
|
1997
|
+
options.forEach(
|
|
1998
|
+
(el, i2) => el.setAttribute("data-active", String(i2 === index))
|
|
1999
|
+
);
|
|
2000
|
+
options[index].focus();
|
|
2001
|
+
}
|
|
2002
|
+
// Open state is view-only, so it lives on the element rather than the store.
|
|
2003
|
+
// Active-option attributes and focus are set after the synchronous re-render.
|
|
2004
|
+
toggleListbox(open) {
|
|
2005
|
+
const button = this.segmentButton();
|
|
2006
|
+
if (button?.disabled) return;
|
|
2007
|
+
this.listboxOpen = open;
|
|
2008
|
+
this.segmentFilter = "";
|
|
2009
|
+
this.renderPanel(this.state);
|
|
2010
|
+
if (open) {
|
|
2011
|
+
const options = this.optionEls();
|
|
2012
|
+
const selectedIndex = options.findIndex(
|
|
2013
|
+
(el) => el.getAttribute("aria-selected") === "true"
|
|
2014
|
+
);
|
|
2015
|
+
const activeIndex = selectedIndex >= 0 ? selectedIndex : 0;
|
|
2016
|
+
options.forEach(
|
|
2017
|
+
(el, i2) => el.setAttribute("data-active", String(i2 === activeIndex))
|
|
2018
|
+
);
|
|
2019
|
+
this.searchInput()?.focus();
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
searchInput() {
|
|
2023
|
+
return this.shadowRoot?.querySelector(
|
|
2024
|
+
'[data-prepr="segment-search"]'
|
|
2025
|
+
) ?? null;
|
|
2026
|
+
}
|
|
2027
|
+
chooseSegment(id) {
|
|
2028
|
+
if (!this.state.features.segments) return;
|
|
2029
|
+
this.listboxOpen = false;
|
|
2030
|
+
this.segmentFilter = "";
|
|
2031
|
+
this.set({ selectedSegment: id });
|
|
2032
|
+
this.renderPanel(this.state);
|
|
2033
|
+
this.segmentButton()?.focus();
|
|
2034
|
+
}
|
|
2035
|
+
};
|
|
2036
|
+
function definePreprToolbar() {
|
|
2037
|
+
if (typeof customElements === "undefined") return;
|
|
2038
|
+
if (!customElements.get(TAG_NAME)) {
|
|
2039
|
+
customElements.define(TAG_NAME, PreprToolbarElement);
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
// src/core/create-preview.ts
|
|
2044
|
+
var debug7 = createScopedLogger("create-preview");
|
|
2045
|
+
var controllerStores = /* @__PURE__ */ new WeakMap();
|
|
2046
|
+
function defaultNavigation() {
|
|
2047
|
+
return {
|
|
2048
|
+
navigate: (url) => window.location.assign(url),
|
|
2049
|
+
currentPath: () => window.location.pathname + window.location.search
|
|
2050
|
+
};
|
|
2051
|
+
}
|
|
2052
|
+
function buildSegments(data) {
|
|
2053
|
+
return [{ _id: "all_other_users", name: "All other users" }, ...data];
|
|
2054
|
+
}
|
|
2055
|
+
function resolveLocale(options) {
|
|
2056
|
+
const explicit = options?.locale;
|
|
2057
|
+
if (isLocale(explicit)) return explicit;
|
|
2058
|
+
if (typeof navigator !== "undefined") {
|
|
2059
|
+
const candidates = Array.isArray(navigator.languages) && navigator.languages.length ? navigator.languages : [navigator.language];
|
|
2060
|
+
const match = candidates.filter(Boolean).map((l2) => l2.toLowerCase().split("-")[0]).find(isLocale);
|
|
2061
|
+
if (match) return match;
|
|
2062
|
+
}
|
|
2063
|
+
return "en";
|
|
2064
|
+
}
|
|
2065
|
+
function createPreprPreview(opts = {}) {
|
|
2066
|
+
const { props, options } = opts;
|
|
2067
|
+
const navigation = opts.navigation ?? defaultNavigation();
|
|
2068
|
+
initDebugLogger(options?.debug ?? false);
|
|
2069
|
+
const noop = () => ({ destroy: () => {
|
|
2070
|
+
} });
|
|
2071
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
2072
|
+
return noop();
|
|
2073
|
+
}
|
|
2074
|
+
const isIframe = window.parent !== window;
|
|
2075
|
+
const search = new URLSearchParams(window.location.search);
|
|
2076
|
+
const hideBar = search.get(PARAM_HIDE_BAR) === "true";
|
|
2077
|
+
if (hideBar) {
|
|
2078
|
+
debug7.log(`${PARAM_HIDE_BAR}=true \u2014 no visible toolbar`);
|
|
2079
|
+
}
|
|
2080
|
+
const mountUi = (options?.ui ?? true) && !isIframe && !hideBar;
|
|
2081
|
+
const locale = resolveLocale(options);
|
|
2082
|
+
const features = resolveFeatures(options?.features);
|
|
2083
|
+
const previewMode = getCookie(COOKIE_PREVIEW_MODE) === "true";
|
|
2084
|
+
const toolbarOpen = getCookie(COOKIE_TOOLBAR_OPEN) === "true";
|
|
2085
|
+
const cookieSegment = features.segments ? getCookie(COOKIE_SEGMENT) : null;
|
|
2086
|
+
const cookieVariant = features.abTesting ? getCookie(COOKIE_VARIANT) : null;
|
|
2087
|
+
const rawVariant = features.abTesting ? props?.activeVariant ?? cookieVariant : null;
|
|
2088
|
+
const selectedVariant = rawVariant === "A" || rawVariant === "B" ? rawVariant : null;
|
|
2089
|
+
const store = createToolbarStore({
|
|
2090
|
+
locale,
|
|
2091
|
+
features,
|
|
2092
|
+
segments: features.segments ? buildSegments(props?.segments ?? props?.data ?? []) : [],
|
|
2093
|
+
selectedSegment: features.segments ? props?.activeSegment ?? cookieSegment ?? null : null,
|
|
2094
|
+
selectedVariant,
|
|
2095
|
+
previewMode,
|
|
2096
|
+
toolbarOpen,
|
|
2097
|
+
isIframe
|
|
2098
|
+
});
|
|
2099
|
+
let el = null;
|
|
2100
|
+
if (mountUi) {
|
|
2101
|
+
definePreprToolbar();
|
|
2102
|
+
el = document.createElement("prepr-toolbar");
|
|
2103
|
+
document.body.appendChild(el);
|
|
2104
|
+
el.connect(store, (key) => t(key, locale));
|
|
2105
|
+
}
|
|
2106
|
+
const editingEnabled = features.editMode || isIframe;
|
|
2107
|
+
const stega = createStegaController({
|
|
2108
|
+
// The CMS deep-link tooltip is chrome, so it follows the same decision as
|
|
2109
|
+
// the bar: noise inside the editor (clicking the element itself requests
|
|
2110
|
+
// the edit there), and unwanted in a headless preview that asked for no UI.
|
|
2111
|
+
tooltip: mountUi,
|
|
2112
|
+
// In the editor, ask the parent to focus the field instead of opening a new
|
|
2113
|
+
// tab. Standalone previews keep the window.open behaviour.
|
|
2114
|
+
onEdit: ({ href, origin, id, field }) => {
|
|
2115
|
+
if (isIframe) {
|
|
2116
|
+
sendPreprEvent("field_edit_requested", { href, origin, id, field });
|
|
2117
|
+
} else if (href) {
|
|
2118
|
+
window.open(href);
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
});
|
|
2122
|
+
const autoClean = createStegaAutoClean();
|
|
2123
|
+
let autoCleanActive = false;
|
|
2124
|
+
function syncAutoClean(active) {
|
|
2125
|
+
if (active && !autoCleanActive) {
|
|
2126
|
+
autoClean.start();
|
|
2127
|
+
autoCleanActive = true;
|
|
2128
|
+
} else if (!active && autoCleanActive) {
|
|
2129
|
+
autoClean.stop();
|
|
2130
|
+
autoCleanActive = false;
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
const handleChange = createChangeHandler({
|
|
2134
|
+
store,
|
|
2135
|
+
features,
|
|
2136
|
+
editingEnabled,
|
|
2137
|
+
navigate: (url) => navigation.navigate(url),
|
|
2138
|
+
currentPath: () => navigation.currentPath(),
|
|
2139
|
+
reload: navigation.reload ?? (() => window.location.reload()),
|
|
2140
|
+
stega,
|
|
2141
|
+
syncAutoClean
|
|
2142
|
+
});
|
|
2143
|
+
let prev = store.get();
|
|
2144
|
+
const unsubscribe = store.subscribe((state) => {
|
|
2145
|
+
const before = prev;
|
|
2146
|
+
prev = state;
|
|
2147
|
+
handleChange(before, state);
|
|
2148
|
+
});
|
|
2149
|
+
syncAutoClean(store.get().previewMode);
|
|
2150
|
+
const bridge = createIframeBridge(store, {
|
|
2151
|
+
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2152
|
+
});
|
|
2153
|
+
sendPreprEvent("getScrollPosition", { value: 0 }, {
|
|
2154
|
+
allowUntrustedTarget: true
|
|
2155
|
+
});
|
|
2156
|
+
if (isIframe) {
|
|
2157
|
+
bridge.start();
|
|
2158
|
+
}
|
|
2159
|
+
function destroy() {
|
|
2160
|
+
unsubscribe();
|
|
2161
|
+
stega.stop();
|
|
2162
|
+
syncAutoClean(false);
|
|
2163
|
+
if (isIframe) {
|
|
2164
|
+
bridge.stop();
|
|
2165
|
+
}
|
|
2166
|
+
el?.remove();
|
|
2167
|
+
debug7.log("preview destroyed");
|
|
2168
|
+
}
|
|
2169
|
+
const controller = { destroy };
|
|
2170
|
+
controllerStores.set(controller, store);
|
|
2171
|
+
return controller;
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
// src/core/pixel.ts
|
|
2175
|
+
var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr-v2.min.js";
|
|
2176
|
+
var CACHE_BUST_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
2177
|
+
function loadTrackingPixel(trackingId, config) {
|
|
2178
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
2179
|
+
return;
|
|
2180
|
+
}
|
|
2181
|
+
if (window.prepr) {
|
|
2182
|
+
return;
|
|
2183
|
+
}
|
|
2184
|
+
const queueFn = ((...args) => {
|
|
2185
|
+
if (queueFn.process) {
|
|
2186
|
+
queueFn.process(...args);
|
|
2187
|
+
} else {
|
|
2188
|
+
queueFn.queue.push(args);
|
|
2189
|
+
}
|
|
2190
|
+
});
|
|
2191
|
+
queueFn.queue = [];
|
|
2192
|
+
queueFn.t = Date.now();
|
|
2193
|
+
window.prepr = queueFn;
|
|
2194
|
+
const script = document.createElement("script");
|
|
2195
|
+
script.async = true;
|
|
2196
|
+
const cacheBuster = Math.ceil(Date.now() / CACHE_BUST_INTERVAL_MS) * CACHE_BUST_INTERVAL_MS;
|
|
2197
|
+
script.src = `${PIXEL_SCRIPT_URL}?t=${cacheBuster}`;
|
|
2198
|
+
const firstScript = document.getElementsByTagName("script")[0];
|
|
2199
|
+
if (firstScript?.parentNode) {
|
|
2200
|
+
firstScript.parentNode.insertBefore(script, firstScript);
|
|
2201
|
+
} else {
|
|
2202
|
+
document.head.appendChild(script);
|
|
2203
|
+
}
|
|
2204
|
+
if (config !== void 0) {
|
|
2205
|
+
queueFn("init", trackingId, config);
|
|
2206
|
+
} else {
|
|
2207
|
+
queueFn("init", trackingId);
|
|
2208
|
+
}
|
|
2209
|
+
queueFn("event", "pageload");
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2212
|
+
// src/react/components.ts
|
|
2213
|
+
function PreprPreview({
|
|
2214
|
+
options,
|
|
2215
|
+
navigation,
|
|
2216
|
+
...props
|
|
2217
|
+
}) {
|
|
2218
|
+
(0, import_react.useEffect)(() => {
|
|
2219
|
+
const preview = createPreprPreview({ props, options, navigation });
|
|
2220
|
+
return () => preview.destroy();
|
|
2221
|
+
}, []);
|
|
2222
|
+
return null;
|
|
2223
|
+
}
|
|
2224
|
+
function PreprTrackingPixel({
|
|
2225
|
+
id,
|
|
2226
|
+
config
|
|
2227
|
+
}) {
|
|
2228
|
+
(0, import_react.useEffect)(() => {
|
|
2229
|
+
loadTrackingPixel(id, config);
|
|
2230
|
+
}, []);
|
|
2231
|
+
return null;
|
|
2232
|
+
}
|
|
2233
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2234
|
+
0 && (module.exports = {
|
|
2235
|
+
PreprPreview,
|
|
2236
|
+
PreprTrackingPixel
|
|
2237
|
+
});
|