@syntrologie/adapt-content 2.8.0-canary.31 → 2.8.0-canary.310

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.
Files changed (109) hide show
  1. package/dist/runtime.d.ts.map +1 -1
  2. package/dist/runtime.js +431 -348
  3. package/dist/runtime.js.map +7 -0
  4. package/dist/schema.d.ts +56 -16
  5. package/dist/schema.d.ts.map +1 -1
  6. package/dist/schema.js +363 -62
  7. package/dist/schema.js.map +7 -0
  8. package/package.json +8 -26
  9. package/dist/cdn.d.ts +0 -35
  10. package/dist/cdn.d.ts.map +0 -1
  11. package/dist/cdn.js +0 -39
  12. package/dist/components/AnchorPicker.d.ts +0 -8
  13. package/dist/components/AnchorPicker.d.ts.map +0 -1
  14. package/dist/components/AnchorPicker.js +0 -6
  15. package/dist/content-editor-state.d.ts +0 -45
  16. package/dist/content-editor-state.d.ts.map +0 -1
  17. package/dist/content-editor-state.js +0 -123
  18. package/dist/content-editor-ui.d.ts +0 -26
  19. package/dist/content-editor-ui.d.ts.map +0 -1
  20. package/dist/content-editor-ui.js +0 -301
  21. package/dist/editor.d.ts +0 -9
  22. package/dist/editor.d.ts.map +0 -1
  23. package/dist/editor.js +0 -8
  24. package/dist/reconciliation-guard.js +0 -80
  25. package/dist/sanitizer.js +0 -95
  26. package/dist/summarize.js +0 -88
  27. package/dist/types.js +0 -7
  28. package/dist/utils/selectorGenerator.d.ts +0 -6
  29. package/dist/utils/selectorGenerator.d.ts.map +0 -1
  30. package/dist/utils/selectorGenerator.js +0 -4
  31. package/node_modules/@syntrologie/shared-editor-ui/dist/cn.d.ts +0 -2
  32. package/node_modules/@syntrologie/shared-editor-ui/dist/cn.d.ts.map +0 -1
  33. package/node_modules/@syntrologie/shared-editor-ui/dist/cn.js +0 -3
  34. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.d.ts +0 -34
  35. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.d.ts.map +0 -1
  36. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.js +0 -158
  37. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.d.ts +0 -7
  38. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.d.ts.map +0 -1
  39. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.js +0 -9
  40. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.d.ts +0 -23
  41. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.d.ts.map +0 -1
  42. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.js +0 -40
  43. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.d.ts +0 -7
  44. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.d.ts.map +0 -1
  45. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.js +0 -22
  46. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.d.ts +0 -8
  47. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.d.ts.map +0 -1
  48. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.js +0 -9
  49. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.d.ts +0 -7
  50. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.d.ts.map +0 -1
  51. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.js +0 -4
  52. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.d.ts +0 -7
  53. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.d.ts.map +0 -1
  54. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.js +0 -4
  55. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.d.ts +0 -13
  56. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.d.ts.map +0 -1
  57. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.js +0 -15
  58. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.d.ts +0 -7
  59. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.d.ts.map +0 -1
  60. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.js +0 -4
  61. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.d.ts +0 -9
  62. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.d.ts.map +0 -1
  63. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.js +0 -4
  64. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.d.ts +0 -8
  65. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.d.ts.map +0 -1
  66. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.js +0 -8
  67. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.d.ts +0 -7
  68. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.d.ts.map +0 -1
  69. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.js +0 -4
  70. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.d.ts +0 -25
  71. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.d.ts.map +0 -1
  72. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.js +0 -379
  73. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.d.ts +0 -8
  74. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.d.ts.map +0 -1
  75. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.js +0 -8
  76. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.d.ts +0 -8
  77. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.d.ts.map +0 -1
  78. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.js +0 -17
  79. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.d.ts +0 -32
  80. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.d.ts.map +0 -1
  81. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.js +0 -85
  82. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.d.ts +0 -6
  83. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.d.ts.map +0 -1
  84. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.js +0 -4
  85. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.d.ts +0 -8
  86. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.d.ts.map +0 -1
  87. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.js +0 -5
  88. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.d.ts +0 -12
  89. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.d.ts.map +0 -1
  90. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.js +0 -40
  91. package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.d.ts +0 -26
  92. package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.d.ts.map +0 -1
  93. package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.js +0 -202
  94. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.d.ts +0 -8
  95. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.d.ts.map +0 -1
  96. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.js +0 -46
  97. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useTriggerWhenStatus.d.ts +0 -24
  98. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useTriggerWhenStatus.d.ts.map +0 -1
  99. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useTriggerWhenStatus.js +0 -86
  100. package/node_modules/@syntrologie/shared-editor-ui/dist/index.d.ts +0 -34
  101. package/node_modules/@syntrologie/shared-editor-ui/dist/index.d.ts.map +0 -1
  102. package/node_modules/@syntrologie/shared-editor-ui/dist/index.js +0 -25
  103. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.d.ts +0 -37
  104. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.d.ts.map +0 -1
  105. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.js +0 -52
  106. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.d.ts +0 -22
  107. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.d.ts.map +0 -1
  108. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.js +0 -143
  109. package/node_modules/@syntrologie/shared-editor-ui/package.json +0 -45
