@hypen-space/web 0.4.36 → 0.4.37
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/dist/canvas/accessibility.js +174 -174
- package/dist/canvas/accessibility.js.map +1 -10
- package/dist/canvas/events.js +264 -360
- package/dist/canvas/events.js.map +1 -11
- package/dist/canvas/index.js +11 -47
- package/dist/canvas/index.js.map +1 -9
- package/dist/canvas/input.js +178 -289
- package/dist/canvas/input.js.map +1 -11
- package/dist/canvas/layout.js +349 -547
- package/dist/canvas/layout.js.map +1 -12
- package/dist/canvas/paint.js +1122 -1146
- package/dist/canvas/paint.js.map +1 -12
- package/dist/canvas/renderer.js +352 -2259
- package/dist/canvas/renderer.js.map +1 -17
- package/dist/canvas/text.js +129 -264
- package/dist/canvas/text.js.map +1 -11
- package/dist/canvas/types.js +7 -2
- package/dist/canvas/types.js.map +1 -9
- package/dist/canvas/utils.js +158 -161
- package/dist/canvas/utils.js.map +1 -10
- package/dist/client.js +19 -45
- package/dist/client.js.map +1 -9
- package/dist/dom/applicators/advanced-layout.js +105 -138
- package/dist/dom/applicators/advanced-layout.js.map +1 -10
- package/dist/dom/applicators/background.js +36 -76
- package/dist/dom/applicators/background.js.map +1 -10
- package/dist/dom/applicators/border.js +82 -106
- package/dist/dom/applicators/border.js.map +1 -10
- package/dist/dom/applicators/color.js +17 -58
- package/dist/dom/applicators/color.js.map +1 -10
- package/dist/dom/applicators/display.js +39 -79
- package/dist/dom/applicators/display.js.map +1 -10
- package/dist/dom/applicators/effects.js +121 -147
- package/dist/dom/applicators/effects.js.map +1 -10
- package/dist/dom/applicators/events.js +413 -450
- package/dist/dom/applicators/events.js.map +1 -11
- package/dist/dom/applicators/font.js +119 -140
- package/dist/dom/applicators/font.js.map +1 -10
- package/dist/dom/applicators/index.js +386 -1770
- package/dist/dom/applicators/index.js.map +1 -26
- package/dist/dom/applicators/layout.js +143 -149
- package/dist/dom/applicators/layout.js.map +1 -10
- package/dist/dom/applicators/margin.js +64 -105
- package/dist/dom/applicators/margin.js.map +1 -10
- package/dist/dom/applicators/padding.js +64 -105
- package/dist/dom/applicators/padding.js.map +1 -10
- package/dist/dom/applicators/size.js +169 -172
- package/dist/dom/applicators/size.js.map +1 -10
- package/dist/dom/applicators/transform.js +73 -114
- package/dist/dom/applicators/transform.js.map +1 -10
- package/dist/dom/applicators/transition.js +47 -88
- package/dist/dom/applicators/transition.js.map +1 -10
- package/dist/dom/applicators/types.js +7 -2
- package/dist/dom/applicators/types.js.map +1 -9
- package/dist/dom/applicators/typography.js +68 -109
- package/dist/dom/applicators/typography.js.map +1 -10
- package/dist/dom/canvas/index.js +49 -83
- package/dist/dom/canvas/index.js.map +1 -10
- package/dist/dom/components/app.js +16 -63
- package/dist/dom/components/app.js.map +1 -10
- package/dist/dom/components/audio.js +31 -76
- package/dist/dom/components/audio.js.map +1 -10
- package/dist/dom/components/avatar.js +41 -87
- package/dist/dom/components/avatar.js.map +1 -10
- package/dist/dom/components/badge.js +35 -83
- package/dist/dom/components/badge.js.map +1 -10
- package/dist/dom/components/button.js +26 -69
- package/dist/dom/components/button.js.map +1 -10
- package/dist/dom/components/card.js +13 -63
- package/dist/dom/components/card.js.map +1 -10
- package/dist/dom/components/center.js +21 -65
- package/dist/dom/components/center.js.map +1 -10
- package/dist/dom/components/checkbox.js +37 -82
- package/dist/dom/components/checkbox.js.map +1 -10
- package/dist/dom/components/column.js +16 -62
- package/dist/dom/components/column.js.map +1 -10
- package/dist/dom/components/container.js +11 -59
- package/dist/dom/components/container.js.map +1 -10
- package/dist/dom/components/divider.js +27 -73
- package/dist/dom/components/divider.js.map +1 -10
- package/dist/dom/components/grid.js +41 -80
- package/dist/dom/components/grid.js.map +1 -10
- package/dist/dom/components/heading.js +28 -74
- package/dist/dom/components/heading.js.map +1 -10
- package/dist/dom/components/hypenapp.js +291 -288
- package/dist/dom/components/hypenapp.js.map +1 -10
- package/dist/dom/components/image.js +18 -67
- package/dist/dom/components/image.js.map +1 -10
- package/dist/dom/components/index.js +109 -1427
- package/dist/dom/components/index.js.map +1 -42
- package/dist/dom/components/input.js +19 -69
- package/dist/dom/components/input.js.map +1 -10
- package/dist/dom/components/link.js +23 -70
- package/dist/dom/components/link.js.map +1 -10
- package/dist/dom/components/list.js +26 -72
- package/dist/dom/components/list.js.map +1 -10
- package/dist/dom/components/paragraph.js +14 -63
- package/dist/dom/components/paragraph.js.map +1 -10
- package/dist/dom/components/progressbar.js +38 -85
- package/dist/dom/components/progressbar.js.map +1 -10
- package/dist/dom/components/route.js +27 -73
- package/dist/dom/components/route.js.map +1 -10
- package/dist/dom/components/router.js +15 -62
- package/dist/dom/components/router.js.map +1 -10
- package/dist/dom/components/row.js +25 -70
- package/dist/dom/components/row.js.map +1 -10
- package/dist/dom/components/select.js +42 -85
- package/dist/dom/components/select.js.map +1 -10
- package/dist/dom/components/slider.js +31 -76
- package/dist/dom/components/slider.js.map +1 -10
- package/dist/dom/components/spacer.js +10 -60
- package/dist/dom/components/spacer.js.map +1 -10
- package/dist/dom/components/spinner.js +41 -88
- package/dist/dom/components/spinner.js.map +1 -10
- package/dist/dom/components/stack.js +19 -67
- package/dist/dom/components/stack.js.map +1 -10
- package/dist/dom/components/switch.js +50 -93
- package/dist/dom/components/switch.js.map +1 -10
- package/dist/dom/components/text.js +24 -69
- package/dist/dom/components/text.js.map +1 -10
- package/dist/dom/components/textarea.js +35 -79
- package/dist/dom/components/textarea.js.map +1 -10
- package/dist/dom/components/video.js +35 -79
- package/dist/dom/components/video.js.map +1 -10
- package/dist/dom/debug.js +159 -160
- package/dist/dom/debug.js.map +1 -10
- package/dist/dom/element-data.js +181 -143
- package/dist/dom/element-data.js.map +1 -10
- package/dist/dom/events.js +133 -142
- package/dist/dom/events.js.map +1 -10
- package/dist/dom/index.js +11 -48
- package/dist/dom/index.js.map +1 -9
- package/dist/dom/renderer.js +311 -3596
- package/dist/dom/renderer.js.map +1 -62
- package/dist/hypen.js +385 -3880
- package/dist/hypen.js.map +1 -63
- package/dist/index.js +36 -53
- package/dist/index.js.map +1 -9
- package/package.json +2 -2
package/dist/dom/element-data.js
CHANGED
|
@@ -1,145 +1,183 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
var __toCommonJS = (from) => {
|
|
9
|
-
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
-
if (entry)
|
|
11
|
-
return entry;
|
|
12
|
-
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (var key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(entry, key))
|
|
16
|
-
__defProp(entry, key, {
|
|
17
|
-
get: __accessProp.bind(from, key),
|
|
18
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
__moduleCache.set(from, entry);
|
|
22
|
-
return entry;
|
|
23
|
-
};
|
|
24
|
-
var __moduleCache;
|
|
25
|
-
var __returnValue = (v) => v;
|
|
26
|
-
function __exportSetter(name, newValue) {
|
|
27
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
-
}
|
|
29
|
-
var __export = (target, all) => {
|
|
30
|
-
for (var name in all)
|
|
31
|
-
__defProp(target, name, {
|
|
32
|
-
get: all[name],
|
|
33
|
-
enumerable: true,
|
|
34
|
-
configurable: true,
|
|
35
|
-
set: __exportSetter.bind(all, name)
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
39
|
-
|
|
40
|
-
// src/dom/element-data.ts
|
|
1
|
+
/**
|
|
2
|
+
* Type-Safe Element Data
|
|
3
|
+
*
|
|
4
|
+
* Provides strongly-typed access to Hypen-specific data attached to DOM elements.
|
|
5
|
+
* Eliminates `as any` casts throughout the codebase.
|
|
6
|
+
*/
|
|
41
7
|
import { getElementDisposables } from "@hypen-space/core/disposable";
|
|
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
|
-
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Private Storage
|
|
10
|
+
// ============================================================================
|
|
11
|
+
/**
|
|
12
|
+
* WeakMap to store Hypen data without polluting the element
|
|
13
|
+
*/
|
|
14
|
+
const elementDataMap = new WeakMap();
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Core API
|
|
17
|
+
// ============================================================================
|
|
18
|
+
/**
|
|
19
|
+
* Get Hypen data for an element, creating if needed
|
|
20
|
+
*/
|
|
21
|
+
export function getHypenData(element) {
|
|
22
|
+
let data = elementDataMap.get(element);
|
|
23
|
+
if (!data) {
|
|
24
|
+
data = {};
|
|
25
|
+
elementDataMap.set(element, data);
|
|
26
|
+
}
|
|
27
|
+
return data;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Check if element has Hypen data
|
|
31
|
+
*/
|
|
32
|
+
export function hasHypenData(element) {
|
|
33
|
+
return elementDataMap.has(element);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Clear Hypen data from an element
|
|
37
|
+
*/
|
|
38
|
+
export function clearHypenData(element) {
|
|
39
|
+
elementDataMap.delete(element);
|
|
40
|
+
}
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// Engine Access
|
|
43
|
+
// ============================================================================
|
|
44
|
+
/**
|
|
45
|
+
* Get the engine attached to an element
|
|
46
|
+
*/
|
|
47
|
+
export function getEngine(element) {
|
|
48
|
+
return getHypenData(element).engine;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Set the engine on an element
|
|
52
|
+
*/
|
|
53
|
+
export function setEngine(element, engine) {
|
|
54
|
+
getHypenData(element).engine = engine;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Find engine by walking up the DOM tree
|
|
58
|
+
*/
|
|
59
|
+
export function findEngine(element) {
|
|
60
|
+
let current = element;
|
|
61
|
+
while (current) {
|
|
62
|
+
const engine = getEngine(current);
|
|
63
|
+
if (engine)
|
|
64
|
+
return engine;
|
|
65
|
+
current = current.parentElement;
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// Event Registration Tracking
|
|
71
|
+
// ============================================================================
|
|
72
|
+
/**
|
|
73
|
+
* Get registered events set for an element
|
|
74
|
+
*/
|
|
75
|
+
export function getRegisteredEvents(element) {
|
|
76
|
+
const data = getHypenData(element);
|
|
77
|
+
if (!data.registeredEvents) {
|
|
78
|
+
data.registeredEvents = new Set();
|
|
79
|
+
}
|
|
80
|
+
return data.registeredEvents;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check if an event handler is registered
|
|
84
|
+
*/
|
|
85
|
+
export function isEventRegistered(element, eventKey) {
|
|
86
|
+
return getRegisteredEvents(element).has(eventKey);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Mark an event handler as registered
|
|
90
|
+
*/
|
|
91
|
+
export function registerEvent(element, eventKey) {
|
|
92
|
+
getRegisteredEvents(element).add(eventKey);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Unregister an event handler
|
|
96
|
+
*/
|
|
97
|
+
export function unregisterEvent(element, eventKey) {
|
|
98
|
+
getRegisteredEvents(element).delete(eventKey);
|
|
99
|
+
}
|
|
100
|
+
// ============================================================================
|
|
101
|
+
// Keyboard Event Key Target
|
|
102
|
+
// ============================================================================
|
|
103
|
+
/**
|
|
104
|
+
* Get the target key for keyboard events
|
|
105
|
+
*/
|
|
106
|
+
export function getKeyTarget(element) {
|
|
107
|
+
return getHypenData(element).keyTarget;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Set the target key for keyboard events
|
|
111
|
+
*/
|
|
112
|
+
export function setKeyTarget(element, key) {
|
|
113
|
+
getHypenData(element).keyTarget = key;
|
|
114
|
+
}
|
|
115
|
+
// ============================================================================
|
|
116
|
+
// Metadata
|
|
117
|
+
// ============================================================================
|
|
118
|
+
/**
|
|
119
|
+
* Get custom metadata value
|
|
120
|
+
*/
|
|
121
|
+
export function getMeta(element, key) {
|
|
122
|
+
return getHypenData(element).meta?.[key];
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Set custom metadata value
|
|
126
|
+
*/
|
|
127
|
+
export function setMeta(element, key, value) {
|
|
128
|
+
const data = getHypenData(element);
|
|
129
|
+
if (!data.meta) {
|
|
130
|
+
data.meta = {};
|
|
131
|
+
}
|
|
132
|
+
data.meta[key] = value;
|
|
133
|
+
}
|
|
134
|
+
// ============================================================================
|
|
135
|
+
// Cleanup
|
|
136
|
+
// ============================================================================
|
|
137
|
+
/**
|
|
138
|
+
* Dispose all resources attached to an element and clear data
|
|
139
|
+
* Call this when removing an element from the DOM
|
|
140
|
+
*/
|
|
141
|
+
export function disposeHypenElement(element) {
|
|
142
|
+
// Dispose any registered disposables
|
|
143
|
+
try {
|
|
144
|
+
const disposables = getElementDisposables(element);
|
|
145
|
+
disposables.dispose();
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// Ignore if no disposables
|
|
149
|
+
}
|
|
150
|
+
// Clear Hypen data
|
|
151
|
+
clearHypenData(element);
|
|
152
|
+
}
|
|
153
|
+
// ============================================================================
|
|
154
|
+
// Legacy Compatibility Layer
|
|
155
|
+
// ============================================================================
|
|
156
|
+
/**
|
|
157
|
+
* Symbol-based legacy accessor (for backwards compatibility)
|
|
158
|
+
* Use the typed functions above instead when possible
|
|
159
|
+
*/
|
|
160
|
+
const HYPEN_ENGINE_SYMBOL = Symbol.for("hypen.engine");
|
|
161
|
+
const REGISTERED_EVENTS_SYMBOL = Symbol.for("hypen.registeredEvents");
|
|
162
|
+
const KEY_TARGET_SYMBOL = Symbol.for("hypen.keyTarget");
|
|
163
|
+
/**
|
|
164
|
+
* Legacy accessor for engine (backwards compatible with existing code)
|
|
165
|
+
*/
|
|
166
|
+
export function getLegacyEngine(element) {
|
|
167
|
+
// Try new storage first
|
|
168
|
+
const engine = getEngine(element);
|
|
67
169
|
if (engine)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
function registerEvent(element, eventKey) {
|
|
84
|
-
getRegisteredEvents(element).add(eventKey);
|
|
85
|
-
}
|
|
86
|
-
function unregisterEvent(element, eventKey) {
|
|
87
|
-
getRegisteredEvents(element).delete(eventKey);
|
|
88
|
-
}
|
|
89
|
-
function getKeyTarget(element) {
|
|
90
|
-
return getHypenData(element).keyTarget;
|
|
91
|
-
}
|
|
92
|
-
function setKeyTarget(element, key) {
|
|
93
|
-
getHypenData(element).keyTarget = key;
|
|
94
|
-
}
|
|
95
|
-
function getMeta(element, key) {
|
|
96
|
-
return getHypenData(element).meta?.[key];
|
|
97
|
-
}
|
|
98
|
-
function setMeta(element, key, value) {
|
|
99
|
-
const data = getHypenData(element);
|
|
100
|
-
if (!data.meta) {
|
|
101
|
-
data.meta = {};
|
|
102
|
-
}
|
|
103
|
-
data.meta[key] = value;
|
|
104
|
-
}
|
|
105
|
-
function disposeHypenElement(element) {
|
|
106
|
-
try {
|
|
107
|
-
const disposables = getElementDisposables(element);
|
|
108
|
-
disposables.dispose();
|
|
109
|
-
} catch {}
|
|
110
|
-
clearHypenData(element);
|
|
111
|
-
}
|
|
112
|
-
var HYPEN_ENGINE_SYMBOL = Symbol.for("hypen.engine");
|
|
113
|
-
var REGISTERED_EVENTS_SYMBOL = Symbol.for("hypen.registeredEvents");
|
|
114
|
-
var KEY_TARGET_SYMBOL = Symbol.for("hypen.keyTarget");
|
|
115
|
-
function getLegacyEngine(element) {
|
|
116
|
-
const engine = getEngine(element);
|
|
117
|
-
if (engine)
|
|
118
|
-
return engine;
|
|
119
|
-
return element[HYPEN_ENGINE_SYMBOL] ?? element.__hypenEngine;
|
|
120
|
-
}
|
|
121
|
-
function setLegacyEngine(element, engine) {
|
|
122
|
-
setEngine(element, engine);
|
|
123
|
-
element.__hypenEngine = engine;
|
|
124
|
-
}
|
|
125
|
-
export {
|
|
126
|
-
unregisterEvent,
|
|
127
|
-
setMeta,
|
|
128
|
-
setLegacyEngine,
|
|
129
|
-
setKeyTarget,
|
|
130
|
-
setEngine,
|
|
131
|
-
registerEvent,
|
|
132
|
-
isEventRegistered,
|
|
133
|
-
hasHypenData,
|
|
134
|
-
getRegisteredEvents,
|
|
135
|
-
getMeta,
|
|
136
|
-
getLegacyEngine,
|
|
137
|
-
getKeyTarget,
|
|
138
|
-
getHypenData,
|
|
139
|
-
getEngine,
|
|
140
|
-
findEngine,
|
|
141
|
-
disposeHypenElement,
|
|
142
|
-
clearHypenData
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
//# debugId=C4AD9BA640CB84F264756E2164756E21
|
|
170
|
+
return engine;
|
|
171
|
+
// Fall back to legacy storage
|
|
172
|
+
return element[HYPEN_ENGINE_SYMBOL] ??
|
|
173
|
+
element.__hypenEngine;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Legacy setter for engine (backwards compatible)
|
|
177
|
+
*/
|
|
178
|
+
export function setLegacyEngine(element, engine) {
|
|
179
|
+
// Set in both locations for compatibility
|
|
180
|
+
setEngine(element, engine);
|
|
181
|
+
element.__hypenEngine = engine;
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=element-data.js.map
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/dom/element-data.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Type-Safe Element Data\n *\n * Provides strongly-typed access to Hypen-specific data attached to DOM elements.\n * Eliminates `as any` casts throughout the codebase.\n */\n\nimport { type DisposableStack, getElementDisposables } from \"@hypen-space/core/disposable\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Engine interface for dispatching actions\n */\nexport interface IEngine {\n dispatchAction(name: string, payload?: unknown): void;\n}\n\n/**\n * All Hypen-specific data attached to an element\n */\nexport interface HypenElementData {\n /** Engine reference for action dispatch */\n engine?: IEngine;\n /** Target key for keyboard events (e.g., \"Enter\", \"Escape\") */\n keyTarget?: string;\n /** Set of registered event type:action pairs */\n registeredEvents?: Set<string>;\n /** Custom element metadata */\n meta?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Private Storage\n// ============================================================================\n\n/**\n * WeakMap to store Hypen data without polluting the element\n */\nconst elementDataMap = new WeakMap<HTMLElement, HypenElementData>();\n\n// ============================================================================\n// Core API\n// ============================================================================\n\n/**\n * Get Hypen data for an element, creating if needed\n */\nexport function getHypenData(element: HTMLElement): HypenElementData {\n let data = elementDataMap.get(element);\n if (!data) {\n data = {};\n elementDataMap.set(element, data);\n }\n return data;\n}\n\n/**\n * Check if element has Hypen data\n */\nexport function hasHypenData(element: HTMLElement): boolean {\n return elementDataMap.has(element);\n}\n\n/**\n * Clear Hypen data from an element\n */\nexport function clearHypenData(element: HTMLElement): void {\n elementDataMap.delete(element);\n}\n\n// ============================================================================\n// Engine Access\n// ============================================================================\n\n/**\n * Get the engine attached to an element\n */\nexport function getEngine(element: HTMLElement): IEngine | undefined {\n return getHypenData(element).engine;\n}\n\n/**\n * Set the engine on an element\n */\nexport function setEngine(element: HTMLElement, engine: IEngine): void {\n getHypenData(element).engine = engine;\n}\n\n/**\n * Find engine by walking up the DOM tree\n */\nexport function findEngine(element: HTMLElement): IEngine | undefined {\n let current: HTMLElement | null = element;\n while (current) {\n const engine = getEngine(current);\n if (engine) return engine;\n current = current.parentElement;\n }\n return undefined;\n}\n\n// ============================================================================\n// Event Registration Tracking\n// ============================================================================\n\n/**\n * Get registered events set for an element\n */\nexport function getRegisteredEvents(element: HTMLElement): Set<string> {\n const data = getHypenData(element);\n if (!data.registeredEvents) {\n data.registeredEvents = new Set();\n }\n return data.registeredEvents;\n}\n\n/**\n * Check if an event handler is registered\n */\nexport function isEventRegistered(element: HTMLElement, eventKey: string): boolean {\n return getRegisteredEvents(element).has(eventKey);\n}\n\n/**\n * Mark an event handler as registered\n */\nexport function registerEvent(element: HTMLElement, eventKey: string): void {\n getRegisteredEvents(element).add(eventKey);\n}\n\n/**\n * Unregister an event handler\n */\nexport function unregisterEvent(element: HTMLElement, eventKey: string): void {\n getRegisteredEvents(element).delete(eventKey);\n}\n\n// ============================================================================\n// Keyboard Event Key Target\n// ============================================================================\n\n/**\n * Get the target key for keyboard events\n */\nexport function getKeyTarget(element: HTMLElement): string | undefined {\n return getHypenData(element).keyTarget;\n}\n\n/**\n * Set the target key for keyboard events\n */\nexport function setKeyTarget(element: HTMLElement, key: string): void {\n getHypenData(element).keyTarget = key;\n}\n\n// ============================================================================\n// Metadata\n// ============================================================================\n\n/**\n * Get custom metadata value\n */\nexport function getMeta<T>(element: HTMLElement, key: string): T | undefined {\n return getHypenData(element).meta?.[key] as T | undefined;\n}\n\n/**\n * Set custom metadata value\n */\nexport function setMeta<T>(element: HTMLElement, key: string, value: T): void {\n const data = getHypenData(element);\n if (!data.meta) {\n data.meta = {};\n }\n data.meta[key] = value;\n}\n\n// ============================================================================\n// Cleanup\n// ============================================================================\n\n/**\n * Dispose all resources attached to an element and clear data\n * Call this when removing an element from the DOM\n */\nexport function disposeHypenElement(element: HTMLElement): void {\n // Dispose any registered disposables\n try {\n const disposables = getElementDisposables(element);\n disposables.dispose();\n } catch {\n // Ignore if no disposables\n }\n\n // Clear Hypen data\n clearHypenData(element);\n}\n\n// ============================================================================\n// Legacy Compatibility Layer\n// ============================================================================\n\n/**\n * Symbol-based legacy accessor (for backwards compatibility)\n * Use the typed functions above instead when possible\n */\nconst HYPEN_ENGINE_SYMBOL = Symbol.for(\"hypen.engine\");\nconst REGISTERED_EVENTS_SYMBOL = Symbol.for(\"hypen.registeredEvents\");\nconst KEY_TARGET_SYMBOL = Symbol.for(\"hypen.keyTarget\");\n\n/**\n * Legacy accessor for engine (backwards compatible with existing code)\n */\nexport function getLegacyEngine(element: HTMLElement): IEngine | undefined {\n // Try new storage first\n const engine = getEngine(element);\n if (engine) return engine;\n\n // Fall back to legacy storage\n return (element as any)[HYPEN_ENGINE_SYMBOL] ??\n (element as any).__hypenEngine;\n}\n\n/**\n * Legacy setter for engine (backwards compatible)\n */\nexport function setLegacyEngine(element: HTMLElement, engine: IEngine): void {\n // Set in both locations for compatibility\n setEngine(element, engine);\n (element as any).__hypenEngine = engine;\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA;AAkCA,IAAM,iBAAiB,IAAI;AASpB,SAAS,YAAY,CAAC,SAAwC;AAAA,EACnE,IAAI,OAAO,eAAe,IAAI,OAAO;AAAA,EACrC,IAAI,CAAC,MAAM;AAAA,IACT,OAAO,CAAC;AAAA,IACR,eAAe,IAAI,SAAS,IAAI;AAAA,EAClC;AAAA,EACA,OAAO;AAAA;AAMF,SAAS,YAAY,CAAC,SAA+B;AAAA,EAC1D,OAAO,eAAe,IAAI,OAAO;AAAA;AAM5B,SAAS,cAAc,CAAC,SAA4B;AAAA,EACzD,eAAe,OAAO,OAAO;AAAA;AAUxB,SAAS,SAAS,CAAC,SAA2C;AAAA,EACnE,OAAO,aAAa,OAAO,EAAE;AAAA;AAMxB,SAAS,SAAS,CAAC,SAAsB,QAAuB;AAAA,EACrE,aAAa,OAAO,EAAE,SAAS;AAAA;AAM1B,SAAS,UAAU,CAAC,SAA2C;AAAA,EACpE,IAAI,UAA8B;AAAA,EAClC,OAAO,SAAS;AAAA,IACd,MAAM,SAAS,UAAU,OAAO;AAAA,IAChC,IAAI;AAAA,MAAQ,OAAO;AAAA,IACnB,UAAU,QAAQ;AAAA,EACpB;AAAA,EACA;AAAA;AAUK,SAAS,mBAAmB,CAAC,SAAmC;AAAA,EACrE,MAAM,OAAO,aAAa,OAAO;AAAA,EACjC,IAAI,CAAC,KAAK,kBAAkB;AAAA,IAC1B,KAAK,mBAAmB,IAAI;AAAA,EAC9B;AAAA,EACA,OAAO,KAAK;AAAA;AAMP,SAAS,iBAAiB,CAAC,SAAsB,UAA2B;AAAA,EACjF,OAAO,oBAAoB,OAAO,EAAE,IAAI,QAAQ;AAAA;AAM3C,SAAS,aAAa,CAAC,SAAsB,UAAwB;AAAA,EAC1E,oBAAoB,OAAO,EAAE,IAAI,QAAQ;AAAA;AAMpC,SAAS,eAAe,CAAC,SAAsB,UAAwB;AAAA,EAC5E,oBAAoB,OAAO,EAAE,OAAO,QAAQ;AAAA;AAUvC,SAAS,YAAY,CAAC,SAA0C;AAAA,EACrE,OAAO,aAAa,OAAO,EAAE;AAAA;AAMxB,SAAS,YAAY,CAAC,SAAsB,KAAmB;AAAA,EACpE,aAAa,OAAO,EAAE,YAAY;AAAA;AAU7B,SAAS,OAAU,CAAC,SAAsB,KAA4B;AAAA,EAC3E,OAAO,aAAa,OAAO,EAAE,OAAO;AAAA;AAM/B,SAAS,OAAU,CAAC,SAAsB,KAAa,OAAgB;AAAA,EAC5E,MAAM,OAAO,aAAa,OAAO;AAAA,EACjC,IAAI,CAAC,KAAK,MAAM;AAAA,IACd,KAAK,OAAO,CAAC;AAAA,EACf;AAAA,EACA,KAAK,KAAK,OAAO;AAAA;AAWZ,SAAS,mBAAmB,CAAC,SAA4B;AAAA,EAE9D,IAAI;AAAA,IACF,MAAM,cAAc,sBAAsB,OAAO;AAAA,IACjD,YAAY,QAAQ;AAAA,IACpB,MAAM;AAAA,EAKR,eAAe,OAAO;AAAA;AAWxB,IAAM,sBAAsB,OAAO,IAAI,cAAc;AACrD,IAAM,2BAA2B,OAAO,IAAI,wBAAwB;AACpE,IAAM,oBAAoB,OAAO,IAAI,iBAAiB;AAK/C,SAAS,eAAe,CAAC,SAA2C;AAAA,EAEzE,MAAM,SAAS,UAAU,OAAO;AAAA,EAChC,IAAI;AAAA,IAAQ,OAAO;AAAA,EAGnB,OAAQ,QAAgB,wBACrB,QAAgB;AAAA;AAMd,SAAS,eAAe,CAAC,SAAsB,QAAuB;AAAA,EAE3E,UAAU,SAAS,MAAM;AAAA,EACxB,QAAgB,gBAAgB;AAAA;",
|
|
8
|
-
"debugId": "C4AD9BA640CB84F264756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
1
|
+
{"version":3,"file":"element-data.js","sourceRoot":"","sources":["../../src/dom/element-data.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAwB,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AA2B3F,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,cAAc,GAAG,IAAI,OAAO,EAAiC,CAAC;AAEpE,+EAA+E;AAC/E,WAAW;AACX,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAoB;IAC/C,IAAI,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,GAAG,EAAE,CAAC;QACV,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAoB;IAC/C,OAAO,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAoB;IACjD,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,OAAoB;IAC5C,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,OAAoB,EAAE,MAAe;IAC7D,YAAY,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAoB;IAC7C,IAAI,OAAO,GAAuB,OAAO,CAAC;IAC1C,OAAO,OAAO,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAC1B,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IAClC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+EAA+E;AAC/E,8BAA8B;AAC9B,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAoB;IACtD,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC3B,IAAI,CAAC,gBAAgB,GAAG,IAAI,GAAG,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC,gBAAgB,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAoB,EAAE,QAAgB;IACtE,OAAO,mBAAmB,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAoB,EAAE,QAAgB;IAClE,mBAAmB,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAoB,EAAE,QAAgB;IACpE,mBAAmB,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAChD,CAAC;AAED,+EAA+E;AAC/E,4BAA4B;AAC5B,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAoB;IAC/C,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAoB,EAAE,GAAW;IAC5D,YAAY,CAAC,OAAO,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC;AACxC,CAAC;AAED,+EAA+E;AAC/E,WAAW;AACX,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,OAAO,CAAI,OAAoB,EAAE,GAAW;IAC1D,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAkB,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAI,OAAoB,EAAE,GAAW,EAAE,KAAQ;IACpE,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;IACjB,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AACzB,CAAC;AAED,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAoB;IACtD,qCAAqC;IACrC,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QACnD,WAAW,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;IAC7B,CAAC;IAED,mBAAmB;IACnB,cAAc,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED,+EAA+E;AAC/E,6BAA6B;AAC7B,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AACvD,MAAM,wBAAwB,GAAG,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;AACtE,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAExD;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAoB;IAClD,wBAAwB;IACxB,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,8BAA8B;IAC9B,OAAQ,OAAe,CAAC,mBAAmB,CAAC;QACzC,OAAe,CAAC,aAAa,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAoB,EAAE,MAAe;IACnE,0CAA0C;IAC1C,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1B,OAAe,CAAC,aAAa,GAAG,MAAM,CAAC;AAC1C,CAAC"}
|
package/dist/dom/events.js
CHANGED
|
@@ -1,150 +1,141 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return this[key];
|
|
7
|
-
}
|
|
8
|
-
var __toCommonJS = (from) => {
|
|
9
|
-
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
-
if (entry)
|
|
11
|
-
return entry;
|
|
12
|
-
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (var key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(entry, key))
|
|
16
|
-
__defProp(entry, key, {
|
|
17
|
-
get: __accessProp.bind(from, key),
|
|
18
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
__moduleCache.set(from, entry);
|
|
22
|
-
return entry;
|
|
23
|
-
};
|
|
24
|
-
var __moduleCache;
|
|
25
|
-
var __returnValue = (v) => v;
|
|
26
|
-
function __exportSetter(name, newValue) {
|
|
27
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
-
}
|
|
29
|
-
var __export = (target, all) => {
|
|
30
|
-
for (var name in all)
|
|
31
|
-
__defProp(target, name, {
|
|
32
|
-
get: all[name],
|
|
33
|
-
enumerable: true,
|
|
34
|
-
configurable: true,
|
|
35
|
-
set: __exportSetter.bind(all, name)
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
39
|
-
|
|
40
|
-
// src/dom/events.ts
|
|
1
|
+
/**
|
|
2
|
+
* Event Management System
|
|
3
|
+
*
|
|
4
|
+
* Handles DOM event binding and action dispatching
|
|
5
|
+
*/
|
|
41
6
|
import { frameworkLoggers } from "@hypen-space/core/logger";
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.engine = engine;
|
|
49
|
-
}
|
|
50
|
-
attach(elementId, element, eventName, actionName) {
|
|
51
|
-
const domEventName = eventName === "onClick" ? "click" : eventName;
|
|
52
|
-
log.debug(`Attaching ${eventName} (DOM: ${domEventName}) to element ${elementId}, action: ${actionName}`);
|
|
53
|
-
const listener = (event) => {
|
|
54
|
-
log.debug(`Event fired: ${eventName} on ${elementId}, dispatching action: ${actionName}`);
|
|
55
|
-
log.debug(`Event object:`, event);
|
|
56
|
-
log.debug(`Element:`, element);
|
|
57
|
-
if (eventName === "submit" || eventName === "click" && element.tagName === "A") {
|
|
58
|
-
event.preventDefault();
|
|
59
|
-
}
|
|
60
|
-
const payload = this.extractEventData(event, element);
|
|
61
|
-
log.debug(`Event payload:`, payload);
|
|
62
|
-
log.debug(`Calling engine.dispatchAction(${actionName})`);
|
|
63
|
-
try {
|
|
64
|
-
this.engine.dispatchAction(actionName, payload);
|
|
65
|
-
log.debug(`dispatchAction succeeded`);
|
|
66
|
-
} catch (error) {
|
|
67
|
-
log.error(`dispatchAction failed:`, error);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
let elementBindings = this.bindings.get(elementId);
|
|
71
|
-
if (!elementBindings) {
|
|
72
|
-
elementBindings = new Map;
|
|
73
|
-
this.bindings.set(elementId, elementBindings);
|
|
74
|
-
}
|
|
75
|
-
const existingListener = elementBindings.get(domEventName);
|
|
76
|
-
if (existingListener) {
|
|
77
|
-
element.removeEventListener(domEventName, existingListener);
|
|
7
|
+
const log = frameworkLoggers.events;
|
|
8
|
+
export class EventManager {
|
|
9
|
+
engine;
|
|
10
|
+
bindings = new Map();
|
|
11
|
+
constructor(engine) {
|
|
12
|
+
this.engine = engine;
|
|
78
13
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Attach an event listener to an element
|
|
16
|
+
*/
|
|
17
|
+
attach(elementId, element, eventName, actionName) {
|
|
18
|
+
// Convert onClick to click for DOM events
|
|
19
|
+
const domEventName = eventName === "onClick" ? "click" : eventName;
|
|
20
|
+
log.debug(`Attaching ${eventName} (DOM: ${domEventName}) to element ${elementId}, action: ${actionName}`);
|
|
21
|
+
// Create event listener that dispatches action
|
|
22
|
+
const listener = (event) => {
|
|
23
|
+
log.debug(`Event fired: ${eventName} on ${elementId}, dispatching action: ${actionName}`);
|
|
24
|
+
log.debug(`Event object:`, event);
|
|
25
|
+
log.debug(`Element:`, element);
|
|
26
|
+
// Prevent default for certain events
|
|
27
|
+
if (eventName === "submit" || (eventName === "click" && element.tagName === "A")) {
|
|
28
|
+
event.preventDefault();
|
|
29
|
+
}
|
|
30
|
+
// Extract event data
|
|
31
|
+
const payload = this.extractEventData(event, element);
|
|
32
|
+
log.debug(`Event payload:`, payload);
|
|
33
|
+
// Dispatch action to engine
|
|
34
|
+
log.debug(`Calling engine.dispatchAction(${actionName})`);
|
|
35
|
+
try {
|
|
36
|
+
this.engine.dispatchAction(actionName, payload);
|
|
37
|
+
log.debug(`dispatchAction succeeded`);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
log.error(`dispatchAction failed:`, error);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
// Store listener reference using `domEventName` so `detach()` uses the correct name
|
|
44
|
+
let elementBindings = this.bindings.get(elementId);
|
|
45
|
+
if (!elementBindings) {
|
|
46
|
+
elementBindings = new Map();
|
|
47
|
+
this.bindings.set(elementId, elementBindings);
|
|
48
|
+
}
|
|
49
|
+
// Remove any previously attached listener for this event before overwriting,
|
|
50
|
+
// otherwise the old DOM listener leaks and fires alongside the new one.
|
|
51
|
+
const existingListener = elementBindings.get(domEventName);
|
|
52
|
+
if (existingListener) {
|
|
53
|
+
element.removeEventListener(domEventName, existingListener);
|
|
54
|
+
}
|
|
55
|
+
elementBindings.set(domEventName, listener);
|
|
56
|
+
// Attach to DOM
|
|
57
|
+
element.addEventListener(domEventName, listener);
|
|
58
|
+
log.debug(`Listener attached to DOM for ${domEventName}`);
|
|
59
|
+
log.debug(`Element details:`, {
|
|
60
|
+
tagName: element.tagName,
|
|
61
|
+
id: element.id,
|
|
62
|
+
dataset: element.dataset,
|
|
63
|
+
textContent: element.textContent?.substring(0, 50)
|
|
64
|
+
});
|
|
120
65
|
}
|
|
121
|
-
|
|
122
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Detach an event listener from an element
|
|
68
|
+
*/
|
|
69
|
+
detach(elementId, element, eventName) {
|
|
70
|
+
// Convert framework event name to DOM event name, matching `attach()`
|
|
71
|
+
const domEventName = eventName === "onClick" ? "click" : eventName;
|
|
72
|
+
const elementBindings = this.bindings.get(elementId);
|
|
73
|
+
if (!elementBindings)
|
|
74
|
+
return;
|
|
75
|
+
const listener = elementBindings.get(domEventName);
|
|
76
|
+
if (listener) {
|
|
77
|
+
element.removeEventListener(domEventName, listener);
|
|
78
|
+
elementBindings.delete(domEventName);
|
|
79
|
+
}
|
|
80
|
+
if (elementBindings.size === 0) {
|
|
81
|
+
this.bindings.delete(elementId);
|
|
82
|
+
}
|
|
123
83
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Extract relevant data from an event
|
|
86
|
+
*/
|
|
87
|
+
extractEventData(event, element) {
|
|
88
|
+
const data = {
|
|
89
|
+
type: event.type,
|
|
90
|
+
timestamp: Date.now(),
|
|
91
|
+
};
|
|
92
|
+
// Mouse events
|
|
93
|
+
if (event instanceof MouseEvent) {
|
|
94
|
+
data.clientX = event.clientX;
|
|
95
|
+
data.clientY = event.clientY;
|
|
96
|
+
data.button = event.button;
|
|
97
|
+
}
|
|
98
|
+
// Keyboard events
|
|
99
|
+
if (event instanceof KeyboardEvent) {
|
|
100
|
+
data.key = event.key;
|
|
101
|
+
data.code = event.code;
|
|
102
|
+
data.ctrlKey = event.ctrlKey;
|
|
103
|
+
data.shiftKey = event.shiftKey;
|
|
104
|
+
data.altKey = event.altKey;
|
|
105
|
+
data.metaKey = event.metaKey;
|
|
106
|
+
}
|
|
107
|
+
// Input events (for form elements)
|
|
108
|
+
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
|
|
109
|
+
data.value = element.value;
|
|
110
|
+
}
|
|
111
|
+
// Select events
|
|
112
|
+
if (element instanceof HTMLSelectElement) {
|
|
113
|
+
data.value = element.value;
|
|
114
|
+
data.selectedIndex = element.selectedIndex;
|
|
115
|
+
}
|
|
116
|
+
// Form events
|
|
117
|
+
if (event.type === "submit" && element instanceof HTMLFormElement) {
|
|
118
|
+
data.formData = new FormData(element);
|
|
119
|
+
}
|
|
120
|
+
return data;
|
|
127
121
|
}
|
|
128
|
-
|
|
129
|
-
|
|
122
|
+
/**
|
|
123
|
+
* Clear all event bindings for an element
|
|
124
|
+
*/
|
|
125
|
+
clearElement(elementId, element) {
|
|
126
|
+
const elementBindings = this.bindings.get(elementId);
|
|
127
|
+
if (!elementBindings)
|
|
128
|
+
return;
|
|
129
|
+
for (const [eventName, listener] of elementBindings) {
|
|
130
|
+
element.removeEventListener(eventName, listener);
|
|
131
|
+
}
|
|
132
|
+
this.bindings.delete(elementId);
|
|
130
133
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return;
|
|
137
|
-
for (const [eventName, listener] of elementBindings) {
|
|
138
|
-
element.removeEventListener(eventName, listener);
|
|
134
|
+
/**
|
|
135
|
+
* Clear all event bindings
|
|
136
|
+
*/
|
|
137
|
+
clearAll() {
|
|
138
|
+
this.bindings.clear();
|
|
139
139
|
}
|
|
140
|
-
this.bindings.delete(elementId);
|
|
141
|
-
}
|
|
142
|
-
clearAll() {
|
|
143
|
-
this.bindings.clear();
|
|
144
|
-
}
|
|
145
140
|
}
|
|
146
|
-
|
|
147
|
-
EventManager
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
//# debugId=0AF5B59AAE95400964756E2164756E21
|
|
141
|
+
//# sourceMappingURL=events.js.map
|