@preprio/toolkit 0.3.2 → 0.3.5

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.
@@ -417,28 +417,45 @@ function tagEncodedElement(element, decoded) {
417
417
 
418
418
  // src/core/stega/auto-clean.ts
419
419
  var debug2 = createScopedLogger("stega:auto-clean");
420
- function createStegaAutoClean() {
420
+ function createStegaAutoClean(options) {
421
+ const stripText = options?.enabled ?? true;
421
422
  let observer = null;
422
423
  let processing = false;
423
424
  let cleaned = /* @__PURE__ */ new WeakMap();
425
+ let pendingHidden = /* @__PURE__ */ new Set();
426
+ let pendingDirty = /* @__PURE__ */ new Set();
424
427
  let debounceTimeout = null;
425
428
  function cleanTextNode(textNode) {
426
429
  if (isIgnoredTextNode(textNode)) return false;
427
430
  const textContent = textNode.textContent;
428
431
  const info = cleaned.get(textNode);
429
- if (info && textContent === info.cleaned) return false;
432
+ const settled = stripText ? info?.cleaned : info?.original;
433
+ if (info && textContent === settled) {
434
+ const shown = resolveEditTarget(textNode);
435
+ if (!shown) return false;
436
+ pendingHidden.delete(textNode);
437
+ if (shown.hasAttribute("data-prepr-encoded")) return false;
438
+ tagEncodedElement(shown, info.decoded);
439
+ return true;
440
+ }
430
441
  try {
431
442
  const { cleaned: stripped, encoded } = (0, import_stega2.vercelStegaSplit)(textContent);
432
443
  if (!encoded || stripped === textContent) return false;
433
444
  const decoded = decodeStega(textContent);
434
445
  if (!decoded?.href) return false;
435
- cleaned.set(textNode, { original: textContent, cleaned: stripped });
436
- textNode.textContent = stripped;
446
+ cleaned.set(textNode, {
447
+ original: textContent,
448
+ cleaned: stripped,
449
+ decoded
450
+ });
451
+ if (stripText) textNode.textContent = stripped;
437
452
  const target = resolveEditTarget(textNode);
438
453
  if (target) {
454
+ pendingHidden.delete(textNode);
439
455
  tagEncodedElement(target, decoded);
440
456
  return true;
441
457
  }
458
+ pendingHidden.add(textNode);
442
459
  } catch (error) {
443
460
  debug2.log("error cleaning text node", error);
444
461
  }
@@ -447,8 +464,10 @@ function createStegaAutoClean() {
447
464
  function scanAndClean() {
448
465
  processing = true;
449
466
  walkTextNodes(document.body, cleanTextNode);
450
- const title = (0, import_stega2.vercelStegaSplit)(document.title);
451
- if (title.encoded) document.title = title.cleaned;
467
+ if (stripText) {
468
+ const title = (0, import_stega2.vercelStegaSplit)(document.title);
469
+ if (title.encoded) document.title = title.cleaned;
470
+ }
452
471
  processing = false;
453
472
  }
454
473
  function collectAffected(mutations) {
@@ -473,15 +492,37 @@ function createStegaAutoClean() {
473
492
  });
474
493
  return affected;
475
494
  }
495
+ function retryPendingHidden() {
496
+ if (pendingHidden.size === 0) return;
497
+ processing = true;
498
+ [...pendingHidden].forEach((textNode) => {
499
+ if (!textNode.isConnected) {
500
+ pendingHidden.delete(textNode);
501
+ return;
502
+ }
503
+ cleanTextNode(textNode);
504
+ });
505
+ processing = false;
506
+ }
476
507
  function handleMutations(mutations) {
477
508
  if (processing) return;
478
509
  const affected = collectAffected(mutations);
479
- if (affected.size === 0) return;
510
+ if (affected.size === 0) {
511
+ retryPendingHidden();
512
+ return;
513
+ }
514
+ affected.forEach((textNode) => pendingDirty.add(textNode));
480
515
  if (debounceTimeout) clearTimeout(debounceTimeout);
481
516
  debounceTimeout = setTimeout(() => {
517
+ debounceTimeout = null;
482
518
  processing = true;
483
- affected.forEach((textNode) => cleanTextNode(textNode));
519
+ const batch = [...pendingDirty];
520
+ pendingDirty.clear();
521
+ batch.forEach((textNode) => {
522
+ if (textNode.isConnected) cleanTextNode(textNode);
523
+ });
484
524
  processing = false;
525
+ retryPendingHidden();
485
526
  }, 50);
486
527
  }
487
528
  function setupObserver() {
@@ -489,7 +530,11 @@ function createStegaAutoClean() {
489
530
  observer.observe(document.body, {
490
531
  childList: true,
491
532
  subtree: true,
492
- characterData: true
533
+ characterData: true,
534
+ // A dropdown opening only toggles a class or inline style; without these
535
+ // the nodes it reveals are never revisited and stay untagged.
536
+ attributes: true,
537
+ attributeFilter: ["class", "style", "hidden", "open", "aria-expanded"]
493
538
  });
494
539
  }
495
540
  function start() {
@@ -508,6 +553,8 @@ function createStegaAutoClean() {
508
553
  observer = null;
509
554
  }
510
555
  cleaned = /* @__PURE__ */ new WeakMap();
556
+ pendingHidden = /* @__PURE__ */ new Set();
557
+ pendingDirty = /* @__PURE__ */ new Set();
511
558
  debug2.log("stega auto-clean stopped");
512
559
  }
513
560
  return { start, stop };
@@ -576,8 +623,13 @@ var StegaElements = class {
576
623
  if (mutation.type === "characterData") {
577
624
  addedNodes.add(mutation.target);
578
625
  }
626
+ if (mutation.type === "attributes") {
627
+ addedNodes.add(mutation.target);
628
+ }
629
+ });
630
+ addedNodes.forEach((node) => {
631
+ if (node.isConnected) this.scanNode(node);
579
632
  });
580
- addedNodes.forEach((node) => this.scanNode(node));
581
633
  pending = [];
582
634
  this.elements = document.querySelectorAll("[data-prepr-encoded]");
583
635
  onUpdate?.();
@@ -590,7 +642,11 @@ var StegaElements = class {
590
642
  this.observer.observe(document.body, {
591
643
  childList: true,
592
644
  subtree: true,
593
- characterData: true
645
+ characterData: true,
646
+ // Reveal-on-class/style (dropdowns, accordions) changes no text and adds
647
+ // no nodes, but does change what is hoverable and needs a rescan.
648
+ attributes: true,
649
+ attributeFilter: ["class", "style", "hidden", "open", "aria-expanded"]
594
650
  });
595
651
  }
596
652
  /** Drops the active class but keeps the data attributes, unlike cleanup(). */
@@ -679,11 +735,13 @@ var StegaOverlay = class {
679
735
  const maxTop = window.scrollY + window.innerHeight - tooltip.clientHeight - 4;
680
736
  const minLeft = window.scrollX + 4;
681
737
  const maxLeft = window.scrollX + window.innerWidth - tooltip.clientWidth - 4;
682
- if (top < minTop) {
738
+ const below = top < minTop;
739
+ if (below) {
683
740
  top = rect.bottom + window.scrollY + 2;
684
741
  }
685
742
  top = Math.max(minTop, Math.min(top, maxTop));
686
743
  left = Math.max(minLeft, Math.min(left, maxLeft));
744
+ tooltip.dataset.preprPlacement = below ? "below" : "above";
687
745
  tooltip.style.top = `${top}px`;
688
746
  tooltip.style.left = `${left}px`;
689
747
  });
@@ -815,7 +873,7 @@ var StegaProximity = class {
815
873
  };
816
874
 
817
875
  // src/core/stega/stega.generated.ts
818
- 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}';
876
+ 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[data-prepr-placement=below]{border-radius:0 0 4px 4px}.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}';
819
877
 
820
878
  // src/core/stega/styles.ts
821
879
  var STEGA_STYLE_MARKER = "data-prepr-stega";
@@ -1364,7 +1422,7 @@ var CLOSE_ICON_SVG = `<svg width="10" height="10" viewBox="0 0 10 10" fill="none
1364
1422
  </svg>`;
1365
1423
 
1366
1424
  // src/core/ui/toolbar.generated.ts
1367
- 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>span{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}}";
1425
+ 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>span{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[data-interactive=false]{cursor:default;opacity:1;color:#fff}.prepr-status-pill[data-interactive=true]: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}}";
1368
1426
 
1369
1427
  // ../../node_modules/.pnpm/preact@10.29.7/node_modules/preact/jsx-runtime/dist/jsxRuntime.mjs
1370
1428
  var f2 = 0;
@@ -1623,13 +1681,17 @@ function StatusPill({
1623
1681
  } else {
1624
1682
  segmentLabel = defaultSegmentName;
1625
1683
  }
1684
+ const dirty = features.segments && state.selectedSegment !== null || features.abTesting && state.selectedVariant === "B";
1685
+ const interactive = !state.previewMode || dirty;
1626
1686
  return /* @__PURE__ */ u2(
1627
1687
  "button",
1628
1688
  {
1629
1689
  type: "button",
1630
1690
  class: "prepr-status-pill",
1631
1691
  "data-prepr": "status-pill",
1692
+ "data-interactive": String(interactive),
1632
1693
  hidden: state.isIframe,
1694
+ disabled: !interactive,
1633
1695
  onClick: () => handlers.onStatusPill(),
1634
1696
  children: [
1635
1697
  /* @__PURE__ */ u2("span", { class: "prepr-status-viewing", "data-prepr": "status-viewing", children: t3("common.viewingAs") }),
@@ -1648,7 +1710,7 @@ function StatusPill({
1648
1710
  {
1649
1711
  class: "prepr-status-x",
1650
1712
  "data-prepr": "status-x",
1651
- hidden: !state.previewMode || !(features.segments && state.selectedSegment !== null || features.abTesting && state.selectedVariant === "B"),
1713
+ hidden: !state.previewMode || !dirty,
1652
1714
  children: /* @__PURE__ */ u2(RawSvg, { svg: XMARK_ICON_SVG })
1653
1715
  }
1654
1716
  )
@@ -2152,7 +2214,9 @@ function createPreprPreview(opts = {}) {
2152
2214
  }
2153
2215
  }
2154
2216
  });
2155
- const autoClean = createStegaAutoClean();
2217
+ const autoClean = createStegaAutoClean({
2218
+ enabled: options?.autoClean
2219
+ });
2156
2220
  autoClean.start();
2157
2221
  const handleChange = createChangeHandler({
2158
2222
  store,
@@ -2198,7 +2262,7 @@ function createPreprPreview(opts = {}) {
2198
2262
  }
2199
2263
 
2200
2264
  // src/core/pixel.ts
2201
- var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr-v2.min.js";
2265
+ var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
2202
2266
  var CACHE_BUST_INTERVAL_MS = 24 * 60 * 60 * 1e3;
2203
2267
  function loadTrackingPixel(trackingId, config) {
2204
2268
  if (typeof window === "undefined" || typeof document === "undefined") {
@@ -62,6 +62,20 @@ interface PreprPreviewOptions extends PreprToolbarOptions {
62
62
  * Intended for self-hosted editors; when set, the wildcard no longer applies.
63
63
  */
64
64
  allowedEditorOrigins?: string[];
65
+ /**
66
+ * Strip the invisible stega characters out of visible text at runtime.
67
+ * Default `true`.
68
+ *
69
+ * Preview content carries an encoded payload inside the text itself. Left in
70
+ * place it is invisible but real: it inflates `String.length`, breaks text
71
+ * measurement and truncation, and is announced by screen readers.
72
+ *
73
+ * Set `false` only when the site already strips the characters itself — for
74
+ * example by passing every field through `stegaClean` as it renders.
75
+ * Click-to-edit is unaffected either way: elements are still tagged from the
76
+ * payload, so the overlay keeps working.
77
+ */
78
+ autoClean?: boolean;
65
79
  }
66
80
  interface PreprToolbarProps {
67
81
  /**
@@ -62,6 +62,20 @@ interface PreprPreviewOptions extends PreprToolbarOptions {
62
62
  * Intended for self-hosted editors; when set, the wildcard no longer applies.
63
63
  */
64
64
  allowedEditorOrigins?: string[];
65
+ /**
66
+ * Strip the invisible stega characters out of visible text at runtime.
67
+ * Default `true`.
68
+ *
69
+ * Preview content carries an encoded payload inside the text itself. Left in
70
+ * place it is invisible but real: it inflates `String.length`, breaks text
71
+ * measurement and truncation, and is announced by screen readers.
72
+ *
73
+ * Set `false` only when the site already strips the characters itself — for
74
+ * example by passing every field through `stegaClean` as it renders.
75
+ * Click-to-edit is unaffected either way: elements are still tagged from the
76
+ * payload, so the overlay keeps working.
77
+ */
78
+ autoClean?: boolean;
65
79
  }
66
80
  interface PreprToolbarProps {
67
81
  /**
@@ -393,28 +393,45 @@ function tagEncodedElement(element, decoded) {
393
393
 
394
394
  // src/core/stega/auto-clean.ts
395
395
  var debug2 = createScopedLogger("stega:auto-clean");
396
- function createStegaAutoClean() {
396
+ function createStegaAutoClean(options) {
397
+ const stripText = options?.enabled ?? true;
397
398
  let observer = null;
398
399
  let processing = false;
399
400
  let cleaned = /* @__PURE__ */ new WeakMap();
401
+ let pendingHidden = /* @__PURE__ */ new Set();
402
+ let pendingDirty = /* @__PURE__ */ new Set();
400
403
  let debounceTimeout = null;
401
404
  function cleanTextNode(textNode) {
402
405
  if (isIgnoredTextNode(textNode)) return false;
403
406
  const textContent = textNode.textContent;
404
407
  const info = cleaned.get(textNode);
405
- if (info && textContent === info.cleaned) return false;
408
+ const settled = stripText ? info?.cleaned : info?.original;
409
+ if (info && textContent === settled) {
410
+ const shown = resolveEditTarget(textNode);
411
+ if (!shown) return false;
412
+ pendingHidden.delete(textNode);
413
+ if (shown.hasAttribute("data-prepr-encoded")) return false;
414
+ tagEncodedElement(shown, info.decoded);
415
+ return true;
416
+ }
406
417
  try {
407
418
  const { cleaned: stripped, encoded } = vercelStegaSplit(textContent);
408
419
  if (!encoded || stripped === textContent) return false;
409
420
  const decoded = decodeStega(textContent);
410
421
  if (!decoded?.href) return false;
411
- cleaned.set(textNode, { original: textContent, cleaned: stripped });
412
- textNode.textContent = stripped;
422
+ cleaned.set(textNode, {
423
+ original: textContent,
424
+ cleaned: stripped,
425
+ decoded
426
+ });
427
+ if (stripText) textNode.textContent = stripped;
413
428
  const target = resolveEditTarget(textNode);
414
429
  if (target) {
430
+ pendingHidden.delete(textNode);
415
431
  tagEncodedElement(target, decoded);
416
432
  return true;
417
433
  }
434
+ pendingHidden.add(textNode);
418
435
  } catch (error) {
419
436
  debug2.log("error cleaning text node", error);
420
437
  }
@@ -423,8 +440,10 @@ function createStegaAutoClean() {
423
440
  function scanAndClean() {
424
441
  processing = true;
425
442
  walkTextNodes(document.body, cleanTextNode);
426
- const title = vercelStegaSplit(document.title);
427
- if (title.encoded) document.title = title.cleaned;
443
+ if (stripText) {
444
+ const title = vercelStegaSplit(document.title);
445
+ if (title.encoded) document.title = title.cleaned;
446
+ }
428
447
  processing = false;
429
448
  }
430
449
  function collectAffected(mutations) {
@@ -449,15 +468,37 @@ function createStegaAutoClean() {
449
468
  });
450
469
  return affected;
451
470
  }
471
+ function retryPendingHidden() {
472
+ if (pendingHidden.size === 0) return;
473
+ processing = true;
474
+ [...pendingHidden].forEach((textNode) => {
475
+ if (!textNode.isConnected) {
476
+ pendingHidden.delete(textNode);
477
+ return;
478
+ }
479
+ cleanTextNode(textNode);
480
+ });
481
+ processing = false;
482
+ }
452
483
  function handleMutations(mutations) {
453
484
  if (processing) return;
454
485
  const affected = collectAffected(mutations);
455
- if (affected.size === 0) return;
486
+ if (affected.size === 0) {
487
+ retryPendingHidden();
488
+ return;
489
+ }
490
+ affected.forEach((textNode) => pendingDirty.add(textNode));
456
491
  if (debounceTimeout) clearTimeout(debounceTimeout);
457
492
  debounceTimeout = setTimeout(() => {
493
+ debounceTimeout = null;
458
494
  processing = true;
459
- affected.forEach((textNode) => cleanTextNode(textNode));
495
+ const batch = [...pendingDirty];
496
+ pendingDirty.clear();
497
+ batch.forEach((textNode) => {
498
+ if (textNode.isConnected) cleanTextNode(textNode);
499
+ });
460
500
  processing = false;
501
+ retryPendingHidden();
461
502
  }, 50);
462
503
  }
463
504
  function setupObserver() {
@@ -465,7 +506,11 @@ function createStegaAutoClean() {
465
506
  observer.observe(document.body, {
466
507
  childList: true,
467
508
  subtree: true,
468
- characterData: true
509
+ characterData: true,
510
+ // A dropdown opening only toggles a class or inline style; without these
511
+ // the nodes it reveals are never revisited and stay untagged.
512
+ attributes: true,
513
+ attributeFilter: ["class", "style", "hidden", "open", "aria-expanded"]
469
514
  });
470
515
  }
471
516
  function start() {
@@ -484,6 +529,8 @@ function createStegaAutoClean() {
484
529
  observer = null;
485
530
  }
486
531
  cleaned = /* @__PURE__ */ new WeakMap();
532
+ pendingHidden = /* @__PURE__ */ new Set();
533
+ pendingDirty = /* @__PURE__ */ new Set();
487
534
  debug2.log("stega auto-clean stopped");
488
535
  }
489
536
  return { start, stop };
@@ -552,8 +599,13 @@ var StegaElements = class {
552
599
  if (mutation.type === "characterData") {
553
600
  addedNodes.add(mutation.target);
554
601
  }
602
+ if (mutation.type === "attributes") {
603
+ addedNodes.add(mutation.target);
604
+ }
605
+ });
606
+ addedNodes.forEach((node) => {
607
+ if (node.isConnected) this.scanNode(node);
555
608
  });
556
- addedNodes.forEach((node) => this.scanNode(node));
557
609
  pending = [];
558
610
  this.elements = document.querySelectorAll("[data-prepr-encoded]");
559
611
  onUpdate?.();
@@ -566,7 +618,11 @@ var StegaElements = class {
566
618
  this.observer.observe(document.body, {
567
619
  childList: true,
568
620
  subtree: true,
569
- characterData: true
621
+ characterData: true,
622
+ // Reveal-on-class/style (dropdowns, accordions) changes no text and adds
623
+ // no nodes, but does change what is hoverable and needs a rescan.
624
+ attributes: true,
625
+ attributeFilter: ["class", "style", "hidden", "open", "aria-expanded"]
570
626
  });
571
627
  }
572
628
  /** Drops the active class but keeps the data attributes, unlike cleanup(). */
@@ -655,11 +711,13 @@ var StegaOverlay = class {
655
711
  const maxTop = window.scrollY + window.innerHeight - tooltip.clientHeight - 4;
656
712
  const minLeft = window.scrollX + 4;
657
713
  const maxLeft = window.scrollX + window.innerWidth - tooltip.clientWidth - 4;
658
- if (top < minTop) {
714
+ const below = top < minTop;
715
+ if (below) {
659
716
  top = rect.bottom + window.scrollY + 2;
660
717
  }
661
718
  top = Math.max(minTop, Math.min(top, maxTop));
662
719
  left = Math.max(minLeft, Math.min(left, maxLeft));
720
+ tooltip.dataset.preprPlacement = below ? "below" : "above";
663
721
  tooltip.style.top = `${top}px`;
664
722
  tooltip.style.left = `${left}px`;
665
723
  });
@@ -791,7 +849,7 @@ var StegaProximity = class {
791
849
  };
792
850
 
793
851
  // src/core/stega/stega.generated.ts
794
- 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}';
852
+ 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[data-prepr-placement=below]{border-radius:0 0 4px 4px}.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}';
795
853
 
796
854
  // src/core/stega/styles.ts
797
855
  var STEGA_STYLE_MARKER = "data-prepr-stega";
@@ -1340,7 +1398,7 @@ var CLOSE_ICON_SVG = `<svg width="10" height="10" viewBox="0 0 10 10" fill="none
1340
1398
  </svg>`;
1341
1399
 
1342
1400
  // src/core/ui/toolbar.generated.ts
1343
- 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>span{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}}";
1401
+ 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>span{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[data-interactive=false]{cursor:default;opacity:1;color:#fff}.prepr-status-pill[data-interactive=true]: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}}";
1344
1402
 
1345
1403
  // ../../node_modules/.pnpm/preact@10.29.7/node_modules/preact/jsx-runtime/dist/jsxRuntime.mjs
1346
1404
  var f2 = 0;
@@ -1599,13 +1657,17 @@ function StatusPill({
1599
1657
  } else {
1600
1658
  segmentLabel = defaultSegmentName;
1601
1659
  }
1660
+ const dirty = features.segments && state.selectedSegment !== null || features.abTesting && state.selectedVariant === "B";
1661
+ const interactive = !state.previewMode || dirty;
1602
1662
  return /* @__PURE__ */ u2(
1603
1663
  "button",
1604
1664
  {
1605
1665
  type: "button",
1606
1666
  class: "prepr-status-pill",
1607
1667
  "data-prepr": "status-pill",
1668
+ "data-interactive": String(interactive),
1608
1669
  hidden: state.isIframe,
1670
+ disabled: !interactive,
1609
1671
  onClick: () => handlers.onStatusPill(),
1610
1672
  children: [
1611
1673
  /* @__PURE__ */ u2("span", { class: "prepr-status-viewing", "data-prepr": "status-viewing", children: t3("common.viewingAs") }),
@@ -1624,7 +1686,7 @@ function StatusPill({
1624
1686
  {
1625
1687
  class: "prepr-status-x",
1626
1688
  "data-prepr": "status-x",
1627
- hidden: !state.previewMode || !(features.segments && state.selectedSegment !== null || features.abTesting && state.selectedVariant === "B"),
1689
+ hidden: !state.previewMode || !dirty,
1628
1690
  children: /* @__PURE__ */ u2(RawSvg, { svg: XMARK_ICON_SVG })
1629
1691
  }
1630
1692
  )
@@ -2128,7 +2190,9 @@ function createPreprPreview(opts = {}) {
2128
2190
  }
2129
2191
  }
2130
2192
  });
2131
- const autoClean = createStegaAutoClean();
2193
+ const autoClean = createStegaAutoClean({
2194
+ enabled: options?.autoClean
2195
+ });
2132
2196
  autoClean.start();
2133
2197
  const handleChange = createChangeHandler({
2134
2198
  store,
@@ -2174,7 +2238,7 @@ function createPreprPreview(opts = {}) {
2174
2238
  }
2175
2239
 
2176
2240
  // src/core/pixel.ts
2177
- var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr-v2.min.js";
2241
+ var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
2178
2242
  var CACHE_BUST_INTERVAL_MS = 24 * 60 * 60 * 1e3;
2179
2243
  function loadTrackingPixel(trackingId, config) {
2180
2244
  if (typeof window === "undefined" || typeof document === "undefined") {
@@ -35,7 +35,7 @@ __export(sveltekit_exports, {
35
35
  module.exports = __toCommonJS(sveltekit_exports);
36
36
 
37
37
  // src/version.ts
38
- var VERSION = "0.3.2";
38
+ var VERSION = "0.3.5";
39
39
 
40
40
  // src/core/constants.ts
41
41
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "0.3.2";
2
+ var VERSION = "0.3.5";
3
3
 
4
4
  // src/core/constants.ts
5
5
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preprio/toolkit",
3
- "version": "0.3.2",
3
+ "version": "0.3.5",
4
4
  "description": "Prepr personalization, A/B testing and preview toolkit for React, Next.js, Nuxt, Astro, SvelteKit and Express",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Prepr B.V. (https://prepr.io)",