donobu 2.17.0 → 2.17.1

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.
@@ -14,35 +14,6 @@
14
14
  "additionalProperties": false,
15
15
  "required": ["targetId", "bindingName"]
16
16
  },
17
- "BaseToolGptParameters": {
18
- "description": "This interface is intended to be the base for all tool parameters that are generated by a GPT.",
19
- "type": "object",
20
- "properties": {
21
- "rationale": {
22
- "description": "The reason why this particular action is being taken. It MUST relate to the overall objective.",
23
- "type": "string"
24
- }
25
- },
26
- "additionalProperties": false,
27
- "required": ["rationale"]
28
- },
29
- "RunAccessibilityTestToolCoreParameters": {
30
- "type": "object",
31
- "additionalProperties": false,
32
- "required": [],
33
- "properties": {}
34
- },
35
- "RunAccessibilityTestToolGptParameters": {
36
- "type": "object",
37
- "properties": {
38
- "rationale": {
39
- "description": "The reason why this particular action is being taken. It MUST relate to the overall objective.",
40
- "type": "string"
41
- }
42
- },
43
- "additionalProperties": false,
44
- "required": ["rationale"]
45
- },
46
17
  "ToolParameters": {
47
18
  "anyOf": [
48
19
  {
@@ -117,7 +88,7 @@
117
88
  "type": "object",
118
89
  "additionalProperties": false
119
90
  },
120
- "__@validatorSymbol@9584": {
91
+ "__@validatorSymbol@6486": {
121
92
  "description": "Used to mark validator functions so we can support both Zod and custom schemas.",
122
93
  "type": "boolean",
123
94
  "const": true
@@ -129,21 +100,50 @@
129
100
  "$ref": "#/definitions/JSONSchema7",
130
101
  "description": "The JSON Schema for the schema. It is passed to the providers."
131
102
  },
132
- "__@schemaSymbol@9589": {
103
+ "__@schemaSymbol@6491": {
133
104
  "description": "Used to mark schemas so we can support both Zod and custom schemas.",
134
105
  "type": "boolean",
135
106
  "const": true
136
107
  }
137
108
  },
138
109
  "required": [
139
- "__@schemaSymbol@9589",
140
- "__@validatorSymbol@9584",
110
+ "__@schemaSymbol@6491",
111
+ "__@validatorSymbol@6486",
141
112
  "_type",
142
113
  "jsonSchema"
143
114
  ]
144
115
  }
145
116
  ]
146
117
  },
