pi-ele-picker 0.3.2 → 0.4.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/README.md CHANGED
@@ -94,6 +94,8 @@ The launcher starts in the **bottom-right** corner and stays out of the way:
94
94
  - **Draggable** — grab it and drop it anywhere; the position is remembered per browser (`localStorage`).
95
95
  - **Fades when idle** (opacity `0.5`) and returns to full opacity on hover.
96
96
  - **Shows the live pi session status** as a coloured dot **when enabled** — green while pi is running, amber while follow-ups are queued, grey while awaiting input, red when the bridge is gone (see [Session status](#session-status)).
97
+ - **Hovering the launcher reopens the panel** for the element you captured last — no need to pick it again, and the captured element is only replaced when you commit a new pick. Closing the panel with **✕** keeps it available this way.
98
+ - Clicking the launcher starts a **new pick**: the panel steps out of the way, and pressing **Esc** keeps the previously captured element intact.
97
99
  - The panel always opens **next to the launcher**, flipping sides and clamping to stay on screen.
98
100
  - **The panel is draggable too** — grab its title bar (or any empty spot) to move it; the offset from the launcher is remembered per browser (`localStorage`), and the panel still follows the launcher while clamping itself to stay on screen.
99
101
 
package/client/picker.js CHANGED
@@ -119,7 +119,7 @@
119
119
  triggerDot.className = 'dot st-off';
120
120
  trigger.appendChild(triggerDot);
121
121
  trigger.appendChild(document.createTextNode('Pi Picker'));
122
- trigger.title = '拖拽可移动 · 面板标题栏也可拖拽 · 点击开始选择元素';
122
+ trigger.title = '拖拽可移动 · 面板标题栏也可拖拽 · 悬浮可再次打开上次元素 · 点击开始选择元素';
123
123
  root.appendChild(trigger);
124
124
 
125
125
  var panel = document.createElement('div');
@@ -149,6 +149,8 @@
149
149
  var fileEl = panel.querySelector('.file');
150
150
 
151
151
  var picking = false;
152
+ // The captured element the panel acts on. Stays put across close/reopen so
153
+ // hovering the launcher can bring the panel back without overwriting it.
152
154
  var target = null;
153
155
  var shots = [];
154
156
  // Set when a pick commits on pointerdown; swallows the follow-up click so the
@@ -281,6 +283,7 @@
281
283
 
282
284
  trigger.addEventListener('pointerdown', function (e) {
283
285
  if (e.pointerType === 'mouse' && e.button !== 0) return;
286
+ clearHoverOpen();
284
287
  var r = trigger.getBoundingClientRect();
285
288
  drag = { id: e.pointerId, sx: e.clientX, sy: e.clientY, ox: r.left, oy: r.top, moved: false };
286
289
  try {
@@ -419,7 +422,8 @@
419
422
  function onMove(e) {
420
423
  var el = elFromEvent(e);
421
424
  if (!el) return;
422
- target = el;
425
+ // Highlight only: `target` is replaced solely by a committed pick, so Esc
426
+ // or pausing on another element never clobbers the panel's element.
423
427
  showHighlight(el);
424
428
  }
425
429
 
@@ -464,6 +468,12 @@
464
468
  hint.style.display = on ? 'block' : 'none';
465
469
  trigger.style.display = on ? 'none' : 'flex';
466
470
  if (on) {
471
+ // Picking means "choose another element": hide the panel so it never
472
+ // covers the page. It reopens when the new pick commits, and the previous
473
+ // element only gets replaced at that point.
474
+ clearHoverOpen();
475
+ panel.classList.remove('open');
476
+ hideHighlight();
467
477
  window.addEventListener('mousemove', onMove, true);
468
478
  window.addEventListener('pointerdown', onPointerDown, true);
469
479
  window.addEventListener('keydown', onKey, true);
@@ -475,12 +485,19 @@
475
485
  }
476
486
  }
477
487
 
488
+ /** Re-show the panel for the element already captured — no re-pick, no overwrite. */
489
+ function openPanel() {
490
+ if (!target) return false;
491
+ panel.classList.add('open');
492
+ showHighlight(target);
493
+ positionPanel();
494
+ return true;
495
+ }
496
+
478
497
  function select(el) {
479
498
  target = el;
480
- showHighlight(el);
481
499
  metaEl.innerHTML = '<code>' + escapeHtml(cssPath(el)) + '</code>' + vueLine(el);
482
- panel.classList.add('open');
483
- positionPanel();
500
+ openPanel();
484
501
  taEl.focus();
485
502
  }
486
503
 
@@ -722,6 +739,33 @@
722
739
  window.addEventListener('pointerdown', function () { swallowClick = false; }, true);
723
740
  window.addEventListener('click', onClick, true);
724
741
 
742
+ /* --- hover reopens the last captured element --- */
743
+ var HOVER_OPEN_DELAY = 200;
744
+ var hoverOpenTimer = null;
745
+
746
+ function clearHoverOpen() {
747
+ if (hoverOpenTimer) {
748
+ clearTimeout(hoverOpenTimer);
749
+ hoverOpenTimer = null;
750
+ }
751
+ }
752
+
753
+ trigger.addEventListener('pointerenter', function (e) {
754
+ // Mouse only: touch/pen enter is part of a tap, which must keep its click.
755
+ if (e.pointerType !== 'mouse') return;
756
+ if (picking || drag) return;
757
+ clearHoverOpen();
758
+ // A short dwell keeps a mouse merely passing over the launcher from popping
759
+ // the panel open, while still feeling immediate when you aim at it.
760
+ hoverOpenTimer = setTimeout(function () {
761
+ hoverOpenTimer = null;
762
+ if (picking || drag) return;
763
+ openPanel();
764
+ }, HOVER_OPEN_DELAY);
765
+ });
766
+
767
+ trigger.addEventListener('pointerleave', clearHoverOpen);
768
+
725
769
  trigger.addEventListener('click', function () {
726
770
  if (suppressClick) {
727
771
  suppressClick = false;
@@ -802,7 +846,7 @@
802
846
  if (info && info.sessionId) detail.push('会话 ' + String(info.sessionId).slice(0, 8));
803
847
  var line = STATUS_LABEL[st] + (detail.length ? ' · ' + detail.join(' · ') : '');
804
848
  sessionText.textContent = line;
805
- var title = line + ' · 拖拽可移动 · 面板标题栏也可拖拽 · 点击开始选择元素';
849
+ var title = line + ' · 拖拽可移动 · 面板标题栏也可拖拽 · 悬浮可再次打开上次元素 · 点击开始选择元素';
806
850
  if (title !== statusTitle) {
807
851
  trigger.title = title;
808
852
  statusTitle = title;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ele-picker",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "Pick an element in your running page, describe the change, and send it to a pi session. Ships a Vite dev plugin (browser picker + discovery endpoint) and the matching pi bridge extension.",
5
5
  "type": "module",
6
6
  "license": "MIT",