dom-primitive-bindings 1.0.0 → 1.3.1
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 +101 -64
- package/docs/architecture.md +111 -0
- package/docs/binding-spec.md +86 -0
- package/docs/dist/min.js +7 -6
- package/docs/dist/v2/min.js +64 -0
- package/docs/dist/v3/min.js +64 -0
- package/docs/index.html +102 -79
- package/docs/stories/01-the-listener-trap.html +189 -0
- package/docs/stories/02-the-delegation-epiphany.html +185 -0
- package/docs/stories/03-the-staged-pipeline.html +162 -0
- package/docs/stories/04-declarative-json-bindings.html +159 -0
- package/package.json +3 -3
- package/src/index.js +2 -2
- package/src/{v1 → v3}/register/index.js +2 -1
- package/src/{v1 → v3}/register/meta.js +1 -2
- /package/src/{v1 → v3}/dispatch/executeBinding.js +0 -0
- /package/src/{v1 → v3}/dispatch/getClientData.js +0 -0
- /package/src/{v1 → v3}/dispatch/getStartInput.js +0 -0
- /package/src/{v1 → v3}/dispatch/index.js +0 -0
- /package/src/{v1 → v3}/guards/bindings/index.js +0 -0
- /package/src/{v1 → v3}/guards/bindings/validateArray.js +0 -0
- /package/src/{v1 → v3}/guards/container/index.js +0 -0
- /package/src/{v1 → v3}/guards/container/resolveElement.js +0 -0
- /package/src/{v1 → v3}/guards/index.js +0 -0
- /package/src/{v1 → v3}/index.js +0 -0
- /package/src/{v1 → v3}/listeners/attachListener.js +0 -0
- /package/src/{v1 → v3}/listeners/index.js +0 -0
- /package/src/{v1 → v3}/prepare/groupBindings.js +0 -0
- /package/src/{v1 → v3}/prepare/index.js +0 -0
package/README.md
CHANGED
|
@@ -1,61 +1,91 @@
|
|
|
1
1
|
# DOM Primitive Bindings
|
|
2
2
|
|
|
3
|
-
> Modern, lightweight, delegated event engine for browser DOMs.
|
|
3
|
+
> Modern, lightweight, single-listener delegated event engine for browser DOMs. Driven by declarative `bindings.json` configurations with zero DOM manipulation and zero schema extraction.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/dom-primitive-bindings)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[]()
|
|
8
|
+
[](./docs/index.html)
|
|
8
9
|
|
|
9
10
|
---
|
|
10
11
|
|
|
11
|
-
##
|
|
12
|
+
## 📖 The 4-Part Event Delegation Story
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
Explore the interactive interactive story chapters in [`docs/stories/`](./docs/index.html):
|
|
14
15
|
|
|
15
|
-
**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
1. **[Chapter 1: The Everyday Habit & The Listener Trap](./docs/stories/01-the-listener-trap.html)**
|
|
17
|
+
Why attaching listeners to individual elements causes memory leaks, double-trigger cascades, and dead-zones on dynamic elements.
|
|
18
|
+
2. **[Chapter 2: The Delegation Epiphany](./docs/stories/02-the-delegation-epiphany.html)**
|
|
19
|
+
Harnessing browser event bubbling: 1 container listener catching bubbling events forever.
|
|
20
|
+
3. **[Chapter 3: The Staged Pipeline Architecture](./docs/stories/03-the-staged-pipeline.html)**
|
|
21
|
+
Inside the decoupled 4-stage pipeline: `guards` $\to$ `prepare` $\to$ `listeners` $\to$ `dispatch`.
|
|
22
|
+
4. **[Chapter 4: The Joy of Declarative JSON](./docs/stories/04-declarative-json-bindings.html)**
|
|
23
|
+
Moving from imperative JavaScript arrays to clean, serializable `bindings.json` specifications with a live interactive demo.
|
|
20
24
|
|
|
21
25
|
---
|
|
22
26
|
|
|
23
|
-
##
|
|
27
|
+
## 🎯 The Philosophy: The Wiring Layer
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
A common mistake in UI architecture is conflating **event wiring** with **DOM manipulation** or **data extraction**:
|
|
30
|
+
|
|
31
|
+
- **`dom-primitive-bindings` (This Repository):**
|
|
32
|
+
Pure **Wiring Layer**. Attaches one container listener per event type, matches bubbling targets via `closest(selector)`, and delivers `{ event, targetElement }`. It does **not** manipulate DOM elements and does **not** extract table schemas into objects.
|
|
33
|
+
- **`dom-primitive-engine` (Sibling Repository):**
|
|
34
|
+
Pure **Extraction Layer**. Receives the matched target element and executes declarative instruction pipelines (e.g. `closest("tr")`, `querySelectorAll("td")`, column mapping) to produce clean JSON.
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
[ User Action in Browser ]
|
|
38
|
+
│
|
|
39
|
+
▼
|
|
40
|
+
┌───────────────────────────────┐
|
|
41
|
+
│ dom-primitive-bindings │ ◄── Wiring Layer: Catches event & matches target
|
|
42
|
+
│ (guards → prepare → dispatch)│
|
|
43
|
+
└──────────────┬────────────────┘
|
|
44
|
+
│ delivers { event, targetElement }
|
|
45
|
+
▼
|
|
46
|
+
┌───────────────────────────────┐
|
|
47
|
+
│ Consumer / App Logic │ ◄── Extraction (dom-primitive-engine) or App Handler
|
|
48
|
+
└───────────────────────────────┘
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 🏗️ Staged Architecture (`src/v3/`)
|
|
54
|
+
|
|
55
|
+
The engine enforces a staged pipeline where every directory contains an `index.js` and all files export a single function as `default`:
|
|
26
56
|
|
|
27
57
|
```text
|
|
28
|
-
src/
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
└── index.js # Orchestrator exporting bindEvents
|
|
58
|
+
src/v3/
|
|
59
|
+
├── guards/ # Validates container & bindings array
|
|
60
|
+
│ ├── container/ # Resolves 1st input (container ID or DOM element)
|
|
61
|
+
│ ├── bindings/ # Filters and validates 2nd input (bindings array)
|
|
62
|
+
│ └── index.js
|
|
63
|
+
├── prepare/ # Groups bindings by event type into Map
|
|
64
|
+
│ ├── groupBindings.js
|
|
65
|
+
│ └── index.js
|
|
66
|
+
├── listeners/ # Attaches single container listener per event type
|
|
67
|
+
│ ├── attachListener.js
|
|
68
|
+
│ └── index.js
|
|
69
|
+
├── dispatch/ # Handles event bubbling, target matching & execution
|
|
70
|
+
│ ├── getStartInput.js
|
|
71
|
+
│ ├── getClientData.js
|
|
72
|
+
│ ├── executeBinding.js
|
|
73
|
+
│ └── index.js
|
|
74
|
+
├── register/ # Exposes module onto window.ks.domPrimitiveBindings
|
|
75
|
+
│ ├── meta.js
|
|
76
|
+
│ └── index.js
|
|
77
|
+
└── index.js # Orchestrator
|
|
49
78
|
```
|
|
50
79
|
|
|
51
80
|
### Key Design Disciplines
|
|
52
81
|
1. **Zero Comments:** The folder hierarchy and descriptive file names convey the full narrative without inline code comments.
|
|
53
82
|
2. **Folder Discipline:** Every folder contains an `index.js` public gateway.
|
|
54
83
|
3. **Single Function Default Export:** No default export objects; every file exports a single function.
|
|
84
|
+
4. **Declarative JSON:** Bindings are defined in serializable `bindings.json` files.
|
|
55
85
|
|
|
56
86
|
---
|
|
57
87
|
|
|
58
|
-
## 🚀 Interactive Browser Samples (`samples/
|
|
88
|
+
## 🚀 Interactive Browser Samples (`samples/v3/`)
|
|
59
89
|
|
|
60
90
|
Start the Vite development server to view and interact with real browser DOM events:
|
|
61
91
|
|
|
@@ -65,47 +95,55 @@ npm run dev
|
|
|
65
95
|
```
|
|
66
96
|
|
|
67
97
|
Open in Chrome or Edge:
|
|
68
|
-
- **`samples/
|
|
69
|
-
- **`samples/
|
|
70
|
-
- **`samples/
|
|
98
|
+
- **`samples/v3/tableWithSearch/`** — Declarative table row clicks and live Enter-key search input loaded from `bindings.json`.
|
|
99
|
+
- **`samples/v3/cardGrid/`** — Declarative card button and card body click bindings loaded from `bindings.json`.
|
|
100
|
+
- **`samples/v3/formEvents/`** — Declarative input, change, and button click bindings loaded from `bindings.json`.
|
|
71
101
|
|
|
72
102
|
---
|
|
73
103
|
|
|
74
104
|
## 📦 Usage
|
|
75
105
|
|
|
76
|
-
###
|
|
106
|
+
### 1. Declare `bindings.json`
|
|
77
107
|
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
window.ks.domPrimitiveBindings.bindEvents("products-container", bindings);
|
|
91
|
-
</script>
|
|
108
|
+
```json
|
|
109
|
+
[
|
|
110
|
+
{
|
|
111
|
+
"event": "click",
|
|
112
|
+
"selector": ".btn-action"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"event": "keydown",
|
|
116
|
+
"selector": "input[type='search']"
|
|
117
|
+
}
|
|
118
|
+
]
|
|
92
119
|
```
|
|
93
120
|
|
|
94
|
-
###
|
|
121
|
+
### 2. Run with `bindEvents`
|
|
95
122
|
|
|
96
123
|
```javascript
|
|
124
|
+
import bindings from "./bindings.json" with { type: "json" };
|
|
97
125
|
import { bindEvents } from "dom-primitive-bindings";
|
|
98
126
|
|
|
99
|
-
bindEvents(
|
|
100
|
-
{
|
|
101
|
-
event: "click",
|
|
102
|
-
selector: ".action-btn",
|
|
103
|
-
runner: (btn) => btn.dataset.action,
|
|
104
|
-
onExtract: (action) => console.log("Action:", action)
|
|
105
|
-
}
|
|
106
|
-
]);
|
|
127
|
+
bindEvents("container-id", bindings);
|
|
107
128
|
```
|
|
108
129
|
|
|
130
|
+
Or via global browser script:
|
|
131
|
+
|
|
132
|
+
```html
|
|
133
|
+
<script type="module" src="./docs/dist/v3/min.js"></script>
|
|
134
|
+
<script type="module">
|
|
135
|
+
import bindings from "./bindings.json" with { type: "json" };
|
|
136
|
+
window.ks.domPrimitiveBindings.bindEvents("container-id", bindings);
|
|
137
|
+
</script>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 📚 Technical Specifications
|
|
143
|
+
|
|
144
|
+
- **[Architecture & Design Story](./docs/architecture.md)**: Deep dive into the 4 internal stages and data flow.
|
|
145
|
+
- **[Binding Specification Schema](./docs/binding-spec.md)**: Complete property reference for `bindings.json`.
|
|
146
|
+
|
|
109
147
|
---
|
|
110
148
|
|
|
111
149
|
## 🧪 Testing & Build
|
|
@@ -114,7 +152,7 @@ bindEvents(containerElement, [
|
|
|
114
152
|
# Run unit tests
|
|
115
153
|
npm test
|
|
116
154
|
|
|
117
|
-
# Build production bundle to docs/dist/
|
|
155
|
+
# Build production bundle to docs/dist/v3/min.js
|
|
118
156
|
npm run build
|
|
119
157
|
```
|
|
120
158
|
|
|
@@ -123,4 +161,3 @@ npm run build
|
|
|
123
161
|
## 📄 License
|
|
124
162
|
|
|
125
163
|
MIT © KeshavSoft
|
|
126
|
-
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Architecture & Design Story — DOM Primitive Bindings
|
|
2
|
+
|
|
3
|
+
This document details the architectural philosophy, data flow, and design trade-offs behind **DOM Primitive Bindings**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. The Core Architectural Philosophy
|
|
8
|
+
|
|
9
|
+
### Separation of Concerns: The Wiring Layer vs. The Extraction Layer
|
|
10
|
+
|
|
11
|
+
Modern frontend architectures fail when they blur the boundary between **how events are wired** and **how data is extracted or mutated**:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
┌─────────────────────────────────┐
|
|
15
|
+
│ Browser DOM │ <-- Stateful View (Table, Form, Cards)
|
|
16
|
+
└────────────────┬────────────────┘
|
|
17
|
+
│ user interaction (click, input, keydown)
|
|
18
|
+
▼
|
|
19
|
+
┌─────────────────────────────────┐
|
|
20
|
+
│ dom-primitive-bindings │ <-- Responsibility: The Wiring Layer
|
|
21
|
+
│ (guards → prepare → dispatch) │ • Single listener on container
|
|
22
|
+
└────────────────┬────────────────┘ • Matches closest(selector)
|
|
23
|
+
│ passes { event, targetElement }
|
|
24
|
+
▼
|
|
25
|
+
┌─────────────────────────────────┐
|
|
26
|
+
│ dom-primitive-engine │ <-- Responsibility: The Extraction Layer
|
|
27
|
+
│ (declarative instructions) │ • Traverses DOM (tr, td)
|
|
28
|
+
└────────────────┬────────────────┘ • Produces clean JSON object
|
|
29
|
+
│ outputs clean Plain Data
|
|
30
|
+
▼
|
|
31
|
+
┌─────────────────────────────────┐
|
|
32
|
+
│ Business Logic / API Call │ <-- Consumes Plain Data
|
|
33
|
+
└─────────────────────────────────┘
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
By strictly separating event wiring into `dom-primitive-bindings`:
|
|
37
|
+
1. **Zero DOM manipulation**: Bindings never alter, insert, or delete DOM elements.
|
|
38
|
+
2. **Zero schema extraction**: Bindings never parse table cells or form schemas into business models.
|
|
39
|
+
3. **Pure delegation**: Exactly **one listener per event type** is attached to the parent container. Bubbling handles target matching.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 2. Why Delegated Bindings over Element Listeners?
|
|
44
|
+
|
|
45
|
+
| Approach | Memory Usage | Dynamic Element Support | Duplicate Fire Risk |
|
|
46
|
+
| :--- | :--- | :--- | :--- |
|
|
47
|
+
| **Direct Listeners** (`element.addEventListener`) | High ($O(N)$ listeners) | Fails on newly added DOM elements | High (re-attaching duplicates listeners) |
|
|
48
|
+
| **DOM Primitive Bindings** (Container Delegation) | Minimal ($O(1)$ listener per event type) | Works instantly on dynamic elements | Zero (single stable container listener) |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 3. The 4-Stage Internal Pipeline (`src/v3/`)
|
|
53
|
+
|
|
54
|
+
The engine operates on a strictly staged, functional pipeline where every folder contains an `index.js` and exports a single function as `default`:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
src/v3/
|
|
58
|
+
├── guards/ # Validates container & bindings array
|
|
59
|
+
│ ├── container/ # Resolves 1st input (container ID or DOM element)
|
|
60
|
+
│ ├── bindings/ # Filters and validates 2nd input (bindings array)
|
|
61
|
+
│ └── index.js
|
|
62
|
+
├── prepare/ # Groups bindings by event type into Map
|
|
63
|
+
│ ├── groupBindings.js
|
|
64
|
+
│ └── index.js
|
|
65
|
+
├── listeners/ # Attaches single container listener per event type
|
|
66
|
+
│ ├── attachListener.js
|
|
67
|
+
│ └── index.js
|
|
68
|
+
├── dispatch/ # Handles event bubbling, target matching & execution
|
|
69
|
+
│ ├── getStartInput.js
|
|
70
|
+
│ ├── getClientData.js
|
|
71
|
+
│ ├── executeBinding.js
|
|
72
|
+
│ └── index.js
|
|
73
|
+
├── register/ # Exposes module onto window.ks.domPrimitiveBindings
|
|
74
|
+
│ ├── meta.js
|
|
75
|
+
│ └── index.js
|
|
76
|
+
└── index.js # Orchestrator
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Stage Details
|
|
80
|
+
|
|
81
|
+
1. **`guards/`**: Validates inputs before any DOM mutation occurs.
|
|
82
|
+
- `container/`: Resolves string IDs via `document.getElementById` or verifies existing element.
|
|
83
|
+
- `bindings/`: Filters invalid items and ensures at least one valid binding exists.
|
|
84
|
+
2. **`prepare/`**: Groups bindings into a `Map<eventType, bindings[]>`.
|
|
85
|
+
- If 10 separate selectors listen for `click`, they are aggregated under the single `"click"` event group.
|
|
86
|
+
3. **`listeners/`**: Attaches exactly one native event listener to the container per event type.
|
|
87
|
+
4. **`dispatch/`**:
|
|
88
|
+
- Intercepts the bubbling event.
|
|
89
|
+
- Resolves matching element via `event.target.closest(binding.selector)`.
|
|
90
|
+
- Resolves starting input (`event` for keyboard events, `matchElement` for clicks).
|
|
91
|
+
- Invokes runner and forwards data to `onExtract`.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 4. Responsibility Boundaries
|
|
96
|
+
|
|
97
|
+
| Actor | What It Does | What It NEVER Does |
|
|
98
|
+
| :--- | :--- | :--- |
|
|
99
|
+
| **Container Element** | Acts as the stable anchor for bubbling events | Does not know about inner button schemas |
|
|
100
|
+
| **`bindings.json`** | Declares `event` and `selector` | Does not execute imperative logic |
|
|
101
|
+
| **`dom-primitive-bindings`** | Resolves target, manages delegation pipeline | Does not extract table rows or mutate markup |
|
|
102
|
+
| **`dom-primitive-engine`** | Extracts clean JSON data from the matched target | Does not manage event listeners |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 5. Version Evolution (`v3` as Single Source of Truth)
|
|
107
|
+
|
|
108
|
+
- **v1**: Staged architecture established with zero code comments and single-function default exports.
|
|
109
|
+
- **v2**: Removed accidental DOM manipulation and cell extraction from samples, solidifying the pure delegation boundary.
|
|
110
|
+
- **v3**: Declarative JSON transformation. Replaced imperative `.js` event arrays with pure, serializable `bindings.json` configurations.
|
|
111
|
+
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Binding Specification — DOM Primitive Bindings
|
|
2
|
+
|
|
3
|
+
This document defines the normative schema and runtime behavior for declarative `bindings.json` files.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Schema Overview
|
|
8
|
+
|
|
9
|
+
A bindings file is an array of binding specification objects:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
[
|
|
13
|
+
{
|
|
14
|
+
"event": "click",
|
|
15
|
+
"selector": ".ks-btn-show",
|
|
16
|
+
"root": "element",
|
|
17
|
+
"clientData": {
|
|
18
|
+
"context": "tableRow"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 2. Property Definitions
|
|
27
|
+
|
|
28
|
+
### `event` (Required)
|
|
29
|
+
- **Type**: `string`
|
|
30
|
+
- **Description**: The standard browser DOM event name to listen for on the container (e.g. `"click"`, `"keydown"`, `"input"`, `"change"`, `"submit"`).
|
|
31
|
+
- **Behavior**: The engine groups all bindings with the same `event` name under a single native event listener on the container element.
|
|
32
|
+
|
|
33
|
+
### `selector` (Required)
|
|
34
|
+
- **Type**: `string`
|
|
35
|
+
- **Description**: Standard CSS selector used by `event.target.closest(selector)` to identify whether the bubbling event originated from or within a target element.
|
|
36
|
+
- **Examples**:
|
|
37
|
+
- `".ks-btn-show"`
|
|
38
|
+
- `"input[type='search'], input"`
|
|
39
|
+
- `".btn-action"`
|
|
40
|
+
- `".product-card"`
|
|
41
|
+
|
|
42
|
+
### `root` (Optional)
|
|
43
|
+
- **Type**: `string` (`"element"` | `"event"`)
|
|
44
|
+
- **Default**: `"element"` (automatically defaults to `"event"` for key events such as `keydown`, `keyup`, `keypress`).
|
|
45
|
+
- **Description**: Determines what is passed as the first argument to the runner function:
|
|
46
|
+
- `"element"`: passes the matched DOM element (`matchElement`).
|
|
47
|
+
- `"event"`: passes the native browser `Event` object.
|
|
48
|
+
|
|
49
|
+
### `clientData` (Optional)
|
|
50
|
+
- **Type**: `object`
|
|
51
|
+
- **Description**: Arbitrary user-defined context passed along into the dispatch pipeline. The engine merges this into the client context object alongside `event` and `targetElement`.
|
|
52
|
+
|
|
53
|
+
### `instructions` (Optional)
|
|
54
|
+
- **Type**: `array`
|
|
55
|
+
- **Description**: Declarative extraction instructions intended for handoff to `dom-primitive-engine`.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 3. Runtime Dispatch Lifecycle
|
|
60
|
+
|
|
61
|
+
When an event fires inside the container:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
Browser Event Fires
|
|
65
|
+
│
|
|
66
|
+
▼
|
|
67
|
+
Container Listener Intercepts (listeners/attachListener.js)
|
|
68
|
+
│
|
|
69
|
+
▼
|
|
70
|
+
Find Matching Element: event.target.closest(binding.selector)
|
|
71
|
+
│
|
|
72
|
+
├── No match / not inside container ──> Discard (continue)
|
|
73
|
+
│
|
|
74
|
+
▼
|
|
75
|
+
Resolve Start Input (dispatch/getStartInput.js)
|
|
76
|
+
│
|
|
77
|
+
├── Key event or root === "event" ──> Pass event
|
|
78
|
+
└── Otherwise ──> Pass matchElement
|
|
79
|
+
│
|
|
80
|
+
▼
|
|
81
|
+
Execute Runner (dispatch/executeBinding.js)
|
|
82
|
+
│
|
|
83
|
+
▼
|
|
84
|
+
Forward to onExtract(result, event, matchElement)
|
|
85
|
+
```
|
|
86
|
+
|
package/docs/dist/min.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
const u = {
|
|
2
2
|
name: "dom-primitive-bindings",
|
|
3
|
-
version: "
|
|
3
|
+
version: "3.0.0"
|
|
4
4
|
}, c = (t, n = u) => {
|
|
5
|
+
var e;
|
|
5
6
|
if (!(!t || typeof globalThis > "u"))
|
|
6
7
|
return globalThis.ks ?? (globalThis.ks = {}), globalThis.ks.domPrimitiveBindings = {
|
|
7
8
|
meta: n,
|
|
8
9
|
bindEvents: t
|
|
9
|
-
}, globalThis.ks.domPrimitiveBindings;
|
|
10
|
+
}, (e = globalThis.ks).bindEvents ?? (e.bindEvents = t), globalThis.ks.domPrimitiveBindings;
|
|
10
11
|
}, l = (t) => typeof t == "string" ? document.getElementById(t) || document.querySelector(t) : t && typeof t == "object" && "addEventListener" in t ? t : null, a = (t) => {
|
|
11
12
|
if (!t) return null;
|
|
12
13
|
const n = l(t);
|
|
@@ -42,19 +43,19 @@ const u = {
|
|
|
42
43
|
const s = (i = (r = n.target) == null ? void 0 : r.closest) == null ? void 0 : i.call(r, o.selector);
|
|
43
44
|
!s || !e.contains(s) || v({ binding: o, event: n, matchElement: s });
|
|
44
45
|
}
|
|
45
|
-
},
|
|
46
|
+
}, k = (t, n, e) => {
|
|
46
47
|
t.addEventListener(n, (r) => {
|
|
47
48
|
B({ bindings: e, event: r, container: t });
|
|
48
49
|
});
|
|
49
|
-
},
|
|
50
|
+
}, E = (t, n) => {
|
|
50
51
|
for (const [e, r] of n.entries())
|
|
51
|
-
|
|
52
|
+
k(t, e, r);
|
|
52
53
|
return t;
|
|
53
54
|
}, T = (t, n = []) => {
|
|
54
55
|
const e = p(t, n);
|
|
55
56
|
if (!e) return null;
|
|
56
57
|
const { container: r, bindings: i } = e, o = y(i);
|
|
57
|
-
return
|
|
58
|
+
return E(r, o), r;
|
|
58
59
|
};
|
|
59
60
|
c(T);
|
|
60
61
|
export {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const u = {
|
|
2
|
+
name: "dom-primitive-bindings",
|
|
3
|
+
version: "2.0.0"
|
|
4
|
+
}, c = (t, n = u) => {
|
|
5
|
+
var e;
|
|
6
|
+
if (!(!t || typeof globalThis > "u"))
|
|
7
|
+
return globalThis.ks ?? (globalThis.ks = {}), globalThis.ks.domPrimitiveBindings = {
|
|
8
|
+
meta: n,
|
|
9
|
+
bindEvents: t
|
|
10
|
+
}, (e = globalThis.ks).bindEvents ?? (e.bindEvents = t), globalThis.ks.domPrimitiveBindings;
|
|
11
|
+
}, l = (t) => typeof t == "string" ? document.getElementById(t) || document.querySelector(t) : t && typeof t == "object" && "addEventListener" in t ? t : null, a = (t) => {
|
|
12
|
+
if (!t) return null;
|
|
13
|
+
const n = l(t);
|
|
14
|
+
return n || null;
|
|
15
|
+
}, f = (t) => Array.isArray(t) ? t.filter((n) => n && typeof n == "object" && typeof n.event == "string" && typeof n.selector == "string") : [], g = (t) => {
|
|
16
|
+
const n = f(t);
|
|
17
|
+
return n.length === 0 ? null : n;
|
|
18
|
+
}, p = (t, n) => {
|
|
19
|
+
const e = a(t);
|
|
20
|
+
if (!e) return null;
|
|
21
|
+
const r = g(n);
|
|
22
|
+
return r ? { container: e, bindings: r } : null;
|
|
23
|
+
}, d = (t) => {
|
|
24
|
+
const n = /* @__PURE__ */ new Map();
|
|
25
|
+
for (const e of t) {
|
|
26
|
+
const r = n.get(e.event) ?? [];
|
|
27
|
+
r.push(e), n.set(e.event, r);
|
|
28
|
+
}
|
|
29
|
+
return n;
|
|
30
|
+
}, y = (t) => d(t), m = (t, n, e) => {
|
|
31
|
+
var r;
|
|
32
|
+
return t.root === "event" || (r = n == null ? void 0 : n.type) != null && r.startsWith("key") ? n : e;
|
|
33
|
+
}, h = (t, n, e) => ({
|
|
34
|
+
...t.clientData,
|
|
35
|
+
event: n,
|
|
36
|
+
targetElement: e
|
|
37
|
+
}), v = ({ binding: t, event: n, matchElement: e }) => {
|
|
38
|
+
const r = m(t, n, e), i = h(t, n, e), o = t.runner, s = typeof o == "function" ? o(r, t.instructions, i) : r;
|
|
39
|
+
return s != null && typeof t.onExtract == "function" && t.onExtract(s, n, e), s;
|
|
40
|
+
}, B = ({ bindings: t, event: n, container: e }) => {
|
|
41
|
+
var r, i;
|
|
42
|
+
for (const o of t) {
|
|
43
|
+
const s = (i = (r = n.target) == null ? void 0 : r.closest) == null ? void 0 : i.call(r, o.selector);
|
|
44
|
+
!s || !e.contains(s) || v({ binding: o, event: n, matchElement: s });
|
|
45
|
+
}
|
|
46
|
+
}, k = (t, n, e) => {
|
|
47
|
+
t.addEventListener(n, (r) => {
|
|
48
|
+
B({ bindings: e, event: r, container: t });
|
|
49
|
+
});
|
|
50
|
+
}, E = (t, n) => {
|
|
51
|
+
for (const [e, r] of n.entries())
|
|
52
|
+
k(t, e, r);
|
|
53
|
+
return t;
|
|
54
|
+
}, T = (t, n = []) => {
|
|
55
|
+
const e = p(t, n);
|
|
56
|
+
if (!e) return null;
|
|
57
|
+
const { container: r, bindings: i } = e, o = y(i);
|
|
58
|
+
return E(r, o), r;
|
|
59
|
+
};
|
|
60
|
+
c(T);
|
|
61
|
+
export {
|
|
62
|
+
T as bindEvents,
|
|
63
|
+
T as default
|
|
64
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const u = {
|
|
2
|
+
name: "dom-primitive-bindings",
|
|
3
|
+
version: "3.0.0"
|
|
4
|
+
}, c = (t, n = u) => {
|
|
5
|
+
var e;
|
|
6
|
+
if (!(!t || typeof globalThis > "u"))
|
|
7
|
+
return globalThis.ks ?? (globalThis.ks = {}), globalThis.ks.domPrimitiveBindings = {
|
|
8
|
+
meta: n,
|
|
9
|
+
bindEvents: t
|
|
10
|
+
}, (e = globalThis.ks).bindEvents ?? (e.bindEvents = t), globalThis.ks.domPrimitiveBindings;
|
|
11
|
+
}, l = (t) => typeof t == "string" ? document.getElementById(t) || document.querySelector(t) : t && typeof t == "object" && "addEventListener" in t ? t : null, a = (t) => {
|
|
12
|
+
if (!t) return null;
|
|
13
|
+
const n = l(t);
|
|
14
|
+
return n || null;
|
|
15
|
+
}, f = (t) => Array.isArray(t) ? t.filter((n) => n && typeof n == "object" && typeof n.event == "string" && typeof n.selector == "string") : [], g = (t) => {
|
|
16
|
+
const n = f(t);
|
|
17
|
+
return n.length === 0 ? null : n;
|
|
18
|
+
}, p = (t, n) => {
|
|
19
|
+
const e = a(t);
|
|
20
|
+
if (!e) return null;
|
|
21
|
+
const r = g(n);
|
|
22
|
+
return r ? { container: e, bindings: r } : null;
|
|
23
|
+
}, d = (t) => {
|
|
24
|
+
const n = /* @__PURE__ */ new Map();
|
|
25
|
+
for (const e of t) {
|
|
26
|
+
const r = n.get(e.event) ?? [];
|
|
27
|
+
r.push(e), n.set(e.event, r);
|
|
28
|
+
}
|
|
29
|
+
return n;
|
|
30
|
+
}, y = (t) => d(t), m = (t, n, e) => {
|
|
31
|
+
var r;
|
|
32
|
+
return t.root === "event" || (r = n == null ? void 0 : n.type) != null && r.startsWith("key") ? n : e;
|
|
33
|
+
}, h = (t, n, e) => ({
|
|
34
|
+
...t.clientData,
|
|
35
|
+
event: n,
|
|
36
|
+
targetElement: e
|
|
37
|
+
}), v = ({ binding: t, event: n, matchElement: e }) => {
|
|
38
|
+
const r = m(t, n, e), i = h(t, n, e), o = t.runner, s = typeof o == "function" ? o(r, t.instructions, i) : r;
|
|
39
|
+
return s != null && typeof t.onExtract == "function" && t.onExtract(s, n, e), s;
|
|
40
|
+
}, B = ({ bindings: t, event: n, container: e }) => {
|
|
41
|
+
var r, i;
|
|
42
|
+
for (const o of t) {
|
|
43
|
+
const s = (i = (r = n.target) == null ? void 0 : r.closest) == null ? void 0 : i.call(r, o.selector);
|
|
44
|
+
!s || !e.contains(s) || v({ binding: o, event: n, matchElement: s });
|
|
45
|
+
}
|
|
46
|
+
}, k = (t, n, e) => {
|
|
47
|
+
t.addEventListener(n, (r) => {
|
|
48
|
+
B({ bindings: e, event: r, container: t });
|
|
49
|
+
});
|
|
50
|
+
}, E = (t, n) => {
|
|
51
|
+
for (const [e, r] of n.entries())
|
|
52
|
+
k(t, e, r);
|
|
53
|
+
return t;
|
|
54
|
+
}, T = (t, n = []) => {
|
|
55
|
+
const e = p(t, n);
|
|
56
|
+
if (!e) return null;
|
|
57
|
+
const { container: r, bindings: i } = e, o = y(i);
|
|
58
|
+
return E(r, o), r;
|
|
59
|
+
};
|
|
60
|
+
c(T);
|
|
61
|
+
export {
|
|
62
|
+
T as bindEvents,
|
|
63
|
+
T as default
|
|
64
|
+
};
|