@visulima/dev-toolbar 1.0.0-alpha.14 → 1.0.0-alpha.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## @visulima/dev-toolbar [1.0.0-alpha.16](https://github.com/visulima/visulima/compare/@visulima/dev-toolbar@1.0.0-alpha.15...@visulima/dev-toolbar@1.0.0-alpha.16) (2026-05-06)
2
+
3
+ ### Miscellaneous Chores
4
+
5
+ * **dev-toolbar:** apply prettier and eslint quote-style auto-fix ([3bb9b50](https://github.com/visulima/visulima/commit/3bb9b50337d5bbc0e3a1bd372a69ceebad1fb188))
6
+ * **dev-toolbar:** housekeeping cleanup ([d7c5ed5](https://github.com/visulima/visulima/commit/d7c5ed5518069405476212d8a9814af50cf2ef15))
7
+
8
+ ## @visulima/dev-toolbar [1.0.0-alpha.15](https://github.com/visulima/visulima/compare/@visulima/dev-toolbar@1.0.0-alpha.14...@visulima/dev-toolbar@1.0.0-alpha.15) (2026-05-04)
9
+
10
+ ### Miscellaneous Chores
11
+
12
+ * **dev-toolbar:** allow zod v4 and align eslint-plugin-zod with catalog ([70733ad](https://github.com/visulima/visulima/commit/70733ad6155c3bc460d2bc0943f88af59b7b6725))
13
+
1
14
  ## @visulima/dev-toolbar [1.0.0-alpha.14](https://github.com/visulima/visulima/compare/@visulima/dev-toolbar@1.0.0-alpha.13...@visulima/dev-toolbar@1.0.0-alpha.14) (2026-04-30)
2
15
 
3
16
  ### Miscellaneous Chores
@@ -18,7 +18,7 @@ var Bn=Object.defineProperty;var ae=(e,t)=>Bn(e,"name",{value:t,configurable:!0}
18
18
 
19
19
  No annotations found.`;if(t==="compact"){const o=[`# Annotations (${e.length})`,""];for(const i of e){const r=i.elementLabel??i.elementTag,a=i.selectedText?` (re: "${i.selectedText.slice(0,30)}...")`:"";o.push(`- **${r}:** ${i.comment}${a}`)}return o.join(`
20
20
  `)}const n=["# Annotations","",`> ${e.length} annotation(s)`,""];for(const[o,i]of e.entries()){const r=i.elementLabel??i.elementTag;if(n.push(`## ${o+1}. [${i.intent.toUpperCase()}] ${i.severity} — ${r}`,"",`**Status:** ${i.status}`,`**URL:** ${i.url}`),i.elementPath&&n.push(`**Selector:** \`${i.elementPath}\``),i.source&&n.push(`**Source:** \`${i.source}\``),i.frameworkContext){const a=i.frameworkContext;n.push(`**Component:** ${a.componentName} (${a.framework})`),a.componentStack&&a.componentStack.length>1&&n.push(`**Stack:** ${a.componentStack.join(" > ")}`),a.sourceFile&&n.push(`**File:** \`${a.sourceFile}${a.sourceLine?`:${a.sourceLine}`:""}\``)}i.selectedText&&n.push(`**Selected:** "${i.selectedText}"`),(t==="detailed"||t==="forensic")&&(i.cssClasses&&n.push(`**Classes:** \`${i.cssClasses}\``),i.nearbyText&&n.push(`**Context:** ${i.nearbyText}`),i.fullPath&&n.push(`**DOM Path:** \`${i.fullPath}\``)),t==="forensic"&&(i.accessibility?.role&&n.push(`**Role:** ${i.accessibility.role}`),i.nearbyElements&&n.push(`**Nearby:** ${i.nearbyElements}`),i.computedStyles&&n.push(`**Styles:** \`${i.computedStyles}\``)),n.push("",i.comment,"","---","")}return n.join(`
21
- `)},"annotationsToMarkdown"),Vn=Object.defineProperty({__proto__:null,annotationsToMarkdown:Ct,captureAccessibility:dn,captureComputedStyles:wt,captureElementScreenshot:un,cleanCssClasses:rn,deepElementFromPoint:_e,detectFrameworkComponent:pn,generateSelector:nn,getElementBoundingBoxes:gn,getElementLabel:Tt,getElementsInRect:mn,getFullDomPath:an,getNearbyElements:sn,getNearbyText:ln,getParentElement:en,getSelectedText:cn,getViewportRect:st,isElementFixed:tn,pierceElementFromPoint:rt},Symbol.toStringTag,{value:"Module"});var Yn=Object.defineProperty,ue=ae((e,t)=>Yn(e,"name",{value:t,configurable:!0}),"r$1");const Xn=["id^='__vdt_'","class*='__vdt_'"],xt=Xn.flatMap(e=>[`:not([${e}])`,`:not([${e}] *)`]).join(""),$t="__vdt_freeze_styles",ht="__vdt_freeze_state",ce=1e3,Un=ue(()=>{if(globalThis.window===void 0)return{frozen:!1,frozenRAFQueue:[],frozenTimeoutQueue:[],installed:!0,origRAF:ue((()=>0),"origRAF"),origSetInterval:ue((()=>0),"origSetInterval"),origSetTimeout:ue((()=>0),"origSetTimeout"),pausedAnimations:[]};const e=globalThis;return e[ht]||(e[ht]={frozen:!1,frozenRAFQueue:[],frozenTimeoutQueue:[],installed:!1,origRAF:null,origSetInterval:null,origSetTimeout:null,pausedAnimations:[]}),e[ht]},"getState"),E=Un();globalThis.window!==void 0&&!E.installed&&(E.origSetTimeout=globalThis.setTimeout.bind(globalThis),E.origSetInterval=globalThis.setInterval.bind(globalThis),E.origRAF=globalThis.requestAnimationFrame.bind(globalThis),globalThis.setTimeout=(e,t,...n)=>typeof e=="string"?E.origSetTimeout(e,t):E.origSetTimeout((...o)=>{E.frozen?E.frozenTimeoutQueue.length<ce?E.frozenTimeoutQueue.push(()=>e(...o)):E.frozenTimeoutQueue.length===ce&&(E.frozenTimeoutQueue.push(()=>{}),console.warn(`[dev-toolbar] frozenTimeoutQueue exceeded ${ce} entries — further callbacks are being dropped.`)):e(...o)},t,...n),globalThis.setInterval=(e,t,...n)=>typeof e=="string"?E.origSetInterval(e,t):E.origSetInterval((...o)=>{E.frozen||e(...o)},t,...n),globalThis.requestAnimationFrame=e=>E.origRAF(t=>{E.frozen?E.frozenRAFQueue.length<ce?E.frozenRAFQueue.push(e):E.frozenRAFQueue.length===ce&&(E.frozenRAFQueue.push(()=>{}),console.warn(`[dev-toolbar] frozenRAFQueue exceeded ${ce} entries — further callbacks are being dropped.`)):e(t)}),E.installed=!0);const xn=E.origSetTimeout,Qn=ue(()=>E.frozen,"isFrozen"),Kn=ue(()=>{if(typeof document>"u"||E.frozen)return;E.frozen=!0,E.frozenTimeoutQueue=[],E.frozenRAFQueue=[];let e=document.getElementById($t);e||(e=document.createElement("style"),e.id=$t),e.textContent=`
21
+ `)},"annotationsToMarkdown"),Vn=Object.defineProperty({__proto__:null,annotationsToMarkdown:Ct,captureAccessibility:dn,captureComputedStyles:wt,captureElementScreenshot:un,cleanCssClasses:rn,deepElementFromPoint:_e,detectFrameworkComponent:pn,generateSelector:nn,getElementBoundingBoxes:gn,getElementLabel:Tt,getElementsInRect:mn,getFullDomPath:an,getNearbyElements:sn,getNearbyText:ln,getParentElement:en,getSelectedText:cn,getViewportRect:st,isElementFixed:tn,pierceElementFromPoint:rt},Symbol.toStringTag,{value:"Module"});var Yn=Object.defineProperty,ue=ae((e,t)=>Yn(e,"name",{value:t,configurable:!0}),"r$1");const Xn=["id^='__vdt_'","class*='__vdt_'"],xt=Xn.flatMap(e=>[`:not([${e}])`,`:not([${e}] *)`]).join(""),$t="__vdt_freeze_styles",ht="__vdt_freeze_state",ce=1e3,Un=ue(()=>{if(globalThis.window===void 0)return{frozen:!1,frozenRAFQueue:[],frozenTimeoutQueue:[],installed:!0,origRAF:ue(()=>0,"origRAF"),origSetInterval:ue((()=>0),"origSetInterval"),origSetTimeout:ue((()=>0),"origSetTimeout"),pausedAnimations:[]};const e=globalThis;return e[ht]||(e[ht]={frozen:!1,frozenRAFQueue:[],frozenTimeoutQueue:[],installed:!1,origRAF:null,origSetInterval:null,origSetTimeout:null,pausedAnimations:[]}),e[ht]},"getState"),E=Un();globalThis.window!==void 0&&!E.installed&&(E.origSetTimeout=globalThis.setTimeout.bind(globalThis),E.origSetInterval=globalThis.setInterval.bind(globalThis),E.origRAF=globalThis.requestAnimationFrame.bind(globalThis),globalThis.setTimeout=(e,t,...n)=>typeof e=="string"?E.origSetTimeout(e,t):E.origSetTimeout((...o)=>{E.frozen?E.frozenTimeoutQueue.length<ce?E.frozenTimeoutQueue.push(()=>e(...o)):E.frozenTimeoutQueue.length===ce&&(E.frozenTimeoutQueue.push(()=>{}),console.warn(`[dev-toolbar] frozenTimeoutQueue exceeded ${ce} entries — further callbacks are being dropped.`)):e(...o)},t,...n),globalThis.setInterval=(e,t,...n)=>typeof e=="string"?E.origSetInterval(e,t):E.origSetInterval((...o)=>{E.frozen||e(...o)},t,...n),globalThis.requestAnimationFrame=e=>E.origRAF(t=>{E.frozen?E.frozenRAFQueue.length<ce?E.frozenRAFQueue.push(e):E.frozenRAFQueue.length===ce&&(E.frozenRAFQueue.push(()=>{}),console.warn(`[dev-toolbar] frozenRAFQueue exceeded ${ce} entries — further callbacks are being dropped.`)):e(t)}),E.installed=!0);const xn=E.origSetTimeout,Qn=ue(()=>E.frozen,"isFrozen"),Kn=ue(()=>{if(typeof document>"u"||E.frozen)return;E.frozen=!0,E.frozenTimeoutQueue=[],E.frozenRAFQueue=[];let e=document.getElementById($t);e||(e=document.createElement("style"),e.id=$t),e.textContent=`
22
22
  *${xt},
23
23
  *${xt}::before,
24
24
  *${xt}::after {
package/dist/index.d.ts CHANGED
@@ -1,54 +1,11 @@
1
1
  import { D as DevToolbarApp, T as ToolbarSettings } from "./packem_shared/app.d-SmKEDxsI.js";
2
2
  export { A as AppView, b as DEFAULT_TOOLBAR_SETTINGS, a as DevToolbarAppState, F as FrameState, N as NotificationLevel, P as PositionAnchor, S as ServerFunctions, c as ServerHelpers, d as ToolbarAppEventTarget, e as ToolbarPlacement } from "./packem_shared/app.d-SmKEDxsI.js";
3
- import { T as TimelineEvent, D as DevToolbarHook, C as ClientFunctions, a as ClientRPCContext, S as ServerFunctions, b as ServerRPCContext, c as TimelineGroup } from "./packem_shared/global-api.d-BLfn-OUA.js";
4
- export { A as AccessibilityInfo, d as Annotation, e as AnnotationIntent, f as AnnotationSeverity, g as AnnotationStatus, B as BoundingBox, h as CreateAnnotationData, i as DEFAULT_TIMELINE_GROUPS, F as FrameworkContext, H as HookEvents, j as ThreadMessage, k as TimelineEventLevel, U as UpdateAnnotationData, V as VisulimaDevTools } from "./packem_shared/global-api.d-BLfn-OUA.js";
3
+ import { T as TimelineEvent, D as DevToolbarHook, C as ClientFunctions, a as ClientRPCContext, S as ServerFunctions, b as ServerRPCContext, c as TimelineGroup } from "./packem_shared/global-api.d-DG2WYakl.js";
4
+ export { A as AccessibilityInfo, d as Annotation, e as AnnotationIntent, f as AnnotationSeverity, g as AnnotationStatus, B as BoundingBox, h as CreateAnnotationData, i as DEFAULT_TIMELINE_GROUPS, F as FrameworkContext, H as HookEvents, j as ThreadMessage, k as TimelineEventLevel, U as UpdateAnnotationData, V as VisulimaDevTools } from "./packem_shared/global-api.d-DG2WYakl.js";
5
5
  import { ViteDevServer } from 'vite';
6
6
  export { DevToolbar } from "./toolbar/index.js";
7
7
  import 'preact';
8
8
  /**
9
- * Message channel interface for bidirectional communication
10
- */
11
- interface MessageChannel<TEvents extends Record<string, (...args: any[]) => void>> {
12
- /**
13
- * Unsubscribe from an event
14
- * @param event Event name
15
- * @param handler Optional specific handler to remove
16
- */
17
- off: <K extends keyof TEvents>(event: K, handler?: TEvents[K]) => void;
18
- /**
19
- * Subscribe to an event
20
- * @param event Event name
21
- * @param handler Event handler
22
- * @returns Unsubscribe function
23
- */
24
- on: <K extends keyof TEvents>(event: K, handler: TEvents[K]) => () => void;
25
- /**
26
- * Subscribe to an event once
27
- * @param event Event name
28
- * @param handler Event handler
29
- */
30
- once: <K extends keyof TEvents>(event: K, handler: TEvents[K]) => void;
31
- /**
32
- * Send a message/event
33
- * @param event Event name
34
- * @param data Event data
35
- */
36
- send: <K extends keyof TEvents>(event: K, ...args: Parameters<TEvents[K]>) => void;
37
- }
38
- /**
39
- * Channel factory function
40
- */
41
- type ChannelFactory<TEvents extends Record<string, (...args: any[]) => void>> = () => MessageChannel<TEvents>;
42
- /**
43
- * Factory result providing a method to instantiate named message channels.
44
- */
45
- interface MessageChannelContext<TEvents extends Record<string, (...args: any[]) => void>> {
46
- /**
47
- * Creates and returns a new channel instance.
48
- */
49
- createChannel: () => MessageChannel<TEvents>;
50
- }
51
- /**
52
9
  * Creates a dev toolbar hook instance.
53
10
  * @param onRegisterApp Callback when app is registered.
54
11
  * @param onTimelineEvent Callback when timeline event is added.
@@ -125,6 +82,49 @@ declare class TimelineStore {
125
82
  */
126
83
  declare const getTimelineStore: () => TimelineStore;
127
84
  /**
85
+ * Message channel interface for bidirectional communication
86
+ */
87
+ interface MessageChannel<TEvents extends Record<string, (...args: any[]) => void>> {
88
+ /**
89
+ * Unsubscribe from an event
90
+ * @param event Event name
91
+ * @param handler Optional specific handler to remove
92
+ */
93
+ off: <K extends keyof TEvents>(event: K, handler?: TEvents[K]) => void;
94
+ /**
95
+ * Subscribe to an event
96
+ * @param event Event name
97
+ * @param handler Event handler
98
+ * @returns Unsubscribe function
99
+ */
100
+ on: <K extends keyof TEvents>(event: K, handler: TEvents[K]) => () => void;
101
+ /**
102
+ * Subscribe to an event once
103
+ * @param event Event name
104
+ * @param handler Event handler
105
+ */
106
+ once: <K extends keyof TEvents>(event: K, handler: TEvents[K]) => void;
107
+ /**
108
+ * Send a message/event
109
+ * @param event Event name
110
+ * @param data Event data
111
+ */
112
+ send: <K extends keyof TEvents>(event: K, ...args: Parameters<TEvents[K]>) => void;
113
+ }
114
+ /**
115
+ * Channel factory function
116
+ */
117
+ type ChannelFactory<TEvents extends Record<string, (...args: any[]) => void>> = () => MessageChannel<TEvents>;
118
+ /**
119
+ * Factory result providing a method to instantiate named message channels.
120
+ */
121
+ interface MessageChannelContext<TEvents extends Record<string, (...args: any[]) => void>> {
122
+ /**
123
+ * Creates and returns a new channel instance.
124
+ */
125
+ createChannel: () => MessageChannel<TEvents>;
126
+ }
127
+ /**
128
128
  * Loads settings from localStorage, merging with defaults.
129
129
  * @returns Toolbar settings.
130
130
  */
@@ -1,5 +1,5 @@
1
1
  import { D as DevToolbarApp, a as DevToolbarAppState } from "../packem_shared/app.d-SmKEDxsI.js";
2
- import "../packem_shared/global-api.d-BLfn-OUA.js";
2
+ import "../packem_shared/global-api.d-DG2WYakl.js";
3
3
  import 'vite';
4
4
  import 'preact';
5
5
  /**
@@ -1,6 +1,6 @@
1
1
  import { Plugin } from 'vite';
2
2
  import { D as DevToolbarApp, S as ServerFunctions } from "./packem_shared/app.d-SmKEDxsI.js";
3
- import "./packem_shared/global-api.d-BLfn-OUA.js";
3
+ import "./packem_shared/global-api.d-DG2WYakl.js";
4
4
  import '@babel/generator';
5
5
  import 'preact';
6
6
  interface InjectSourceIgnore {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visulima/dev-toolbar",
3
- "version": "1.0.0-alpha.14",
3
+ "version": "1.0.0-alpha.16",
4
4
  "description": "Devtools is a set of tools for building advanced devtools for your application",
5
5
  "keywords": [
6
6
  "dev-toolbar",
@@ -10,6 +10,11 @@
10
10
  "bugs": {
11
11
  "url": "https://github.com/visulima/visulima/issues"
12
12
  },
13
+ "license": "MIT",
14
+ "author": {
15
+ "name": "Daniel Bannert",
16
+ "email": "d.bannert@anolilab.de"
17
+ },
13
18
  "repository": {
14
19
  "type": "git",
15
20
  "url": "git+https://github.com/visulima/visulima.git",
@@ -25,13 +30,17 @@
25
30
  "url": "https://anolilab.com/support"
26
31
  }
27
32
  ],
28
- "license": "MIT",
29
- "author": {
30
- "name": "Daniel Bannert",
31
- "email": "d.bannert@anolilab.de"
33
+ "bin": {
34
+ "visulima-dev-toolbar-mcp": "./bin/mcp.js"
32
35
  },
33
- "sideEffects": false,
36
+ "files": [
37
+ "bin",
38
+ "dist",
39
+ "README.md",
40
+ "CHANGELOG.md"
41
+ ],
34
42
  "type": "module",
43
+ "sideEffects": false,
35
44
  "exports": {
36
45
  ".": {
37
46
  "types": "./dist/index.d.ts",
@@ -103,18 +112,13 @@
103
112
  },
104
113
  "./package.json": "./package.json"
105
114
  },
106
- "bin": {
107
- "visulima-dev-toolbar-mcp": "./bin/mcp.js"
115
+ "publishConfig": {
116
+ "access": "public",
117
+ "provenance": true
108
118
  },
109
- "files": [
110
- "bin",
111
- "dist",
112
- "README.md",
113
- "CHANGELOG.md"
114
- ],
115
119
  "dependencies": {
116
120
  "@babel/generator": "^7.29.1",
117
- "@babel/parser": "7.29.2",
121
+ "@babel/parser": "7.29.3",
118
122
  "@babel/traverse": "^7.29.0",
119
123
  "@floating-ui/dom": "^1.7.6",
120
124
  "launch-editor": "2.13.2",
@@ -124,7 +128,7 @@
124
128
  "@modelcontextprotocol/sdk": "^1.0.0",
125
129
  "axe-core": "4.11.4",
126
130
  "vite": "^6 || ^7 || ^8",
127
- "zod": "^3.0.0"
131
+ "zod": "^3.25.0 || ^4.0.0"
128
132
  },
129
133
  "peerDependenciesMeta": {
130
134
  "@modelcontextprotocol/sdk": {
@@ -139,9 +143,5 @@
139
143
  },
140
144
  "engines": {
141
145
  "node": "^22.14.0 || >=24.10.0"
142
- },
143
- "publishConfig": {
144
- "access": "public",
145
- "provenance": true
146
146
  }
147
147
  }
@@ -1,162 +1,6 @@
1
1
  import { D as DevToolbarApp, T as ToolbarSettings } from "./app.d-SmKEDxsI.js";
2
2
  import { ViteDevServer } from 'vite';
3
3
  /**
4
- * Annotation intent — describes what the user wants to communicate.
5
- */
6
- type AnnotationIntent = "approve" | "change" | "fix" | "question";
7
- /**
8
- * Annotation severity — how urgent or important the annotation is.
9
- */
10
- type AnnotationSeverity = "blocking" | "important" | "suggestion";
11
- /**
12
- * Annotation status — lifecycle state.
13
- */
14
- type AnnotationStatus = "acknowledged" | "dismissed" | "pending" | "resolved";
15
- /**
16
- * A single message in a conversation thread attached to an annotation.
17
- */
18
- interface ThreadMessage {
19
- /** Message text */
20
- content: string;
21
- /** Unique message identifier */
22
- id?: string;
23
- /** Who wrote it — e.g. "human", "agent", or a specific agent name */
24
- role: string;
25
- /** ISO 8601 timestamp */
26
- timestamp: string;
27
- }
28
- /**
29
- * Bounding box of the annotated element relative to the viewport.
30
- */
31
- interface BoundingBox {
32
- height: number;
33
- width: number;
34
- x: number;
35
- y: number;
36
- }
37
- /**
38
- * Detected framework component information.
39
- */
40
- interface FrameworkContext {
41
- /** Component name */
42
- componentName?: string;
43
- /** Full component stack (e.g. ["App", "Layout", "Header", "Button"]) */
44
- componentStack?: string[];
45
- /** Additional framework-specific data (e.g. props) */
46
- data?: Record<string, unknown>;
47
- /** Framework identifier (react, vue, svelte, etc.) */
48
- framework: string;
49
- /** Source file path */
50
- sourceFile?: string;
51
- /** Source line number */
52
- sourceLine?: number;
53
- }
54
- /**
55
- * Captured accessibility attributes for an element.
56
- */
57
- interface AccessibilityInfo {
58
- /** aria-describedby content */
59
- ariaDescribedBy?: string;
60
- /** aria-label value */
61
- ariaLabel?: string;
62
- /** Whether the element is focusable */
63
- focusable: boolean;
64
- /** ARIA role (explicit or implicit) */
65
- role?: string;
66
- /** tabindex value */
67
- tabindex?: number;
68
- }
69
- /**
70
- * A visual annotation placed on a page element during development.
71
- * Stored in `.devtoolbar/annotations.json`.
72
- */
73
- interface Annotation {
74
- /** Captured accessibility attributes */
75
- accessibility?: AccessibilityInfo;
76
- /** Element bounding box at annotation time */
77
- boundingBox?: BoundingBox;
78
- /** User feedback / description */
79
- comment: string;
80
- /** Key computed CSS properties for forensic context */
81
- computedStyles?: string;
82
- /** ISO 8601 creation timestamp */
83
- createdAt: string;
84
- /** CSS classes on the annotated element (module hashes cleaned) */
85
- cssClasses?: string;
86
- /** Bounding boxes for multi-select annotations */
87
- elementBoundingBoxes?: BoundingBox[];
88
- /** Human-readable element label (e.g. 'button "Submit"') */
89
- elementLabel?: string;
90
- /** CSS selector path to the element */
91
- elementPath?: string;
92
- /** HTML tag name of the annotated element */
93
- elementTag: string;
94
- /** Detected framework component context */
95
- frameworkContext?: FrameworkContext;
96
- /** Full DOM ancestry path (e.g. "body > main > article > p") */
97
- fullPath?: string;
98
- /** Unique identifier (crypto.randomUUID) */
99
- id: string;
100
- /** What the user wants — fix, change, question, or approve */
101
- intent: AnnotationIntent;
102
- /** Whether the element has fixed/sticky positioning */
103
- isFixed?: boolean;
104
- /** Whether this is a multi-select (drag) annotation */
105
- isMultiSelect?: boolean;
106
- /** Sibling elements for spatial context */
107
- nearbyElements?: string;
108
- /** Text near the annotated element for additional context */
109
- nearbyText?: string;
110
- /** ISO 8601 resolution timestamp */
111
- resolvedAt?: string;
112
- /** Who resolved it — "human" or "agent" (or a specific agent name) */
113
- resolvedBy?: string;
114
- /** Path to screenshot file relative to .devtoolbar/ (e.g. "screenshots/&lt;id>.png") */
115
- screenshot?: string;
116
- /** Text the user had selected when annotating */
117
- selectedText?: string;
118
- /** Severity level */
119
- severity: AnnotationSeverity;
120
- /** Source file location from data-vdt-source (file:line:col) */
121
- source?: string;
122
- /** Lifecycle status */
123
- status: AnnotationStatus;
124
- /** Conversation thread (human ↔ AI agent) */
125
- thread?: ThreadMessage[];
126
- /** ISO 8601 last-updated timestamp */
127
- updatedAt: string;
128
- /** Page URL where the annotation was created */
129
- url: string;
130
- /** Click X as percentage of viewport width (0-100) — survives resize */
131
- x: number;
132
- /**
133
- * Click Y as absolute page position (pixels from document top) — survives scroll.
134
- * For fixed/sticky elements, Y is viewport-relative instead.
135
- */
136
- y: number;
137
- }
138
- /**
139
- * Data required to create a new annotation (server-generated fields omitted).
140
- */
141
- type CreateAnnotationData = Omit<Annotation, "createdAt" | "id" | "resolvedAt" | "resolvedBy" | "status" | "thread" | "updatedAt">;
142
- /**
143
- * Fields that can be updated on an existing annotation.
144
- */
145
- interface UpdateAnnotationData {
146
- /** Updated comment text */
147
- comment?: string;
148
- /** Updated intent */
149
- intent?: AnnotationIntent;
150
- /** Who resolved the annotation */
151
- resolvedBy?: string;
152
- /** Updated severity */
153
- severity?: AnnotationSeverity;
154
- /** New status */
155
- status?: AnnotationStatus;
156
- /** Append a thread message */
157
- threadMessage?: ThreadMessage;
158
- }
159
- /**
160
4
  * Severity levels for timeline events.
161
5
  */
162
6
  type TimelineEventLevel = "info" | "warning" | "error";
@@ -328,6 +172,162 @@ interface TailwindConfigResult {
328
172
  version: "v3" | "v4" | "unknown";
329
173
  }
330
174
  /**
175
+ * Annotation intent — describes what the user wants to communicate.
176
+ */
177
+ type AnnotationIntent = "approve" | "change" | "fix" | "question";
178
+ /**
179
+ * Annotation severity — how urgent or important the annotation is.
180
+ */
181
+ type AnnotationSeverity = "blocking" | "important" | "suggestion";
182
+ /**
183
+ * Annotation status — lifecycle state.
184
+ */
185
+ type AnnotationStatus = "acknowledged" | "dismissed" | "pending" | "resolved";
186
+ /**
187
+ * A single message in a conversation thread attached to an annotation.
188
+ */
189
+ interface ThreadMessage {
190
+ /** Message text */
191
+ content: string;
192
+ /** Unique message identifier */
193
+ id?: string;
194
+ /** Who wrote it — e.g. "human", "agent", or a specific agent name */
195
+ role: string;
196
+ /** ISO 8601 timestamp */
197
+ timestamp: string;
198
+ }
199
+ /**
200
+ * Bounding box of the annotated element relative to the viewport.
201
+ */
202
+ interface BoundingBox {
203
+ height: number;
204
+ width: number;
205
+ x: number;
206
+ y: number;
207
+ }
208
+ /**
209
+ * Detected framework component information.
210
+ */
211
+ interface FrameworkContext {
212
+ /** Component name */
213
+ componentName?: string;
214
+ /** Full component stack (e.g. ["App", "Layout", "Header", "Button"]) */
215
+ componentStack?: string[];
216
+ /** Additional framework-specific data (e.g. props) */
217
+ data?: Record<string, unknown>;
218
+ /** Framework identifier (react, vue, svelte, etc.) */
219
+ framework: string;
220
+ /** Source file path */
221
+ sourceFile?: string;
222
+ /** Source line number */
223
+ sourceLine?: number;
224
+ }
225
+ /**
226
+ * Captured accessibility attributes for an element.
227
+ */
228
+ interface AccessibilityInfo {
229
+ /** aria-describedby content */
230
+ ariaDescribedBy?: string;
231
+ /** aria-label value */
232
+ ariaLabel?: string;
233
+ /** Whether the element is focusable */
234
+ focusable: boolean;
235
+ /** ARIA role (explicit or implicit) */
236
+ role?: string;
237
+ /** tabindex value */
238
+ tabindex?: number;
239
+ }
240
+ /**
241
+ * A visual annotation placed on a page element during development.
242
+ * Stored in `.devtoolbar/annotations.json`.
243
+ */
244
+ interface Annotation {
245
+ /** Captured accessibility attributes */
246
+ accessibility?: AccessibilityInfo;
247
+ /** Element bounding box at annotation time */
248
+ boundingBox?: BoundingBox;
249
+ /** User feedback / description */
250
+ comment: string;
251
+ /** Key computed CSS properties for forensic context */
252
+ computedStyles?: string;
253
+ /** ISO 8601 creation timestamp */
254
+ createdAt: string;
255
+ /** CSS classes on the annotated element (module hashes cleaned) */
256
+ cssClasses?: string;
257
+ /** Bounding boxes for multi-select annotations */
258
+ elementBoundingBoxes?: BoundingBox[];
259
+ /** Human-readable element label (e.g. 'button "Submit"') */
260
+ elementLabel?: string;
261
+ /** CSS selector path to the element */
262
+ elementPath?: string;
263
+ /** HTML tag name of the annotated element */
264
+ elementTag: string;
265
+ /** Detected framework component context */
266
+ frameworkContext?: FrameworkContext;
267
+ /** Full DOM ancestry path (e.g. "body > main > article > p") */
268
+ fullPath?: string;
269
+ /** Unique identifier (crypto.randomUUID) */
270
+ id: string;
271
+ /** What the user wants — fix, change, question, or approve */
272
+ intent: AnnotationIntent;
273
+ /** Whether the element has fixed/sticky positioning */
274
+ isFixed?: boolean;
275
+ /** Whether this is a multi-select (drag) annotation */
276
+ isMultiSelect?: boolean;
277
+ /** Sibling elements for spatial context */
278
+ nearbyElements?: string;
279
+ /** Text near the annotated element for additional context */
280
+ nearbyText?: string;
281
+ /** ISO 8601 resolution timestamp */
282
+ resolvedAt?: string;
283
+ /** Who resolved it — "human" or "agent" (or a specific agent name) */
284
+ resolvedBy?: string;
285
+ /** Path to screenshot file relative to .devtoolbar/ (e.g. "screenshots/&lt;id>.png") */
286
+ screenshot?: string;
287
+ /** Text the user had selected when annotating */
288
+ selectedText?: string;
289
+ /** Severity level */
290
+ severity: AnnotationSeverity;
291
+ /** Source file location from data-vdt-source (file:line:col) */
292
+ source?: string;
293
+ /** Lifecycle status */
294
+ status: AnnotationStatus;
295
+ /** Conversation thread (human ↔ AI agent) */
296
+ thread?: ThreadMessage[];
297
+ /** ISO 8601 last-updated timestamp */
298
+ updatedAt: string;
299
+ /** Page URL where the annotation was created */
300
+ url: string;
301
+ /** Click X as percentage of viewport width (0-100) — survives resize */
302
+ x: number;
303
+ /**
304
+ * Click Y as absolute page position (pixels from document top) — survives scroll.
305
+ * For fixed/sticky elements, Y is viewport-relative instead.
306
+ */
307
+ y: number;
308
+ }
309
+ /**
310
+ * Data required to create a new annotation (server-generated fields omitted).
311
+ */
312
+ type CreateAnnotationData = Omit<Annotation, "createdAt" | "id" | "resolvedAt" | "resolvedBy" | "status" | "thread" | "updatedAt">;
313
+ /**
314
+ * Fields that can be updated on an existing annotation.
315
+ */
316
+ interface UpdateAnnotationData {
317
+ /** Updated comment text */
318
+ comment?: string;
319
+ /** Updated intent */
320
+ intent?: AnnotationIntent;
321
+ /** Who resolved the annotation */
322
+ resolvedBy?: string;
323
+ /** Updated severity */
324
+ severity?: AnnotationSeverity;
325
+ /** New status */
326
+ status?: AnnotationStatus;
327
+ /** Append a thread message */
328
+ threadMessage?: ThreadMessage;
329
+ }
330
+ /**
331
331
  * Server-side RPC functions
332
332
  * These can be called from the client
333
333
  */