listenable-element
Declarative event and lifecycle listening for Neutron elements —
filter, debounce, vibrate, and hand off to your actionHandler.
Features
- Event / lifecycle hooks Listen for DOM events or
connected/disconnected/adopted - Host retarget
host-ref="window"/document/ any selector — Escape to dismiss, shortcuts outside the bubble path - Target filters Selector, keycode (
shift+kchords), and pathname gates - Debounce / delay Coalesce noisy input
- Event hygiene
prevent-default/stop-propagation/stop-immediate-propagation - Haptic pulse Optional
vibrate-mson handle
Installation
This package is available in the
<script src="https://unpkg.com/@excom/kit-utils@0.3.0/dist/index.umd.min.js"></script>
<script src="https://unpkg.com/@excom/neutron@0.2.0/dist/index.umd.min.js"></script>
<script src="https://unpkg.com/@excom/listenable-element@0.2.2/dist/index.umd.min.js"></script>npm install @excom/listenable-elementimport { /* … */ } from "@excom/listenable-element";Peer dependencies (0)
Packages a consumer must install alongside this one. Workspace deps are bundled.
| Package | Version |
|---|---|
|
Usage
Compose ListenableElement and implement actionHandler. Concrete
consumers include <spa-a> and <event-handler>.
import { Neutron } from "@excom/neutron";
import { ListenableElement } from "@excom/listenable-element";
export const TapLog = Neutron.compose([
ListenableElement,
Neutron({ tag: "tap-log" }),
])
.defineMethods({
actionHandler: (_el, e) => {
console.log("handled", e.type);
},
});
TapLog.define();import { Neutron } from "@excom/neutron";
import { ListenableElement } from "@excom/listenable-element";
export const TapLog = Neutron.compose([
ListenableElement,
Neutron({ tag: "tap-log" }),
])
.defineMethods({
actionHandler: (_el, e) => {
console.log("handled", e.type);
},
});
TapLog.define();<tap-log listen-for="click keydown" keycode-filter="enter">
Tap or Enter
</tap-log><tap-log listen-for="click keydown" keycode-filter="enter">
Tap or Enter
</tap-log>host-ref moves listening off :scope — e.g. host-ref="window" for
global keydown. See <event-handler> for Escape-to-dismiss examples.
API Reference
Attributes
Role —option is configurable, state
is managed by the element (read-only), or hybrid which is both.
Provision
Thisprovision property lives on the DOM node.
Read / watch it with Quark’s prop("provision"), or listen
for the neutron-provision event from app JS.
Events
Type
command event (HTML Command API): from a
<button command commandfor>, an <event-handler
command-name>, or a CommandEvent.
Recognized Elements
Child or descendant elements are recognized by and relevant to its functionality.Styles
@custom-selector synonyms so custom elements can share
semantic styles. Element aliases match the host tag / .tag-* class; state
aliases match attributes (nested under the element alias).
Attributes (13)
Role —option is configurable, state
is managed by the element (read-only), or hybrid which is both.
delay-ms
delayMs
number
nullhost-ref
window / document — e.g. Escape to dismiss a dialog from a global keydown. Defaults to :scope. Used with listen-for. Not compatible with listen-for-lifecycle. The selector MUST resolve when host-ref is set — it will not wait for a match to appear.
hostRef
string
<CSS Selector> | "window" | "document" | "html" | "body" | "head"nullis-debounced
delay-ms, coalesce bursts into one trailing call (debounce).
isDebounced
boolean
falsekeycode-filter
+ (AND, any order): shift+k tab → Shift+K or Tab. Modifiers: shift, alt, ctrl/control, meta/cmd. Name the space bar space / spacebar and the plus key plus (shift+space). Case-insensitive.
keycodeFilter
tokenlist
<key | mod+key>…nulllisten-for
click when unset (and no lifecycle list is set).
listenFor
tokenlist
<EventName>…nulllisten-for-lifecycle
listenForLifecycle
tokenlist
"connected" | "disconnected" | "adopted"nulllisten-once
listenOnce
boolean
falsepathname-filter
location.pathname is one of these values — route-aware behaviors without a separate router element.
pathnameFilter
tokenlist
<pathname>…nullprevent-default
preventDefault() on matched events (ignored for lifecycles).
preventDefault
boolean
falseselector-filter
event.target matches this CSS selector. Does not support :scope in the selector.
selectorFilter
string
<CSS Selector>nullstop-immediate-propagation
stopImmediatePropagation() on matched events (ignored for lifecycles).
stopImmediatePropagation
boolean
falsestop-propagation
stopPropagation() on matched events (ignored for lifecycles).
stopPropagation
boolean
falsevibrate-ms
navigator.vibrate). Empty / 0 uses a 20ms pulse.
vibrateMs
number
"20 (when attribute is present with no value)"Provision (0)
Thisprovision property lives on the DOM node.
Read / watch it with Quark’s prop("provision"), or listen
for the neutron-provision event from app JS.
Events (0)
e.preventDefault() is not
synchronously called on the event.
Type
command event (HTML Command API): from a
<button command commandfor>, an <event-handler
command-name>, or a CommandEvent.
Recognized Elements (0)
Child or descendant elements are recognized by and relevant to its functionality.Styles (0)
all: revert-layer.
Valence.css ships this as .unstyled and .unstyled-all for the entire tree.
@custom-selector synonyms so custom elements can share
semantic styles. Element aliases match the host tag / .tag-* class; state
aliases match attributes (nested under the element alias).
Release notes (2)
0.2.0
- Add the key names
space/spacebarandplustokeycode-filter(shift+space), andcmdas an alias ofmeta - Update a
keycode-filterholding only spaces to match no key and warn once (it was no filter); writespacefor the space bar
0.1.1
- Ship only dist (and declared extras) in the npm tarball; drop build logs, tests and sources
Release notes
e.preventDefault() is not
synchronously called on the event.
all: revert-layer.
Valence.css ships this as .unstyled and .unstyled-all for the entire tree.
Examples
Default click → navigate
<spa-a> inherits this base and defaults to click when listen-for
is unset:
<spa-a route-href="/pricing">Pricing</spa-a><spa-a route-href="/pricing">Pricing</spa-a>Filter & debounce
<event-handler
listen-for="input"
delay-ms="200"
is-debounced
fire-event="search-query"
>
<input name="q" />
</event-handler><event-handler
listen-for="input"
delay-ms="200"
is-debounced
fire-event="search-query"
>
<input name="q" />
</event-handler>See <event-handler> and <spa-a> package docs for more examples
built on this mixin.