agentation-vue 0.2.4 → 0.2.6

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.
@@ -8,6 +8,7 @@ type __VLS_Props = {
8
8
  pageUrl?: string;
9
9
  theme?: 'light' | 'dark' | 'auto';
10
10
  activationKey?: 'none' | 'Meta' | 'Alt' | 'Shift';
11
+ disablePortal?: boolean;
11
12
  };
12
13
  declare const _default: import("vue-demi").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue-demi").ComponentOptionsMixin, import("vue-demi").ComponentOptionsMixin, {
13
14
  copy: (markdown: string) => any;
@@ -5,23 +5,23 @@ import AnnotationInput from "./components/AnnotationInput.vue";
5
5
  import AnnotationMarker from "./components/AnnotationMarker.vue";
6
6
  import ElementHighlight from "./components/ElementHighlight.vue";
7
7
  import SettingsPopover from "./components/SettingsPopover.vue";
8
- import { useAnimationPause } from "./composables/useAnimationPause";
9
- import { useAnnotations } from "./composables/useAnnotations";
10
- import { useAreaSelect } from "./composables/useAreaSelect";
11
- import { useElementDetection } from "./composables/useElementDetection";
12
- import { useInteractionMode } from "./composables/useInteractionMode";
13
- import { DEFAULT_SHORTCUT_CONFIG, useKeyboardShortcuts } from "./composables/useKeyboardShortcuts";
14
- import { useMarkerPositions } from "./composables/useMarkerPositions";
15
- import { useMultiSelect } from "./composables/useMultiSelect";
16
- import { useOutputFormatter } from "./composables/useOutputFormatter";
17
- import { useSettings } from "./composables/useSettings";
18
- import { useTextSelection } from "./composables/useTextSelection";
19
- import { VA_DATA_ATTR_SELECTOR } from "./constants";
20
- import { copyToClipboard } from "./utils/clipboard";
21
- import { isFixed as checkIsFixed, detectVueComponents, getAccessibilityInfo, getComputedStylesSummary, getNearbyElements, getNearbyText, getRelevantComputedStyles } from "./utils/dom-inspector";
22
- import { createPortalContainer, destroyPortalContainer } from "./utils/portal";
23
- import { getElementName, getElementPath } from "./utils/selectors";
24
- import { boundingBoxToStyle } from "./utils/style";
8
+ import { useAnimationPause } from "./composables/useAnimationPause.mjs";
9
+ import { useAnnotations } from "./composables/useAnnotations.mjs";
10
+ import { useAreaSelect } from "./composables/useAreaSelect.mjs";
11
+ import { useElementDetection } from "./composables/useElementDetection.mjs";
12
+ import { useInteractionMode } from "./composables/useInteractionMode.mjs";
13
+ import { DEFAULT_SHORTCUT_CONFIG, useKeyboardShortcuts } from "./composables/useKeyboardShortcuts.mjs";
14
+ import { useMarkerPositions } from "./composables/useMarkerPositions.mjs";
15
+ import { useMultiSelect } from "./composables/useMultiSelect.mjs";
16
+ import { useOutputFormatter } from "./composables/useOutputFormatter.mjs";
17
+ import { useSettings } from "./composables/useSettings.mjs";
18
+ import { useTextSelection } from "./composables/useTextSelection.mjs";
19
+ import { isInsideAgentationTree } from "./utils/agentation-tree.mjs";
20
+ import { copyToClipboard } from "./utils/clipboard.mjs";
21
+ import { isFixed as checkIsFixed, detectVueComponents, getAccessibilityInfo, getComputedStylesSummary, getNearbyElements, getNearbyText, getRelevantComputedStyles } from "./utils/dom-inspector.mjs";
22
+ import { createPortalContainer, destroyPortalContainer } from "./utils/portal.mjs";
23
+ import { getElementName, getElementPath } from "./utils/selectors.mjs";
24
+ import { boundingBoxToStyle } from "./utils/style.mjs";
25
25
  const props = defineProps({
26
26
  outputDetail: { type: String, required: false },
27
27
  markerColor: { type: String, required: false },
@@ -30,7 +30,8 @@ const props = defineProps({
30
30
  autoHideToolbar: { type: Boolean, required: false },
31
31
  pageUrl: { type: String, required: false },
32
32
  theme: { type: String, required: false },
33
- activationKey: { type: String, required: false }
33
+ activationKey: { type: String, required: false },
34
+ disablePortal: { type: Boolean, required: false }
34
35
  });
35
36
  const emit = defineEmits(["annotation-add", "annotation-delete", "annotation-update", "annotations-clear", "copy"]);
36
37
  const HISTORY_CHANGE_EVENT = "va:history-change";
@@ -114,10 +115,10 @@ const PassThrough = defineComponent({
114
115
  return (typeof slot === "function" ? slot() : slot?.[0]) || null;
115
116
  }
116
117
  });
117
- const portalWrapper = isVue2 ? PassThrough : "Teleport";
118
- const portalProps = isVue2 ? {} : { to: "body" };
118
+ const portalWrapper = computed(() => props.disablePortal || isVue2 ? PassThrough : "Teleport");
119
+ const portalProps = computed(() => props.disablePortal || isVue2 ? {} : { to: "body" });
119
120
  onMounted(() => {
120
- if (isVue2 && rootEl.value) {
121
+ if (!props.disablePortal && isVue2 && rootEl.value) {
121
122
  portalContainer = createPortalContainer();
122
123
  portalContainer.appendChild(rootEl.value);
123
124
  }
@@ -244,7 +245,7 @@ function onOverlayMouseUp(e) {
244
245
  return;
245
246
  }
246
247
  const el = getElementUnderOverlay(e);
247
- if (!el || el.closest(VA_DATA_ATTR_SELECTOR))
248
+ if (!el || isInsideAgentationTree(el))
248
249
  return;
249
250
  pendingPosition.value = { x: e.clientX, y: e.clientY };
250
251
  pendingElementName.value = getElementName(el);
@@ -335,7 +336,7 @@ function onDocumentClick(e) {
335
336
  if (mode.value === "idle")
336
337
  return;
337
338
  const target = e.target;
338
- if (!target || target.closest(VA_DATA_ATTR_SELECTOR))
339
+ if (!target || isInsideAgentationTree(target, e))
339
340
  return;
340
341
  e.preventDefault();
341
342
  e.stopPropagation();
@@ -8,6 +8,7 @@ type __VLS_Props = {
8
8
  pageUrl?: string;
9
9
  theme?: 'light' | 'dark' | 'auto';
10
10
  activationKey?: 'none' | 'Meta' | 'Alt' | 'Shift';
11
+ disablePortal?: boolean;
11
12
  };
12
13
  declare const _default: import("vue-demi").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue-demi").ComponentOptionsMixin, import("vue-demi").ComponentOptionsMixin, {
13
14
  copy: (markdown: string) => any;
@@ -1,7 +1,7 @@
1
1
  <script setup>
2
2
  import { computed, onBeforeUnmount, ref, toRef, watch } from "vue-demi";
3
- import { useToolbarAutoHide } from "../composables/useToolbarAutoHide";
4
- import { useToolbarDragSnap } from "../composables/useToolbarDragSnap";
3
+ import { useToolbarAutoHide } from "../composables/useToolbarAutoHide.mjs";
4
+ import { useToolbarDragSnap } from "../composables/useToolbarDragSnap.mjs";
5
5
  import VaIcon from "./VaIcon.vue";
6
6
  import VaIconButton from "./VaIconButton.vue";
7
7
  const props = defineProps({
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
2
  import { computed } from "vue-demi";
3
- import { boundingBoxToStyle } from "../utils/style";
3
+ import { boundingBoxToStyle } from "../utils/style.mjs";
4
4
  import ComponentChain from "./ComponentChain.vue";
5
5
  const props = defineProps({
6
6
  rect: { type: [Object, null], required: true },
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
2
  import { computed, toRef } from "vue-demi";
3
- import { vaTooltipDirective } from "../directives/vaTooltip";
3
+ import { vaTooltipDirective } from "../directives/vaTooltip.mjs";
4
4
  import VaIcon from "./VaIcon.vue";
5
5
  import VaToggle from "./VaToggle.vue";
6
6
  const props = defineProps({
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
2
  import { nextTick, onBeforeUnmount, ref, watch } from "vue-demi";
3
- import { clamp } from "../utils/math";
3
+ import { clamp } from "../utils/math.mjs";
4
4
  import SettingsPanel from "./SettingsPanel.vue";
5
5
  const props = defineProps({
6
6
  open: { type: Boolean, required: true },
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { icons } from "../icons";
2
+ import { icons } from "../icons.mjs";
3
3
  defineProps({
4
4
  name: { type: null, required: true }
5
5
  });
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
2
  import { computed } from "vue-demi";
3
- import { vaTooltipDirective } from "../directives/vaTooltip";
3
+ import { vaTooltipDirective } from "../directives/vaTooltip.mjs";
4
4
  const props = defineProps({
5
5
  active: { type: Boolean, required: false, default: false },
6
6
  disabled: { type: Boolean, required: false, default: false },
@@ -1,9 +1,11 @@
1
- import type { Annotation } from '../types';
1
+ import type { Annotation, StorageAdapter } from '../types';
2
2
  declare function setScopeUrl(url: string): void;
3
3
  declare function addAnnotation(annotation: Omit<Annotation, 'id' | 'timestamp'>): Annotation;
4
4
  declare function removeAnnotation(id: string): Annotation | undefined;
5
5
  declare function updateAnnotation(id: string, updates: Partial<Annotation>): Annotation | undefined;
6
6
  declare function clearAnnotations(): Annotation[];
7
+ export declare function setAnnotationStorage(adapter: StorageAdapter): void;
8
+ export declare function resetAnnotationStorage(): void;
7
9
  export declare function useAnnotations(initialUrl?: string): {
8
10
  annotations: import("vue-demi").Ref<{
9
11
  id: string;
@@ -1,5 +1,14 @@
1
1
  import { ref } from "vue-demi";
2
2
  const STORAGE_KEY = "agentation-vue-annotations";
3
+ const fallbackAnnotationStorage = {
4
+ getItem(key) {
5
+ return sessionStorage.getItem(key);
6
+ },
7
+ setItem(key, value) {
8
+ sessionStorage.setItem(key, value);
9
+ }
10
+ };
11
+ let annotationStorage = fallbackAnnotationStorage;
3
12
  function serializeAnnotations(annotations2) {
4
13
  return JSON.stringify(annotations2.map(({ _targetRef, ...rest }) => rest));
5
14
  }
@@ -24,7 +33,7 @@ function parseStore(raw, currentUrl) {
24
33
  }
25
34
  function loadAnnotations(url) {
26
35
  try {
27
- const stored = sessionStorage.getItem(STORAGE_KEY);
36
+ const stored = annotationStorage.getItem(STORAGE_KEY);
28
37
  const store = parseStore(stored, url);
29
38
  const annotations2 = store[url];
30
39
  return Array.isArray(annotations2) ? annotations2 : [];
@@ -48,7 +57,7 @@ function setScopeUrl(url) {
48
57
  }
49
58
  function save() {
50
59
  try {
51
- const stored = sessionStorage.getItem(STORAGE_KEY);
60
+ const stored = annotationStorage.getItem(STORAGE_KEY);
52
61
  const store = parseStore(stored, scopedUrl);
53
62
  if (annotations.value.length > 0)
54
63
  store[scopedUrl] = annotations.value;
@@ -62,7 +71,7 @@ function save() {
62
71
  ])
63
72
  )
64
73
  );
65
- sessionStorage.setItem(STORAGE_KEY, serialized);
74
+ annotationStorage.setItem(STORAGE_KEY, serialized);
66
75
  } catch {
67
76
  }
68
77
  }
@@ -102,6 +111,14 @@ function clearAnnotations() {
102
111
  return cleared;
103
112
  }
104
113
  setScopeUrl(scopedUrl);
114
+ export function setAnnotationStorage(adapter) {
115
+ annotationStorage = adapter;
116
+ setScopeUrl(scopedUrl);
117
+ }
118
+ export function resetAnnotationStorage() {
119
+ annotationStorage = fallbackAnnotationStorage;
120
+ setScopeUrl(scopedUrl);
121
+ }
105
122
  export function useAnnotations(initialUrl = getCurrentUrl()) {
106
123
  setScopeUrl(initialUrl);
107
124
  return { annotations, addAnnotation, removeAnnotation, updateAnnotation, clearAnnotations, setScopeUrl };
@@ -1,5 +1,5 @@
1
1
  import { ref } from "vue-demi";
2
- import { VA_DATA_ATTR_SELECTOR } from "../constants.mjs";
2
+ import { isInsideAgentationTree } from "../utils/agentation-tree.mjs";
3
3
  import { detectVueComponents } from "../utils/dom-inspector.mjs";
4
4
  import { getElementName } from "../utils/selectors.mjs";
5
5
  export function useElementDetection(overlayRef, showComponentTree) {
@@ -50,7 +50,7 @@ export function useElementDetection(overlayRef, showComponentTree) {
50
50
  const el = getElementUnderOverlay(e);
51
51
  if (el === lastElement)
52
52
  return;
53
- if (el?.closest(VA_DATA_ATTR_SELECTOR)) {
53
+ if (el && isInsideAgentationTree(el)) {
54
54
  clearHighlight();
55
55
  return;
56
56
  }
@@ -1,5 +1,5 @@
1
1
  import { onBeforeUnmount, onMounted, watch } from "vue-demi";
2
- import { VA_DATA_ATTR_SELECTOR } from "../constants.mjs";
2
+ import { getDeepActiveElement, isInsideAgentationTree } from "../utils/agentation-tree.mjs";
3
3
  const DEFAULT_KEYMAP = {
4
4
  "activate": "",
5
5
  "element-select": "v",
@@ -69,14 +69,14 @@ export function useKeyboardShortcuts(options) {
69
69
  return "open";
70
70
  }
71
71
  function isForeignEditable() {
72
- const active = document.activeElement;
72
+ const active = getDeepActiveElement();
73
73
  if (!active)
74
74
  return false;
75
75
  const tag = active.tagName.toLowerCase();
76
76
  const isEditable = tag === "input" || tag === "textarea" || active.isContentEditable;
77
77
  if (!isEditable)
78
78
  return false;
79
- return !active.closest(VA_DATA_ATTR_SELECTOR);
79
+ return !isInsideAgentationTree(active);
80
80
  }
81
81
  function isBrowserCombo(e) {
82
82
  if (!e.metaKey && !e.ctrlKey)
@@ -1,5 +1,5 @@
1
1
  import { ref } from "vue-demi";
2
- import { VA_DATA_ATTR_SELECTOR } from "../constants.mjs";
2
+ import { isInsideAgentationTree } from "../utils/agentation-tree.mjs";
3
3
  const LEAF_TAGS = /* @__PURE__ */ new Set(["button", "a", "input", "img"]);
4
4
  export function useMultiSelect(mode, transitionFn) {
5
5
  const selectionRect = ref(null);
@@ -11,7 +11,7 @@ export function useMultiSelect(mode, transitionFn) {
11
11
  function cacheElements() {
12
12
  cachedElements = [];
13
13
  for (const el of document.querySelectorAll("body *")) {
14
- if (el.closest(VA_DATA_ATTR_SELECTOR))
14
+ if (isInsideAgentationTree(el))
15
15
  continue;
16
16
  const rect = el.getBoundingClientRect();
17
17
  if (rect.width === 0 || rect.height === 0)
@@ -1,3 +1,6 @@
1
+ import type { StorageAdapter } from '../types';
2
+ export declare function setSettingsStorage(adapter: StorageAdapter): void;
3
+ export declare function resetSettingsStorage(): void;
1
4
  export declare function useSettings(): {
2
5
  settings: {
3
6
  outputDetail: import("../types").OutputDetail;
@@ -1,5 +1,14 @@
1
1
  import { reactive, watch } from "vue-demi";
2
2
  const STORAGE_KEY = "agentation-vue-settings";
3
+ const fallbackSettingsStorage = {
4
+ getItem(key) {
5
+ return localStorage.getItem(key);
6
+ },
7
+ setItem(key, value) {
8
+ localStorage.setItem(key, value);
9
+ }
10
+ };
11
+ let settingsStorage = fallbackSettingsStorage;
3
12
  const defaults = {
4
13
  outputDetail: "standard",
5
14
  markerColor: "#42B883",
@@ -13,7 +22,7 @@ const defaults = {
13
22
  };
14
23
  function loadSettings() {
15
24
  try {
16
- const stored = localStorage.getItem(STORAGE_KEY);
25
+ const stored = settingsStorage.getItem(STORAGE_KEY);
17
26
  if (stored)
18
27
  return { ...defaults, ...JSON.parse(stored) };
19
28
  } catch {
@@ -25,11 +34,19 @@ watch(
25
34
  () => ({ ...settings }),
26
35
  (val) => {
27
36
  try {
28
- localStorage.setItem(STORAGE_KEY, JSON.stringify(val));
37
+ settingsStorage.setItem(STORAGE_KEY, JSON.stringify(val));
29
38
  } catch {
30
39
  }
31
40
  }
32
41
  );
42
+ export function setSettingsStorage(adapter) {
43
+ settingsStorage = adapter;
44
+ Object.assign(settings, loadSettings());
45
+ }
46
+ export function resetSettingsStorage() {
47
+ settingsStorage = fallbackSettingsStorage;
48
+ Object.assign(settings, loadSettings());
49
+ }
33
50
  export function useSettings() {
34
51
  function resetSettings() {
35
52
  Object.assign(settings, defaults);
package/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ export { default as VaIconButton } from './components/VaIconButton.vue';
13
13
  export { default as VaToggle } from './components/VaToggle.vue';
14
14
  export { vaTooltipDirective };
15
15
  export { useAnimationPause } from './composables/useAnimationPause';
16
- export { useAnnotations } from './composables/useAnnotations';
16
+ export { resetAnnotationStorage, setAnnotationStorage, useAnnotations, } from './composables/useAnnotations';
17
17
  export { useAreaSelect } from './composables/useAreaSelect';
18
18
  export { useElementDetection } from './composables/useElementDetection';
19
19
  export { useInteractionMode } from './composables/useInteractionMode';
@@ -22,10 +22,12 @@ export type { DoubleTapConfig, KeyboardShortcutConfig, KeyboardShortcutState, Sh
22
22
  export { useMarkerPositions } from './composables/useMarkerPositions';
23
23
  export { useMultiSelect } from './composables/useMultiSelect';
24
24
  export { formatAnnotations, useOutputFormatter } from './composables/useOutputFormatter';
25
- export { useSettings } from './composables/useSettings';
25
+ export { resetSettingsStorage, setSettingsStorage, useSettings, } from './composables/useSettings';
26
26
  export { useTextSelection } from './composables/useTextSelection';
27
27
  export { useToolbarAutoHide } from './composables/useToolbarAutoHide';
28
28
  export type { VaTooltipOptions, VaTooltipPlacement, VaTooltipValue } from './directives/vaTooltip';
29
29
  export { icons } from './icons';
30
30
  export type { IconName } from './icons';
31
- export type { AgentationEmits, AgentationProps, Annotation, BoundingBox, ElementRef, InteractionMode, OutputDetail, Settings, } from './types';
31
+ export type { AgentationEmits, AgentationProps, Annotation, BoundingBox, ElementRef, InteractionMode, OutputDetail, Settings, StorageAdapter, } from './types';
32
+ export { resetVueDetector, setVueDetector } from './utils/dom-inspector';
33
+ export type { VueDetector } from './utils/dom-inspector';
package/dist/index.mjs CHANGED
@@ -16,7 +16,11 @@ export { default as VaIconButton } from "./components/VaIconButton.vue";
16
16
  export { default as VaToggle } from "./components/VaToggle.vue";
17
17
  export { vaTooltipDirective };
18
18
  export { useAnimationPause } from "./composables/useAnimationPause.mjs";
19
- export { useAnnotations } from "./composables/useAnnotations.mjs";
19
+ export {
20
+ resetAnnotationStorage,
21
+ setAnnotationStorage,
22
+ useAnnotations
23
+ } from "./composables/useAnnotations.mjs";
20
24
  export { useAreaSelect } from "./composables/useAreaSelect.mjs";
21
25
  export { useElementDetection } from "./composables/useElementDetection.mjs";
22
26
  export { useInteractionMode } from "./composables/useInteractionMode.mjs";
@@ -24,7 +28,12 @@ export { DEFAULT_SHORTCUT_CONFIG, useKeyboardShortcuts } from "./composables/use
24
28
  export { useMarkerPositions } from "./composables/useMarkerPositions.mjs";
25
29
  export { useMultiSelect } from "./composables/useMultiSelect.mjs";
26
30
  export { formatAnnotations, useOutputFormatter } from "./composables/useOutputFormatter.mjs";
27
- export { useSettings } from "./composables/useSettings.mjs";
31
+ export {
32
+ resetSettingsStorage,
33
+ setSettingsStorage,
34
+ useSettings
35
+ } from "./composables/useSettings.mjs";
28
36
  export { useTextSelection } from "./composables/useTextSelection.mjs";
29
37
  export { useToolbarAutoHide } from "./composables/useToolbarAutoHide.mjs";
30
38
  export { icons } from "./icons.mjs";
39
+ export { resetVueDetector, setVueDetector } from "./utils/dom-inspector.mjs";
@@ -1 +1 @@
1
- [data-agentation-vue]{--va-bg:#fff;--va-bg-secondary:#f5f5f5;--va-text:#1a1a1a;--va-text-secondary:#666;--va-border:#e5e5e5}[data-agentation-vue]:not([data-agentation-vue] [data-agentation-vue]){--va-accent:#42b883;--va-accent-rgb:66,184,131}@media (prefers-color-scheme:dark){[data-agentation-vue]:not([data-va-theme=light]){--va-bg:#1a1a1a;--va-bg-secondary:#2a2a2a;--va-text:#f5f5f5;--va-text-secondary:#999;--va-border:#333}}[data-agentation-vue][data-va-theme=dark],[data-agentation-vue][data-va-theme=dark] [data-agentation-vue]{--va-bg:#1a1a1a;--va-bg-secondary:#2a2a2a;--va-text:#f5f5f5;--va-text-secondary:#999;--va-border:#333}[data-agentation-vue][data-va-theme=light],[data-agentation-vue][data-va-theme=light] [data-agentation-vue]{--va-bg:#fff;--va-bg-secondary:#f5f5f5;--va-text:#1a1a1a;--va-text-secondary:#666;--va-border:#e5e5e5}:where(#__va-portal,#__va-portal *){border:none;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;line-height:1.5;list-style:none;margin:0;padding:0;text-decoration:none}.__va-intercept{background:transparent;cursor:crosshair;inset:0;position:fixed;z-index:2147483646}.__va-intercept--input-open{pointer-events:none}.__va-toolbar{position:fixed;--va-toolbar-base-transform:translate(0);--va-toolbar-auto-hide-transform:translate(0);--va-toolbar-size:42px;--va-toolbar-edge-offset:20px;--va-toolbar-auto-hide-peek:8px;--va-toolbar-auto-hide-corner-peek:16px;--va-toolbar-auto-hide-shift:calc(var(--va-toolbar-edge-offset) + var(--va-toolbar-size) - var(--va-toolbar-auto-hide-peek));--va-toolbar-auto-hide-corner-shift:calc(var(--va-toolbar-edge-offset) + var(--va-toolbar-size) - var(--va-toolbar-auto-hide-corner-peek));display:block;max-width:42px;min-height:42px;z-index:2147483647;--va-toolbar-resize-delay:0ms;background:var(--va-bg);border:1px solid var(--va-border);border-radius:999px;box-shadow:0 4px 12px rgba(0,0,0,.15);padding:0;transform:var(--va-toolbar-base-transform) var(--va-toolbar-auto-hide-transform);transition:border-radius .12s cubic-bezier(.32,.72,0,1),padding .12s cubic-bezier(.32,.72,0,1),max-width .24s cubic-bezier(.22,1,.36,1) var(--va-toolbar-resize-delay),transform .15s ease,opacity .15s ease,box-shadow .15s ease;-webkit-user-select:none;-moz-user-select:none;user-select:none}.__va-toolbar--place-bottom-right{bottom:20px;right:20px}.__va-toolbar--place-bottom-center{bottom:20px;left:50%;--va-toolbar-base-transform:translateX(-50%)}.__va-toolbar--place-bottom-left{bottom:20px;left:20px}.__va-toolbar--place-top-right{right:20px;top:20px}.__va-toolbar--place-top-center{left:50%;top:20px;--va-toolbar-base-transform:translateX(-50%)}.__va-toolbar--place-top-left{left:20px;top:20px}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-top-left{--va-toolbar-auto-hide-transform:translate(calc(var(--va-toolbar-auto-hide-corner-shift)*-1),calc(var(--va-toolbar-auto-hide-corner-shift)*-1))}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-top-center{--va-toolbar-auto-hide-transform:translateY(calc(var(--va-toolbar-auto-hide-shift)*-1))}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-top-right{--va-toolbar-auto-hide-transform:translate(var(--va-toolbar-auto-hide-corner-shift),calc(var(--va-toolbar-auto-hide-corner-shift)*-1))}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-bottom-left{--va-toolbar-auto-hide-transform:translate(calc(var(--va-toolbar-auto-hide-corner-shift)*-1),var(--va-toolbar-auto-hide-corner-shift))}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-bottom-center{--va-toolbar-auto-hide-transform:translateY(var(--va-toolbar-auto-hide-shift))}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-bottom-right{--va-toolbar-auto-hide-transform:translate(var(--va-toolbar-auto-hide-corner-shift),var(--va-toolbar-auto-hide-corner-shift))}.__va-toolbar--collapsed{cursor:pointer;max-width:42px;min-height:42px}.__va-toolbar--expanded{--va-toolbar-resize-delay:110ms;border-radius:10px;max-width:520px;padding:4px}.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide):hover{box-shadow:0 6px 16px rgba(0,0,0,.2)}.__va-toolbar--dragging{bottom:auto;left:0;right:auto;top:0;transform:none;transition:none}.__va-toolbar--dragging.__va-toolbar--collapsed:hover{transform:none}.__va-toolbar-stage{align-items:center;display:flex;gap:4px}.__va-toolbar-stage--toggle{inset:0;justify-content:center;opacity:1;pointer-events:auto;position:absolute;transform:scale(1);transition:opacity .11s ease,transform .18s cubic-bezier(.22,1,.36,1),visibility 0s linear 0s;visibility:visible}.__va-toolbar-stage--menu{--va-toolbar-menu-enter-x:8px;filter:blur(4px);opacity:0;overflow:hidden;pointer-events:none;transform:translateX(var(--va-toolbar-menu-enter-x));transition:opacity .14s ease 0s,transform .22s cubic-bezier(.22,1,.36,1) 0s,visibility 0s linear .14s,filter 80ms ease 0s;visibility:hidden}.__va-toolbar--expanded .__va-toolbar-stage--toggle{opacity:0;pointer-events:none;transform:scale(.94);transition:opacity 90ms ease,transform .12s ease,visibility 0s linear 90ms;visibility:hidden}.__va-toolbar--expanded .__va-toolbar-stage--menu{filter:blur(0);opacity:1;pointer-events:auto;transform:translateX(0);transition:opacity .15s ease .15s,transform .24s cubic-bezier(.22,1,.36,1) .12s,visibility 0s linear 0s,filter .15s ease .2s;visibility:visible}.__va-toolbar--place-bottom-right .__va-toolbar-stage--menu,.__va-toolbar--place-top-right .__va-toolbar-stage--menu{--va-toolbar-menu-enter-x:-8px}.__va-toolbar--place-bottom-center .__va-toolbar-stage--menu,.__va-toolbar--place-top-center .__va-toolbar-stage--menu{--va-toolbar-menu-enter-x:0px}.__va-snap-zones{inset:0;pointer-events:none;position:fixed;z-index:2147483646}.__va-snap-zone{background:rgba(var(--va-accent-rgb),.035);border:1.5px dashed rgba(var(--va-accent-rgb),.18);border-radius:999px;box-shadow:0 0 0 1px rgba(var(--va-accent-rgb),.04);height:42px;position:fixed;transform:translate(-50%,-50%);transition:all .12s ease;width:42px}.__va-snap-zone--active{background:rgba(var(--va-accent-rgb),.09);border-color:rgba(var(--va-accent-rgb),.4)}.__va-snap-zone--rect{border-radius:8px;transform:none}.__va-snap-zone--rect.__va-snap-zone--active{transform:none}.__va-icon-btn{align-items:center;background:transparent;border:none;border-radius:6px;color:var(--va-text-secondary);cursor:pointer;display:flex;flex-shrink:0;height:32px;justify-content:center;outline:none;padding:0;transition:background .15s ease,color .15s ease;width:32px}.__va-icon-btn:hover{background:var(--va-bg-secondary);color:var(--va-text)}.__va-icon-btn--active{background:rgba(var(--va-accent-rgb),.15);color:var(--va-accent)}.__va-icon-btn--active:hover{background:rgba(var(--va-accent-rgb),.25)}.__va-icon-btn:disabled{cursor:not-allowed;opacity:.3}.__va-icon-btn:disabled:hover{background:transparent}.__va-icon-btn svg{height:18px;width:18px}.__va-toolbar-toggle{align-items:center;background:transparent;border:none;color:var(--va-accent);cursor:pointer;display:flex;height:100%;justify-content:center;line-height:0;outline:none;padding:0;position:relative;width:100%}.__va-toolbar-toggle svg{flex-shrink:0;height:22px;width:22px}.__va-toolbar-sep{background:var(--va-border);flex-shrink:0;height:20px;width:1px}.__va-drag-handle{align-items:center;background:transparent;border:none;border-radius:6px;color:var(--va-text-secondary);cursor:grab;display:flex;flex-shrink:0;height:32px;justify-content:center;outline:none;padding:0;transition:all .15s ease;width:24px}.__va-drag-handle:hover{background:var(--va-bg-secondary);color:var(--va-text)}.__va-drag-handle:active{cursor:grabbing}.__va-drag-handle-dots{display:grid;gap:2.5px;grid-template-columns:repeat(2,3px);grid-template-rows:repeat(3,3px)}.__va-drag-handle-dots span{background:currentColor;border-radius:50%;height:3px;opacity:.6;width:3px}.__va-toolbar-badge{align-items:center;background:var(--va-accent);border-radius:9px;color:#fff;display:flex;font-size:11px;font-weight:600;height:18px;justify-content:center;min-width:18px;padding:0 4px;position:absolute;right:-6px;top:-6px}.__va-tooltip{align-items:center;background:#131518;border:1px solid hsla(0,0%,100%,.08);border-radius:10px;box-shadow:0 10px 24px rgba(0,0,0,.32),0 2px 6px rgba(0,0,0,.28);color:#dce1e7;display:inline-flex;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:11px;font-weight:500;gap:6px;left:0;line-height:1.15;max-width:min(360px,calc(100vw - 16px));opacity:0;padding:6px 9px;pointer-events:none;position:fixed;top:0;transform:translateY(4px) scale(.98);transform-origin:center bottom;transition:opacity .12s ease,transform .12s ease;white-space:nowrap;z-index:2147483647}.__va-tooltip[data-placement=bottom]{transform:translateY(-4px) scale(.98);transform-origin:center top}.__va-tooltip.__va-tooltip--visible{opacity:1}.__va-tooltip.__va-tooltip--visible[data-placement=bottom],.__va-tooltip.__va-tooltip--visible[data-placement=top]{transform:translateY(0) scale(1)}.__va-tooltip-label{overflow:hidden;text-overflow:ellipsis}.__va-tooltip-shortcut{align-items:center;background:hsla(0,0%,100%,.1);border:1px solid hsla(0,0%,100%,.18);border-radius:6px;color:#b5bec8;display:inline-flex;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:11px;font-weight:600;letter-spacing:.03em;line-height:1;min-height:18px;padding:2px 6px}.__va-tooltip-arrow{background:#131518;border:1px solid hsla(0,0%,100%,.08);border-left:none;border-top:none;height:10px;left:50%;position:absolute;transform:translateX(-50%) rotate(45deg);width:10px}.__va-tooltip[data-placement=top] .__va-tooltip-arrow{bottom:-5px}.__va-tooltip[data-placement=bottom] .__va-tooltip-arrow{top:-5px;transform:translateX(-50%) rotate(225deg)}.__va-highlight{background:rgba(var(--va-accent-rgb),.08);border:2px solid var(--va-accent);border-radius:4px;pointer-events:none;position:fixed;transition:all 80ms ease;z-index:2147483645}.__va-highlight-label{background:var(--va-accent);border-radius:4px;color:#fff;font-size:11px;font-weight:500;left:0;max-width:300px;overflow:hidden;padding:2px 8px;position:absolute;text-overflow:ellipsis;top:-28px;white-space:nowrap}.__va-highlight-label--chain{background:#1a1a1a;max-width:500px;overflow:visible;padding:4px 10px}.__va-marker{align-items:center;background:var(--va-accent);border-radius:50%;box-shadow:0 2px 6px rgba(0,0,0,.3);color:#fff;cursor:pointer;display:flex;font-size:12px;font-weight:700;height:24px;justify-content:center;position:absolute;transform:translate(-50%,-50%);transition:all .15s ease;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:24px;z-index:2147483647}.__va-marker:hover{box-shadow:0 3px 10px rgba(0,0,0,.4);transform:translate(-50%,-50%) scale(1.2)}.__va-marker--fixed{position:fixed}.__va-marker--stale{opacity:.5}.__va-marker-plus{height:14px;stroke-width:3;width:14px}.__va-marker-pencil{display:none;height:12px;width:12px}.__va-marker:not(.__va-marker--pending):hover .__va-marker-number{display:none}.__va-marker:not(.__va-marker--pending):hover .__va-marker-pencil{display:block}.__va-marker--pending{animation:__va-pulse 1.5s ease-in-out infinite}.__va-marker--selection{border-radius:6px;height:26px;width:26px}@keyframes __va-pulse{0%,to{box-shadow:0 2px 6px rgba(0,0,0,.3)}50%{box-shadow:0 2px 12px rgba(var(--va-accent-rgb),.5)}}.__va-input{background:var(--va-bg);border:1px solid var(--va-border);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.15);max-width:360px;min-width:280px;padding:12px;position:fixed;z-index:2147483647}.__va-input-label{color:var(--va-text-secondary);display:block;font-size:12px;margin-bottom:8px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__va-input-chain{margin-bottom:8px}.__va-input-styles{margin-bottom:10px}.__va-input-styles-summary{align-items:center;color:var(--va-text-secondary);cursor:pointer;display:flex;font-size:12px;gap:6px;min-width:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.__va-input-styles-summary::-webkit-details-marker{display:none}.__va-input-styles-summary:before{content:"▸";flex-shrink:0;font-size:11px;transition:transform .16s ease}.__va-input-styles[open] .__va-input-styles-summary:before{transform:rotate(90deg)}.__va-input-styles-block{background:var(--va-bg-secondary);border:1px solid var(--va-border);border-radius:6px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,monospace;font-size:11px;line-height:1.55;margin-top:8px;padding:8px 10px}.__va-input-styles-element{color:var(--va-text-secondary);display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__va-input-style-line{color:var(--va-text);word-break:break-word}.__va-input-style-prop{color:#a855f7}.__va-input-style-value{color:var(--va-text)}.__va-comp-chain{align-items:center;display:inline-flex;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,monospace;font-size:11px;gap:6px}.__va-comp,.__va-comp-chain{white-space:nowrap}.__va-comp-bracket{opacity:.4}.__va-comp-chain--dark{color:#fff}.__va-comp-chain--light{color:var(--va-accent)}.__va-comp-ellipsis{font-size:11px;letter-spacing:1px;opacity:.5}.__va-comp-chain--collapsible{cursor:pointer;flex-wrap:wrap}.__va-comp-toggle{flex-shrink:0;font-size:10px;opacity:.6;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:10px}.__va-input input{background:var(--va-bg);border:1px solid var(--va-border);border-radius:6px;color:var(--va-text);font-size:13px;outline:none;padding:8px 10px;transition:border-color .15s ease;width:100%}.__va-input input:focus{border-color:var(--va-accent)}.__va-input-actions{align-items:center;display:flex;gap:8px;justify-content:space-between;margin-top:8px}.__va-input-actions-right{display:flex;gap:8px;margin-left:auto}.__va-input-delete-btn{align-items:center;background:transparent;border:none;border-radius:6px;color:var(--va-text-secondary);cursor:pointer;display:flex;height:32px;justify-content:center;outline:none;padding:0;transition:all .15s ease;width:32px}.__va-input-delete-btn svg{height:16px;width:16px}.__va-input-delete-btn:hover{background:var(--va-bg-secondary);color:#ef4444}.__va-btn{border:none;border-radius:6px;cursor:pointer;font-size:12px;font-weight:500;outline:none;padding:6px 14px;transition:all .15s ease}.__va-btn--secondary{background:var(--va-bg-secondary);color:var(--va-text-secondary)}.__va-btn--secondary:hover{background:var(--va-border)}.__va-btn--primary{background:var(--va-accent);color:#fff}.__va-btn--primary:hover{opacity:.9}.__va-btn:disabled{cursor:not-allowed;opacity:.4}.__va-settings-popover{position:fixed;z-index:2147483647}.__va-settings{background:var(--va-bg);border:1px solid var(--va-border);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.15);max-width:min(340px,calc(100vw - 16px));min-width:260px;padding:16px;position:relative}.__va-settings-top{border-bottom:1px solid var(--va-border);display:flex;justify-content:flex-end;margin-bottom:12px;padding-bottom:10px}.__va-theme-toggle{align-items:center;background:var(--va-bg-secondary);border:1px solid var(--va-border);border-radius:999px;color:var(--va-text-secondary);cursor:pointer;display:inline-flex;height:28px;justify-content:center;transition:all .15s ease;width:28px}.__va-theme-toggle:hover{border-color:var(--va-text-secondary);color:var(--va-text)}.__va-theme-toggle svg{height:15px;width:15px}.__va-settings-row{align-items:center;display:flex;gap:12px;justify-content:space-between;margin-bottom:10px}.__va-settings-label{color:var(--va-text-secondary);font-size:12px;white-space:nowrap}.__va-settings-row--stack{display:block}.__va-settings-row--stack .__va-settings-label{display:block;margin-bottom:8px}.__va-settings-row:last-child{margin-bottom:0}.__va-settings-divider{background:var(--va-border);height:1px;margin:8px 0 12px}.__va-settings select{background:var(--va-bg);border:1px solid var(--va-border);border-radius:4px;color:var(--va-text);font-size:12px;outline:none;padding:4px 8px}.__va-color-swatches{align-items:center;display:flex;gap:6px}.__va-color-swatch{border:2px solid var(--va-border);border-radius:50%;cursor:pointer;flex-shrink:0;height:22px;outline:none;padding:0;transition:all .15s ease;width:22px}.__va-color-swatch:hover{transform:scale(1.15)}.__va-color-swatch--active{border-color:var(--va-text);transform:scale(1.15)}.__va-toggle{background:var(--va-border);border:none;border-radius:10px;cursor:pointer;flex-shrink:0;height:20px;outline:none;padding:0;position:relative;transition:background .15s ease;width:36px}.__va-toggle--active{background:var(--va-accent)}.__va-toggle:after{background:#fff;border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,.2);content:"";height:16px;left:2px;position:absolute;top:2px;transition:transform .15s ease;width:16px}.__va-toggle--active:after{transform:translateX(16px)}.__va-selection-rect{background:rgba(var(--va-accent-rgb),.06);border:2px dashed var(--va-accent);border-radius:2px;pointer-events:none;position:fixed;z-index:2147483645}.__va-copy-feedback{animation:__va-fadeIn .15s ease;background:var(--va-accent);border-radius:6px;bottom:72px;box-shadow:0 4px 12px rgba(0,0,0,.15);color:#fff;font-size:13px;font-weight:500;padding:8px 16px;position:fixed;right:20px;z-index:2147483647}@keyframes __va-fadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
1
+ [data-agentation-vue]{--va-bg:#fff;--va-bg-secondary:#f5f5f5;--va-text:#1a1a1a;--va-text-secondary:#666;--va-border:#e5e5e5}[data-agentation-vue]:not([data-agentation-vue] [data-agentation-vue]){--va-accent:#42b883;--va-accent-rgb:66,184,131}@media (prefers-color-scheme:dark){[data-agentation-vue]:not([data-va-theme=light]){--va-bg:#1a1a1a;--va-bg-secondary:#2a2a2a;--va-text:#f5f5f5;--va-text-secondary:#999;--va-border:#333}}[data-agentation-vue][data-va-theme=dark],[data-agentation-vue][data-va-theme=dark] [data-agentation-vue]{--va-bg:#1a1a1a;--va-bg-secondary:#2a2a2a;--va-text:#f5f5f5;--va-text-secondary:#999;--va-border:#333}[data-agentation-vue][data-va-theme=light],[data-agentation-vue][data-va-theme=light] [data-agentation-vue]{--va-bg:#fff;--va-bg-secondary:#f5f5f5;--va-text:#1a1a1a;--va-text-secondary:#666;--va-border:#e5e5e5}:where([data-agentation-vue],[data-agentation-vue] *){border:none;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;line-height:1.5;list-style:none;margin:0;padding:0;text-decoration:none}.__va-intercept{background:transparent;cursor:crosshair;inset:0;position:fixed;z-index:2147483646}.__va-intercept--input-open{pointer-events:none}.__va-toolbar{position:fixed;--va-toolbar-base-transform:translate(0);--va-toolbar-auto-hide-transform:translate(0);--va-toolbar-size:42px;--va-toolbar-edge-offset:20px;--va-toolbar-auto-hide-peek:8px;--va-toolbar-auto-hide-corner-peek:16px;--va-toolbar-auto-hide-shift:calc(var(--va-toolbar-edge-offset) + var(--va-toolbar-size) - var(--va-toolbar-auto-hide-peek));--va-toolbar-auto-hide-corner-shift:calc(var(--va-toolbar-edge-offset) + var(--va-toolbar-size) - var(--va-toolbar-auto-hide-corner-peek));display:block;max-width:42px;min-height:42px;z-index:2147483647;--va-toolbar-resize-delay:0ms;background:var(--va-bg);border:1px solid var(--va-border);border-radius:999px;box-shadow:0 4px 12px rgba(0,0,0,.15);padding:0;transform:var(--va-toolbar-base-transform) var(--va-toolbar-auto-hide-transform);transition:border-radius .12s cubic-bezier(.32,.72,0,1),padding .12s cubic-bezier(.32,.72,0,1),max-width .24s cubic-bezier(.22,1,.36,1) var(--va-toolbar-resize-delay),transform .15s ease,opacity .15s ease,box-shadow .15s ease;-webkit-user-select:none;-moz-user-select:none;user-select:none}.__va-toolbar--place-bottom-right{bottom:20px;right:20px}.__va-toolbar--place-bottom-center{bottom:20px;left:50%;--va-toolbar-base-transform:translateX(-50%)}.__va-toolbar--place-bottom-left{bottom:20px;left:20px}.__va-toolbar--place-top-right{right:20px;top:20px}.__va-toolbar--place-top-center{left:50%;top:20px;--va-toolbar-base-transform:translateX(-50%)}.__va-toolbar--place-top-left{left:20px;top:20px}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-top-left{--va-toolbar-auto-hide-transform:translate(calc(var(--va-toolbar-auto-hide-corner-shift)*-1),calc(var(--va-toolbar-auto-hide-corner-shift)*-1))}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-top-center{--va-toolbar-auto-hide-transform:translateY(calc(var(--va-toolbar-auto-hide-shift)*-1))}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-top-right{--va-toolbar-auto-hide-transform:translate(var(--va-toolbar-auto-hide-corner-shift),calc(var(--va-toolbar-auto-hide-corner-shift)*-1))}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-bottom-left{--va-toolbar-auto-hide-transform:translate(calc(var(--va-toolbar-auto-hide-corner-shift)*-1),var(--va-toolbar-auto-hide-corner-shift))}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-bottom-center{--va-toolbar-auto-hide-transform:translateY(var(--va-toolbar-auto-hide-shift))}.__va-toolbar--auto-hide.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide-revealed).__va-toolbar--place-bottom-right{--va-toolbar-auto-hide-transform:translate(var(--va-toolbar-auto-hide-corner-shift),var(--va-toolbar-auto-hide-corner-shift))}.__va-toolbar--collapsed{cursor:pointer;max-width:42px;min-height:42px}.__va-toolbar--expanded{--va-toolbar-resize-delay:110ms;border-radius:10px;max-width:520px;padding:4px}.__va-toolbar--collapsed:not(.__va-toolbar--auto-hide):hover{box-shadow:0 6px 16px rgba(0,0,0,.2)}.__va-toolbar--dragging{bottom:auto;left:0;right:auto;top:0;transform:none;transition:none}.__va-toolbar--dragging.__va-toolbar--collapsed:hover{transform:none}.__va-toolbar-stage{align-items:center;display:flex;gap:4px}.__va-toolbar-stage--toggle{inset:0;justify-content:center;opacity:1;pointer-events:auto;position:absolute;transform:scale(1);transition:opacity .11s ease,transform .18s cubic-bezier(.22,1,.36,1),visibility 0s linear 0s;visibility:visible}.__va-toolbar-stage--menu{--va-toolbar-menu-enter-x:8px;filter:blur(4px);opacity:0;overflow:hidden;pointer-events:none;transform:translateX(var(--va-toolbar-menu-enter-x));transition:opacity .14s ease 0s,transform .22s cubic-bezier(.22,1,.36,1) 0s,visibility 0s linear .14s,filter 80ms ease 0s;visibility:hidden}.__va-toolbar--expanded .__va-toolbar-stage--toggle{opacity:0;pointer-events:none;transform:scale(.94);transition:opacity 90ms ease,transform .12s ease,visibility 0s linear 90ms;visibility:hidden}.__va-toolbar--expanded .__va-toolbar-stage--menu{filter:blur(0);opacity:1;pointer-events:auto;transform:translateX(0);transition:opacity .15s ease .15s,transform .24s cubic-bezier(.22,1,.36,1) .12s,visibility 0s linear 0s,filter .15s ease .2s;visibility:visible}.__va-toolbar--place-bottom-right .__va-toolbar-stage--menu,.__va-toolbar--place-top-right .__va-toolbar-stage--menu{--va-toolbar-menu-enter-x:-8px}.__va-toolbar--place-bottom-center .__va-toolbar-stage--menu,.__va-toolbar--place-top-center .__va-toolbar-stage--menu{--va-toolbar-menu-enter-x:0px}.__va-snap-zones{inset:0;pointer-events:none;position:fixed;z-index:2147483646}.__va-snap-zone{background:rgba(var(--va-accent-rgb),.035);border:1.5px dashed rgba(var(--va-accent-rgb),.18);border-radius:999px;box-shadow:0 0 0 1px rgba(var(--va-accent-rgb),.04);height:42px;position:fixed;transform:translate(-50%,-50%);transition:all .12s ease;width:42px}.__va-snap-zone--active{background:rgba(var(--va-accent-rgb),.09);border-color:rgba(var(--va-accent-rgb),.4)}.__va-snap-zone--rect{border-radius:8px;transform:none}.__va-snap-zone--rect.__va-snap-zone--active{transform:none}.__va-icon-btn{align-items:center;background:transparent;border:none;border-radius:6px;color:var(--va-text-secondary);cursor:pointer;display:flex;flex-shrink:0;height:32px;justify-content:center;outline:none;padding:0;transition:background .15s ease,color .15s ease;width:32px}.__va-icon-btn:hover{background:var(--va-bg-secondary);color:var(--va-text)}.__va-icon-btn--active{background:rgba(var(--va-accent-rgb),.15);color:var(--va-accent)}.__va-icon-btn--active:hover{background:rgba(var(--va-accent-rgb),.25)}.__va-icon-btn:disabled{cursor:not-allowed;opacity:.3}.__va-icon-btn:disabled:hover{background:transparent}.__va-icon-btn svg{height:18px;width:18px}.__va-toolbar-toggle{align-items:center;background:transparent;border:none;color:var(--va-accent);cursor:pointer;display:flex;height:100%;justify-content:center;line-height:0;outline:none;padding:0;position:relative;width:100%}.__va-toolbar-toggle svg{flex-shrink:0;height:22px;width:22px}.__va-toolbar-sep{background:var(--va-border);flex-shrink:0;height:20px;width:1px}.__va-drag-handle{align-items:center;background:transparent;border:none;border-radius:6px;color:var(--va-text-secondary);cursor:grab;display:flex;flex-shrink:0;height:32px;justify-content:center;outline:none;padding:0;transition:all .15s ease;width:24px}.__va-drag-handle:hover{background:var(--va-bg-secondary);color:var(--va-text)}.__va-drag-handle:active{cursor:grabbing}.__va-drag-handle-dots{display:grid;gap:2.5px;grid-template-columns:repeat(2,3px);grid-template-rows:repeat(3,3px)}.__va-drag-handle-dots span{background:currentColor;border-radius:50%;height:3px;opacity:.6;width:3px}.__va-toolbar-badge{align-items:center;background:var(--va-accent);border-radius:9px;color:#fff;display:flex;font-size:11px;font-weight:600;height:18px;justify-content:center;min-width:18px;padding:0 4px;position:absolute;right:-6px;top:-6px}.__va-tooltip{align-items:center;background:#131518;border:1px solid hsla(0,0%,100%,.08);border-radius:10px;box-shadow:0 10px 24px rgba(0,0,0,.32),0 2px 6px rgba(0,0,0,.28);color:#dce1e7;display:inline-flex;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:11px;font-weight:500;gap:6px;left:0;line-height:1.15;max-width:min(360px,calc(100vw - 16px));opacity:0;padding:6px 9px;pointer-events:none;position:fixed;top:0;transform:translateY(4px) scale(.98);transform-origin:center bottom;transition:opacity .12s ease,transform .12s ease;white-space:nowrap;z-index:2147483647}.__va-tooltip[data-placement=bottom]{transform:translateY(-4px) scale(.98);transform-origin:center top}.__va-tooltip.__va-tooltip--visible{opacity:1}.__va-tooltip.__va-tooltip--visible[data-placement=bottom],.__va-tooltip.__va-tooltip--visible[data-placement=top]{transform:translateY(0) scale(1)}.__va-tooltip-label{overflow:hidden;text-overflow:ellipsis}.__va-tooltip-shortcut{align-items:center;background:hsla(0,0%,100%,.1);border:1px solid hsla(0,0%,100%,.18);border-radius:6px;color:#b5bec8;display:inline-flex;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:11px;font-weight:600;letter-spacing:.03em;line-height:1;min-height:18px;padding:2px 6px}.__va-tooltip-arrow{background:#131518;border:1px solid hsla(0,0%,100%,.08);border-left:none;border-top:none;height:10px;left:50%;position:absolute;transform:translateX(-50%) rotate(45deg);width:10px}.__va-tooltip[data-placement=top] .__va-tooltip-arrow{bottom:-5px}.__va-tooltip[data-placement=bottom] .__va-tooltip-arrow{top:-5px;transform:translateX(-50%) rotate(225deg)}.__va-highlight{background:rgba(var(--va-accent-rgb),.08);border:2px solid var(--va-accent);border-radius:4px;pointer-events:none;position:fixed;transition:all 80ms ease;z-index:2147483645}.__va-highlight-label{background:var(--va-accent);border-radius:4px;color:#fff;font-size:11px;font-weight:500;left:0;max-width:300px;overflow:hidden;padding:2px 8px;position:absolute;text-overflow:ellipsis;top:-28px;white-space:nowrap}.__va-highlight-label--chain{background:#1a1a1a;max-width:500px;overflow:visible;padding:4px 10px}.__va-marker{align-items:center;background:var(--va-accent);border-radius:50%;box-shadow:0 2px 6px rgba(0,0,0,.3);color:#fff;cursor:pointer;display:flex;font-size:12px;font-weight:700;height:24px;justify-content:center;position:absolute;transform:translate(-50%,-50%);transition:all .15s ease;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:24px;z-index:2147483647}.__va-marker:hover{box-shadow:0 3px 10px rgba(0,0,0,.4);transform:translate(-50%,-50%) scale(1.2)}.__va-marker--fixed{position:fixed}.__va-marker--stale{opacity:.5}.__va-marker-plus{height:14px;stroke-width:3;width:14px}.__va-marker-pencil{display:none;height:12px;width:12px}.__va-marker:not(.__va-marker--pending):hover .__va-marker-number{display:none}.__va-marker:not(.__va-marker--pending):hover .__va-marker-pencil{display:block}.__va-marker--pending{animation:__va-pulse 1.5s ease-in-out infinite}.__va-marker--selection{border-radius:6px;height:26px;width:26px}@keyframes __va-pulse{0%,to{box-shadow:0 2px 6px rgba(0,0,0,.3)}50%{box-shadow:0 2px 12px rgba(var(--va-accent-rgb),.5)}}.__va-input{background:var(--va-bg);border:1px solid var(--va-border);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.15);max-width:360px;min-width:280px;padding:12px;position:fixed;z-index:2147483647}.__va-input-label{color:var(--va-text-secondary);display:block;font-size:12px;margin-bottom:8px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__va-input-chain{margin-bottom:8px}.__va-input-styles{margin-bottom:10px}.__va-input-styles-summary{align-items:center;color:var(--va-text-secondary);cursor:pointer;display:flex;font-size:12px;gap:6px;min-width:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.__va-input-styles-summary::-webkit-details-marker{display:none}.__va-input-styles-summary:before{content:"▸";flex-shrink:0;font-size:11px;transition:transform .16s ease}.__va-input-styles[open] .__va-input-styles-summary:before{transform:rotate(90deg)}.__va-input-styles-block{background:var(--va-bg-secondary);border:1px solid var(--va-border);border-radius:6px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,monospace;font-size:11px;line-height:1.55;margin-top:8px;padding:8px 10px}.__va-input-styles-element{color:var(--va-text-secondary);display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.__va-input-style-line{color:var(--va-text);word-break:break-word}.__va-input-style-prop{color:#a855f7}.__va-input-style-value{color:var(--va-text)}.__va-comp-chain{align-items:center;display:inline-flex;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,monospace;font-size:11px;gap:6px}.__va-comp,.__va-comp-chain{white-space:nowrap}.__va-comp-bracket{opacity:.4}.__va-comp-chain--dark{color:#fff}.__va-comp-chain--light{color:var(--va-accent)}.__va-comp-ellipsis{font-size:11px;letter-spacing:1px;opacity:.5}.__va-comp-chain--collapsible{cursor:pointer;flex-wrap:wrap}.__va-comp-toggle{flex-shrink:0;font-size:10px;opacity:.6;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:10px}.__va-input input{background:var(--va-bg);border:1px solid var(--va-border);border-radius:6px;color:var(--va-text);font-size:13px;outline:none;padding:8px 10px;transition:border-color .15s ease;width:100%}.__va-input input:focus{border-color:var(--va-accent)}.__va-input-actions{align-items:center;display:flex;gap:8px;justify-content:space-between;margin-top:8px}.__va-input-actions-right{display:flex;gap:8px;margin-left:auto}.__va-input-delete-btn{align-items:center;background:transparent;border:none;border-radius:6px;color:var(--va-text-secondary);cursor:pointer;display:flex;height:32px;justify-content:center;outline:none;padding:0;transition:all .15s ease;width:32px}.__va-input-delete-btn svg{height:16px;width:16px}.__va-input-delete-btn:hover{background:var(--va-bg-secondary);color:#ef4444}.__va-btn{border:none;border-radius:6px;cursor:pointer;font-size:12px;font-weight:500;outline:none;padding:6px 14px;transition:all .15s ease}.__va-btn--secondary{background:var(--va-bg-secondary);color:var(--va-text-secondary)}.__va-btn--secondary:hover{background:var(--va-border)}.__va-btn--primary{background:var(--va-accent);color:#fff}.__va-btn--primary:hover{opacity:.9}.__va-btn:disabled{cursor:not-allowed;opacity:.4}.__va-settings-popover{position:fixed;z-index:2147483647}.__va-settings{background:var(--va-bg);border:1px solid var(--va-border);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.15);max-width:min(340px,calc(100vw - 16px));min-width:260px;padding:16px;position:relative}.__va-settings-top{border-bottom:1px solid var(--va-border);display:flex;justify-content:flex-end;margin-bottom:12px;padding-bottom:10px}.__va-theme-toggle{align-items:center;background:var(--va-bg-secondary);border:1px solid var(--va-border);border-radius:999px;color:var(--va-text-secondary);cursor:pointer;display:inline-flex;height:28px;justify-content:center;transition:all .15s ease;width:28px}.__va-theme-toggle:hover{border-color:var(--va-text-secondary);color:var(--va-text)}.__va-theme-toggle svg{height:15px;width:15px}.__va-settings-row{align-items:center;display:flex;gap:12px;justify-content:space-between;margin-bottom:10px}.__va-settings-label{color:var(--va-text-secondary);font-size:12px;white-space:nowrap}.__va-settings-row--stack{display:block}.__va-settings-row--stack .__va-settings-label{display:block;margin-bottom:8px}.__va-settings-row:last-child{margin-bottom:0}.__va-settings-divider{background:var(--va-border);height:1px;margin:8px 0 12px}.__va-settings select{background:var(--va-bg);border:1px solid var(--va-border);border-radius:4px;color:var(--va-text);font-size:12px;outline:none;padding:4px 8px}.__va-color-swatches{align-items:center;display:flex;gap:6px}.__va-color-swatch{border:2px solid var(--va-border);border-radius:50%;cursor:pointer;flex-shrink:0;height:22px;outline:none;padding:0;transition:all .15s ease;width:22px}.__va-color-swatch:hover{transform:scale(1.15)}.__va-color-swatch--active{border-color:var(--va-text);transform:scale(1.15)}.__va-toggle{background:var(--va-border);border:none;border-radius:10px;cursor:pointer;flex-shrink:0;height:20px;outline:none;padding:0;position:relative;transition:background .15s ease;width:36px}.__va-toggle--active{background:var(--va-accent)}.__va-toggle:after{background:#fff;border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,.2);content:"";height:16px;left:2px;position:absolute;top:2px;transition:transform .15s ease;width:16px}.__va-toggle--active:after{transform:translateX(16px)}.__va-selection-rect{background:rgba(var(--va-accent-rgb),.06);border:2px dashed var(--va-accent);border-radius:2px;pointer-events:none;position:fixed;z-index:2147483645}.__va-copy-feedback{animation:__va-fadeIn .15s ease;background:var(--va-accent);border-radius:6px;bottom:72px;box-shadow:0 4px 12px rgba(0,0,0,.15);color:#fff;font-size:13px;font-weight:500;padding:8px 16px;position:fixed;right:20px;z-index:2147483647}@keyframes __va-fadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
package/dist/types.d.ts CHANGED
@@ -49,6 +49,7 @@ export interface AgentationProps {
49
49
  demoAnnotations?: Annotation[];
50
50
  theme?: 'light' | 'dark' | 'auto';
51
51
  activationKey?: 'none' | 'Meta' | 'Alt' | 'Shift';
52
+ disablePortal?: boolean;
52
53
  }
53
54
  export interface AgentationEmits {
54
55
  'annotation-add': [annotation: Annotation];
@@ -68,3 +69,7 @@ export interface Settings {
68
69
  theme: 'light' | 'dark' | 'auto';
69
70
  activationKey: 'none' | 'Meta' | 'Alt' | 'Shift';
70
71
  }
72
+ export interface StorageAdapter {
73
+ getItem: (key: string) => string | null;
74
+ setItem: (key: string, value: string) => void;
75
+ }
@@ -0,0 +1,2 @@
1
+ export declare function isInsideAgentationTree(target: EventTarget | null, event?: Event): boolean;
2
+ export declare function getDeepActiveElement(root?: Document | ShadowRoot): Element | null;
@@ -0,0 +1,21 @@
1
+ import { VA_DATA_ATTR_SELECTOR } from "../constants.mjs";
2
+ function isElement(node) {
3
+ return typeof Element !== "undefined" && node instanceof Element;
4
+ }
5
+ function hasAgentationAncestor(node) {
6
+ return isElement(node) && !!node.closest(VA_DATA_ATTR_SELECTOR);
7
+ }
8
+ export function isInsideAgentationTree(target, event) {
9
+ if (hasAgentationAncestor(target))
10
+ return true;
11
+ if (!event || typeof event.composedPath !== "function")
12
+ return false;
13
+ return event.composedPath().some(hasAgentationAncestor);
14
+ }
15
+ export function getDeepActiveElement(root = document) {
16
+ let activeElement = root.activeElement;
17
+ while (activeElement && activeElement.shadowRoot?.activeElement) {
18
+ activeElement = activeElement.shadowRoot.activeElement;
19
+ }
20
+ return activeElement;
21
+ }
@@ -1,4 +1,7 @@
1
1
  export declare function detectVueComponents(el: Element, includeFile?: boolean): string | undefined;
2
+ export type VueDetector = (el: Element, includeFile?: boolean) => string | undefined;
3
+ export declare function setVueDetector(detector: VueDetector): void;
4
+ export declare function resetVueDetector(): void;
2
5
  export declare function isFixed(el: Element): boolean;
3
6
  export declare function getNearbyElements(el: Element, maxCount?: number): string;
4
7
  export declare function getNearbyText(el: Element, maxLen?: number): string | undefined;
@@ -1,4 +1,5 @@
1
1
  let vueDetectionAvailable = null;
2
+ let customVueDetector = null;
2
3
  const DEFAULT_STYLE_VALUES = /* @__PURE__ */ new Set([
3
4
  "none",
4
5
  "normal",
@@ -117,6 +118,8 @@ function walkComponentChain(inst, includeFile) {
117
118
  return chain.reverse();
118
119
  }
119
120
  export function detectVueComponents(el, includeFile = false) {
121
+ if (customVueDetector)
122
+ return customVueDetector(el, includeFile);
120
123
  if (vueDetectionAvailable === false)
121
124
  return void 0;
122
125
  const inst = getComponentFromElement(el);
@@ -131,6 +134,14 @@ export function detectVueComponents(el, includeFile = false) {
131
134
  }
132
135
  return void 0;
133
136
  }
137
+ export function setVueDetector(detector) {
138
+ customVueDetector = detector;
139
+ vueDetectionAvailable = null;
140
+ }
141
+ export function resetVueDetector() {
142
+ customVueDetector = null;
143
+ vueDetectionAvailable = null;
144
+ }
134
145
  export function isFixed(el) {
135
146
  let current = el;
136
147
  while (current && current !== document.body) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentation-vue",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Visual feedback tool for AI coding agents — Vue 2.7 & 3",
5
5
  "author": "Dorian Becker",
6
6
  "license": "PolyForm-Shield-1.0.0",