playwriter 0.0.105 → 0.2.0
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/dist/bippy.js +5 -5
- package/dist/cdp-relay.d.ts.map +1 -1
- package/dist/cdp-relay.js +17 -5
- package/dist/cdp-relay.js.map +1 -1
- package/dist/cli-help.test.d.ts +2 -0
- package/dist/cli-help.test.d.ts.map +1 -0
- package/dist/cli-help.test.js +53 -0
- package/dist/cli-help.test.js.map +1 -0
- package/dist/cli.js +74 -25
- package/dist/cli.js.map +1 -1
- package/dist/executor.d.ts +1 -0
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +55 -12
- package/dist/executor.js.map +1 -1
- package/dist/extension/background.js +675 -27
- package/dist/extension/manifest.json +1 -1
- package/dist/ghost-cursor-client.js +170 -83
- package/dist/{recording-ghost-cursor.d.ts → ghost-cursor-controller.d.ts} +15 -10
- package/dist/ghost-cursor-controller.d.ts.map +1 -0
- package/dist/ghost-cursor-controller.js +98 -0
- package/dist/ghost-cursor-controller.js.map +1 -0
- package/dist/ghost-cursor.d.ts.map +1 -1
- package/dist/ghost-cursor.js +42 -26
- package/dist/ghost-cursor.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +6 -1
- package/dist/mcp.js.map +1 -1
- package/dist/on-mouse-action.test.js +25 -0
- package/dist/on-mouse-action.test.js.map +1 -1
- package/dist/performance-examples.d.ts +5 -0
- package/dist/performance-examples.d.ts.map +1 -0
- package/dist/performance-examples.js +112 -0
- package/dist/performance-examples.js.map +1 -0
- package/dist/performance-profiling.md +417 -0
- package/dist/prompt.md +22 -8
- package/dist/react-source.d.ts +44 -0
- package/dist/react-source.d.ts.map +1 -1
- package/dist/react-source.js +207 -20
- package/dist/react-source.js.map +1 -1
- package/dist/readability.js +1 -1
- package/dist/relay-core.test.d.ts.map +1 -1
- package/dist/relay-core.test.js +101 -1
- package/dist/relay-core.test.js.map +1 -1
- package/dist/relay-session.test.js +34 -6
- package/dist/relay-session.test.js.map +1 -1
- package/dist/screen-recording.d.ts +2 -2
- package/dist/screen-recording.d.ts.map +1 -1
- package/dist/screen-recording.js +19 -7
- package/dist/screen-recording.js.map +1 -1
- package/dist/selector-generator.js +1 -1
- package/package.json +7 -7
- package/src/aria-snapshots/github-interactive.txt +5 -3
- package/src/aria-snapshots/github-raw.txt +8 -5
- package/src/aria-snapshots/hackernews-interactive.txt +241 -238
- package/src/aria-snapshots/hackernews-raw.txt +269 -265
- package/src/aria-snapshots/prosemirror-interactive.txt +3 -1
- package/src/aria-snapshots/prosemirror-raw.txt +4 -1
- package/src/assets/aria-labels-hacker-news.png +0 -0
- package/src/assets/aria-labels-old-reddit.png +0 -0
- package/src/cdp-relay.ts +17 -5
- package/src/cli-help.test.ts +63 -0
- package/src/cli.ts +80 -28
- package/src/executor.ts +65 -15
- package/src/ghost-cursor-client.ts +221 -96
- package/src/{recording-ghost-cursor.ts → ghost-cursor-controller.ts} +50 -34
- package/src/ghost-cursor.ts +54 -41
- package/src/mcp.ts +6 -1
- package/src/on-mouse-action.test.ts +30 -0
- package/src/performance-examples.ts +186 -0
- package/src/react-source.ts +310 -24
- package/src/relay-core.test.ts +117 -0
- package/src/relay-session.test.ts +36 -10
- package/src/screen-recording.ts +23 -10
- package/src/skill.md +33 -9
- package/src/snapshots/shadcn-ui-accessibility-full.md +6 -3
- package/src/snapshots/shadcn-ui-accessibility-interactive.md +2 -0
- package/dist/recording-ghost-cursor.d.ts.map +0 -1
- package/dist/recording-ghost-cursor.js +0 -79
- package/dist/recording-ghost-cursor.js.map +0 -1
|
@@ -31,31 +31,46 @@
|
|
|
31
31
|
var SCREENSTUDIO_POINTER_MACOS_TAHOE_DATA_URL = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjE4IiBoZWlnaHQ9Ijk1OCIgdmlld0JveD0iMCAwIDYxOCA5NTgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGZpbHRlcj0idXJsKCNmaWx0ZXIwX2RfMzg0XzI3KSI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTI3LjA2MiAzNy4wMzMxTDU0MC42OTYgNDUxLjU1NUM1OTIuNjUzIDUwMy42NiA1NTUuNzk0IDU5Mi41NzQgNDgyLjIyNiA1OTIuNTc0TDQyMS44MzEgNTkyLjU2OUw0ODEuODIxIDczNS4wNTRDNDkyLjMzMSA3NjAuMDIxIDQ5Mi40NzkgNzg3LjY1MiA0ODIuMjY1IDgxMi43NjdDNDcyLjAwMiA4MzcuOTMyIDQ1Mi41NjEgODU3LjU3IDQyNy40OTYgODY4LjA4QzQxNC44NjQgODczLjM1OSA0MDEuNjQgODc2LjAyNCAzODguMTIxIDg3Ni4wMjRDMzQ3LjExNyA4NzYuMDI0IDMxMC4zNTggODUxLjYgMjk0LjQ3IDgxMy44MDRMMjMxLjQyIDY2My45MThMMTkwLjM2OCA3MDAuMzM3QzEzNy4wMjkgNzQ3LjUwOCA1MyA3MDkuNjYzIDUzIDYzOC40MTNWNjcuNjc0NEM1MyAyOC45OTAzIDk5LjcyNjggOS42NDgyOCAxMjcuMDYyIDM3LjAzMzFaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTEwMi4zMTYgOTkuNjUyQzEwMi4zMTYgOTMuMTg4MiAxMTAuMTYyIDg5LjkzMTYgMTE0LjcwMSA5NC41MjA0TDUwNC44OTcgNDg1LjU1NUM1MjYuMTY0IDUwNi44NzEgNTExLjA2NSA1NDMuMjM2IDQ4MC45NjcgNTQzLjIzNkwzNDcuNTQ2IDU0My4xNjFMNDM2LjM0MiA3NTQuMTQzQzQ0Ny41NDIgNzgwLjc4OCA0MzUuMDA5IDgxMS40MjkgNDA4LjQxNCA4MjIuNTgxQzM4MS43MiA4MzMuNzgxIDM1MS4xMjggODIxLjI5OCAzMzkuOTc3IDc5NC43MDJMMjUwLjI5MyA1ODEuMzUyTDE1OC41MTcgNjYyLjY0NEMxMzcuOTkxIDY4MC44MDEgMTA2LjMxOSA2NjguMTQ1IDEwMi42NjQgNjQyLjMyM0wxMDIuMzE2IDYzNy4zMzFWOTkuNjUyWiIgZmlsbD0iYmxhY2siLz4KPC9nPgo8ZGVmcz4KPGZpbHRlciBpZD0iZmlsdGVyMF9kXzM4NF8yNyIgeD0iMC4zNCIgeT0iMC43OTkyMTkiIHdpZHRoPSI2MTcuMzIiIGhlaWdodD0iOTU3LjE0NCIgZmlsdGVyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiPgo8ZmVGbG9vZCBmbG9vZC1vcGFjaXR5PSIwIiByZXN1bHQ9IkJhY2tncm91bmRJbWFnZUZpeCIvPgo8ZmVDb2xvck1hdHJpeCBpbj0iU291cmNlQWxwaGEiIHR5cGU9Im1hdHJpeCIgdmFsdWVzPSIwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAxMjcgMCIgcmVzdWx0PSJoYXJkQWxwaGEiLz4KPGZlT2Zmc2V0IGR5PSIyOS4yNiIvPgo8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIyNi4zMyIvPgo8ZmVDb21wb3NpdGUgaW4yPSJoYXJkQWxwaGEiIG9wZXJhdG9yPSJvdXQiLz4KPGZlQ29sb3JNYXRyaXggdHlwZT0ibWF0cml4IiB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAuNjUgMCIvPgo8ZmVCbGVuZCBtb2RlPSJub3JtYWwiIGluMj0iQmFja2dyb3VuZEltYWdlRml4IiByZXN1bHQ9ImVmZmVjdDFfZHJvcFNoYWRvd18zODRfMjciLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbj0iU291cmNlR3JhcGhpYyIgaW4yPSJlZmZlY3QxX2Ryb3BTaGFkb3dfMzg0XzI3IiByZXN1bHQ9InNoYXBlIi8+CjwvZmlsdGVyPgo8L2RlZnM+Cjwvc3ZnPg==";
|
|
32
32
|
|
|
33
33
|
// src/ghost-cursor-client.ts
|
|
34
|
+
var isTopFrame = (() => {
|
|
35
|
+
try {
|
|
36
|
+
return window === window.top;
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
})();
|
|
34
41
|
var CURSOR_ID = "__playwriter_ghost_cursor__";
|
|
35
42
|
var SCREENSTUDIO_POINTER_ASPECT_RATIO = 618 / 958;
|
|
36
43
|
var SCREENSTUDIO_HOTSPOT_X_RATIO = 0.14;
|
|
37
44
|
var SCREENSTUDIO_HOTSPOT_Y_RATIO = 0.06;
|
|
38
45
|
var MINIMAL_TRIANGLE_HOTSPOT_X_RATIO = 0.07;
|
|
39
46
|
var MINIMAL_TRIANGLE_HOTSPOT_Y_RATIO = 0.06;
|
|
47
|
+
var MOVE_EASING = "cubic-bezier(0.65, 0, 0.35, 1)";
|
|
48
|
+
var PRESS_EASING = "cubic-bezier(0.23, 1, 0.32, 1)";
|
|
49
|
+
var PRESS_DURATION_MS = 140;
|
|
50
|
+
var IDLE_HIDE_DELAY_MS = 5000;
|
|
51
|
+
var IDLE_FADE_OUT_MS = 600;
|
|
40
52
|
var DEFAULT_OPTIONS = {
|
|
41
53
|
style: "minimal",
|
|
42
54
|
color: "#111827",
|
|
43
55
|
size: 22,
|
|
44
56
|
zIndex: 2147483647,
|
|
45
|
-
easing:
|
|
46
|
-
minDurationMs:
|
|
47
|
-
maxDurationMs:
|
|
48
|
-
speedPxPerMs:
|
|
57
|
+
easing: MOVE_EASING,
|
|
58
|
+
minDurationMs: 220,
|
|
59
|
+
maxDurationMs: 1500,
|
|
60
|
+
speedPxPerMs: 1.2
|
|
49
61
|
};
|
|
50
62
|
var runtime = {
|
|
51
|
-
|
|
63
|
+
outerElement: null,
|
|
64
|
+
innerElement: null,
|
|
52
65
|
options: DEFAULT_OPTIONS,
|
|
53
66
|
x: 0,
|
|
54
67
|
y: 0,
|
|
55
68
|
scale: 1,
|
|
56
69
|
hasPosition: false,
|
|
57
|
-
enabled: false
|
|
70
|
+
enabled: false,
|
|
71
|
+
idleHidden: false
|
|
58
72
|
};
|
|
73
|
+
var idleHideTimer = null;
|
|
59
74
|
function clamp(options) {
|
|
60
75
|
const { value, min, max } = options;
|
|
61
76
|
return Math.min(max, Math.max(min, value));
|
|
@@ -115,12 +130,18 @@
|
|
|
115
130
|
}
|
|
116
131
|
return "0.72";
|
|
117
132
|
}
|
|
118
|
-
function
|
|
119
|
-
if (!runtime.
|
|
133
|
+
function applyTranslate() {
|
|
134
|
+
if (!runtime.outerElement) {
|
|
120
135
|
return;
|
|
121
136
|
}
|
|
122
137
|
const hotspot = getHotspotOffsetPx();
|
|
123
|
-
runtime.
|
|
138
|
+
runtime.outerElement.style.transform = `translate3d(${runtime.x - hotspot.x}px, ${runtime.y - hotspot.y}px, 0)`;
|
|
139
|
+
}
|
|
140
|
+
function applyScale() {
|
|
141
|
+
if (!runtime.innerElement) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
runtime.innerElement.style.transform = `scale(${runtime.scale})`;
|
|
124
145
|
}
|
|
125
146
|
function computeDurationMs(options) {
|
|
126
147
|
if (!runtime.hasPosition) {
|
|
@@ -137,103 +158,146 @@
|
|
|
137
158
|
});
|
|
138
159
|
}
|
|
139
160
|
function createCursorElement() {
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
161
|
+
const outer = document.createElement("div");
|
|
162
|
+
outer.id = CURSOR_ID;
|
|
163
|
+
outer.setAttribute("aria-hidden", "true");
|
|
164
|
+
outer.style.position = "fixed";
|
|
165
|
+
outer.style.left = "0";
|
|
166
|
+
outer.style.top = "0";
|
|
167
|
+
outer.style.pointerEvents = "none";
|
|
168
|
+
outer.style.zIndex = `${runtime.options.zIndex}`;
|
|
169
|
+
outer.style.transitionProperty = "transform";
|
|
170
|
+
outer.style.transitionTimingFunction = runtime.options.easing;
|
|
171
|
+
outer.style.transitionDuration = "0ms";
|
|
172
|
+
outer.style.willChange = "transform";
|
|
173
|
+
const inner = document.createElement("div");
|
|
174
|
+
inner.style.transitionProperty = "transform, opacity";
|
|
175
|
+
inner.style.transitionTimingFunction = PRESS_EASING;
|
|
176
|
+
inner.style.transitionDuration = `${PRESS_DURATION_MS}ms`;
|
|
177
|
+
inner.style.opacity = getBaseOpacity();
|
|
178
|
+
outer.appendChild(inner);
|
|
179
|
+
runtime.outerElement = outer;
|
|
180
|
+
runtime.innerElement = inner;
|
|
154
181
|
applyRuntimeVisualOptions();
|
|
155
|
-
return
|
|
182
|
+
return outer;
|
|
156
183
|
}
|
|
157
184
|
function ensureCursorElement() {
|
|
158
185
|
const existing = document.getElementById(CURSOR_ID);
|
|
159
186
|
if (existing) {
|
|
160
|
-
runtime.
|
|
187
|
+
runtime.outerElement = existing;
|
|
188
|
+
runtime.innerElement = existing.firstElementChild || null;
|
|
161
189
|
return existing;
|
|
162
190
|
}
|
|
163
|
-
const
|
|
164
|
-
runtime.cursorElement = element;
|
|
191
|
+
const outer = createCursorElement();
|
|
165
192
|
const root = document.documentElement || document.body;
|
|
166
|
-
root.appendChild(
|
|
167
|
-
return
|
|
193
|
+
root.appendChild(outer);
|
|
194
|
+
return outer;
|
|
168
195
|
}
|
|
169
196
|
function applyRuntimeVisualOptions() {
|
|
170
|
-
if (!runtime.
|
|
197
|
+
if (!runtime.innerElement) {
|
|
171
198
|
return;
|
|
172
199
|
}
|
|
173
200
|
const dimensions = getCursorDimensions();
|
|
174
|
-
runtime.
|
|
175
|
-
runtime.
|
|
176
|
-
runtime.
|
|
177
|
-
|
|
201
|
+
runtime.innerElement.style.width = `${dimensions.width}px`;
|
|
202
|
+
runtime.innerElement.style.height = `${dimensions.height}px`;
|
|
203
|
+
if (runtime.outerElement) {
|
|
204
|
+
runtime.outerElement.style.zIndex = `${runtime.options.zIndex}`;
|
|
205
|
+
runtime.outerElement.style.transitionTimingFunction = runtime.options.easing;
|
|
206
|
+
}
|
|
207
|
+
const hotspot = getHotspotOffsetPx();
|
|
208
|
+
runtime.innerElement.style.transformOrigin = `${hotspot.x}px ${hotspot.y}px`;
|
|
178
209
|
if (runtime.options.style === "screenstudio") {
|
|
179
|
-
runtime.
|
|
180
|
-
runtime.
|
|
181
|
-
runtime.
|
|
182
|
-
runtime.
|
|
183
|
-
runtime.
|
|
184
|
-
runtime.
|
|
185
|
-
runtime.
|
|
186
|
-
runtime.
|
|
187
|
-
runtime.
|
|
188
|
-
runtime.
|
|
189
|
-
runtime.
|
|
210
|
+
runtime.innerElement.style.borderRadius = "0";
|
|
211
|
+
runtime.innerElement.style.border = "none";
|
|
212
|
+
runtime.innerElement.style.backgroundColor = "transparent";
|
|
213
|
+
runtime.innerElement.style.backgroundImage = `url("${SCREENSTUDIO_POINTER_MACOS_TAHOE_DATA_URL}")`;
|
|
214
|
+
runtime.innerElement.style.backgroundRepeat = "no-repeat";
|
|
215
|
+
runtime.innerElement.style.backgroundPosition = "left top";
|
|
216
|
+
runtime.innerElement.style.backgroundSize = "contain";
|
|
217
|
+
runtime.innerElement.style.backdropFilter = "none";
|
|
218
|
+
runtime.innerElement.style.filter = "none";
|
|
219
|
+
runtime.innerElement.style.boxShadow = "none";
|
|
220
|
+
runtime.innerElement.style.opacity = getBaseOpacity();
|
|
190
221
|
return;
|
|
191
222
|
}
|
|
192
223
|
if (runtime.options.style === "minimal") {
|
|
193
224
|
const triangleSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-1 -1 26 26"><path fill="white" stroke="${runtime.options.color}" stroke-width="1.5" stroke-linejoin="round" d="m23.284 19.124l-6.866-6.895a.4.4 0 0 1-.118-.296a.43.43 0 0 1 .163-.282l4.439-3.077a1.48 1.48 0 0 0 .621-1.48a1.48 1.48 0 0 0-1.036-1.198L1.623.302a1.14 1.14 0 0 0-1.11.282A1.13 1.13 0 0 0 .29 1.649L5.928 20.44a1.48 1.48 0 0 0 1.183 1.035a1.48 1.48 0 0 0 1.48-.621l3.078-4.44a.37.37 0 0 1 .31-.118a.43.43 0 0 1 .296.104l6.91 6.91a1.48 1.48 0 0 0 2.087 0l2.086-2.086a1.48 1.48 0 0 0-.074-2.101"/></svg>`;
|
|
194
225
|
const triangleDataUrl = `url("data:image/svg+xml,${encodeURIComponent(triangleSvg)}")`;
|
|
195
|
-
runtime.
|
|
196
|
-
runtime.
|
|
197
|
-
runtime.
|
|
198
|
-
runtime.
|
|
199
|
-
runtime.
|
|
200
|
-
runtime.
|
|
201
|
-
runtime.
|
|
202
|
-
runtime.
|
|
203
|
-
runtime.
|
|
204
|
-
runtime.
|
|
205
|
-
runtime.
|
|
226
|
+
runtime.innerElement.style.borderRadius = "0";
|
|
227
|
+
runtime.innerElement.style.border = "none";
|
|
228
|
+
runtime.innerElement.style.backgroundColor = "transparent";
|
|
229
|
+
runtime.innerElement.style.backgroundImage = triangleDataUrl;
|
|
230
|
+
runtime.innerElement.style.backgroundRepeat = "no-repeat";
|
|
231
|
+
runtime.innerElement.style.backgroundSize = "contain";
|
|
232
|
+
runtime.innerElement.style.backgroundPosition = "left top";
|
|
233
|
+
runtime.innerElement.style.backdropFilter = "none";
|
|
234
|
+
runtime.innerElement.style.boxShadow = "none";
|
|
235
|
+
runtime.innerElement.style.filter = "drop-shadow(0 1px 2px rgba(0, 0, 0, 0.4))";
|
|
236
|
+
runtime.innerElement.style.opacity = getBaseOpacity();
|
|
206
237
|
return;
|
|
207
238
|
}
|
|
208
|
-
runtime.
|
|
209
|
-
runtime.
|
|
210
|
-
runtime.
|
|
211
|
-
runtime.
|
|
212
|
-
runtime.
|
|
213
|
-
runtime.
|
|
214
|
-
runtime.
|
|
215
|
-
runtime.
|
|
239
|
+
runtime.innerElement.style.borderRadius = "999px";
|
|
240
|
+
runtime.innerElement.style.border = "none";
|
|
241
|
+
runtime.innerElement.style.backgroundColor = runtime.options.color;
|
|
242
|
+
runtime.innerElement.style.backgroundImage = "none";
|
|
243
|
+
runtime.innerElement.style.backdropFilter = "none";
|
|
244
|
+
runtime.innerElement.style.filter = "none";
|
|
245
|
+
runtime.innerElement.style.boxShadow = "0 2px 10px rgba(0, 0, 0, 0.18), inset 0 0 0 2px rgba(255, 255, 255, 0.55)";
|
|
246
|
+
runtime.innerElement.style.opacity = getBaseOpacity();
|
|
247
|
+
}
|
|
248
|
+
function clearIdleHideTimer() {
|
|
249
|
+
if (idleHideTimer !== null) {
|
|
250
|
+
clearTimeout(idleHideTimer);
|
|
251
|
+
idleHideTimer = null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function scheduleIdleHide() {
|
|
255
|
+
clearIdleHideTimer();
|
|
256
|
+
idleHideTimer = setTimeout(() => {
|
|
257
|
+
idleHideTimer = null;
|
|
258
|
+
if (!runtime.enabled || !runtime.innerElement) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
runtime.idleHidden = true;
|
|
262
|
+
runtime.innerElement.style.transitionDuration = `${IDLE_FADE_OUT_MS}ms`;
|
|
263
|
+
runtime.innerElement.style.transitionTimingFunction = PRESS_EASING;
|
|
264
|
+
runtime.innerElement.style.opacity = "0";
|
|
265
|
+
}, IDLE_HIDE_DELAY_MS);
|
|
266
|
+
}
|
|
267
|
+
function wakeFromIdle(options) {
|
|
268
|
+
runtime.x = options.x;
|
|
269
|
+
runtime.y = options.y;
|
|
270
|
+
runtime.hasPosition = true;
|
|
271
|
+
if (runtime.innerElement) {
|
|
272
|
+
runtime.innerElement.style.transitionDuration = `${PRESS_DURATION_MS}ms`;
|
|
273
|
+
runtime.innerElement.style.transitionTimingFunction = PRESS_EASING;
|
|
274
|
+
runtime.innerElement.style.opacity = getBaseOpacity();
|
|
275
|
+
}
|
|
216
276
|
}
|
|
217
277
|
function moveCursor(options) {
|
|
218
278
|
if (!runtime.enabled) {
|
|
219
279
|
return;
|
|
220
280
|
}
|
|
221
|
-
|
|
281
|
+
ensureCursorElement();
|
|
222
282
|
const durationMs = computeDurationMs({ targetX: options.x, targetY: options.y });
|
|
223
|
-
|
|
283
|
+
if (runtime.outerElement) {
|
|
284
|
+
runtime.outerElement.style.transitionDuration = `${Math.round(durationMs)}ms`;
|
|
285
|
+
runtime.outerElement.style.transitionTimingFunction = runtime.options.easing;
|
|
286
|
+
}
|
|
224
287
|
runtime.x = options.x;
|
|
225
288
|
runtime.y = options.y;
|
|
226
289
|
runtime.hasPosition = true;
|
|
227
|
-
|
|
290
|
+
applyTranslate();
|
|
228
291
|
}
|
|
229
292
|
function setPressed(options) {
|
|
230
|
-
if (!runtime.enabled) {
|
|
293
|
+
if (!runtime.enabled || !runtime.innerElement) {
|
|
231
294
|
return;
|
|
232
295
|
}
|
|
233
|
-
|
|
234
|
-
runtime.
|
|
235
|
-
|
|
236
|
-
|
|
296
|
+
runtime.scale = options.pressed ? runtime.options.style === "dot" ? 0.92 : 0.95 : 1;
|
|
297
|
+
runtime.innerElement.style.transitionDuration = `${PRESS_DURATION_MS}ms`;
|
|
298
|
+
runtime.innerElement.style.transitionTimingFunction = PRESS_EASING;
|
|
299
|
+
runtime.innerElement.style.opacity = options.pressed ? "1" : getBaseOpacity();
|
|
300
|
+
applyScale();
|
|
237
301
|
}
|
|
238
302
|
function enable(options) {
|
|
239
303
|
runtime.options = mergeOptions(options);
|
|
@@ -246,34 +310,44 @@
|
|
|
246
310
|
runtime.scale = 1;
|
|
247
311
|
runtime.hasPosition = true;
|
|
248
312
|
}
|
|
249
|
-
|
|
313
|
+
runtime.idleHidden = false;
|
|
314
|
+
if (runtime.innerElement) {
|
|
315
|
+
runtime.innerElement.style.opacity = getBaseOpacity();
|
|
316
|
+
}
|
|
317
|
+
applyTranslate();
|
|
318
|
+
applyScale();
|
|
319
|
+
scheduleIdleHide();
|
|
250
320
|
}
|
|
251
321
|
function disable() {
|
|
252
322
|
runtime.enabled = false;
|
|
253
323
|
runtime.scale = 1;
|
|
254
324
|
runtime.hasPosition = false;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
325
|
+
runtime.idleHidden = false;
|
|
326
|
+
clearIdleHideTimer();
|
|
327
|
+
if (runtime.outerElement) {
|
|
328
|
+
runtime.outerElement.remove();
|
|
329
|
+
runtime.outerElement = null;
|
|
330
|
+
runtime.innerElement = null;
|
|
258
331
|
}
|
|
259
332
|
}
|
|
260
333
|
function applyMouseAction(action) {
|
|
261
334
|
if (!runtime.enabled) {
|
|
262
335
|
return;
|
|
263
336
|
}
|
|
337
|
+
if (runtime.idleHidden) {
|
|
338
|
+
runtime.idleHidden = false;
|
|
339
|
+
wakeFromIdle({ x: action.x, y: action.y });
|
|
340
|
+
}
|
|
264
341
|
if (action.type === "move" || action.type === "wheel") {
|
|
265
342
|
moveCursor({ x: action.x, y: action.y });
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
if (action.type === "down") {
|
|
343
|
+
} else if (action.type === "down") {
|
|
269
344
|
moveCursor({ x: action.x, y: action.y });
|
|
270
345
|
setPressed({ pressed: true });
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
if (action.type === "up") {
|
|
346
|
+
} else if (action.type === "up") {
|
|
274
347
|
moveCursor({ x: action.x, y: action.y });
|
|
275
348
|
setPressed({ pressed: false });
|
|
276
349
|
}
|
|
350
|
+
scheduleIdleHide();
|
|
277
351
|
}
|
|
278
352
|
var api = {
|
|
279
353
|
enable,
|
|
@@ -283,5 +357,18 @@
|
|
|
283
357
|
return runtime.enabled;
|
|
284
358
|
}
|
|
285
359
|
};
|
|
286
|
-
|
|
360
|
+
if (isTopFrame) {
|
|
361
|
+
globalThis.__playwriterGhostCursor = api;
|
|
362
|
+
try {
|
|
363
|
+
if (document.readyState === "loading") {
|
|
364
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
365
|
+
try {
|
|
366
|
+
api.enable();
|
|
367
|
+
} catch {}
|
|
368
|
+
}, { once: true });
|
|
369
|
+
} else {
|
|
370
|
+
api.enable();
|
|
371
|
+
}
|
|
372
|
+
} catch {}
|
|
373
|
+
}
|
|
287
374
|
})();
|
|
@@ -1,34 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Always-on ghost cursor controller (Node side).
|
|
3
|
+
*
|
|
4
|
+
* Wires page.onMouseAction → applyGhostCursorMouseAction for every page.
|
|
5
|
+
* Chains with any pre-existing onMouseAction callback. Cursor-apply is
|
|
6
|
+
* fire-and-forget via a per-page queue so it does not block action completion.
|
|
4
7
|
*/
|
|
5
8
|
import type { BrowserContext, Page } from '@xmorse/playwright-core';
|
|
6
9
|
import { type GhostCursorClientOptions } from './ghost-cursor.js';
|
|
7
|
-
interface
|
|
10
|
+
interface GhostCursorLogger {
|
|
8
11
|
error: (...args: unknown[]) => void;
|
|
9
12
|
}
|
|
10
13
|
interface RecordingTargetOptions {
|
|
11
14
|
page?: Page;
|
|
12
15
|
sessionId?: string;
|
|
13
16
|
}
|
|
14
|
-
export declare class
|
|
17
|
+
export declare class GhostCursorController {
|
|
15
18
|
private readonly previousMouseActionByPage;
|
|
16
19
|
private readonly cursorApplyQueueByPage;
|
|
20
|
+
private readonly attachedPages;
|
|
17
21
|
private readonly logger;
|
|
18
22
|
constructor(options: {
|
|
19
|
-
logger:
|
|
23
|
+
logger: GhostCursorLogger;
|
|
20
24
|
});
|
|
21
25
|
resolveRecordingTargetPage(options: {
|
|
22
26
|
context: BrowserContext;
|
|
23
27
|
defaultPage: Page;
|
|
24
28
|
target?: RecordingTargetOptions;
|
|
25
29
|
}): Page;
|
|
26
|
-
|
|
30
|
+
/** Wire onMouseAction. Idempotent. */
|
|
31
|
+
attachToPage(options: {
|
|
27
32
|
page: Page;
|
|
28
|
-
}):
|
|
29
|
-
|
|
33
|
+
}): void;
|
|
34
|
+
detachFromPage(options: {
|
|
30
35
|
page: Page;
|
|
31
|
-
}):
|
|
36
|
+
}): void;
|
|
32
37
|
show(options: {
|
|
33
38
|
page: Page;
|
|
34
39
|
cursorOptions?: GhostCursorClientOptions;
|
|
@@ -38,4 +43,4 @@ export declare class RecordingGhostCursorController {
|
|
|
38
43
|
}): Promise<void>;
|
|
39
44
|
}
|
|
40
45
|
export {};
|
|
41
|
-
//# sourceMappingURL=
|
|
46
|
+
//# sourceMappingURL=ghost-cursor-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ghost-cursor-controller.d.ts","sourceRoot":"","sources":["../src/ghost-cursor-controller.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AACnE,OAAO,EAIL,KAAK,wBAAwB,EAC9B,MAAM,mBAAmB,CAAA;AAE1B,UAAU,iBAAiB;IACzB,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CACpC;AAED,UAAU,sBAAsB;IAC9B,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAA6C;IACvF,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAqC;IAC5E,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;gBAE9B,OAAO,EAAE;QAAE,MAAM,EAAE,iBAAiB,CAAA;KAAE;IAIlD,0BAA0B,CAAC,OAAO,EAAE;QAClC,OAAO,EAAE,cAAc,CAAA;QACvB,WAAW,EAAE,IAAI,CAAA;QACjB,MAAM,CAAC,EAAE,sBAAsB,CAAA;KAChC,GAAG,IAAI;IAoBR,sCAAsC;IACtC,YAAY,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,GAAG,IAAI;IAwC3C,cAAc,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,GAAG,IAAI;IAWvC,IAAI,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,aAAa,CAAC,EAAE,wBAAwB,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAStF,IAAI,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAQnD"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Always-on ghost cursor controller (Node side).
|
|
3
|
+
*
|
|
4
|
+
* Wires page.onMouseAction → applyGhostCursorMouseAction for every page.
|
|
5
|
+
* Chains with any pre-existing onMouseAction callback. Cursor-apply is
|
|
6
|
+
* fire-and-forget via a per-page queue so it does not block action completion.
|
|
7
|
+
*/
|
|
8
|
+
import { applyGhostCursorMouseAction, disableGhostCursor, enableGhostCursor, } from './ghost-cursor.js';
|
|
9
|
+
export class GhostCursorController {
|
|
10
|
+
previousMouseActionByPage = new WeakMap();
|
|
11
|
+
cursorApplyQueueByPage = new WeakMap();
|
|
12
|
+
attachedPages = new WeakSet();
|
|
13
|
+
logger;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.logger = options.logger;
|
|
16
|
+
}
|
|
17
|
+
resolveRecordingTargetPage(options) {
|
|
18
|
+
const { context, defaultPage, target } = options;
|
|
19
|
+
if (target?.page) {
|
|
20
|
+
return target.page;
|
|
21
|
+
}
|
|
22
|
+
if (target?.sessionId) {
|
|
23
|
+
const pageForSession = context.pages().find((candidatePage) => {
|
|
24
|
+
return candidatePage.sessionId() === target.sessionId;
|
|
25
|
+
});
|
|
26
|
+
if (pageForSession) {
|
|
27
|
+
return pageForSession;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return defaultPage;
|
|
31
|
+
}
|
|
32
|
+
/** Wire onMouseAction. Idempotent. */
|
|
33
|
+
attachToPage(options) {
|
|
34
|
+
const { page } = options;
|
|
35
|
+
if (this.attachedPages.has(page)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this.attachedPages.add(page);
|
|
39
|
+
if (!this.previousMouseActionByPage.has(page)) {
|
|
40
|
+
this.previousMouseActionByPage.set(page, page.onMouseAction);
|
|
41
|
+
}
|
|
42
|
+
const previousMouseAction = this.previousMouseActionByPage.get(page);
|
|
43
|
+
page.onMouseAction = async (event) => {
|
|
44
|
+
// Ghost cursor must never crash the main Playwright action (click, move, etc).
|
|
45
|
+
// Wrap the entire cursor logic in try/catch so errors stay cosmetic.
|
|
46
|
+
try {
|
|
47
|
+
const pendingCursorApply = this.cursorApplyQueueByPage.get(page) || Promise.resolve();
|
|
48
|
+
const nextCursorApply = pendingCursorApply
|
|
49
|
+
.then(async () => {
|
|
50
|
+
await applyGhostCursorMouseAction({ page, event });
|
|
51
|
+
})
|
|
52
|
+
.catch((error) => {
|
|
53
|
+
if (page.isClosed()) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.logger.error('[playwriter] Failed to apply ghost cursor action', error);
|
|
57
|
+
});
|
|
58
|
+
this.cursorApplyQueueByPage.set(page, nextCursorApply);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
this.logger.error('[playwriter] Ghost cursor onMouseAction error (non-fatal)', error);
|
|
62
|
+
}
|
|
63
|
+
if (!previousMouseAction) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
await previousMouseAction(event);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
detachFromPage(options) {
|
|
70
|
+
const { page } = options;
|
|
71
|
+
if (!this.attachedPages.has(page)) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
this.attachedPages.delete(page);
|
|
75
|
+
page.onMouseAction = this.previousMouseActionByPage.get(page) ?? null;
|
|
76
|
+
this.previousMouseActionByPage.delete(page);
|
|
77
|
+
this.cursorApplyQueueByPage.delete(page);
|
|
78
|
+
}
|
|
79
|
+
async show(options) {
|
|
80
|
+
try {
|
|
81
|
+
const { page, cursorOptions } = options;
|
|
82
|
+
await enableGhostCursor({ page, cursorOptions });
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Non-fatal — page may be closing or navigating.
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async hide(options) {
|
|
89
|
+
try {
|
|
90
|
+
const { page } = options;
|
|
91
|
+
await disableGhostCursor({ page });
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Non-fatal — page may be closing or navigating.
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=ghost-cursor-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ghost-cursor-controller.js","sourceRoot":"","sources":["../src/ghost-cursor-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ghost-cursor.d.ts","sourceRoot":"","sources":["../src/ghost-cursor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAErE,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,cAAc,CAAA;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAmCD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,IAAI,EAAE,IAAI,CAAA;IACV,aAAa,CAAC,EAAE,wBAAwB,CAAA;CACzC,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"ghost-cursor.d.ts","sourceRoot":"","sources":["../src/ghost-cursor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAErE,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,cAAc,CAAA;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAmCD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,IAAI,EAAE,IAAI,CAAA;IACV,aAAa,CAAC,EAAE,wBAAwB,CAAA;CACzC,GAAG,OAAO,CAAC,IAAI,CAAC,CAehB;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAU/E;AAED,wBAAsB,2BAA2B,CAAC,OAAO,EAAE;IACzD,IAAI,EAAE,IAAI,CAAA;IACV,KAAK,EAAE,gBAAgB,CAAA;CACxB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiChB"}
|
package/dist/ghost-cursor.js
CHANGED
|
@@ -27,37 +27,53 @@ async function ensureGhostCursorInjected(options) {
|
|
|
27
27
|
await page.evaluate(code);
|
|
28
28
|
}
|
|
29
29
|
export async function enableGhostCursor(options) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
try {
|
|
31
|
+
const { page, cursorOptions } = options;
|
|
32
|
+
await ensureGhostCursorInjected({ page });
|
|
33
|
+
await page.evaluate(({ optionsFromNode }) => {
|
|
34
|
+
const api = globalThis.__playwriterGhostCursor;
|
|
35
|
+
api?.enable(optionsFromNode);
|
|
36
|
+
}, { optionsFromNode: cursorOptions });
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Non-fatal — page may be closed or navigating.
|
|
40
|
+
}
|
|
36
41
|
}
|
|
37
42
|
export async function disableGhostCursor(options) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
try {
|
|
44
|
+
const { page } = options;
|
|
45
|
+
await page.evaluate(() => {
|
|
46
|
+
const api = globalThis.__playwriterGhostCursor;
|
|
47
|
+
api?.disable();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Non-fatal — page may be closed or navigating.
|
|
52
|
+
}
|
|
43
53
|
}
|
|
44
54
|
export async function applyGhostCursorMouseAction(options) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
// Never throw — the cursor is cosmetic and must not break the caller's action.
|
|
56
|
+
try {
|
|
57
|
+
const { page, event } = options;
|
|
58
|
+
const applied = await page.evaluate(({ serializedEvent }) => {
|
|
59
|
+
const api = globalThis.__playwriterGhostCursor;
|
|
60
|
+
if (!api) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
api.applyMouseAction(serializedEvent);
|
|
64
|
+
return true;
|
|
65
|
+
}, { serializedEvent: event });
|
|
66
|
+
if (applied) {
|
|
67
|
+
return;
|
|
50
68
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
69
|
+
await ensureGhostCursorInjected({ page });
|
|
70
|
+
await page.evaluate(({ serializedEvent }) => {
|
|
71
|
+
const api = globalThis.__playwriterGhostCursor;
|
|
72
|
+
api?.applyMouseAction(serializedEvent);
|
|
73
|
+
}, { serializedEvent: event });
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Swallow — page may be closed, navigating, or debugger detached.
|
|
56
77
|
}
|
|
57
|
-
await ensureGhostCursorInjected({ page });
|
|
58
|
-
await page.evaluate(({ serializedEvent }) => {
|
|
59
|
-
const api = globalThis.__playwriterGhostCursor;
|
|
60
|
-
api?.applyMouseAction(serializedEvent);
|
|
61
|
-
}, { serializedEvent: event });
|
|
62
78
|
}
|
|
63
79
|
//# sourceMappingURL=ghost-cursor.js.map
|
package/dist/ghost-cursor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ghost-cursor.js","sourceRoot":"","sources":["../src/ghost-cursor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAoBxC,IAAI,eAAe,GAAkB,IAAI,CAAA;AAEzC,SAAS,kBAAkB;IACzB,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,eAAe,CAAA;IACxB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,wBAAwB,CAAC,CAAA;IAChF,eAAe,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IACtD,OAAO,eAAe,CAAA;AACxB,CAAC;AAED,KAAK,UAAU,yBAAyB,CAAC,OAAuB;IAC9D,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;IACxB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;QAC9C,OAAO,OAAO,CAAE,UAAoD,CAAC,uBAAuB,CAAC,CAAA;IAC/F,CAAC,CAAC,CAAA;IAEF,IAAI,cAAc,EAAE,CAAC;QACnB,OAAM;IACR,CAAC;IAED,MAAM,IAAI,GAAG,kBAAkB,EAAE,CAAA;IACjC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAGvC;IACC,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"ghost-cursor.js","sourceRoot":"","sources":["../src/ghost-cursor.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAgWA,wBAAsB,QAAQ,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,iBAuB7E"}
|