118
+ "BaseToolGptParameters": {
119
+ "description": "This interface is intended to be the base for all tool parameters that are generated by a GPT.",
120
+ "type": "object",
121
+ "properties": {
122
+ "rationale": {
123
+ "description": "The reason why this particular action is being taken. It MUST relate to the overall objective.",
124
+ "type": "string"
125
+ }
126
+ },
127
+ "additionalProperties": false,
128
+ "required": ["rationale"]
129
+ },
130
+ "RunAccessibilityTestToolCoreParameters": {
131
+ "type": "object",
132
+ "additionalProperties": false,
133
+ "required": [],
134
+ "properties": {}
135
+ },
136
+ "RunAccessibilityTestToolGptParameters": {
137
+ "type": "object",
138
+ "properties": {
139
+ "rationale": {
140
+ "description": "The reason why this particular action is being taken. It MUST relate to the overall objective.",
141
+ "type": "string"
142
+ }
143
+ },
144
+ "additionalProperties": false,
145
+ "required": ["rationale"]
146
+ },
147
147
  "ChooseSelectOptionToolCoreParameters": {
148
148
  "type": "object",
149
149
  "properties": {
@@ -1 +1 @@
1
- 1151
1
+ 1153
@@ -14,35 +14,6 @@
14
14
  "additionalProperties": false,
15
15
  "required": ["targetId", "bindingName"]
16
16
  },
17
- "BaseToolGptParameters": {
18
- "description": "This interface is intended to be the base for all tool parameters that are generated by a GPT.",
19
- "type": "object",
20
- "properties": {
21
- "rationale": {
22
- "description": "The reason why this particular action is being taken. It MUST relate to the overall objective.",
23
- "type": "string"
24
- }
25
- },
26
- "additionalProperties": false,
27
- "required": ["rationale"]
28
- },
29
- "RunAccessibilityTestToolCoreParameters": {
30
- "type": "object",
31
- "additionalProperties": false,
32
- "required": [],
33
- "properties": {}
34
- },
35
- "RunAccessibilityTestToolGptParameters": {
36
- "type": "object",
37
- "properties": {
38
- "rationale": {
39
- "description": "The reason why this particular action is being taken. It MUST relate to the overall objective.",
40
- "type": "string"
41
- }
42
- },
43
- "additionalProperties": false,
44
- "required": ["rationale"]
45
- },
46
17
  "ToolParameters": {
47
18
  "anyOf": [
48
19
  {
@@ -117,7 +88,7 @@
117
88
  "type": "object",
118
89
  "additionalProperties": false
119
90
  },
120
- "__@validatorSymbol@9584": {
91
+ "__@validatorSymbol@6486": {
121
92
  "description": "Used to mark validator functions so we can support both Zod and custom schemas.",
122
93
  "type": "boolean",
123
94
  "const": true
@@ -129,21 +100,50 @@
129
100
  "$ref": "#/definitions/JSONSchema7",
130
101
  "description": "The JSON Schema for the schema. It is passed to the providers."
131
102
  },
132
- "__@schemaSymbol@9589": {
103
+ "__@schemaSymbol@6491": {
133
104
  "description": "Used to mark schemas so we can support both Zod and custom schemas.",
134
105
  "type": "boolean",
135
106
  "const": true
136
107
  }
137
108
  },
138
109
  "required": [
139
- "__@schemaSymbol@9589",
140
- "__@validatorSymbol@9584",
110
+ "__@schemaSymbol@6491",
111
+ "__@validatorSymbol@6486",
141
112
  "_type",
142
113
  "jsonSchema"
143
114
  ]
144
115
  }
145
116
  ]
146
117
  },
118
+ "BaseToolGptParameters": {
119
+ "description": "This interface is intended to be the base for all tool parameters that are generated by a GPT.",
120
+ "type": "object",
121
+ "properties": {
122
+ "rationale": {
123
+ "description": "The reason why this particular action is being taken. It MUST relate to the overall objective.",
124
+ "type": "string"
125
+ }
126
+ },
127
+ "additionalProperties": false,
128
+ "required": ["rationale"]
129
+ },
130
+ "RunAccessibilityTestToolCoreParameters": {
131
+ "type": "object",
132
+ "additionalProperties": false,
133
+ "required": [],
134
+ "properties": {}
135
+ },
136
+ "RunAccessibilityTestToolGptParameters": {
137
+ "type": "object",
138
+ "properties": {
139
+ "rationale": {
140
+ "description": "The reason why this particular action is being taken. It MUST relate to the overall objective.",
141
+ "type": "string"
142
+ }
143
+ },
144
+ "additionalProperties": false,
145
+ "required": ["rationale"]
146
+ },
147
147
  "ChooseSelectOptionToolCoreParameters": {
148
148
  "type": "object",
149
149
  "properties": {
@@ -1 +1 @@
1
- 1151
1
+ 1153
@@ -1,37 +1,15 @@
1
1
  import { Page, Locator } from 'playwright';
2
- /**
3
- * Class for visualizing interactions in a webpage with a virtual mouse and messages.
4
- */
5
2
  export declare class InteractionVisualizer {
6
3
  readonly defaultMessageDurationMillis: number;
7
- private static readonly VIRTUAL_MOUSE_SVG;
4
+ private static readonly SVG_MOUSE;
8
5
  private static readonly CSS;
9
- private static readonly MESSAGE_CONTAINER_ID;
10
- private static readonly VIRTUAL_MOUSE_ID;
11
- private static readonly registeredContexts;
12
- private currentMousePosition;
13
- /**
14
- * Creates an instance of InteractionVisualizer.
15
- * @param defaultMessageDurationMillis - Default duration for displaying messages in milliseconds.
16
- */
6
+ private static readonly CONTAINER_ID;
7
+ private cursorPos;
17
8
  constructor(defaultMessageDurationMillis: number);
18
- /**
19
- * Moves the virtual mouse to the element with a smooth animation and
20
- * optionally displays a message at element.
21
- */
22
- pointAt(page: Page, element: Locator, message?: string, durationMillis?: number): Promise<void>;
23
- /**
24
- * Moves the virtual mouse to the target position with a smooth animation.
25
- */
26
- private moveVirtualMouse;
27
- /**
28
- * Creates a message adjacent to the element, inside a shadow root to avoid CSS collisions.
29
- */
30
- private displayMessageNearElement;
31
- /**
32
- * Ensures routes are registered for the given browser context.
33
- * @param browserContext - The browser context to register routes on.
34
- */
35
- private static ensureRoutesRegistered;
9
+ /** Move the virtual cursor to the centre of the locator and optionally show a message. */
10
+ pointAt(page: Page, locator: Locator, message?: string, duration?: number): Promise<void>;
11
+ private ensureContainer;
12
+ private moveCursor;
13
+ private showMessage;
36
14
  }
37
15
  //# sourceMappingURL=InteractionVisualizer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"InteractionVisualizer.d.ts","sourceRoot":"","sources":["../../../src/managers/InteractionVisualizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAkB,MAAM,YAAY,CAAC;AAK3D;;GAEG;AACH,qBAAa,qBAAqB;aAeG,4BAA4B,EAAE,MAAM;IAdvE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAEvC;IACF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAmD;IAC9E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CACR;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IAC3D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAiC;IAC3E,OAAO,CAAC,oBAAoB,CAAkB;IAE9C;;;OAGG;gBACgC,4BAA4B,EAAE,MAAM;IAEvE;;;OAGG;IACU,OAAO,CAClB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,MAAM,EAChB,cAAc,GAAE,MAA0C,GACzD,OAAO,CAAC,IAAI,CAAC;IA4DhB;;OAEG;YACW,gBAAgB;IA8F9B;;OAEG;YACW,yBAAyB;IAgDvC;;;OAGG;mBACkB,sBAAsB;CAkC5C"}
1
+ {"version":3,"file":"InteractionVisualizer.d.ts","sourceRoot":"","sources":["../../../src/managers/InteractionVisualizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE3C,qBAAa,qBAAqB;aA6BG,4BAA4B,EAAE,MAAM;IAxBvE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAW3B;IAEN,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAM3B;IAEA,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAuB;IAC3D,OAAO,CAAC,SAAS,CAA4C;gBAE1B,4BAA4B,EAAE,MAAM;IAMvE,0FAA0F;IAC7E,OAAO,CAClB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,MAAM,EAChB,QAAQ,SAAoC,GAC3C,OAAO,CAAC,IAAI,CAAC;YAsBF,eAAe;YA8Bf,UAAU;YAkDV,WAAW;CA8C1B"}
@@ -1,223 +1,151 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InteractionVisualizer = void 0;
4
- const Logger_1 = require("../utils/Logger");
5
- const PlaywrightUtils_1 = require("../utils/PlaywrightUtils");
6
- const MiscUtils_1 = require("../utils/MiscUtils");
7
- /**
8
- * Class for visualizing interactions in a webpage with a virtual mouse and messages.
9
- */
10
4
  class InteractionVisualizer {
11
- /**
12
- * Creates an instance of InteractionVisualizer.
13
- * @param defaultMessageDurationMillis - Default duration for displaying messages in milliseconds.
14
- */
15
5
  constructor(defaultMessageDurationMillis) {
16
6
  this.defaultMessageDurationMillis = defaultMessageDurationMillis;
17
- this.currentMousePosition = { x: 0, y: 0 };
7
+ this.cursorPos = { x: 0, y: 0 };
18
8
  }
19
- /**
20
- * Moves the virtual mouse to the element with a smooth animation and
21
- * optionally displays a message at element.
22
- */
23
- async pointAt(page, element, message, durationMillis = this.defaultMessageDurationMillis) {
24
- if (!durationMillis || durationMillis <= 0) {
9
+ /* ------------------------------------------------------------------ */
10
+ /* Public API */
11
+ /* ------------------------------------------------------------------ */
12
+ /** Move the virtual cursor to the centre of the locator and optionally show a message. */
13
+ async pointAt(page, locator, message, duration = this.defaultMessageDurationMillis) {
14
+ if (!duration || duration <= 0)
25
15
  return;
26
- }
27
- await InteractionVisualizer.ensureRoutesRegistered(page.context());
28
- try {
29
- // Get element position for mouse movement
30
- const boundingBox = await element.boundingBox();
31
- if (!boundingBox) {
32
- Logger_1.appLogger.error('Failed to get element bounding box');
16
+ await locator.scrollIntoViewIfNeeded();
17
+ const box = await locator.boundingBox();
18
+ if (!box)
19
+ throw new Error('Element bounding box unavailable');
20
+ const target = { x: box.x + box.width / 2, y: box.y + box.height / 2 };
21
+ await this.ensureContainer(page);
22
+ await Promise.all([
23
+ this.moveCursor(page, target, duration / 2),
24
+ message && message.trim()
25
+ ? this.showMessage(page, target, message.trim(), duration)
26
+ : Promise.resolve(),
27
+ ]);
28
+ }
29
+ /* ------------------------------------------------------------------ */
30
+ /* Private helpers */
31
+ /* ------------------------------------------------------------------ */
32
+ async ensureContainer(page) {
33
+ const id = InteractionVisualizer.CONTAINER_ID;
34
+ await page.evaluate(([containerId, css]) => {
35
+ if (document.getElementById(containerId))
33
36
  return;
34
- }
35
- // Calculate target position (center of the element)
36
- const targetX = boundingBox.x + boundingBox.width / 2;
37
- const targetY = boundingBox.y + boundingBox.height / 2;
38
- const promises = [];
39
- // Start mouse movement and message display in parallel
40
- promises.push(this.moveVirtualMouse(page, targetX, targetY, durationMillis / 2));
41
- if (message && !message.trim()) {
42
- // Display the message for the element
43
- await this.displayMessageNearElement(element, message);
44
- // Create a promise for the message duration
45
- promises.push(page.waitForTimeout(durationMillis));
46
- }
47
- // Wait for both mouse movement and message duration to complete
48
- await Promise.all(promises);
49
- // Remove only the message after the duration (keep the mouse)
50
- await element.evaluate((_, [messageContainerId]) => {
51
- const container = document.getElementById(messageContainerId);
52
- if (container) {
53
- const shadow = container.shadowRoot;
54
- if (shadow) {
55
- // Remove only message elements but keep the mouse
56
- const messages = Array.from(shadow.querySelectorAll('.donobu-message'));
57
- messages.forEach((msg) => msg.remove());
58
- }
59
- }
60
- }, [InteractionVisualizer.MESSAGE_CONTAINER_ID]);
61
- }
62
- catch (e) {
63
- if (PlaywrightUtils_1.PlaywrightUtils.isPageClosedError(e)) {
64
- throw e;
65
- }
66
- else {
67
- Logger_1.appLogger.error(`Failed to display message at element`, e);
68
- }
69
- }
37
+ const el = document.createElement('div');
38
+ el.id = containerId;
39
+ Object.assign(el.style, {
40
+ position: 'fixed',
41
+ top: '0',
42
+ left: '0',
43
+ width: '100vw',
44
+ height: '100vh',
45
+ pointerEvents: 'none',
46
+ zIndex: '2147483646', // just below the message itself
47
+ });
48
+ const shadow = el.attachShadow({ mode: 'open' });
49
+ const style = document.createElement('style');
50
+ style.textContent = css;
51
+ shadow.appendChild(style);
52
+ // Append to <html> so it is not clipped by overflow/transform on <body>
53
+ (document.documentElement || document.body).appendChild(el);
54
+ }, [id, InteractionVisualizer.CSS]);
70
55
  }
71
- /**
72
- * Moves the virtual mouse to the target position with a smooth animation.
73
- */
74
- async moveVirtualMouse(page, targetX, targetY, durationMillis) {
75
- await InteractionVisualizer.ensureRoutesRegistered(page.context());
76
- await page.evaluate(([containerId, mouseId, startX, startY, endX, endY, duration]) => {
77
- return new Promise((resolve) => {
78
- // 1) Find or create the container
79
- let container = document.getElementById(containerId);
80
- if (!container) {
81
- container = document.createElement('div');
82
- container.id = containerId;
83
- container.style.position = 'absolute';
84
- container.style.top = '0';
85
- container.style.left = '0';
86
- container.style.width = '100%';
87
- container.style.height = '100%';
88
- container.style.pointerEvents = 'none';
89
- document.body.appendChild(container);
90
- const shadowRoot = container.attachShadow({ mode: 'open' });
91
- // Insert style
92
- const styleEl = document.createElement('link');
93
- styleEl.rel = 'stylesheet';
94
- styleEl.href = '/donobu.css';
95
- shadowRoot.appendChild(styleEl);
96
- }
97
- const shadow = container.shadowRoot;
98
- if (!shadow) {
99
- resolve();
100
- return;
101
- }
102
- // Find or create mouse
103
- let mouse = shadow.getElementById(mouseId);
104
- if (!mouse) {
105
- mouse = document.createElement('div');
106
- mouse.id = mouseId;
107
- mouse.className = 'donobu-virtual-mouse';
108
- // Initial position if first time
109
- mouse.style.left = `${startX}px`;
110
- mouse.style.top = `${startY}px`;
111
- mouse.style.transitionDuration = '0s'; // No animation initially
112
- shadow.appendChild(mouse);
113
- // Force reflow to ensure initial position is applied before animation
114
- void mouse.offsetWidth;
115
- }
116
- // Animate the mouse
117
- mouse.style.transitionDuration = `${duration}ms`;
118
- mouse.style.left = `${endX - 16}px`; // Half of 40px
119
- mouse.style.top = `${endY - 8}px`; // Tip adjustment
120
- // Resolve when transition completes or timeout as fallback
121
- const transitionEndHandler = () => {
122
- mouse?.removeEventListener('transitionend', transitionEndHandler);
123
- if (mouse) {
124
- mouse.classList.remove('rippling'); // Reset ripple
125
- void mouse.offsetWidth; // Force reflow
126
- setTimeout(() => {
127
- mouse?.classList.add('rippling'); // Trigger new ripple
128
- }, 10);
129
- }
56
+ async moveCursor(page, target, duration) {
57
+ const id = InteractionVisualizer.CONTAINER_ID;
58
+ await page.evaluate(([containerId, start, end, duration, svg]) => {
59
+ containerId = containerId;
60
+ start = start;
61
+ end = end;
62
+ duration = duration;
63
+ svg = svg;
64
+ const root = document.getElementById(containerId)
65
+ .shadowRoot;
66
+ let cursor = root.querySelector('.donobu-virtual-mouse');
67
+ if (!cursor) {
68
+ cursor = document.createElement('div');
69
+ cursor.className = 'donobu-virtual-mouse';
70
+ cursor.innerHTML = svg;
71
+ cursor.style.left = `${start.x}px`;
72
+ cursor.style.top = `${start.y}px`;
73
+ cursor.style.transitionDuration = '0s';
74
+ root.appendChild(cursor);
75
+ cursor.getBoundingClientRect(); // force reflow
76
+ }
77
+ cursor.style.transitionDuration = `${duration}ms`;
78
+ cursor.style.left = `${end.x - 12}px`; // half width offset
79
+ cursor.style.top = `${end.y - 12}px`; // half height offset
80
+ cursor.classList.add('rippling');
81
+ const done = new Promise((resolve) => {
82
+ const finish = () => {
83
+ cursor.removeEventListener('transitionend', finish);
84
+ cursor.classList.remove('rippling');
130
85
  resolve();
131
86
  };
132
- mouse.addEventListener('transitionend', transitionEndHandler);
133
- // Fallback in case transitionend doesn't fire
134
- setTimeout(resolve, duration + 50);
87
+ cursor.addEventListener('transitionend', finish);
88
+ setTimeout(finish, duration + 50);
135
89
  });
136
- }, [
137
- InteractionVisualizer.MESSAGE_CONTAINER_ID,
138
- InteractionVisualizer.VIRTUAL_MOUSE_ID,
139
- this.currentMousePosition.x,
140
- this.currentMousePosition.y,
141
- targetX,
142
- targetY,
143
- durationMillis,
144
- ]);
145
- // Update current mouse position
146
- this.currentMousePosition = { x: targetX, y: targetY };
90
+ return done;
91
+ }, [id, this.cursorPos, target, duration, InteractionVisualizer.SVG_MOUSE]);
92
+ this.cursorPos = target;
147
93
  }
148
- /**
149
- * Creates a message adjacent to the element, inside a shadow root to avoid CSS collisions.
150
- */
151
- async displayMessageNearElement(element, message) {
152
- await element.evaluate((targetElement, [messageContainerId, message]) => {
153
- // 1) Find container (should already exist from moveVirtualMouse)
154
- const container = document.getElementById(messageContainerId);
155
- if (!container || !container.shadowRoot) {
156
- return;
157
- }
158
- const shadow = container.shadowRoot;
159
- // 2) Insert message
160
- const messageElement = document.createElement('div');
161
- messageElement.className = 'donobu-message';
162
- messageElement.textContent = message;
163
- // Temporarily place off-screen to measure size
164
- messageElement.style.left = '-9999px';
165
- messageElement.style.top = '-9999px';
166
- shadow.appendChild(messageElement);
167
- // 3) Compute final position
168
- const rect = targetElement.getBoundingClientRect();
169
- let x = rect.left + window.scrollX;
170
- let y = rect.bottom + window.scrollY + 10;
171
- messageElement.style.left = `${x}px`;
172
- messageElement.style.top = `${y}px`;
173
- // Adjust if it goes off-screen to the right
174
- const msgRect = messageElement.getBoundingClientRect();
175
- const overflowRight = msgRect.right - window.innerWidth;
176
- if (overflowRight > 0) {
177
- messageElement.style.left = `${x - overflowRight - 10}px`;
178
- }
179
- // Adjust if it goes off-screen to the left
180
- if (msgRect.left < 0) {
181
- messageElement.style.left = `${window.scrollX + 10}px`;
94
+ async showMessage(page, target, text, duration) {
95
+ const id = InteractionVisualizer.CONTAINER_ID;
96
+ await page.evaluate(([containerId, target, text, duration]) => {
97
+ containerId = containerId;
98
+ target = target;
99
+ text = text;
100
+ duration = duration;
101
+ const root = document.getElementById(containerId)
102
+ .shadowRoot;
103
+ const msg = document.createElement('div');
104
+ msg.className = 'donobu-message';
105
+ msg.textContent = text;
106
+ root.appendChild(msg);
107
+ /* ── compute final coordinates ────────────────────────────────── */
108
+ const { width, height } = msg.getBoundingClientRect();
109
+ let x = target.x - width / 2;
110
+ let y = target.y + 24; // default - below cursor
111
+ /* clamp horizontally inside viewport */
112
+ x = Math.max(8, Math.min(window.innerWidth - width - 8, x));
113
+ /* if it overflows bottom, flip above the element */
114
+ if (y + height + 8 > window.innerHeight) {
115
+ y = target.y - height - 24;
182
116
  }
183
- }, [InteractionVisualizer.MESSAGE_CONTAINER_ID, message]);
184
- }
185
- /**
186
- * Ensures routes are registered for the given browser context.
187
- * @param browserContext - The browser context to register routes on.
188
- */
189
- static async ensureRoutesRegistered(browserContext) {
190
- if (this.registeredContexts.has(browserContext)) {
191
- return;
192
- }
193
- try {
194
- await browserContext.route('**/donobu-virtual-mouse.svg', async (route) => {
195
- await route.fulfill({
196
- status: 200,
197
- contentType: 'image/svg+xml',
198
- body: InteractionVisualizer.VIRTUAL_MOUSE_SVG,
199
- });
200
- });
201
- await browserContext.route('**/donobu.css', async (route) => {
202
- await route.fulfill({
203
- status: 200,
204
- contentType: 'text/css',
205
- body: InteractionVisualizer.CSS,
206
- });
207
- });
208
- this.registeredContexts.add(browserContext);
209
- Logger_1.appLogger.debug('Routes registered for InteractionVisualizer');
210
- }
211
- catch (e) {
212
- Logger_1.appLogger.error('Failed to register routes for InteractionVisualizer', e);
213
- throw e;
214
- }
117
+ /* if still off-screen at the top, clamp to 8 px margin */
118
+ if (y < 8)
119
+ y = 8;
120
+ msg.style.left = `${x}px`;
121
+ msg.style.top = `${y}px`;
122
+ /* auto-remove after the requested duration */
123
+ setTimeout(() => msg.remove(), duration);
124
+ }, [id, target, text, duration]);
215
125
  }
216
126
  }
217
127
  exports.InteractionVisualizer = InteractionVisualizer;
218
- InteractionVisualizer.VIRTUAL_MOUSE_SVG = MiscUtils_1.MiscUtils.getResourceFileAsString('donobu-virtual-mouse.svg');
219
- InteractionVisualizer.CSS = MiscUtils_1.MiscUtils.getResourceFileAsString('donobu.css');
220
- InteractionVisualizer.MESSAGE_CONTAINER_ID = 'donobu-message-shadow-container';
221
- InteractionVisualizer.VIRTUAL_MOUSE_ID = 'virtual-mouse';
222
- InteractionVisualizer.registeredContexts = new WeakSet();
128
+ /* ------------------------------------------------------------------ */
129
+ /* Constants */
130
+ /* ------------------------------------------------------------------ */
131
+ InteractionVisualizer.SVG_MOUSE = `
132
+ <svg xmlns="http://www.w3.org/2000/svg"
133
+ width="32"
134
+ height="32"
135
+ viewBox="0 0 24 24"
136
+ fill="oklch(13.09% 0.005 165.18)"
137
+ stroke="oklch(83.04% 0.1698 83.99)"
138
+ stroke-width="2"
139
+ stroke-linecap="round"
140
+ stroke-linejoin="round">
141
+ <path d="M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z" />
142
+ </svg>`;
143
+ InteractionVisualizer.CSS = `
144
+ .donobu-message{position:absolute;z-index:2147483647;background:#000;color:#fff;padding:8px 10px;border-radius:5px;font:12px/1 'Source Sans Pro','Helvetica Neue',Helvetica,Arial,sans-serif;max-width:300px;white-space:pre-wrap;box-shadow:2px 2px 10px rgba(0,0,0,.2);pointer-events:none}
145
+ .donobu-virtual-mouse{width:24px;height:24px;position:absolute;z-index:2147483646;filter:drop-shadow(1px 1px 1px rgba(0,0,0,.5));transition:left .15s ease-in-out,top .15s ease-in-out,transform .15s ease-in-out}
146
+ .donobu-virtual-mouse svg{width:100%;height:100%;display:block}
147
+ .donobu-virtual-mouse.rippling::after{content:"";position:absolute;left:50%;top:50%;width:24px;height:24px;border-radius:50%;background:oklch(83.04% 0.1698 83.99);transform:translate(-50%,-50%) scale(.5);opacity:.4;animation:ripple-pop .6s ease-out forwards}
148
+ @keyframes ripple-pop{40%{transform:translate(-50%,-50%) scale(1);opacity:.5}100%{transform:translate(-50%,-50%) scale(2);opacity:0}}
149
+ `;
150
+ InteractionVisualizer.CONTAINER_ID = 'donobu-iv-overlay';
223
151
  //# sourceMappingURL=InteractionVisualizer.js.map