storyboard-bridge 0.9.39 → 0.9.41

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.
Files changed (2) hide show
  1. package/cdp_flow.py +43 -31
  2. package/package.json +1 -1
package/cdp_flow.py CHANGED
@@ -502,6 +502,12 @@ def main():
502
502
  step_press(page, val[0])
503
503
  elif kind == "wait":
504
504
  time.sleep(float(val[0]))
505
+ # Release mouse if it was held by a drag
506
+ page.input("Input.dispatchMouseEvent", {
507
+ "type": "mouseReleased",
508
+ "x": 0,
509
+ "y": 0,
510
+ })
505
511
  elif kind == "waitfor":
506
512
  step_waitfor(page, val[0], timeout)
507
513
  elif kind == "goto":
@@ -534,40 +540,46 @@ def main():
534
540
  step_vars[var] = ""
535
541
  elif kind == "drag":
536
542
  xpath, direction, steps_count, duration = val[0], val[1], int(val[2]), float(val[3])
537
- delta = 1000 if direction == "right" else -1000
538
- step_ms = int(duration * 1000 / steps_count)
539
- # Simulate drag using JavaScript—fires events synchronously
540
- page.eval(f"""
543
+ # Find handle position
544
+ box = page.eval(f"""
541
545
  (function() {{
542
- const handle = document.evaluate({json.dumps(xpath)}, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
543
- if (!handle) return;
544
- const rect = handle.getBoundingClientRect();
545
- const startX = rect.left + rect.width/2;
546
- const startY = rect.top + rect.height/2;
547
- const endX = startX + {delta};
548
-
549
- // Fire mousedown
550
- handle.dispatchEvent(new MouseEvent('mousedown', {{
551
- clientX: startX, clientY: startY, bubbles: true, cancelable: true
552
- }}));
553
-
554
- // Fire mousemove sequence synchronously
555
- const steps = {steps_count};
556
- for (let i = 0; i <= steps; i++) {{
557
- const x = startX + (endX - startX) * (i / steps);
558
- const el = document.elementFromPoint(x, startY) || handle;
559
- el.dispatchEvent(new MouseEvent('mousemove', {{
560
- clientX: x, clientY: startY, bubbles: true, cancelable: true
561
- }}));
562
- }}
563
-
564
- // Fire mouseup
565
- handle.dispatchEvent(new MouseEvent('mouseup', {{
566
- clientX: endX, clientY: startY, bubbles: true, cancelable: true
567
- }}));
546
+ const el = document.evaluate({json.dumps(xpath)}, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
547
+ if (!el) return null;
548
+ const rect = el.getBoundingClientRect();
549
+ return {{ x: rect.left + rect.width/2, y: rect.top + rect.height/2, width: rect.width }};
568
550
  }})()
569
551
  """)
570
- print(f" dragged {direction}")
552
+ if box:
553
+ start_x, start_y = int(box["x"]), int(box["y"])
554
+ end_x = start_x + (1000 if direction == "right" else -1000)
555
+ step_duration = duration / steps_count
556
+ # Press down to grab slider
557
+ page.input("Input.dispatchMouseEvent", {
558
+ "type": "mousePressed",
559
+ "x": start_x,
560
+ "y": start_y,
561
+ "button": "left",
562
+ "buttons": 1,
563
+ })
564
+ time.sleep(0.1)
565
+ # Move across with button held - many small steps
566
+ for step_i in range(steps_count):
567
+ x = start_x + (end_x - start_x) * (step_i / steps_count)
568
+ page.input("Input.dispatchMouseEvent", {
569
+ "type": "mouseMoved",
570
+ "x": int(x),
571
+ "y": start_y,
572
+ "buttons": 1,
573
+ })
574
+ time.sleep(step_duration)
575
+ # Hold position without releasing (let next step release it)
576
+ page.input("Input.dispatchMouseEvent", {
577
+ "type": "mouseMoved",
578
+ "x": end_x,
579
+ "y": start_y,
580
+ "buttons": 1,
581
+ })
582
+ print(f" dragged {direction}")
571
583
  time.sleep(delay)
572
584
  print("flow complete")
573
585
  if spawned_ctx and temp.get("dispose"):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "storyboard-bridge",
3
- "version": "0.9.39",
3
+ "version": "0.9.41",
4
4
  "description": "Desktop bridge that powers a hosted Storyboard AI webapp with your own local Claude Code / Gemini CLI login (no API key).",
5
5
  "type": "module",
6
6
  "bin": {