@excom/event-handler 0.1.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/.rush/temp/chunked-rush-logs/event-handler.apply-exports.chunks.jsonl +1 -0
- package/.rush/temp/chunked-rush-logs/event-handler.build_docs.chunks.jsonl +1 -0
- package/.rush/temp/chunked-rush-logs/event-handler.build_package-metas.chunks.jsonl +1 -0
- package/.rush/temp/operation/apply-exports/all.log +1 -0
- package/.rush/temp/operation/apply-exports/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/apply-exports/state.json +3 -0
- package/.rush/temp/operation/build_docs/all.log +1 -0
- package/.rush/temp/operation/build_docs/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/build_docs/state.json +3 -0
- package/.rush/temp/operation/build_package-metas/all.log +1 -0
- package/.rush/temp/operation/build_package-metas/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/build_package-metas/state.json +3 -0
- package/.rush/temp/shrinkwrap-deps.json +3 -0
- package/config/rig.json +5 -0
- package/event-handler.ts +178 -0
- package/index.css +5 -0
- package/index.ts +17 -0
- package/package.json +44 -0
- package/rush-logs/event-handler.apply-exports.cache.log +1 -0
- package/rush-logs/event-handler.apply-exports.log +1 -0
- package/rush-logs/event-handler.build_docs.cache.log +1 -0
- package/rush-logs/event-handler.build_docs.log +1 -0
- package/rush-logs/event-handler.build_package-metas.cache.log +1 -0
- package/rush-logs/event-handler.build_package-metas.log +1 -0
- package/src/event-handler.css +19 -0
- package/support/custom-elements.json +245 -0
- package/support/demos/command-dialog.html +9 -0
- package/support/demos/debounce.html +21 -0
- package/support/demos/enter-close.html +13 -0
- package/support/demos/escape-close.html +16 -0
- package/support/demos/fire-event.html +13 -0
- package/support/demos/prevent-default.html +3 -0
- package/support/demos/retarget.html +14 -0
- package/support/demos/with-as.html +8 -0
- package/support/dist-docs/event-handler.md +277 -0
- package/support/docs/INTERNAL.md +1 -0
- package/support/docs/README.md +97 -0
- package/support/package-meta.json +249 -0
- package/support/tests/__snapshots__/debounce.view.test.ts.snap +23 -0
- package/support/tests/__snapshots__/fire-event.view.test.ts.snap +23 -0
- package/support/tests/__snapshots__/retarget.view.test.ts.snap +23 -0
- package/support/tests/command-dialog.view.test.ts +34 -0
- package/support/tests/debounce.view.test.ts +43 -0
- package/support/tests/enter-close.view.test.ts +35 -0
- package/support/tests/escape-close.view.test.ts +44 -0
- package/support/tests/event-handler.form-fallback.test.ts +49 -0
- package/support/tests/event-handler.test.ts +524 -0
- package/support/tests/fire-event.view.test.ts +38 -0
- package/support/tests/prevent-default.view.test.ts +21 -0
- package/support/tests/retarget.view.test.ts +38 -0
- package/support/tests/with-as.view.test.ts +31 -0
- package/tsconfig.json +5 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<div>
|
|
2
|
+
<section>
|
|
3
|
+
<event-handler fire-event="cart-add" detail-sku="sku-1">
|
|
4
|
+
Add to cart
|
|
5
|
+
</event-handler>
|
|
6
|
+
<output>Waiting…</output>
|
|
7
|
+
</section>
|
|
8
|
+
<quark-sheet>
|
|
9
|
+
@use "/demo-utils" as *;
|
|
10
|
+
|
|
11
|
+
section { @on cart-add (handle: setOutputFromDetail); }
|
|
12
|
+
</quark-sheet>
|
|
13
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<div>
|
|
2
|
+
<output>Waiting…</output>
|
|
3
|
+
<event-handler target-ref="output:has(+ :scope)" fire-event="demo-ping"
|
|
4
|
+
detail-label="pong">
|
|
5
|
+
Ping previous output
|
|
6
|
+
</event-handler>
|
|
7
|
+
<quark-sheet>
|
|
8
|
+
@use "/demo-utils" as *;
|
|
9
|
+
|
|
10
|
+
output {
|
|
11
|
+
@on demo-ping (handle: setOutputFromDetail);
|
|
12
|
+
}
|
|
13
|
+
</quark-sheet>
|
|
14
|
+
</div>
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# event-handler
|
|
2
|
+
|
|
3
|
+
Stitch behaviors of your app together, primarily through events.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
```html
|
|
7
|
+
<section>
|
|
8
|
+
<event-handler target-ref=":scope + content-drawer" command-name="--toggle">
|
|
9
|
+
Toggle drawer
|
|
10
|
+
</event-handler>
|
|
11
|
+
<content-drawer>
|
|
12
|
+
<h2>Open!</h2>
|
|
13
|
+
</content-drawer>
|
|
14
|
+
</section>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- **Fire custom events** Map any input event, such as clicks, or lifecycles to custom output events
|
|
21
|
+
- **Commands** `command-name` invokes the HTML Command API — built-in verbs (`show-modal`) and the `--verb` commands elements accept (`--submit`, `--close`)
|
|
22
|
+
- **Retarget** Aim events/commands at any selector (`target-ref`) — where a `<button commandfor>` needs an id
|
|
23
|
+
- **Global / host listening** Listen to events globally or on any element. Helpful for: escape to dismiss, global shortcuts, etc.
|
|
24
|
+
- **Keycode filter** Escape to dismiss, Shift+K shortcuts — keys / modifier chords
|
|
25
|
+
- **Listen filters** Debounce, selector, and pathname gates
|
|
26
|
+
- **Custom Event Payloads** `detail-*` attributes and forms convert to `event.detail` JSON
|
|
27
|
+
|
|
28
|
+
> In a view that already has a `<quark-sheet>`, the same wiring is a rule: `@on click (target: "[data-add]") { @dispatch cart-add (detail: (sku: attr("data-sku"))); }` — `@on` options cover `selector-filter` / `keycode-filter` / `is-debounced` / `host-ref`, and `@dispatch` / `@command` cover `fire-event` / `target-ref` / `form-ref` / `command-name`. Keep `<event-handler>` for markup without a sheet.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
`@excom/event-handler` v0.1.0
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pnpm add @excom/event-handler
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install @excom/event-handler
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
yarn add @excom/event-handler
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Import
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import "@excom/event-handler";
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## Usage
|
|
56
|
+
|
|
57
|
+
Listen (default `click`), then either `fire-event` or `command-name`.
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<event-handler fire-event="cart-add">
|
|
61
|
+
Add to cart
|
|
62
|
+
</event-handler>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Or, for example: a successful form submit re-fetches the related data by invoking the provider's `--fetch` command.
|
|
66
|
+
```html
|
|
67
|
+
<event-handler listen-for="super-form-success" target-ref="#fetch-todos" command-name="--fetch">
|
|
68
|
+
<super-form>
|
|
69
|
+
<form>
|
|
70
|
+
<!-- form to create a new todo -->
|
|
71
|
+
</form>
|
|
72
|
+
</super-form>
|
|
73
|
+
</event-handler>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
In a Nucleus Stack application, this will be one of the most heavily used elements. It is the primary method of linking a functional cause and effect.
|
|
77
|
+
|
|
78
|
+
### API Reference
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
#### Attributes
|
|
82
|
+
|
|
83
|
+
| Name | Surface | Type | Default | Values | Description | Inherited from |
|
|
84
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
85
|
+
| `target-ref` | option | `string` | | `<CSS Selector>` | Where outgoing events / mutations / commands apply. Unset = this element. Supports `:scope` for relative targeting (e.g. `:scope ~ dialog`). | |
|
|
86
|
+
| `fire-event` | option | `tokenlist` | | `<EventName>…` | Space-separated event names to dispatch on the target. Each name gets the same merged `detail`. Ignored when `mutate-target` is set. Pair with `detail-*` attributes for static detail fields. | |
|
|
87
|
+
| `command-name` | option | `tokenlist` | | `<command>…` | Space-separated commands to invoke on the target: custom `--verb` commands (`--submit`, `--close`) dispatch a `command` event, as a `<button command commandfor>` would; built-in verbs (`show-modal`, `close`, `toggle-popover`) run through the platform. | |
|
|
88
|
+
| `not-bubbles` | option | `boolean` | | | Outgoing events use `bubbles: false` (default: bubble). | |
|
|
89
|
+
| `not-cancelable` | option | `boolean` | | | Outgoing events use `cancelable: false` (default: cancelable). | |
|
|
90
|
+
| `not-composed` | option | `boolean` | | | Outgoing events use `composed: false` (default: composed / cross shadow roots). | |
|
|
91
|
+
| `form-ref` | option | `string` | | `<CSS Selector>` | `<form>` whose fields merge into event `detail`, or become attributes when `mutate-target` is set. | |
|
|
92
|
+
| `mutate-target` | option | `boolean` | | | @deprecated Write attributes on the target instead of firing events (sources: `attr-*` on this element plus `form-ref` fields). Use a Quark `@on <event> { … }` block instead — it writes State from the event without one element mutating another. Kept for compatibility; will be removed in a future major. | |
|
|
93
|
+
| `host-ref` | option | `string` | | `<CSS Selector>` \| `"window"` \| `"document"` \| `"html"` \| `"body"` \| `"head"` | Listen on another element / `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. | `@excom/listenable-element` |
|
|
94
|
+
| `listen-for` | option | `tokenlist` | | `<EventName>…` | Space-separated event names to listen for. Defaults to `click` when unset (and no lifecycle list is set). | `@excom/listenable-element` |
|
|
95
|
+
| `listen-for-lifecycle` | option | `tokenlist` | | `"connected"` \| `"disconnected"` \| `"adopted"` | Space-separated element lifecycles to handle. | `@excom/listenable-element` |
|
|
96
|
+
| `listen-once` | option | `boolean` | | | Handle each distinct event name / lifecycle at most once. | `@excom/listenable-element` |
|
|
97
|
+
| `selector-filter` | option | `string` | | `<CSS Selector>` | Only handle events whose `event.target` matches this CSS selector. Does not support `:scope` in the selector. | `@excom/listenable-element` |
|
|
98
|
+
| `keycode-filter` | option | `tokenlist` | | `<key` \| `mod+key>…` | Space-separated key filters (OR). Join modifiers with `+` (AND, any order): `shift+k tab` → Shift+K or Tab. Modifiers: `shift`, `alt`, `ctrl`/`control`, `meta`. Case-insensitive. | `@excom/listenable-element` |
|
|
99
|
+
| `pathname-filter` | option | `tokenlist` | | `<pathname>…` | Only handle when `location.pathname` is one of these values — route-aware behaviors without a separate router element. | `@excom/listenable-element` |
|
|
100
|
+
| `prevent-default` | option | `boolean` | | | Call `preventDefault()` on matched events (ignored for lifecycles). | `@excom/listenable-element` |
|
|
101
|
+
| `stop-propagation` | option | `boolean` | | | Call `stopPropagation()` on matched events (ignored for lifecycles). | `@excom/listenable-element` |
|
|
102
|
+
| `stop-immediate-propagation` | option | `boolean` | | | Call `stopImmediatePropagation()` on matched events (ignored for lifecycles). | `@excom/listenable-element` |
|
|
103
|
+
| `vibrate-ms` | option | `number` | `"20 (when attribute is present with no value)"` | | Vibrate on handle (`navigator.vibrate`). Empty / `0` uses a 20ms pulse. | `@excom/listenable-element` |
|
|
104
|
+
| `delay-ms` | option | `number` | | | Delay handling by this many milliseconds. | `@excom/listenable-element` |
|
|
105
|
+
| `is-debounced` | option | `boolean` | | | With `delay-ms`, coalesce bursts into one trailing call (debounce). | `@excom/listenable-element` |
|
|
106
|
+
|
|
107
|
+
#### CSS Classes
|
|
108
|
+
|
|
109
|
+
| Name | Description |
|
|
110
|
+
| --- | --- |
|
|
111
|
+
| `.unstyled` | Skip the pointer cursor from the listenable mixin. |
|
|
112
|
+
|
|
113
|
+
#### CSS Aliases
|
|
114
|
+
|
|
115
|
+
| Alias | Kind | Matches | Description |
|
|
116
|
+
| --- | --- | --- | --- |
|
|
117
|
+
| `:--event-handler` | element | `event-handler`, `.tag-event-handler` | |
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
### Examples
|
|
122
|
+
|
|
123
|
+
#### Fire a custom event
|
|
124
|
+
|
|
125
|
+
Click dispatches `cart-add` event with `{ sku: "sku-1" }` in `event.detail`.
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
```html
|
|
129
|
+
<div>
|
|
130
|
+
<section>
|
|
131
|
+
<event-handler fire-event="cart-add" detail-sku="sku-1">
|
|
132
|
+
Add to cart
|
|
133
|
+
</event-handler>
|
|
134
|
+
<output>Waiting…</output>
|
|
135
|
+
</section>
|
|
136
|
+
<quark-sheet>
|
|
137
|
+
@use "/demo-utils" as *;
|
|
138
|
+
|
|
139
|
+
section { @on cart-add (handle: setOutputFromDetail); }
|
|
140
|
+
</quark-sheet>
|
|
141
|
+
</div>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
#### Open a dialog
|
|
146
|
+
|
|
147
|
+
`command-name` invokes the HTML Command API — here the built-in `show-modal` opens the sibling `<dialog>`. Custom commands (`command-name="--close"`) reach any element that handles them, such as `<content-drawer>`, through a relative `target-ref`.
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
```html
|
|
151
|
+
<section>
|
|
152
|
+
<event-handler target-ref=":scope + dialog" command-name="show-modal">
|
|
153
|
+
Open dialog
|
|
154
|
+
</event-handler>
|
|
155
|
+
<dialog>
|
|
156
|
+
Hello!
|
|
157
|
+
<form method="dialog"><button>Close</button></form>
|
|
158
|
+
</dialog>
|
|
159
|
+
</section>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
#### Close on Enter
|
|
164
|
+
|
|
165
|
+
`keycode-filter` gates keyboard handling — here Enter, focused in the
|
|
166
|
+
`input`, invokes the drawer's `--close` command (local / bubbling events only).
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
```html
|
|
170
|
+
<section>
|
|
171
|
+
<event-handler target-ref=":scope + content-drawer" command-name="--open">
|
|
172
|
+
Open drawer
|
|
173
|
+
</event-handler>
|
|
174
|
+
<content-drawer id="demo-enter-close-drawer" is-open>
|
|
175
|
+
<event-handler listen-for="keydown" keycode-filter="enter" target-ref="#demo-enter-close-drawer" command-name="--close">
|
|
176
|
+
<label>
|
|
177
|
+
Favorite color
|
|
178
|
+
<input type="text" placeholder="Type something, then press Enter to close drawer" autofocus />
|
|
179
|
+
</label>
|
|
180
|
+
</event-handler>
|
|
181
|
+
</content-drawer>
|
|
182
|
+
</section>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
#### Escape to dismiss (global)
|
|
187
|
+
|
|
188
|
+
`host-ref="window"` listens for `keydown` on the window — Escape closes
|
|
189
|
+
the dialog even when focus is outside it.
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
```html
|
|
193
|
+
<section>
|
|
194
|
+
<event-handler target-ref=":scope ~ dialog" command-name="show-modal">
|
|
195
|
+
Open dialog
|
|
196
|
+
</event-handler>
|
|
197
|
+
<event-handler
|
|
198
|
+
host-ref="window"
|
|
199
|
+
listen-for="keydown"
|
|
200
|
+
keycode-filter="escape"
|
|
201
|
+
target-ref=":scope ~ dialog"
|
|
202
|
+
command-name="close"
|
|
203
|
+
></event-handler>
|
|
204
|
+
<dialog>
|
|
205
|
+
Press Escape anywhere to close.
|
|
206
|
+
<form method="dialog"><button>Close</button></form>
|
|
207
|
+
</dialog>
|
|
208
|
+
</section>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
#### Cancel a link click
|
|
213
|
+
|
|
214
|
+
`prevent-default` cancels the native action — here the wrapped `<a>` never navigates.
|
|
215
|
+
Use `stop-propagation` / `stop-immediate-propagation` the same way when you need to stop bubbling.
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
```html
|
|
219
|
+
<event-handler prevent-default>
|
|
220
|
+
<a href="https://example.com">This native link does nothing</a>
|
|
221
|
+
</event-handler>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
#### Retarget
|
|
226
|
+
|
|
227
|
+
`target-ref` aims the outgoing event at another element — useful when the target sits outside of the bubble path.
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
```html
|
|
231
|
+
<div>
|
|
232
|
+
<output>Waiting…</output>
|
|
233
|
+
<event-handler target-ref="output:has(+ :scope)" fire-event="demo-ping"
|
|
234
|
+
detail-label="pong">
|
|
235
|
+
Ping previous output
|
|
236
|
+
</event-handler>
|
|
237
|
+
<quark-sheet>
|
|
238
|
+
@use "/demo-utils" as *;
|
|
239
|
+
|
|
240
|
+
output {
|
|
241
|
+
@on demo-ping (handle: setOutputFromDetail);
|
|
242
|
+
}
|
|
243
|
+
</quark-sheet>
|
|
244
|
+
</div>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
#### Debounced input / form data
|
|
249
|
+
|
|
250
|
+
Inherited `delay-ms` + `is-debounced` coalesce noisy `input` into one `search-query` event. Demo below is debounced every 200ms.
|
|
251
|
+
|
|
252
|
+
Also demonstrated is form conversion into JSON: `text` -> `string`, `checkbox` -> `boolean`, etc. Including the data structure: `detail.strict` -> `{detail: {strict}}`.
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
```html
|
|
256
|
+
<div>
|
|
257
|
+
<section>
|
|
258
|
+
<event-handler listen-for="input" delay-ms="200" is-debounced fire-event="search-query" form-ref=":scope form">
|
|
259
|
+
<form>
|
|
260
|
+
<label>
|
|
261
|
+
<input name="detail.q" type="search" placeholder="Type to search…" />
|
|
262
|
+
</label>
|
|
263
|
+
<label>
|
|
264
|
+
Strict search
|
|
265
|
+
<input name="detail.strict" type="checkbox" role="switch" />
|
|
266
|
+
</label>
|
|
267
|
+
</form>
|
|
268
|
+
</event-handler>
|
|
269
|
+
<output>Waiting…</output>
|
|
270
|
+
</section>
|
|
271
|
+
<quark-sheet>
|
|
272
|
+
@use "/demo-utils" as *;
|
|
273
|
+
|
|
274
|
+
section { @on search-query (handle: setOutputFromDetail); }
|
|
275
|
+
</quark-sheet>
|
|
276
|
+
</div>
|
|
277
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- `mutate-target` is deprecated (2026-09-11): Quark's `@on <event> { … }` block covers event → attribute writes without one element mutating another. Still functional and tested; every in-repo usage was migrated. Remove in the next major.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# event-handler
|
|
2
|
+
|
|
3
|
+
Stitch behaviors of your app together, primarily through events.
|
|
4
|
+
|
|
5
|
+
<include-content data-demo="with-as"></include-content>
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Fire custom events** Map any input event, such as clicks, or lifecycles to custom output events
|
|
10
|
+
- **Commands** `command-name` invokes the HTML Command API — built-in verbs (`show-modal`) and the `--verb` commands elements accept (`--submit`, `--close`)
|
|
11
|
+
- **Retarget** Aim events/commands at any selector (`target-ref`) — where a `<button commandfor>` needs an id
|
|
12
|
+
- **Global / host listening** Listen to events globally or on any element. Helpful for: escape to dismiss, global shortcuts, etc.
|
|
13
|
+
- **Keycode filter** Escape to dismiss, Shift+K shortcuts — keys / modifier chords
|
|
14
|
+
- **Listen filters** Debounce, selector, and pathname gates
|
|
15
|
+
- **Custom Event Payloads** `detail-*` attributes and forms convert to `event.detail` JSON
|
|
16
|
+
|
|
17
|
+
> In a view that already has a `<quark-sheet>`, the same wiring is a rule: `@on click (target: "[data-add]") { @dispatch cart-add (detail: (sku: attr("data-sku"))); }` — `@on` options cover `selector-filter` / `keycode-filter` / `is-debounced` / `host-ref`, and `@dispatch` / `@command` cover `fire-event` / `target-ref` / `form-ref` / `command-name`. Keep `<event-handler>` for markup without a sheet.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
<include-content is-active template-ref="/views/install-section/install-section.html"></include-content>
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Listen (default `click`), then either `fire-event` or `command-name`.
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<event-handler fire-event="cart-add">
|
|
29
|
+
Add to cart
|
|
30
|
+
</event-handler>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or, for example: a successful form submit re-fetches the related data by invoking the provider's `--fetch` command.
|
|
34
|
+
```html
|
|
35
|
+
<event-handler listen-for="super-form-success" target-ref="#fetch-todos" command-name="--fetch">
|
|
36
|
+
<super-form>
|
|
37
|
+
<form>
|
|
38
|
+
<!-- form to create a new todo -->
|
|
39
|
+
</form>
|
|
40
|
+
</super-form>
|
|
41
|
+
</event-handler>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
In a Nucleus Stack application, this will be one of the most heavily used elements. It is the primary method of linking a functional cause and effect.
|
|
45
|
+
|
|
46
|
+
### API Reference
|
|
47
|
+
|
|
48
|
+
<include-content is-active template-ref="/views/api-reference/api-reference.html"></include-content>
|
|
49
|
+
|
|
50
|
+
### Examples
|
|
51
|
+
|
|
52
|
+
#### Fire a custom event
|
|
53
|
+
|
|
54
|
+
Click dispatches `cart-add` event with `{ sku: "sku-1" }` in `event.detail`.
|
|
55
|
+
|
|
56
|
+
<include-content data-demo="fire-event"></include-content>
|
|
57
|
+
|
|
58
|
+
#### Open a dialog
|
|
59
|
+
|
|
60
|
+
`command-name` invokes the HTML Command API — here the built-in `show-modal` opens the sibling `<dialog>`. Custom commands (`command-name="--close"`) reach any element that handles them, such as `<content-drawer>`, through a relative `target-ref`.
|
|
61
|
+
|
|
62
|
+
<include-content data-demo="command-dialog"></include-content>
|
|
63
|
+
|
|
64
|
+
#### Close on Enter
|
|
65
|
+
|
|
66
|
+
`keycode-filter` gates keyboard handling — here Enter, focused in the
|
|
67
|
+
`input`, invokes the drawer's `--close` command (local / bubbling events only).
|
|
68
|
+
|
|
69
|
+
<include-content data-demo="enter-close"></include-content>
|
|
70
|
+
|
|
71
|
+
#### Escape to dismiss (global)
|
|
72
|
+
|
|
73
|
+
`host-ref="window"` listens for `keydown` on the window — Escape closes
|
|
74
|
+
the dialog even when focus is outside it.
|
|
75
|
+
|
|
76
|
+
<include-content data-demo="escape-close"></include-content>
|
|
77
|
+
|
|
78
|
+
#### Cancel a link click
|
|
79
|
+
|
|
80
|
+
`prevent-default` cancels the native action — here the wrapped `<a>` never navigates.
|
|
81
|
+
Use `stop-propagation` / `stop-immediate-propagation` the same way when you need to stop bubbling.
|
|
82
|
+
|
|
83
|
+
<include-content data-demo="prevent-default"></include-content>
|
|
84
|
+
|
|
85
|
+
#### Retarget
|
|
86
|
+
|
|
87
|
+
`target-ref` aims the outgoing event at another element — useful when the target sits outside of the bubble path.
|
|
88
|
+
|
|
89
|
+
<include-content data-demo="retarget"></include-content>
|
|
90
|
+
|
|
91
|
+
#### Debounced input / form data
|
|
92
|
+
|
|
93
|
+
Inherited `delay-ms` + `is-debounced` coalesce noisy `input` into one `search-query` event. Demo below is debounced every 200ms.
|
|
94
|
+
|
|
95
|
+
Also demonstrated is form conversion into JSON: `text` -> `string`, `checkbox` -> `boolean`, etc. Including the data structure: `detail.strict` -> `{detail: {strict}}`.
|
|
96
|
+
|
|
97
|
+
<include-content data-demo="debounce"></include-content>
|