Skip to content

Commit 5c8ae3f

Browse files
committed
feat: add hover functionality and update styles
- Introduced a new hover area in index.html with interactive hover effects. - Updated styles for hover and gesture areas for better visual feedback. - Implemented hover event handling in hover.ts, supporting enter, move, and leave events. - Removed unused event testing section from index.html.
1 parent 25b9ef7 commit 5c8ae3f

File tree

18 files changed

+288
-58
lines changed

18 files changed

+288
-58
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
same "printed page" as the copyright notice for easier
187187
identification within third-party archives.
188188

189-
Copyright 2025 MAIYUN.NET LiteRT.ORG
189+
Copyright 2026 MAIYUN.NET LiteRT.ORG
190190

191191
Licensed under the Apache License, Version 2.0 (the "License");
192192
you may not use this file except in compliance with the License.

README.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@
1515
</a>
1616
</p>
1717

18-
A lightweight pointer event library for handling mouse, touch, and pen interactions in browsers. Provides unified APIs for down, move, click, long, drag, resize and more.
18+
A lightweight pointer event library for handling mouse, touch, and pen interactions in browsers. Provides unified APIs for down, move, click, long, hover, drag, resize and more.
1919

2020
## Features
2121

2222
- 🖱️ Unified pointer event handling (mouse, touch, pen)
2323
- 📱 Mobile-friendly with touch support
2424
- 🎯 Click, double-click, and long-press detection
25+
- 👆 Hover detection with enter/move/leave callbacks
2526
- 🔄 Drag and drop with customizable constraints
2627
- 📐 Resize functionality with border detection
2728
- 🎨 Global cursor management
@@ -131,6 +132,28 @@ element.addEventListener('pointerdown', (e) => {
131132
});
132133
```
133134

135+
#### `hover(e, options)`
136+
137+
Hover event, handles enter, move, and leave for mouse and touch.
138+
139+
```typescript
140+
const cb = (e) => {
141+
pointer.hover(e, {
142+
enter: (e) => {
143+
console.log('Pointer entered');
144+
},
145+
move: (e) => {
146+
console.log('Pointer moving at:', e.clientX, e.clientY);
147+
},
148+
leave: (e) => {
149+
console.log('Pointer left');
150+
}
151+
});
152+
};
153+
element.addEventListener('pointerdown', cb);
154+
element.addEventListener('pointerenter', cb);
155+
```
156+
134157
#### `move(e, options)`
135158

136159
Drag event, supports boundary detection and constraints.
@@ -348,6 +371,18 @@ interface IDownOptions {
348371
}
349372
```
350373

374+
### `IHoverOptions`
375+
376+
Options for the hover function.
377+
378+
```typescript
379+
interface IHoverOptions {
380+
enter?: (e: PointerEvent) => void;
381+
move?: (e: PointerEvent) => void;
382+
leave?: (e: PointerEvent) => void;
383+
}
384+
```
385+
351386
### `IMoveDetail`
352387

353388
Detailed information in the move callback.

dist/index.esm.js

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,51 @@ function set(type) {
4040
}
4141
}
4242

43+
function hover(oe, opt) {
44+
const el = oe.currentTarget;
45+
if (!el) {
46+
return;
47+
}
48+
if (oe.pointerType === 'touch') {
49+
if (el.dataset.pointerHover) {
50+
return;
51+
}
52+
el.dataset.pointerHover = '1';
53+
opt.enter?.(oe);
54+
const move = function (e) {
55+
opt.move?.(e);
56+
};
57+
const leave = function (e) {
58+
opt.leave?.(e);
59+
delete el.dataset.pointerHover;
60+
el.removeEventListener('pointerleave', leave);
61+
window.removeEventListener('pointermove', move);
62+
window.removeEventListener('pointerup', leave);
63+
window.removeEventListener('pointercancel', leave);
64+
};
65+
el.addEventListener('pointerleave', leave);
66+
window.addEventListener('pointermove', move);
67+
window.addEventListener('pointerup', leave);
68+
window.addEventListener('pointercancel', leave);
69+
}
70+
else {
71+
if (oe.type === 'pointerdown') {
72+
return;
73+
}
74+
opt.enter?.(oe);
75+
const move = function (e) {
76+
opt.move?.(e);
77+
};
78+
const leave = function (e) {
79+
opt.leave?.(e);
80+
window.removeEventListener('pointermove', move);
81+
el.removeEventListener('pointerleave', leave);
82+
};
83+
window.addEventListener('pointermove', move);
84+
el.addEventListener('pointerleave', leave);
85+
}
86+
}
87+
4388
function down(oe, opt) {
4489
const target = oe.target;
4590
let { 'x': ox, 'y': oy } = getEventPos(oe);
@@ -753,4 +798,4 @@ function gesture(oe, before, handler) {
753798
}
754799
}
755800

