on-events 0.0.3 → 0.0.4
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 +94 -16
- package/dist/on-events.d.ts +78 -66
- package/dist/on-events.min.js +1 -1
- package/dist/on-events.min.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
# on-events
|
|
3
|
+
|
|
4
|
+
[](https://www.npmjs.com/package/on-events)
|
|
5
|
+
[](https://www.npmjs.com/package/on-events)
|
|
6
|
+
[](https://github.com/iWhatty/on-event-js)
|
|
7
|
+
[](https://github.com/iWhatty/on-event-js/blob/main/LICENSE)
|
|
8
|
+
|
|
9
|
+
**A tiny DOM event utility with composable sugar.**
|
|
10
|
+
|
|
11
|
+
|
|
1
12
|
# on-events
|
|
2
13
|
|
|
3
14
|
**A tiny DOM event utility with composable sugar.**
|
|
@@ -7,7 +18,7 @@ Write clean event bindings using fluent chains like `On.click(...)`, `On.capture
|
|
|
7
18
|
|
|
8
19
|
## ⚡ Example Usage
|
|
9
20
|
|
|
10
|
-
|
|
21
|
+
Compose `once`, `capture`, `passive`, and delegation without repetitive option objects.
|
|
11
22
|
|
|
12
23
|
```js
|
|
13
24
|
import { On } from 'on-events'
|
|
@@ -20,11 +31,11 @@ function handleLinkClick(e) {
|
|
|
20
31
|
On.first.delegate.capture.click(document, 'a.nav-link', handleLinkClick)
|
|
21
32
|
```
|
|
22
33
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
* Delegated
|
|
35
|
+
* Capture phase
|
|
36
|
+
* Fires once
|
|
37
|
+
* Clean `this` binding
|
|
38
|
+
* Returns `stop()` if you need manual control
|
|
28
39
|
|
|
29
40
|
---
|
|
30
41
|
|
|
@@ -36,10 +47,12 @@ On.first.delegate.capture.click(document, 'a.nav-link', handleLinkClick)
|
|
|
36
47
|
* `On.capture.passive.scroll(el, fn)` — fully composable modifiers
|
|
37
48
|
* `On.delegate.click(el, selector, fn)` — delegated events
|
|
38
49
|
* `On.hover(el, enter, leave)` — mouseenter/leave pair
|
|
39
|
-
* `On.batch(el, { click, ... })` —
|
|
50
|
+
* `On.batch(el, { click, ... })` — bind multiple events at once
|
|
40
51
|
* `On.first.batch(...)` — one-time multi-bind
|
|
41
52
|
* `On.ready(fn)` — run when DOM is ready
|
|
42
|
-
*
|
|
53
|
+
* `On.group()` — collect related listeners and tear them down together
|
|
54
|
+
* Better TS support for simple binds like `On.input(el, fn)` and `On.change(el, fn)`
|
|
55
|
+
* ESM, zero dependencies, tiny footprint
|
|
43
56
|
|
|
44
57
|
---
|
|
45
58
|
|
|
@@ -51,10 +64,6 @@ npm install on-events
|
|
|
51
64
|
|
|
52
65
|
---
|
|
53
66
|
|
|
54
|
-
## Usage
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
67
|
## Fluent & Composable Sugar
|
|
59
68
|
|
|
60
69
|
```js
|
|
@@ -150,7 +159,7 @@ On.first.batch(document, {
|
|
|
150
159
|
|
|
151
160
|
---
|
|
152
161
|
|
|
153
|
-
## Delegate Batch
|
|
162
|
+
## Delegate Batch
|
|
154
163
|
|
|
155
164
|
You may pass `[selector, handler]` for delegated batch entries:
|
|
156
165
|
|
|
@@ -178,9 +187,56 @@ On.ready(handleReady)
|
|
|
178
187
|
|
|
179
188
|
---
|
|
180
189
|
|
|
190
|
+
## Grouped Cleanup
|
|
191
|
+
|
|
192
|
+
When a UI module binds listeners across multiple elements, `On.group()` lets you track them under one scoped teardown handle.
|
|
193
|
+
|
|
194
|
+
```js
|
|
195
|
+
import { On } from 'on-events'
|
|
196
|
+
|
|
197
|
+
const page = On.group()
|
|
198
|
+
|
|
199
|
+
page.click(settingsToggleBtn, () => {
|
|
200
|
+
settingsSection.classList.toggle('collapsed')
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
page.input(searchInput, handleSearch)
|
|
204
|
+
page.delegate.click(document, 'button.save', handleSave)
|
|
205
|
+
|
|
206
|
+
// Later:
|
|
207
|
+
page.stop()
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
You can also manually add an existing cleanup function:
|
|
211
|
+
|
|
212
|
+
```js
|
|
213
|
+
const group = On.group()
|
|
214
|
+
|
|
215
|
+
group.add(On.click(button, handleClick))
|
|
216
|
+
group.add(null) // safely ignored
|
|
217
|
+
|
|
218
|
+
group.stop()
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Custom Events
|
|
224
|
+
|
|
225
|
+
For custom or non-standard event names, use `On.event(type)`:
|
|
226
|
+
|
|
227
|
+
```js
|
|
228
|
+
const stop = On.event('panel:open')(panel, (e) => {
|
|
229
|
+
console.log('opened', e.type)
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
stop()
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
181
237
|
# API Reference
|
|
182
238
|
|
|
183
|
-
|
|
239
|
+
## Composable Modifiers
|
|
184
240
|
|
|
185
241
|
Modifiers can be chained before the event name.
|
|
186
242
|
|
|
@@ -239,6 +295,23 @@ Runs `fn` once the DOM is fully loaded (`DOMContentLoaded` or already ready).
|
|
|
239
295
|
|
|
240
296
|
---
|
|
241
297
|
|
|
298
|
+
## `On.group()`
|
|
299
|
+
|
|
300
|
+
Creates a scoped cleanup collector for related listeners.
|
|
301
|
+
|
|
302
|
+
```js
|
|
303
|
+
const group = On.group()
|
|
304
|
+
|
|
305
|
+
group.click(button, onClick)
|
|
306
|
+
group.input(input, onInput)
|
|
307
|
+
|
|
308
|
+
group.stop()
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Useful when a page, modal, or UI module binds listeners across multiple elements and wants one teardown call.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
242
315
|
## Why not `addEventListener` directly?
|
|
243
316
|
|
|
244
317
|
`addEventListener` is great — this library just removes the repetitive parts when you bind lots of UI events.
|
|
@@ -247,6 +320,7 @@ Runs `fn` once the DOM is fully loaded (`DOMContentLoaded` or already ready).
|
|
|
247
320
|
* Every bind returns a `stop()` cleanup function
|
|
248
321
|
* Delegation helper that sets `this` to the matched element
|
|
249
322
|
* Batch binding to keep setup code tidy
|
|
323
|
+
* Grouped cleanup for lifecycle-based teardown
|
|
250
324
|
* Composable modifiers instead of option object juggling
|
|
251
325
|
* Zero deps and tiny footprint
|
|
252
326
|
|
|
@@ -260,7 +334,7 @@ This library is a thin wrapper around native `addEventListener`.
|
|
|
260
334
|
* **`first` / `capture` / `passive`**: uses native listener options.
|
|
261
335
|
* **Delegation (`On.delegate.*`)**: performs a `closest(selector)` lookup per event. Ideal for reducing listener count, but direct binding is better for extremely hot events like `mousemove`.
|
|
262
336
|
|
|
263
|
-
Rule of thumb: delegate `click
|
|
337
|
+
Rule of thumb: delegate `click`, `input`, and `submit`; bind directly for high-frequency events.
|
|
264
338
|
|
|
265
339
|
---
|
|
266
340
|
|
|
@@ -273,14 +347,18 @@ Rule of thumb: delegate `click/input/submit`, bind directly for high-frequency e
|
|
|
273
347
|
|
|
274
348
|
---
|
|
275
349
|
|
|
276
|
-
## Low-level API (on / off)
|
|
350
|
+
## Low-level API (`on` / `off`)
|
|
277
351
|
|
|
278
352
|
If you prefer a minimal, explicit API without fluent modifiers, you can use the core helpers directly.
|
|
279
353
|
|
|
280
354
|
### `on(el, event, handler)`
|
|
281
355
|
|
|
356
|
+
### `on(el, event, handler, options)`
|
|
357
|
+
|
|
282
358
|
### `on(el, event, selector, handler)`
|
|
283
359
|
|
|
360
|
+
### `on(el, event, selector, handler, options)`
|
|
361
|
+
|
|
284
362
|
Adds a standard or delegated event listener.
|
|
285
363
|
Returns a `stop()` function that removes the listener.
|
|
286
364
|
|
package/dist/on-events.d.ts
CHANGED
|
@@ -5,87 +5,99 @@ export type Stop = () => void
|
|
|
5
5
|
export type Handler<E extends Event = Event> = (this: Element, ev: E) => any
|
|
6
6
|
export type DirectHandler<E extends Event = Event> = (ev: E) => any
|
|
7
7
|
|
|
8
|
+
export type BatchMap = Record<
|
|
9
|
+
string,
|
|
10
|
+
| DirectHandler<any>
|
|
11
|
+
| [string, Handler<any>]
|
|
12
|
+
>
|
|
13
|
+
|
|
8
14
|
// --- Low-level API ---
|
|
9
15
|
|
|
10
16
|
export function on<E extends Event = Event>(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
el: EventTarget,
|
|
18
|
+
event: string,
|
|
19
|
+
handler: DirectHandler<E>,
|
|
20
|
+
options?: AddEventListenerOptions | boolean
|
|
14
21
|
): Stop
|
|
15
22
|
|
|
16
23
|
export function on<E extends Event = Event>(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
el: Element | Document,
|
|
25
|
+
event: string,
|
|
26
|
+
selector: string,
|
|
27
|
+
handler: Handler<E>,
|
|
28
|
+
options?: AddEventListenerOptions | boolean
|
|
21
29
|
): Stop
|
|
22
30
|
|
|
23
31
|
export function off<E extends Event = Event>(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
el: EventTarget,
|
|
33
|
+
event: string,
|
|
34
|
+
handler: DirectHandler<E>,
|
|
35
|
+
selector?: null
|
|
28
36
|
): void
|
|
29
37
|
|
|
30
38
|
export function off<E extends Event = Event>(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
el: Element | Document,
|
|
40
|
+
event: string,
|
|
41
|
+
handler: Handler<E>,
|
|
42
|
+
selector?: string
|
|
35
43
|
): void
|
|
36
44
|
|
|
37
|
-
// --- Fluent
|
|
45
|
+
// --- Fluent Event Binder ---
|
|
46
|
+
|
|
47
|
+
export interface EventBinder<E extends Event = Event> {
|
|
48
|
+
(el: EventTarget, handler: DirectHandler<E>): Stop
|
|
49
|
+
(el: Element | Document, selector: string, handler: Handler<E>): Stop
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// --- Fluent Chain API core ---
|
|
38
53
|
|
|
39
54
|
export interface OnChain {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
[
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
selector: string,
|
|
87
|
-
handler: Handler<E>
|
|
88
|
-
) => Stop)
|
|
55
|
+
first: OnChain
|
|
56
|
+
once: OnChain
|
|
57
|
+
capture: OnChain
|
|
58
|
+
passive: OnChain
|
|
59
|
+
delegate: OnChain
|
|
60
|
+
|
|
61
|
+
hover(
|
|
62
|
+
el: Element,
|
|
63
|
+
enter: (ev: MouseEvent) => any,
|
|
64
|
+
leave: (ev: MouseEvent) => any
|
|
65
|
+
): Stop
|
|
66
|
+
|
|
67
|
+
batch(
|
|
68
|
+
el: EventTarget,
|
|
69
|
+
map: BatchMap
|
|
70
|
+
): Stop
|
|
71
|
+
|
|
72
|
+
ready(fn: () => void): void
|
|
73
|
+
|
|
74
|
+
group(): OnGroup
|
|
75
|
+
|
|
76
|
+
<E extends Event = Event>(
|
|
77
|
+
el: EventTarget,
|
|
78
|
+
handler: DirectHandler<E>
|
|
79
|
+
): Stop
|
|
80
|
+
|
|
81
|
+
<E extends Event = Event>(
|
|
82
|
+
el: Element | Document,
|
|
83
|
+
selector: string,
|
|
84
|
+
handler: Handler<E>
|
|
85
|
+
): Stop
|
|
86
|
+
|
|
87
|
+
// fallback for custom / non-standard event names
|
|
88
|
+
event(type: string): OnChain & EventBinder<Event>
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type OnEventMap = {
|
|
92
|
+
[K in keyof GlobalEventHandlersEventMap]:
|
|
93
|
+
OnChain & EventBinder<GlobalEventHandlersEventMap[K]>
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export type OnAPI = OnChain & OnEventMap
|
|
97
|
+
|
|
98
|
+
export type OnGroup = OnAPI & {
|
|
99
|
+
stop(): void
|
|
100
|
+
add<T extends Stop | null | undefined | false>(stop: T): T
|
|
89
101
|
}
|
|
90
102
|
|
|
91
|
-
export const On:
|
|
103
|
+
export const On: OnAPI
|
package/dist/on-events.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// On-Events - A tiny DOM event utility with sugar.
|
|
2
|
-
var
|
|
2
|
+
var h=new WeakMap;function p(n,u,c,r,t){typeof c=="function"&&(t=r,r=c,c=null);let o=t||void 0,e=c?i=>{let f=i.target instanceof Element?i.target:i.target?.parentElement;if(!f)return;let d=f.closest(c);d&&typeof n.contains=="function"&&n.contains(d)&&r.call(d,i)}:r;return n.addEventListener(u,e,o),h.has(n)||h.set(n,[]),h.get(n).push({type:u,cb:r,selector:c,wrapped:e,capture:!!(o&&o.capture)}),()=>w(n,u,r,c)}function w(n,u,c,r=null){let t=h.get(n);if(t){for(let o=t.length;o-- >0;){let e=t[o];e.type===u&&e.cb===c&&(r?e.selector===r:!e.selector)&&(n.removeEventListener(u,e.wrapped,{capture:e.capture}),t.splice(o,1))}t.length||h.delete(n)}}var m=1,v=2,y=4,l=8,E=n=>{if(!(n&(m|v|y)))return;let u={};return n&m&&(u.once=!0),n&v&&(u.capture=!0),n&y&&(u.passive=!0),u},a=(n=0)=>new Proxy(Object.create(null),{get(u,c){if(Reflect.has(u,c))return Reflect.get(u,c);let r=String(c);return r==="first"||r==="once"?a(n|m):r==="capture"?a(n|v):r==="passive"?a(n|y):r==="delegate"?a(n|l):r==="event"?t=>a(n)[t]:r==="hover"?(t,o,e)=>{let s=E(n),i=p(t,"mouseenter",o,s),f=p(t,"mouseleave",e,s);return()=>{i(),f()}}:r==="batch"?(t,o)=>{let e=[];for(let[s,i]of Object.entries(o)){if(typeof i=="function"){e.push(a(n)[s](t,i));continue}if(Array.isArray(i)){let[f,d]=i;e.push(a(n|l)[s](t,f,d))}}return()=>{for(let s of e)s()}}:r==="ready"?t=>{typeof document>"u"||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",t,{once:!0}):t())}:(t,...o)=>{let e=E(n);if(n&l){let[i,f]=o;return p(t,r,i,f,e)}let[s]=o;return p(t,r,s,e)}}}),g=a();g.group=function(){let u=new Set,c=t=>(typeof t=="function"&&u.add(t),t),r=()=>{let t=[];for(let o of u)try{o()}catch(e){t.push(e)}if(u.clear(),t.length===1)throw t[0];if(t.length>1)throw new AggregateError(t,"On.group().stop() failed for one or more listeners")};return new Proxy(Object.create(null),{get(t,o){if(o==="add")return c;if(o==="stop")return r;let e=g[o];return e==null?e:o==="event"?s=>{let i=e(s);return(...f)=>c(i(...f))}:typeof e=="function"?(...s)=>c(e(...s)):new Proxy(e,{get(s,i){let f=e[i];return typeof f=="function"?(...d)=>c(f(...d)):f}})}})};g.once=g.first;var O=(n,u,...c)=>p(n,u,...c);export{g as On,w as off,O as on};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/on-events.js"],
|
|
4
|
-
"sourcesContent": ["// on-events.js\r\n// On-Events \u2014 tiny DOM event utility with composable sugar.\r\n\r\n// --- internal base ---\r\nconst listeners = new WeakMap()\r\n\r\n/**\r\n * baseOn(el, type, handler)\r\n * baseOn(el, type, selector, handler)\r\n * baseOn(el, type, handler, options)\r\n * baseOn(el, type, selector, handler, options)\r\n */\r\nfunction baseOn(el, type, selector, cb, options) {\r\n //
|
|
5
|
-
"mappings": ";AAIA,IAAMA,EAAY,IAAI,QAQtB,SAASC,EAAOC,EAAIC,EAAMC,EAAUC,EAAIC,EAAS,CAE3C,OAAOF,GAAa,aACtBE,EAAUD,EACVA,EAAKD,EACLA,EAAW,MAGb,IAAMG,EAAOD,GAAW,OAElBE,EAAUJ,EACXK,GAAM,
|
|
6
|
-
"names": ["listeners", "baseOn", "el", "type", "selector", "cb", "options", "opts", "wrapped", "e", "target", "match", "off", "group", "i", "h", "ONCE", "CAPTURE", "PASSIVE", "DELEGATE", "optsFor", "f", "o", "makeOn", "flags", "
|
|
4
|
+
"sourcesContent": ["// on-events.js\r\n// On-Events \u2014 tiny DOM event utility with composable sugar.\r\n\r\n// --- internal base ---\r\nconst listeners = new WeakMap()\r\n\r\n/**\r\n * baseOn(el, type, handler)\r\n * baseOn(el, type, selector, handler)\r\n * baseOn(el, type, handler, options)\r\n * baseOn(el, type, selector, handler, options)\r\n */\r\nfunction baseOn(el, type, selector, cb, options) {\r\n // Normalize overloaded signatures so everything below can use one path.\r\n if (typeof selector === 'function') {\r\n options = cb\r\n cb = selector\r\n selector = null\r\n }\r\n\r\n const opts = options || undefined\r\n\r\n const wrapped = selector\r\n ? (e) => {\r\n // Delegation can receive a Text node as the event target.\r\n // Normalize that to an element before calling closest().\r\n const target = e.target instanceof Element ? e.target : e.target?.parentElement\r\n if (!target) return\r\n\r\n const match = target.closest(selector)\r\n if (!match) return\r\n\r\n // Guard delegated matching so odd targets like window do not explode.\r\n if (typeof el.contains === 'function' && el.contains(match)) {\r\n cb.call(match, e)\r\n }\r\n }\r\n : cb\r\n\r\n el.addEventListener(type, wrapped, opts)\r\n\r\n if (!listeners.has(el)) listeners.set(el, [])\r\n const group = listeners.get(el)\r\n\r\n group.push({\r\n type,\r\n cb,\r\n selector,\r\n wrapped,\r\n capture: !!(opts && opts.capture), // capture must match during removal\r\n })\r\n\r\n return () => off(el, type, cb, selector)\r\n}\r\n\r\nfunction off(el, type, cb, selector = null) {\r\n const group = listeners.get(el)\r\n if (!group) return\r\n\r\n for (let i = group.length; i-- > 0;) {\r\n const h = group[i]\r\n const match =\r\n h.type === type &&\r\n h.cb === cb &&\r\n (selector ? h.selector === selector : !h.selector)\r\n\r\n if (match) {\r\n // removeEventListener only cares about capture on teardown.\r\n el.removeEventListener(type, h.wrapped, { capture: h.capture })\r\n group.splice(i, 1)\r\n }\r\n }\r\n\r\n if (!group.length) listeners.delete(el)\r\n}\r\n\r\n// --- composable sugar: On.<mods>.<event>(...) ---\r\n// Bitflags keep the proxy small and cheap.\r\nconst ONCE = 1\r\nconst CAPTURE = 2\r\nconst PASSIVE = 4\r\nconst DELEGATE = 8\r\n\r\nconst optsFor = (f) => {\r\n // Allocate listener options only when needed.\r\n // Capture is stored separately so removeEventListener can match it later.\r\n if (!(f & (ONCE | CAPTURE | PASSIVE))) return undefined\r\n\r\n const o = {}\r\n if (f & ONCE) o.once = true\r\n if (f & CAPTURE) o.capture = true\r\n if (f & PASSIVE) o.passive = true\r\n return o\r\n}\r\n\r\nconst makeOn = (flags = 0) =>\r\n new Proxy(Object.create(null), {\r\n get(target, prop) {\r\n // Respect concrete properties assigned directly onto the proxy target.\r\n // This is what makes late-added members like On.group work instead of\r\n // being mistaken for an event name.\r\n if (Reflect.has(target, prop)) {\r\n return Reflect.get(target, prop)\r\n }\r\n\r\n const k = String(prop)\r\n\r\n // Modifier chaining accumulates flags and returns a fresh proxy.\r\n if (k === 'first' || k === 'once') return makeOn(flags | ONCE)\r\n if (k === 'capture') return makeOn(flags | CAPTURE)\r\n if (k === 'passive') return makeOn(flags | PASSIVE)\r\n if (k === 'delegate') return makeOn(flags | DELEGATE)\r\n\r\n // Custom event helper: On.event('panel:open')(el, fn)\r\n if (k === 'event') {\r\n return (type) => makeOn(flags)[type]\r\n }\r\n\r\n // Utilities live on the same fluent surface for ergonomics.\r\n if (k === 'hover') {\r\n return (el, enter, leave) => {\r\n const o = optsFor(flags)\r\n const offIn = baseOn(el, 'mouseenter', enter, o)\r\n const offOut = baseOn(el, 'mouseleave', leave, o)\r\n return () => {\r\n offIn()\r\n offOut()\r\n }\r\n }\r\n }\r\n\r\n if (k === 'batch') {\r\n return (el, map) => {\r\n const stops = []\r\n\r\n for (const [event, val] of Object.entries(map)) {\r\n // Direct entry: { click: fn }\r\n if (typeof val === 'function') {\r\n stops.push(makeOn(flags)[event](el, val))\r\n continue\r\n }\r\n\r\n // Delegated entry: { click: ['a', fn] }\r\n if (Array.isArray(val)) {\r\n const [selector, fn] = val\r\n stops.push(makeOn(flags | DELEGATE)[event](el, selector, fn))\r\n }\r\n }\r\n\r\n return () => {\r\n for (const stop of stops) stop()\r\n }\r\n }\r\n }\r\n\r\n if (k === 'ready') {\r\n return (fn) => {\r\n if (typeof document === 'undefined') return\r\n\r\n // Run immediately if the DOM is already ready.\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', fn, { once: true })\r\n } else {\r\n fn()\r\n }\r\n }\r\n }\r\n\r\n // Default path: treat the property name as the event type.\r\n return (el, ...args) => {\r\n const o = optsFor(flags)\r\n\r\n if (flags & DELEGATE) {\r\n const [selector, handler] = args\r\n return baseOn(el, k, selector, handler, o)\r\n }\r\n\r\n const [handler] = args\r\n return baseOn(el, k, handler, o)\r\n }\r\n },\r\n })\r\n\r\nconst On = makeOn()\r\n\r\n// Creates a scoped listener collector.\r\n// Any stop() returned by On.* calls is tracked and can be removed together via group.stop().\r\nOn.group = function group() {\r\n const stops = new Set()\r\n\r\n const track = (stop) => {\r\n // Pass through nullish / false values so callers can safely write:\r\n // group.add(maybeElement ? On.click(...) : null)\r\n if (typeof stop === 'function') stops.add(stop)\r\n return stop\r\n }\r\n\r\n const stopAll = () => {\r\n const errors = []\r\n\r\n // Try every tracked cleanup so one bad stop() does not block the rest.\r\n for (const stop of stops) {\r\n try {\r\n stop()\r\n } catch (err) {\r\n errors.push(err)\r\n }\r\n }\r\n\r\n stops.clear()\r\n\r\n if (errors.length === 1) throw errors[0]\r\n if (errors.length > 1) {\r\n throw new AggregateError(errors, 'On.group().stop() failed for one or more listeners')\r\n }\r\n }\r\n\r\n return new Proxy(Object.create(null), {\r\n get(_target, prop) {\r\n // Hard override these names so they never fall through into event binding.\r\n if (prop === 'add') return track\r\n if (prop === 'stop') return stopAll\r\n\r\n const value = On[prop]\r\n if (value == null) return value\r\n\r\n // event(type) is a factory: it returns a binder, not a stop handle.\r\n // Wrap the binder so the eventual stop() is what gets tracked.\r\n if (prop === 'event') {\r\n return (type) => {\r\n const binder = value(type)\r\n return (...args) => track(binder(...args))\r\n }\r\n }\r\n\r\n // Top-level callables like group.click(...), group.batch(...), group.ready(...)\r\n // are wrapped so any returned stop() is automatically tracked.\r\n if (typeof value === 'function') {\r\n return (...args) => track(value(...args))\r\n }\r\n\r\n // Nested chain objects like group.capture or group.delegate are proxies too.\r\n // Wrap their callable leaves so group.capture.click(...) also tracks cleanup.\r\n return new Proxy(value, {\r\n get(_nestedTarget, nestedProp) {\r\n const nestedValue = value[nestedProp]\r\n\r\n if (typeof nestedValue === 'function') {\r\n return (...args) => track(nestedValue(...args))\r\n }\r\n\r\n return nestedValue\r\n },\r\n })\r\n },\r\n })\r\n}\r\n\r\n// --- legacy alias for backward compatibility ---\r\nOn.once = On.first\r\n\r\n// --- classic support ---\r\nconst on = (el, event, ...args) => baseOn(el, event, ...args)\r\n\r\nexport { on, On, off }\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["listeners", "baseOn", "el", "type", "selector", "cb", "options", "opts", "wrapped", "e", "target", "match", "off", "group", "i", "h", "ONCE", "CAPTURE", "PASSIVE", "DELEGATE", "optsFor", "f", "o", "makeOn", "flags", "prop", "k", "enter", "leave", "offIn", "offOut", "map", "stops", "event", "val", "fn", "stop", "args", "handler", "On", "track", "stopAll", "errors", "err", "_target", "value", "binder", "_nestedTarget", "nestedProp", "nestedValue", "on"]
|
|
7
7
|
}
|