dsh-capyreporter 0.1.1 → 0.1.2

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/lib/client.js CHANGED
@@ -30,7 +30,7 @@ function makeFactory() {
30
30
 
31
31
  const PET_CSS = [
32
32
  '.dsh-pet-float { position:fixed; z-index:2147483000; pointer-events:auto; user-select:none; -webkit-user-select:none; }',
33
- '.dsh-pet-img { display:block; width:132px; height:auto; pointer-events:auto; cursor:grab; filter:drop-shadow(0 6px 16px #0006); transform-origin:center bottom; transition:transform .12s ease-out; }',
33
+ '.dsh-pet-img { display:block; width:132px; height:auto; pointer-events:auto; cursor:grab; touch-action:none; filter:drop-shadow(0 6px 16px #0006); transform-origin:center bottom; transition:transform .12s ease-out; }',
34
34
  '.dsh-pet-img.dragging { cursor:grabbing; }',
35
35
  '.dsh-pet-img.bounce { transform:scale(1.12); }',
36
36
  '.dsh-pet-bubble { position:absolute; bottom:100%; left:50%; transform:translateX(-50%); margin-bottom:8px; background:#fdfdf7; color:#22242c; border-radius:14px; padding:8px 12px; font-size:12.5px; line-height:1.45; box-shadow:0 4px 14px #0007; max-width:900px; min-width:90px; cursor:pointer; z-index:5; flex-direction:column; gap:3px; display:flex; box-sizing:border-box; }',
@@ -218,6 +218,8 @@ function makeFactory() {
218
218
  }
219
219
  const onPointerDown = (e) => {
220
220
  if (e.button !== 0) return
221
+ // pointer capture keeps the move stream alive when the cursor outruns the pet
222
+ try { e.currentTarget.setPointerCapture(e.pointerId) } catch (er) {}
221
223
  dragState.s = { sx: e.clientX, sy: e.clientY, bx: pos[0].left, by: pos[0].top }
222
224
  }
223
225
  const onPointerMove = (e) => {
@@ -232,6 +234,9 @@ function makeFactory() {
232
234
  const onPointerUp = () => {
233
235
  dragState.s = null
234
236
  }
237
+ const onPointerCancel = () => {
238
+ dragState.s = null
239
+ }
235
240
 
236
241
  const menuItems = []
237
242
  if (suppressed[0].sig !== null) menuItems.push(['Restore bubble', () => { suppressed[0].sig = null; setExpanded(false) }])
@@ -289,6 +294,7 @@ function makeFactory() {
289
294
  onPointerDown: onPointerDown,
290
295
  onPointerMove: onPointerMove,
291
296
  onPointerUp: onPointerUp,
297
+ onPointerCancel: onPointerCancel,
292
298
  onClick: onLeftClick,
293
299
  onContextMenu: (e) => {
294
300
  e.preventDefault()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-capyreporter",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "CapyReporter — an always-on-top capybara task reporter for the DeepSeek Harness Web UI. A transparent floating pet that narrates each trajectory step in a speech bubble, tells you which project is reporting, alerts you when a task completes while you are away, and lets you upload your own pet art.",
5
5
  "keywords": [
6
6
  "dsh",
@@ -60,10 +60,10 @@
60
60
  },
61
61
  "peerDependencies": {
62
62
  "@deepseek-ai/cordis": "^4.0.1",
63
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
64
- "@deepseek-ai/dsh-client-connection": "^0.1.1-rc.2",
65
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
66
- "@deepseek-ai/dsh-host-webserver": "^0.1.1-rc.2",
63
+ "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2 || >=0.1.2-0",
64
+ "@deepseek-ai/dsh-client-connection": "^0.1.1-rc.2 || >=0.1.2-0",
65
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2 || >=0.1.2-0",
66
+ "@deepseek-ai/dsh-host-webserver": "^0.1.1-rc.2 || >=0.1.2-0",
67
67
  "react": "^18.2.0"
68
68
  },
69
69
  "engines": {
@@ -107,6 +107,7 @@
107
107
  width: auto;
108
108
  pointer-events: auto;
109
109
  cursor: grab;
110
+ touch-action: none;
110
111
  filter: drop-shadow(0 6px 16px #0008);
111
112
  }
112
113
  #menu {
@@ -202,10 +202,14 @@
202
202
  hideBubble();
203
203
  });
204
204
 
205
- // drag
205
+ // drag — pointer capture keeps the move stream alive even when the cursor
206
+ // outruns the small window, and we hold the window interactive for the whole
207
+ // drag (a mouseleave during a fast drag would otherwise flip it click-through
208
+ // mid-drag and drop the trail).
206
209
  let drag = null;
207
210
  img.addEventListener('pointerdown', (e) => {
208
211
  if (e.button !== 0) return;
212
+ try { img.setPointerCapture(e.pointerId); } catch (err) {}
209
213
  drag = { sx: e.screenX, sy: e.screenY, wx: window.screenX, wy: window.screenY };
210
214
  window.petBridge.setInteractive(true);
211
215
  e.preventDefault();
@@ -213,13 +217,19 @@
213
217
  window.addEventListener('pointermove', (e) => {
214
218
  if (drag) window.petBridge.move(drag.wx + (e.screenX - drag.sx), drag.wy + (e.screenY - drag.sy));
215
219
  });
216
- window.addEventListener('pointerup', () => {
220
+ const endDrag = () => {
221
+ if (!drag) return;
217
222
  drag = null;
218
- });
223
+ window.petBridge.setInteractive(true); // pointer is still over the pet when a drag ends
224
+ };
225
+ window.addEventListener('pointerup', endDrag);
226
+ window.addEventListener('pointercancel', endDrag);
219
227
 
220
- // hover -> interactive (so clicks work); leave -> click-through
228
+ // hover -> interactive (so clicks work); leave -> click-through (never mid-drag)
221
229
  root.addEventListener('mouseenter', () => window.petBridge.setInteractive(true));
222
- root.addEventListener('mouseleave', () => window.petBridge.setInteractive(false));
230
+ root.addEventListener('mouseleave', () => {
231
+ if (!drag) window.petBridge.setInteractive(false);
232
+ });
223
233
 
224
234
  // left-click (not a drag) -> open DSH in default browser
225
235
  img.addEventListener('click', () => window.petBridge.openSite(base));