756-
export { addHook as addMoveHook, allowEvent, click, dblClick, down, drag, gesture, getData as getDragData, getEventPos, getMoveDir, isMoving, isTouch, long, move, removeHook as removeMoveHook, resize, scale, set as setCursor, setData as setDragData };
801+
export { addHook as addMoveHook, allowEvent, click, dblClick, down, drag, gesture, getData as getDragData, getEventPos, getMoveDir, hover, isMoving, isTouch, long, move, removeHook as removeMoveHook, resize, scale, set as setCursor, setData as setDragData };

dist/index.umd.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,51 @@
4646
}
4747
}
4848

49+
function hover(oe, opt) {
50+
const el = oe.currentTarget;
51+
if (!el) {
52+
return;
53+
}
54+
if (oe.pointerType === 'touch') {
55+
if (el.dataset.pointerHover) {
56+
return;
57+
}
58+
el.dataset.pointerHover = '1';
59+
opt.enter?.(oe);
60+
const move = function (e) {
61+
opt.move?.(e);
62+
};
63+
const leave = function (e) {
64+
opt.leave?.(e);
65+
delete el.dataset.pointerHover;
66+
el.removeEventListener('pointerleave', leave);
67+
window.removeEventListener('pointermove', move);
68+
window.removeEventListener('pointerup', leave);
69+
window.removeEventListener('pointercancel', leave);
70+
};
71+
el.addEventListener('pointerleave', leave);
72+
window.addEventListener('pointermove', move);
73+
window.addEventListener('pointerup', leave);
74+
window.addEventListener('pointercancel', leave);
75+
}
76+
else {
77+
if (oe.type === 'pointerdown') {
78+
return;
79+
}
80+
opt.enter?.(oe);
81+
const move = function (e) {
82+
opt.move?.(e);
83+
};
84+
const leave = function (e) {
85+
opt.leave?.(e);
86+
window.removeEventListener('pointermove', move);
87+
el.removeEventListener('pointerleave', leave);
88+
};
89+
window.addEventListener('pointermove', move);
90+
el.addEventListener('pointerleave', leave);
91+
}
92+
}
93+
4994
function down(oe, opt) {
5095
const target = oe.target;
5196
let { 'x': ox, 'y': oy } = getEventPos(oe);
@@ -769,6 +814,7 @@
769814
exports.getDragData = getData;
770815
exports.getEventPos = getEventPos;
771816
exports.getMoveDir = getMoveDir;
817+
exports.hover = hover;
772818
exports.isTouch = isTouch;
773819
exports.long = long;
774820
exports.move = move;

dist/index.umd.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/test/index.html

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -264,41 +264,52 @@
264264
font-size: 12px;
265265
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
266266
}
267-
.gesture-area {
268-
background: #f1f5f9;
267+
.hover-area {
268+
background: #3b82f6;
269269
border-radius: 8px;
270270
height: 100%;
271271
display: flex;
272272
flex-direction: column;
273273
align-items: center;
274274
justify-content: center;
275-
color: #64748b;
275+
color: #fff;
276276
font-weight: 600;
277+
cursor: pointer;
278+
transition: background .2s;
277279
touch-action: none;
278-
cursor: grab;
279280
}
280-
.gesture-area .direction {
281-
font-size: 32px;
281+
.hover-area:hover {
282+
background: #2563eb;
283+
}
284+
.hover-area .status {
285+
font-size: 24px;
282286
margin-bottom: 10px;
283287
}
284-
.gesture-area .hint {
288+
.hover-area .hint {
285289
font-size: 12px;
286-
color: #94a3b8;
290+
opacity: 0.9;
287291
}
288-
.event-test-element {
289-
width: 100px;
290-
height: 100px;
291-
background: #ec4899;
292+
.gesture-area {
293+
background: #f1f5f9;
292294
border-radius: 8px;
295+
height: 100%;
293296
display: flex;
297+
flex-direction: column;
294298
align-items: center;
295299
justify-content: center;
296-
color: #fff;
300+
color: #64748b;
297301
font-weight: 600;
298-
font-size: 12px;
299-
box-shadow: 0 4px 12px rgba(236, 72, 153, 0.3);
300302
touch-action: none;
303+
cursor: grab;
304+
}
305+
.gesture-area .direction {
306+
font-size: 32px;
307+
margin-bottom: 10px;
301308
}
309+
.gesture-area .hint {
310+
font-size: 12px;
311+
color: #94a3b8;
312+
}
302313
</style>
303314
</head>
304315
<body>
@@ -415,6 +426,19 @@ <h2>scale - Zoom</h2>
415426
<div class="log" id="scale-log">Scroll wheel to zoom, drag to pan</div>
416427
</div>
417428

429+
<!-- hover 演示 -->
430+
<div class="demo-card">
431+
<h2>hover - Hover</h2>
432+
<div class="demo-area">
433+
<div class="hover-area" id="hover-area">
434+
<div class="status" id="hover-status">👆 Hover</div>
435+
<div>Hover or touch</div>
436+
<div class="hint">Pointer enter/leave</div>
437+
</div>
438+
</div>
439+
<div class="log" id="hover-log">Move pointer over the area</div>
440+
</div>
441+
418442
<!-- gesture 演示 -->
419443
<div class="demo-card">
420444
<h2>gesture - Swipe</h2>
@@ -427,17 +451,7 @@ <h2>gesture - Swipe</h2>
427451
</div>
428452
<div class="log" id="gesture-log">Swipe up/down/left/right</div>
429453
</div>
430-
431-
<!-- event 测试 -->
432-
<div class="demo-card">
433-
<h2>Event Testing</h2>
434-
<div class="demo-area" id="event-area">
435-
<div class="event-test-element" id="event-element">
436-
Test Element
437-
</div>
438-
</div>
439-
<div class="log" id="event-log">Event log will appear here</div>
440-
</div>
454+
441455
</div>
442456
</div>
443457

@@ -647,6 +661,31 @@ <h2>Event Testing</h2>
647661
scaleArea.addEventListener('pointerdown', handleScale);
648662
scaleArea.addEventListener('wheel', handleScale);
649663

664+
// --- hover 演示 ---
665+
const hoverArea = document.getElementById('hover-area');
666+
const hoverStatus = document.getElementById('hover-status');
667+
const hoverLog = document.getElementById('hover-log');
668+
669+
function handleHover(e) {
670+
pointer.hover(e, {
671+
'enter': function(e) {
672+
hoverStatus.textContent = '✅ Entered';
673+
hoverArea.style.background = '#10b981';
674+
hoverLog.textContent = 'Pointer entered at (' + Math.round(e.clientX) + ', ' + Math.round(e.clientY) + ')';
675+
},
676+
'move': function(e) {
677+
hoverLog.textContent = 'Moving at (' + Math.round(e.clientX) + ', ' + Math.round(e.clientY) + ')';
678+
},
679+
'leave': function(e) {
680+
hoverStatus.textContent = '👆 Hover';
681+
hoverArea.style.background = '#3b82f6';
682+
hoverLog.textContent = 'Pointer left';
683+
}
684+
});
685+
}
686+
hoverArea.addEventListener('pointerdown', handleHover);
687+
hoverArea.addEventListener('pointerenter', handleHover);
688+
650689
// --- gesture 演示 ---
651690
const gestureArea = document.getElementById('gesture-area');
652691
const gestureDir = document.getElementById('gesture-dir');
@@ -676,23 +715,7 @@ <h2>Event Testing</h2>
676715
gestureArea.addEventListener('pointerdown', handleGesture);
677716
gestureArea.addEventListener('wheel', handleGesture);
678717

679-
// --- event 测试 ---
680-
const eventElement = document.getElementById('event-element');
681-
const eventLog = document.getElementById('event-log');
682-
683-
const events = [
684-
'mousedown', 'mouseup', 'click', 'dblclick', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave', 'contextmenu', 'wheel',
685-
'touchstart', 'touchend', 'touchmove', 'touchcancel',
686-
'pointerdown', 'pointerup', 'pointermove', 'pointercancel', 'pointerenter', 'pointerleave', 'pointerover', 'pointerout', 'gotpointercapture', 'lostpointercapture'
687-
];
688-
689-
function logEvent(e) {
690-
eventLog.innerHTML = e.type + '<br>' + eventLog.innerHTML;
691-
}
692-
693-
events.forEach(function(eventType) {
694-
eventElement.addEventListener(eventType, logEvent);
695-
});
718+
696719
</script>
697720
</body>
698721
</html>

src/click.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024-2025 MAIYUYN.NET
2+
* Copyright 2007-2026 MAIYUYN.NET
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

src/cursor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024-2025 MAIYUYN.NET
2+
* Copyright 2007-2026 MAIYUYN.NET
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

src/down.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024-2025 MAIYUYN.NET
2+
* Copyright 2007-2026 MAIYUYN.NET
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

src/drag.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024-2025 MAIYUYN.NET
2+
* Copyright 2007-2026 MAIYUYN.NET
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)