@@ -1,80 +0,0 @@
1
- /**
2
- * Reconciliation Guard - MutationObserver defense against React DOM removal.
3
- *
4
- * When the Syntrologie SDK inserts DOM nodes into a React-managed subtree
5
- * (via content:insertHtml), React's reconciliation will silently remove them
6
- * on the next render because they don't exist in React's virtual DOM.
7
- *
8
- * This guard watches for the removal of our inserted container and re-inserts
9
- * it using a debounced retry mechanism with a maximum retry count to prevent
10
- * infinite loops (e.g., in React StrictMode which double-invokes effects).
11
- */
12
- /**
13
- * Watch for a container element being removed from the DOM by an external
14
- * framework (React, Vue, etc.) and call `reinsertFn` to re-insert it.
15
- *
16
- * @param container The element we inserted (has data-syntro-action-id)
17
- * @param anchor The anchor element our container is positioned relative to
18
- * @param reinsertFn Called when the container is removed — should re-insert it
19
- * @param opts Configuration for retry limits and debounce timing
20
- * @returns Cleanup function that disconnects the observer
21
- */
22
- export function guardAgainstReconciliation(container, anchor, reinsertFn, opts) {
23
- const maxRetries = opts?.maxRetries ?? 3;
24
- const debounceMs = opts?.debounceMs ?? 50;
25
- // Find the nearest parent to observe. Prefer container's parent, then anchor's.
26
- const observeTarget = container.parentElement ?? anchor.parentElement;
27
- if (!observeTarget)
28
- return () => { };
29
- let retries = 0;
30
- let debounceTimer = null;
31
- let disconnected = false;
32
- const observer = new MutationObserver((mutations) => {
33
- if (disconnected)
34
- return;
35
- for (const mutation of mutations) {
36
- for (const removed of mutation.removedNodes) {
37
- // Check if the removed node is our container
38
- if (removed !== container)
39
- continue;
40
- if (retries >= maxRetries) {
41
- observer.disconnect();
42
- disconnected = true;
43
- return;
44
- }
45
- // Debounce to coalesce rapid React re-renders
46
- if (debounceTimer)
47
- clearTimeout(debounceTimer);
48
- debounceTimer = setTimeout(() => {
49
- if (disconnected)
50
- return;
51
- // If the anchor has been removed from the DOM (SPA navigation),
52
- // the page has been torn down — stop fighting React's reconciler.
53
- // Re-inserting into a dying subtree triggers removeChild crashes.
54
- if (!anchor.isConnected) {
55
- observer.disconnect();
56
- disconnected = true;
57
- return;
58
- }
59
- retries++;
60
- try {
61
- reinsertFn();
62
- }
63
- catch {
64
- // Re-insertion failed — stop trying
65
- observer.disconnect();
66
- disconnected = true;
67
- }
68
- }, debounceMs);
69
- return; // Found our container, no need to check further
70
- }
71
- }
72
- });
73
- observer.observe(observeTarget, { childList: true, subtree: true });
74
- return () => {
75
- disconnected = true;
76
- observer.disconnect();
77
- if (debounceTimer)
78
- clearTimeout(debounceTimer);
79
- };
80
- }
package/dist/sanitizer.js DELETED
@@ -1,95 +0,0 @@
1
- /**
2
- * HTML Sanitizer
3
- *
4
- * Sanitizes HTML to prevent XSS attacks.
5
- * Uses native Sanitizer API when available, falls back to whitelist approach.
6
- */
7
- const ALLOWED_TAGS = new Set([
8
- 'b',
9
- 'strong',
10
- 'i',
11
- 'em',
12
- 'u',
13
- 'span',
14
- 'div',
15
- 'p',
16
- 'br',
17
- 'ul',
18
- 'ol',
19
- 'li',
20
- 'code',
21
- 'pre',
22
- 'small',
23
- 'sup',
24
- 'sub',
25
- 'a',
26
- 'button',
27
- // SVG elements (for inline Lucide icons in config HTML)
28
- 'svg',
29
- 'path',
30
- 'circle',
31
- 'line',
32
- 'polyline',
33
- 'polygon',
34
- 'rect',
35
- 'g',
36
- ]);
37
- export function sanitizeHtml(html) {
38
- // Try native Sanitizer API first
39
- const hasNative = typeof window.Sanitizer === 'function';
40
- if (hasNative) {
41
- try {
42
- const s = new window.Sanitizer({});
43
- const frag = s.sanitizeToFragment(html);
44
- const div = document.createElement('div');
45
- div.append(frag);
46
- return div.innerHTML;
47
- }
48
- catch {
49
- // Fall through to manual sanitizer
50
- }
51
- }
52
- // Conservative fallback sanitizer
53
- const tpl = document.createElement('template');
54
- tpl.innerHTML = html;
55
- const root = tpl.content;
56
- const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null);
57
- const toRemove = [];
58
- while (walker.nextNode()) {
59
- const el = walker.currentNode;
60
- const tag = el.tagName.toLowerCase();
61
- if (!ALLOWED_TAGS.has(tag)) {
62
- toRemove.push(el);
63
- continue;
64
- }
65
- // Remove dangerous attributes
66
- for (const attr of Array.from(el.attributes)) {
67
- const name = attr.name.toLowerCase();
68
- const value = attr.value.trim().toLowerCase();
69
- const isEvent = name.startsWith('on');
70
- const isUrlAttr = name === 'href' || name === 'src' || name === 'formaction';
71
- const isDangerousUrl = isUrlAttr &&
72
- (value.startsWith('javascript:') ||
73
- value.startsWith('vbscript:') ||
74
- value.startsWith('data:text/html'));
75
- if (isEvent || isDangerousUrl) {
76
- el.removeAttribute(attr.name);
77
- }
78
- }
79
- }
80
- // Strip SVG elements that contained script children (XSS vector)
81
- const svgs = Array.from(root.querySelectorAll('svg'));
82
- for (const svg of svgs) {
83
- if (toRemove.some((el) => svg.contains(el) && el.tagName.toLowerCase() === 'script')) {
84
- toRemove.push(svg);
85
- }
86
- }
87
- // Remove disallowed elements but keep their children
88
- for (const el of toRemove) {
89
- while (el.firstChild) {
90
- el.parentNode?.insertBefore(el.firstChild, el);
91
- }
92
- el.remove();
93
- }
94
- return tpl.innerHTML;
95
- }
package/dist/summarize.js DELETED
@@ -1,88 +0,0 @@
1
- /**
2
- * Human-readable summary generation for content config changes.
3
- *
4
- * Pure functions — no DOM access, just string formatting from config data.
5
- */
6
- const MAX_TEXT_LEN = 40;
7
- /** Extract the CSS selector string from an anchorId object. */
8
- function resolveAnchorSelector(anchorId) {
9
- if (!anchorId)
10
- return '';
11
- if (typeof anchorId === 'string')
12
- return anchorId;
13
- if (typeof anchorId === 'object')
14
- return anchorId.selector ?? '';
15
- return '';
16
- }
17
- /**
18
- * Convert a CSS selector into a human-friendly element description.
19
- */
20
- export function describeSelector(selector) {
21
- if (!selector)
22
- return '(no target)';
23
- // ID selector: strip # and common prefixes
24
- if (selector.startsWith('#')) {
25
- let name = selector.slice(1);
26
- const prefixes = ['hero-', 'main-', 'page-', 'app-', 'section-'];
27
- for (const prefix of prefixes) {
28
- if (name.startsWith(prefix)) {
29
- name = name.slice(prefix.length);
30
- break;
31
- }
32
- }
33
- return truncate(name, 50);
34
- }
35
- // data-testid selector
36
- const testIdMatch = selector.match(/\[data-testid="([^"]+)"\]/);
37
- if (testIdMatch) {
38
- return `${testIdMatch[1]} element`;
39
- }
40
- // Class selector or complex selector: keep as-is
41
- return truncate(selector, 50);
42
- }
43
- function truncate(text, max) {
44
- if (text.length <= max)
45
- return text;
46
- return `${text.slice(0, max)}...`;
47
- }
48
- function truncateQuoted(text, max) {
49
- if (text.length <= max)
50
- return `"${text}"`;
51
- return `"${text.slice(0, max)}..."`;
52
- }
53
- /**
54
- * Generate a human-readable one-liner for a content config change.
55
- */
56
- export function summarizeContentChange(type, item) {
57
- const desc = describeSelector(resolveAnchorSelector(item.anchorId));
58
- switch (type) {
59
- case 'textReplacements': {
60
- const text = item.text || '';
61
- return `Change ${desc} to ${truncateQuoted(text, MAX_TEXT_LEN)}`;
62
- }
63
- case 'attributeChanges': {
64
- const attr = item.attr || '';
65
- const value = item.value || '';
66
- return `Set ${desc} ${attr} to ${truncateQuoted(value, MAX_TEXT_LEN)}`;
67
- }
68
- case 'styleChanges': {
69
- const styles = item.styles || {};
70
- const count = Object.keys(styles).length;
71
- return `Restyle ${desc} (${count} ${count === 1 ? 'property' : 'properties'})`;
72
- }
73
- case 'htmlInsertions': {
74
- const position = item.position || 'append';
75
- return `Insert HTML ${position} ${desc}`;
76
- }
77
- case 'classAdditions': {
78
- const className = item.className || '';
79
- return `Add class "${className}" to ${desc}`;
80
- }
81
- case 'classRemovals': {
82
- const className = item.className || '';
83
- return `Remove class "${className}" from ${desc}`;
84
- }
85
- default:
86
- return `Unknown change on ${desc}`;
87
- }
88
- }
package/dist/types.js DELETED
@@ -1,7 +0,0 @@
1
- /**
2
- * Types from @syntrologie/runtime-sdk
3
- *
4
- * Minimal type definitions for building this app independently.
5
- * These match the types exported from @syntrologie/runtime-sdk/types.
6
- */
7
- export {};
@@ -1,6 +0,0 @@
1
- /**
2
- * Re-export selector utilities from shared-editor-ui.
3
- */
4
- export type { SelectorOptions } from '@syntrologie/shared-editor-ui';
5
- export { generateSelector, getElementDescription, validateSelector, } from '@syntrologie/shared-editor-ui';
6
- //# sourceMappingURL=selectorGenerator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"selectorGenerator.d.ts","sourceRoot":"","sources":["../../src/utils/selectorGenerator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,+BAA+B,CAAC"}
@@ -1,4 +0,0 @@
1
- /**
2
- * Re-export selector utilities from shared-editor-ui.
3
- */
4
- export { generateSelector, getElementDescription, validateSelector, } from '@syntrologie/shared-editor-ui';
@@ -1,2 +0,0 @@
1
- export declare function cn(...classes: (string | false | null | undefined)[]): string;
2
- //# sourceMappingURL=cn.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../src/cn.ts"],"names":[],"mappings":"AAAA,wBAAgB,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,GAAG,MAAM,CAE5E"}
@@ -1,3 +0,0 @@
1
- export function cn(...classes) {
2
- return classes.filter(Boolean).join(' ');
3
- }
@@ -1,34 +0,0 @@
1
- /**
2
- * AnchorPicker — Shared Element Picker Overlay
3
- *
4
- * Full-page overlay that lets the user hover and click to select a DOM element.
5
- * Returns the element, its CSS selector, and a human-readable description.
6
- *
7
- * Renders via createPortal to document.body. Uses inline styles (not Tailwind)
8
- * because it lives outside the editor's style scope.
9
- *
10
- * EXCEPTION: This component MUST stay on document.body (not in shadow root).
11
- * It uses document.elementFromPoint() to detect host page elements under the
12
- * cursor. If placed inside a shadow root, the overlay would block detection
13
- * of underlying host elements.
14
- *
15
- * Instructions / cancel UI should be rendered by the consumer in their own
16
- * panel — this component only provides the page overlay.
17
- */
18
- export interface PickedElement {
19
- element: Element;
20
- selector: string;
21
- description: string;
22
- }
23
- export interface AnchorPickerProps {
24
- isActive: boolean;
25
- onPick: (picked: PickedElement) => void;
26
- onCancel: () => void;
27
- /** When true, clicks pass through to the page (no preventDefault/stopPropagation).
28
- * The consumer is responsible for capturing the pick via EventBus or other means.
29
- * Hover highlighting still works for visual feedback. */
30
- passthroughClicks?: boolean;
31
- excludeSelector?: string;
32
- }
33
- export declare function AnchorPicker({ isActive, onPick, onCancel, passthroughClicks, excludeSelector, }: AnchorPickerProps): import("react").ReactPortal | null;
34
- //# sourceMappingURL=AnchorPicker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AnchorPicker.d.ts","sourceRoot":"","sources":["../../src/components/AnchorPicker.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAWH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IACxC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;8DAE0D;IAC1D,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAKD,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,iBAAyB,EACzB,eAAuJ,GACxJ,EAAE,iBAAiB,sCAwMnB"}
@@ -1,158 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * AnchorPicker — Shared Element Picker Overlay
4
- *
5
- * Full-page overlay that lets the user hover and click to select a DOM element.
6
- * Returns the element, its CSS selector, and a human-readable description.
7
- *
8
- * Renders via createPortal to document.body. Uses inline styles (not Tailwind)
9
- * because it lives outside the editor's style scope.
10
- *
11
- * EXCEPTION: This component MUST stay on document.body (not in shadow root).
12
- * It uses document.elementFromPoint() to detect host page elements under the
13
- * cursor. If placed inside a shadow root, the overlay would block detection
14
- * of underlying host elements.
15
- *
16
- * Instructions / cancel UI should be rendered by the consumer in their own
17
- * panel — this component only provides the page overlay.
18
- */
19
- import { useCallback, useEffect, useRef, useState } from 'react';
20
- import { createPortal } from 'react-dom';
21
- import { generateSelector, getElementDescription, validateSelector, } from '../utils/selectorGenerator';
22
- const HIGHLIGHT_COLOR = '#3b82f6';
23
- const HIGHLIGHT_BG = 'rgba(59, 130, 246, 0.1)';
24
- export function AnchorPicker({ isActive, onPick, onCancel, passthroughClicks = false, excludeSelector = '[data-syntro-editor-panel], [data-shadow-canvas-id], .syntro-tooltip, .syntro-modal, .syntro-highlight, [data-syntro-anchor-picker]', }) {
25
- const [hoveredElement, setHoveredElement] = useState(null);
26
- const [hoveredSelector, setHoveredSelector] = useState('');
27
- const overlayRef = useRef(null);
28
- const handleMouseMove = useCallback((e) => {
29
- const overlay = overlayRef.current;
30
- if (overlay) {
31
- overlay.style.pointerEvents = 'none';
32
- }
33
- const elementAtPoint = document.elementFromPoint(e.clientX, e.clientY);
34
- if (overlay) {
35
- overlay.style.pointerEvents = 'auto';
36
- }
37
- if (!elementAtPoint) {
38
- setHoveredElement(null);
39
- setHoveredSelector('');
40
- return;
41
- }
42
- if (excludeSelector && elementAtPoint.closest(excludeSelector)) {
43
- setHoveredElement(null);
44
- setHoveredSelector('');
45
- return;
46
- }
47
- if (['HTML', 'BODY', 'HEAD'].includes(elementAtPoint.tagName)) {
48
- setHoveredElement(null);
49
- setHoveredSelector('');
50
- return;
51
- }
52
- setHoveredElement(elementAtPoint);
53
- const selector = generateSelector(elementAtPoint);
54
- setHoveredSelector(selector);
55
- }, [excludeSelector]);
56
- const handleClick = useCallback((e) => {
57
- if (passthroughClicks)
58
- return; // Let click propagate to PostHog
59
- e.preventDefault();
60
- e.stopPropagation();
61
- if (hoveredElement && hoveredSelector) {
62
- if (validateSelector(hoveredSelector, hoveredElement)) {
63
- onPick({
64
- element: hoveredElement,
65
- selector: hoveredSelector,
66
- description: getElementDescription(hoveredElement),
67
- });
68
- }
69
- else {
70
- const newSelector = generateSelector(hoveredElement);
71
- onPick({
72
- element: hoveredElement,
73
- selector: newSelector,
74
- description: getElementDescription(hoveredElement),
75
- });
76
- }
77
- }
78
- }, [passthroughClicks, hoveredElement, hoveredSelector, onPick]);
79
- const handleKeyDown = useCallback((e) => {
80
- if (e.key === 'Escape') {
81
- e.preventDefault();
82
- onCancel();
83
- }
84
- }, [onCancel]);
85
- useEffect(() => {
86
- if (!isActive)
87
- return;
88
- document.addEventListener('mousemove', handleMouseMove, true);
89
- // In passthrough mode, don't register click handler — let clicks reach PostHog
90
- if (!passthroughClicks) {
91
- document.addEventListener('click', handleClick, true);
92
- }
93
- document.addEventListener('keydown', handleKeyDown, true);
94
- return () => {
95
- document.removeEventListener('mousemove', handleMouseMove, true);
96
- if (!passthroughClicks) {
97
- document.removeEventListener('click', handleClick, true);
98
- }
99
- document.removeEventListener('keydown', handleKeyDown, true);
100
- };
101
- }, [isActive, passthroughClicks, handleMouseMove, handleClick, handleKeyDown]);
102
- if (!isActive)
103
- return null;
104
- const rect = hoveredElement?.getBoundingClientRect();
105
- return createPortal(_jsxs("div", { ref: overlayRef, "data-syntro-anchor-picker": true, style: {
106
- position: 'fixed',
107
- inset: 0,
108
- cursor: 'crosshair',
109
- zIndex: 2147483644,
110
- pointerEvents: passthroughClicks ? 'none' : undefined,
111
- }, children: [_jsx("div", { style: {
112
- position: 'absolute',
113
- inset: 0,
114
- background: 'rgba(0, 0, 0, 0.08)',
115
- pointerEvents: 'none',
116
- } }), hoveredElement && rect && (_jsx("div", { style: {
117
- position: 'fixed',
118
- left: rect.left - 2,
119
- top: rect.top - 2,
120
- width: rect.width + 4,
121
- height: rect.height + 4,
122
- border: `2px solid ${HIGHLIGHT_COLOR}`,
123
- backgroundColor: HIGHLIGHT_BG,
124
- borderRadius: '4px',
125
- boxShadow: '0 0 0 9999px rgba(0, 0, 0, 0.2)',
126
- pointerEvents: 'none',
127
- transition: 'all 0.1s ease-out',
128
- } })), hoveredElement && rect && (_jsxs("div", { className: "se-text-xs", style: {
129
- position: 'fixed',
130
- left: Math.max(8, Math.min(rect.left, window.innerWidth - 320)),
131
- top: Math.max(8, rect.top - 68),
132
- backgroundColor: '#1e293b',
133
- color: '#e2e8f0',
134
- padding: '8px 12px',
135
- borderRadius: '6px',
136
- boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
137
- zIndex: 1,
138
- fontFamily: 'monospace',
139
- maxWidth: '300px',
140
- pointerEvents: 'none',
141
- }, children: [_jsx("div", { className: "se-text-xs", style: {
142
- textTransform: 'uppercase',
143
- letterSpacing: '0.05em',
144
- marginBottom: '4px',
145
- color: '#94a3b8',
146
- }, children: "Click to select" }), _jsx("div", { style: {
147
- color: '#38bdf8',
148
- overflow: 'hidden',
149
- textOverflow: 'ellipsis',
150
- whiteSpace: 'nowrap',
151
- }, children: hoveredSelector }), _jsx("div", { style: {
152
- marginTop: '4px',
153
- color: '#cbd5e1',
154
- overflow: 'hidden',
155
- textOverflow: 'ellipsis',
156
- whiteSpace: 'nowrap',
157
- }, children: getElementDescription(hoveredElement) })] }))] }), document.body);
158
- }
@@ -1,7 +0,0 @@
1
- interface BeforeAfterToggleProps {
2
- mode: 'before' | 'after';
3
- onToggle: (mode: 'before' | 'after') => void;
4
- }
5
- export declare function BeforeAfterToggle({ mode, onToggle }: BeforeAfterToggleProps): import("react/jsx-runtime").JSX.Element;
6
- export {};
7
- //# sourceMappingURL=BeforeAfterToggle.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BeforeAfterToggle.d.ts","sourceRoot":"","sources":["../../src/components/BeforeAfterToggle.tsx"],"names":[],"mappings":"AAEA,UAAU,sBAAsB;IAC9B,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,KAAK,IAAI,CAAC;CAC9C;AAED,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,sBAAsB,2CA6B3E"}
@@ -1,9 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { cn } from '../cn';
3
- export function BeforeAfterToggle({ mode, onToggle }) {
4
- return (_jsxs("div", { className: "se-flex se-mb-3 se-rounded-lg se-overflow-hidden se-border se-border-border-primary", children: [_jsx("button", { type: "button", onClick: () => onToggle('before'), className: cn('se-flex-1 se-py-1.5 se-px-3 se-border-none se-text-sm se-font-semibold se-cursor-pointer focus-visible:se-shadow-focus-primary focus-visible:se-outline-none', mode === 'before'
5
- ? 'se-bg-blue-5/30 se-text-blue-5'
6
- : 'se-bg-transparent se-text-text-secondary'), children: "Before" }), _jsx("button", { type: "button", onClick: () => onToggle('after'), className: cn('se-flex-1 se-py-1.5 se-px-3 se-border-none se-border-l se-border-border-primary se-text-sm se-font-semibold se-cursor-pointer focus-visible:se-shadow-focus-primary focus-visible:se-outline-none', mode === 'after'
7
- ? 'se-bg-blue-5/30 se-text-blue-5'
8
- : 'se-bg-transparent se-text-text-secondary'), children: "After" })] }));
9
- }
@@ -1,23 +0,0 @@
1
- /**
2
- * ConditionStatusLine — inline triggerWhen diagnostic on EditorCard.
3
- *
4
- * Shows a compact one-line status for items with triggerWhen conditions.
5
- * Click to expand per-condition detail.
6
- */
7
- import type { FormattedCondition } from '../formatConditionLabel';
8
- export interface ConditionStatus {
9
- type: string;
10
- passed: boolean;
11
- formatted: FormattedCondition;
12
- }
13
- export interface TriggerWhenStatus {
14
- visible: boolean;
15
- isFallback: boolean;
16
- conditions: ConditionStatus[];
17
- }
18
- interface ConditionStatusLineProps {
19
- status: TriggerWhenStatus | null;
20
- }
21
- export declare function ConditionStatusLine({ status }: ConditionStatusLineProps): import("react/jsx-runtime").JSX.Element | null;
22
- export {};
23
- //# sourceMappingURL=ConditionStatusLine.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ConditionStatusLine.d.ts","sourceRoot":"","sources":["../../src/components/ConditionStatusLine.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,UAAU,wBAAwB;IAChC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAClC;AA6CD,wBAAgB,mBAAmB,CAAC,EAAE,MAAM,EAAE,EAAE,wBAAwB,kDAiEvE"}
@@ -1,40 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- /**
3
- * ConditionStatusLine — inline triggerWhen diagnostic on EditorCard.
4
- *
5
- * Shows a compact one-line status for items with triggerWhen conditions.
6
- * Click to expand per-condition detail.
7
- */
8
- import { Check, Clock, X } from 'lucide-react';
9
- import { useState } from 'react';
10
- import { cn } from '../cn';
11
- function ProgressBar({ current, target }) {
12
- const pct = Math.min(100, Math.round((current / Math.max(target, 1)) * 100));
13
- return (_jsx("span", { className: "se-inline-block se-w-12 se-h-1.5 se-rounded-full se-bg-white/20 se-align-middle se-ml-1", title: `${current}/${target} (${pct}%)`, children: _jsx("span", { className: cn('se-block se-h-full se-rounded-full se-transition-all', pct >= 100 ? 'se-bg-green-4' : 'se-bg-blue-4'), style: { width: `${pct}%` } }) }));
14
- }
15
- function ConditionRow({ cs }) {
16
- return (_jsxs("div", { className: "se-flex se-items-center se-gap-1 se-pl-3 se-text-[12px] se-font-medium se-text-text-secondary", children: [cs.passed ? (_jsx(Check, { className: "se-w-3 se-h-3 se-text-green-4" })) : (_jsx(X, { className: "se-w-3 se-h-3 se-text-red-4" })), _jsxs("span", { children: [cs.type, ":"] }), _jsx("span", { className: "se-text-text-secondary", children: cs.formatted.label }), cs.formatted.progress && (_jsxs(_Fragment, { children: [_jsx(ProgressBar, { current: cs.formatted.progress.current, target: cs.formatted.progress.target }), _jsxs("span", { className: "se-text-text-secondary se-ml-0.5", children: [cs.formatted.progress.current, "/", cs.formatted.progress.target] })] }))] }));
17
- }
18
- export function ConditionStatusLine({ status }) {
19
- const [expanded, setExpanded] = useState(false);
20
- if (!status)
21
- return null;
22
- const { visible, conditions } = status;
23
- const passedCount = conditions.filter((c) => c.passed).length;
24
- const totalCount = conditions.length;
25
- // Icon: visible = green check, hidden = clock
26
- const StatusIcon = visible ? Check : Clock;
27
- const iconColor = visible ? 'se-text-green-4' : 'se-text-yellow-5';
28
- // Single condition: show inline detail
29
- // Multi condition: show summary, click to expand
30
- const isSingle = totalCount === 1;
31
- if (isSingle) {
32
- const cs = conditions[0];
33
- return (_jsxs("div", { className: "se-text-[12px] se-font-medium se-text-text-secondary se-mt-0.5 se-flex se-items-center se-gap-1", children: [_jsx(StatusIcon, { className: cn('se-w-3 se-h-3', iconColor) }), _jsxs("span", { children: [cs.type, ":"] }), _jsx("span", { className: "se-text-text-secondary", children: cs.formatted.label }), cs.formatted.progress && (_jsxs(_Fragment, { children: [_jsx(ProgressBar, { current: cs.formatted.progress.current, target: cs.formatted.progress.target }), _jsxs("span", { className: "se-text-text-secondary se-ml-0.5", children: [cs.formatted.progress.current, "/", cs.formatted.progress.target] })] }))] }));
34
- }
35
- // Multi-condition: summary line + expandable detail
36
- return (_jsxs("div", { className: "se-mt-0.5", children: [_jsxs("button", { type: "button", className: "se-flex se-items-center se-gap-1 se-text-[12px] se-font-medium se-text-text-secondary se-bg-transparent se-border-none se-cursor-pointer se-p-0 hover:se-text-text-primary", onClick: (e) => {
37
- e.stopPropagation();
38
- setExpanded(!expanded);
39
- }, children: [_jsx(StatusIcon, { className: cn('se-w-3 se-h-3', iconColor) }), _jsxs("span", { children: [passedCount, " of ", totalCount, " conditions met"] }), _jsx("span", { className: "se-text-[11px] se-ml-0.5", children: expanded ? '\u25b2' : '\u25bc' })] }), expanded && (_jsx("div", { className: "se-mt-0.5 se-space-y-0.5", children: conditions.map((cs, i) => (_jsx(ConditionRow, { cs: cs }, i))) }))] }));
40
- }
@@ -1,7 +0,0 @@
1
- interface DetectionBadgeProps {
2
- found: boolean;
3
- onClick?: (e: React.MouseEvent) => void;
4
- }
5
- export declare function DetectionBadge({ found, onClick }: DetectionBadgeProps): import("react/jsx-runtime").JSX.Element;
6
- export {};
7
- //# sourceMappingURL=DetectionBadge.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DetectionBadge.d.ts","sourceRoot":"","sources":["../../src/components/DetectionBadge.tsx"],"names":[],"mappings":"AAEA,UAAU,mBAAmB;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;CACzC;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,mBAAmB,2CA6CrE"}
@@ -1,22 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { cn } from '../cn';
3
- export function DetectionBadge({ found, onClick }) {
4
- const title = onClick
5
- ? found
6
- ? 'Click to scroll to element'
7
- : 'Click to navigate to page'
8
- : found
9
- ? 'Found on this page'
10
- : 'Not found on this page';
11
- const textColor = found ? 'se-text-green-4' : 'se-text-text-tertiary';
12
- const dotColor = found ? 'se-bg-green-4' : 'se-bg-text-tertiary';
13
- const classes = cn('se-inline-flex se-items-center se-gap-1 se-text-xs se-font-medium se-shrink-0', textColor, onClick && 'se-cursor-pointer hover:se-opacity-80');
14
- const dot = (_jsx("span", { "data-indicator": "", className: cn('se-w-1.5 se-h-1.5 se-rounded-full', dotColor) }));
15
- if (onClick) {
16
- return (_jsxs("button", { type: "button", className: cn(classes, 'se-border-none se-bg-transparent se-p-0'), title: title, onClick: (e) => {
17
- e.stopPropagation();
18
- onClick(e);
19
- }, children: [dot, "GoTo"] }));
20
- }
21
- return (_jsxs("span", { className: classes, title: title, children: [dot, "GoTo"] }));
22
- }
@@ -1,8 +0,0 @@
1
- import type React from 'react';
2
- interface DismissedSectionProps {
3
- count: number;
4
- children: React.ReactNode;
5
- }
6
- export declare function DismissedSection({ count, children }: DismissedSectionProps): import("react/jsx-runtime").JSX.Element;
7
- export {};
8
- //# sourceMappingURL=DismissedSection.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DismissedSection.d.ts","sourceRoot":"","sources":["../../src/components/DismissedSection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,UAAU,qBAAqB;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,qBAAqB,2CAqB1E"}