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 +2 -0
- package/client/picker.js +50 -6
- package/package.json +1 -1
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
|
|
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
|
-
|
|
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
|
+
"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",
|