@coherent.js/client 1.0.0-rc.1 → 1.0.0-rc.3
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/chunk-N36BSMJU.js +201 -0
- package/dist/chunk-N36BSMJU.js.map +7 -0
- package/dist/events/index.js +15 -0
- package/dist/events/index.js.map +7 -0
- package/dist/hmr.js +5 -0
- package/dist/hmr.js.map +7 -0
- package/dist/index.js +8 -192
- package/dist/index.js.map +3 -3
- package/dist/router.js +386 -0
- package/dist/router.js.map +7 -0
- package/package.json +6 -7
- package/types/events.d.ts +7 -0
- package/src/index.js +0 -53
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// src/events/registry.js
|
|
2
|
+
var HandlerRegistry = class {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.handlers = /* @__PURE__ */ new Map();
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Register a handler with optional component context
|
|
8
|
+
* @param {string} handlerId - Unique identifier for the handler
|
|
9
|
+
* @param {Function} handler - The event handler function
|
|
10
|
+
* @param {object|null} componentRef - Optional component reference with state/setState
|
|
11
|
+
*/
|
|
12
|
+
register(handlerId, handler, componentRef = null) {
|
|
13
|
+
if (typeof handler !== "function") {
|
|
14
|
+
throw new Error(`Handler must be a function, received: ${typeof handler}`);
|
|
15
|
+
}
|
|
16
|
+
this.handlers.set(handlerId, { handler, componentRef });
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Unregister a handler by ID
|
|
20
|
+
* @param {string} handlerId - The handler ID to remove
|
|
21
|
+
* @returns {boolean} True if handler was removed, false if not found
|
|
22
|
+
*/
|
|
23
|
+
unregister(handlerId) {
|
|
24
|
+
return this.handlers.delete(handlerId);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get a handler entry by ID
|
|
28
|
+
* @param {string} handlerId - The handler ID to look up
|
|
29
|
+
* @returns {{handler: Function, componentRef: object|null}|undefined} Handler entry or undefined
|
|
30
|
+
*/
|
|
31
|
+
get(handlerId) {
|
|
32
|
+
return this.handlers.get(handlerId);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check if a handler is registered
|
|
36
|
+
* @param {string} handlerId - The handler ID to check
|
|
37
|
+
* @returns {boolean} True if handler exists
|
|
38
|
+
*/
|
|
39
|
+
has(handlerId) {
|
|
40
|
+
return this.handlers.has(handlerId);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Clear all registered handlers
|
|
44
|
+
*/
|
|
45
|
+
clear() {
|
|
46
|
+
this.handlers.clear();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get all handler IDs registered for a specific component
|
|
50
|
+
* @param {object} componentRef - The component reference to search for
|
|
51
|
+
* @returns {string[]} Array of handler IDs belonging to this component
|
|
52
|
+
*/
|
|
53
|
+
getByComponent(componentRef) {
|
|
54
|
+
if (!componentRef) {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
const handlerIds = [];
|
|
58
|
+
for (const [handlerId, entry] of this.handlers) {
|
|
59
|
+
if (entry.componentRef === componentRef) {
|
|
60
|
+
handlerIds.push(handlerId);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return handlerIds;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get the number of registered handlers
|
|
67
|
+
* @returns {number} Count of registered handlers
|
|
68
|
+
*/
|
|
69
|
+
get size() {
|
|
70
|
+
return this.handlers.size;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var handlerRegistry = new HandlerRegistry();
|
|
74
|
+
|
|
75
|
+
// src/events/wrapper.js
|
|
76
|
+
function wrapEvent(originalEvent, target, componentRef = null) {
|
|
77
|
+
return {
|
|
78
|
+
// Native event access
|
|
79
|
+
originalEvent,
|
|
80
|
+
target,
|
|
81
|
+
// Delegate common methods
|
|
82
|
+
preventDefault() {
|
|
83
|
+
originalEvent.preventDefault();
|
|
84
|
+
},
|
|
85
|
+
stopPropagation() {
|
|
86
|
+
originalEvent.stopPropagation();
|
|
87
|
+
},
|
|
88
|
+
// Component context (null if no componentRef provided)
|
|
89
|
+
component: componentRef?.component ?? null,
|
|
90
|
+
state: componentRef?.state ?? null,
|
|
91
|
+
setState: componentRef?.setState ?? null,
|
|
92
|
+
props: componentRef?.props ?? null
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// src/events/delegation.js
|
|
97
|
+
var EventDelegation = class {
|
|
98
|
+
/**
|
|
99
|
+
* @param {import('./registry.js').HandlerRegistry} [registry] - Handler registry instance
|
|
100
|
+
*/
|
|
101
|
+
constructor(registry = handlerRegistry) {
|
|
102
|
+
this.registry = registry;
|
|
103
|
+
this.initialized = false;
|
|
104
|
+
this.root = null;
|
|
105
|
+
this.boundHandlers = /* @__PURE__ */ new Map();
|
|
106
|
+
this.eventTypes = [
|
|
107
|
+
"click",
|
|
108
|
+
"change",
|
|
109
|
+
"input",
|
|
110
|
+
"submit",
|
|
111
|
+
"focus",
|
|
112
|
+
"blur",
|
|
113
|
+
"keydown",
|
|
114
|
+
"keyup",
|
|
115
|
+
"keypress"
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Initialize event delegation by attaching listeners to the root element
|
|
120
|
+
* @param {Document|Element} [root=document] - Root element for event delegation
|
|
121
|
+
*/
|
|
122
|
+
initialize(root = typeof document !== "undefined" ? document : null) {
|
|
123
|
+
if (this.initialized) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (!root) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this.root = root;
|
|
130
|
+
for (const eventType of this.eventTypes) {
|
|
131
|
+
const handler = (event) => this.handleEvent(event, eventType);
|
|
132
|
+
const useCapture = eventType === "focus" || eventType === "blur";
|
|
133
|
+
const options = {
|
|
134
|
+
capture: useCapture,
|
|
135
|
+
passive: eventType !== "submit"
|
|
136
|
+
};
|
|
137
|
+
root.addEventListener(eventType, handler, options);
|
|
138
|
+
this.boundHandlers.set(eventType, { handler, options });
|
|
139
|
+
}
|
|
140
|
+
this.initialized = true;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Handle a delegated event
|
|
144
|
+
* @param {Event} event - The DOM event
|
|
145
|
+
* @param {string} eventType - The type of event (click, change, etc.)
|
|
146
|
+
*/
|
|
147
|
+
handleEvent(event, eventType) {
|
|
148
|
+
const target = event.target;
|
|
149
|
+
if (!target || typeof target.closest !== "function") {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const attrName = `data-coherent-${eventType}`;
|
|
153
|
+
const delegateTarget = target.closest(`[${attrName}]`);
|
|
154
|
+
if (!delegateTarget) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const handlerId = delegateTarget.getAttribute(attrName);
|
|
158
|
+
if (!handlerId) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const entry = this.registry.get(handlerId);
|
|
162
|
+
if (!entry) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const wrappedEvent = wrapEvent(event, delegateTarget, entry.componentRef);
|
|
166
|
+
entry.handler(wrappedEvent);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Destroy the event delegation system
|
|
170
|
+
* Removes all listeners and clears the registry
|
|
171
|
+
*/
|
|
172
|
+
destroy() {
|
|
173
|
+
if (!this.initialized || !this.root) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
for (const [eventType, { handler, options }] of this.boundHandlers) {
|
|
177
|
+
this.root.removeEventListener(eventType, handler, options);
|
|
178
|
+
}
|
|
179
|
+
this.boundHandlers.clear();
|
|
180
|
+
this.registry.clear();
|
|
181
|
+
this.initialized = false;
|
|
182
|
+
this.root = null;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Check if the delegation system is initialized
|
|
186
|
+
* @returns {boolean} True if initialized
|
|
187
|
+
*/
|
|
188
|
+
isInitialized() {
|
|
189
|
+
return this.initialized;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
var eventDelegation = new EventDelegation();
|
|
193
|
+
|
|
194
|
+
export {
|
|
195
|
+
HandlerRegistry,
|
|
196
|
+
handlerRegistry,
|
|
197
|
+
wrapEvent,
|
|
198
|
+
EventDelegation,
|
|
199
|
+
eventDelegation
|
|
200
|
+
};
|
|
201
|
+
//# sourceMappingURL=chunk-N36BSMJU.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/events/registry.js", "../src/events/wrapper.js", "../src/events/delegation.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * Handler Registry for Coherent.js Event Delegation\n *\n * Maps handler IDs to their corresponding functions and component context.\n * Handlers are identified by ID (from data-coherent-{event} attributes) rather\n * than by element reference, allowing them to survive DOM updates.\n */\n\n/**\n * HandlerRegistry class\n * Stores handler functions with their associated component context\n */\nexport class HandlerRegistry {\n constructor() {\n /** @type {Map<string, {handler: Function, componentRef: object|null}>} */\n this.handlers = new Map();\n }\n\n /**\n * Register a handler with optional component context\n * @param {string} handlerId - Unique identifier for the handler\n * @param {Function} handler - The event handler function\n * @param {object|null} componentRef - Optional component reference with state/setState\n */\n register(handlerId, handler, componentRef = null) {\n if (typeof handler !== 'function') {\n throw new Error(`Handler must be a function, received: ${typeof handler}`);\n }\n this.handlers.set(handlerId, { handler, componentRef });\n }\n\n /**\n * Unregister a handler by ID\n * @param {string} handlerId - The handler ID to remove\n * @returns {boolean} True if handler was removed, false if not found\n */\n unregister(handlerId) {\n return this.handlers.delete(handlerId);\n }\n\n /**\n * Get a handler entry by ID\n * @param {string} handlerId - The handler ID to look up\n * @returns {{handler: Function, componentRef: object|null}|undefined} Handler entry or undefined\n */\n get(handlerId) {\n return this.handlers.get(handlerId);\n }\n\n /**\n * Check if a handler is registered\n * @param {string} handlerId - The handler ID to check\n * @returns {boolean} True if handler exists\n */\n has(handlerId) {\n return this.handlers.has(handlerId);\n }\n\n /**\n * Clear all registered handlers\n */\n clear() {\n this.handlers.clear();\n }\n\n /**\n * Get all handler IDs registered for a specific component\n * @param {object} componentRef - The component reference to search for\n * @returns {string[]} Array of handler IDs belonging to this component\n */\n getByComponent(componentRef) {\n if (!componentRef) {\n return [];\n }\n\n const handlerIds = [];\n for (const [handlerId, entry] of this.handlers) {\n if (entry.componentRef === componentRef) {\n handlerIds.push(handlerId);\n }\n }\n return handlerIds;\n }\n\n /**\n * Get the number of registered handlers\n * @returns {number} Count of registered handlers\n */\n get size() {\n return this.handlers.size;\n }\n}\n\n/**\n * Singleton handler registry instance\n * Use this for global event delegation\n */\nexport const handlerRegistry = new HandlerRegistry();\n", "/**\n * Event Wrapper for Coherent.js\n *\n * Wraps native DOM events with component context, providing handlers\n * access to component state, setState, and props.\n */\n\n/**\n * @typedef {object} CoherentEvent\n * @property {Event} originalEvent - The native DOM event\n * @property {Element} target - The element with the data-coherent-* attribute\n * @property {function(): void} preventDefault - Delegates to originalEvent.preventDefault()\n * @property {function(): void} stopPropagation - Delegates to originalEvent.stopPropagation()\n * @property {function|null} component - The component function (if available)\n * @property {object|null} state - Current component state (if available)\n * @property {function|null} setState - State setter function (if available)\n * @property {object|null} props - Component props (if available)\n */\n\n/**\n * Wrap a native DOM event with component context\n *\n * @param {Event} originalEvent - The native DOM event\n * @param {Element} target - The element that matched the data attribute selector\n * @param {object|null} componentRef - Optional component reference object\n * @param {function} [componentRef.component] - The component function\n * @param {object} [componentRef.state] - Current component state\n * @param {function} [componentRef.setState] - State setter function\n * @param {object} [componentRef.props] - Component props\n * @returns {CoherentEvent} Wrapped event with component context\n */\nexport function wrapEvent(originalEvent, target, componentRef = null) {\n return {\n // Native event access\n originalEvent,\n target,\n\n // Delegate common methods\n preventDefault() {\n originalEvent.preventDefault();\n },\n\n stopPropagation() {\n originalEvent.stopPropagation();\n },\n\n // Component context (null if no componentRef provided)\n component: componentRef?.component ?? null,\n state: componentRef?.state ?? null,\n setState: componentRef?.setState ?? null,\n props: componentRef?.props ?? null,\n };\n}\n", "/**\n * Event Delegation for Coherent.js\n *\n * Document-level event delegation that routes events to handlers via\n * data-coherent-{eventType} attributes. This ensures event handlers\n * survive DOM updates since they're registered by ID, not by element.\n */\n\nimport { handlerRegistry as defaultRegistry } from './registry.js';\nimport { wrapEvent } from './wrapper.js';\n\n/**\n * EventDelegation class\n * Manages document-level event listeners and routes to registered handlers\n */\nexport class EventDelegation {\n /**\n * @param {import('./registry.js').HandlerRegistry} [registry] - Handler registry instance\n */\n constructor(registry = defaultRegistry) {\n this.registry = registry;\n this.initialized = false;\n this.root = null;\n this.boundHandlers = new Map();\n\n /**\n * Event types to delegate\n * Focus/blur use capture phase because they don't bubble\n */\n this.eventTypes = [\n 'click',\n 'change',\n 'input',\n 'submit',\n 'focus',\n 'blur',\n 'keydown',\n 'keyup',\n 'keypress',\n ];\n }\n\n /**\n * Initialize event delegation by attaching listeners to the root element\n * @param {Document|Element} [root=document] - Root element for event delegation\n */\n initialize(root = typeof document !== 'undefined' ? document : null) {\n if (this.initialized) {\n return;\n }\n\n if (!root) {\n // No DOM available (SSR context)\n return;\n }\n\n this.root = root;\n\n for (const eventType of this.eventTypes) {\n const handler = (event) => this.handleEvent(event, eventType);\n\n // Focus and blur don't bubble - must use capture phase\n const useCapture = eventType === 'focus' || eventType === 'blur';\n\n // Submit needs preventDefault capability, others can be passive\n const options = {\n capture: useCapture,\n passive: eventType !== 'submit',\n };\n\n root.addEventListener(eventType, handler, options);\n this.boundHandlers.set(eventType, { handler, options });\n }\n\n this.initialized = true;\n }\n\n /**\n * Handle a delegated event\n * @param {Event} event - The DOM event\n * @param {string} eventType - The type of event (click, change, etc.)\n */\n handleEvent(event, eventType) {\n const target = event.target;\n if (!target || typeof target.closest !== 'function') {\n return;\n }\n\n // Find the nearest element with the appropriate data attribute\n const attrName = `data-coherent-${eventType}`;\n const delegateTarget = target.closest(`[${attrName}]`);\n\n if (!delegateTarget) {\n return;\n }\n\n // Get the handler ID from the attribute\n const handlerId = delegateTarget.getAttribute(attrName);\n if (!handlerId) {\n return;\n }\n\n // Look up the handler in the registry\n const entry = this.registry.get(handlerId);\n if (!entry) {\n return;\n }\n\n // Wrap the event with component context and call the handler\n const wrappedEvent = wrapEvent(event, delegateTarget, entry.componentRef);\n entry.handler(wrappedEvent);\n }\n\n /**\n * Destroy the event delegation system\n * Removes all listeners and clears the registry\n */\n destroy() {\n if (!this.initialized || !this.root) {\n return;\n }\n\n // Remove all event listeners\n for (const [eventType, { handler, options }] of this.boundHandlers) {\n this.root.removeEventListener(eventType, handler, options);\n }\n\n this.boundHandlers.clear();\n this.registry.clear();\n this.initialized = false;\n this.root = null;\n }\n\n /**\n * Check if the delegation system is initialized\n * @returns {boolean} True if initialized\n */\n isInitialized() {\n return this.initialized;\n }\n}\n\n/**\n * Singleton event delegation instance\n * Use this for global event delegation\n */\nexport const eventDelegation = new EventDelegation();\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EventDelegation,
|
|
3
|
+
HandlerRegistry,
|
|
4
|
+
eventDelegation,
|
|
5
|
+
handlerRegistry,
|
|
6
|
+
wrapEvent
|
|
7
|
+
} from "../chunk-N36BSMJU.js";
|
|
8
|
+
export {
|
|
9
|
+
EventDelegation,
|
|
10
|
+
HandlerRegistry,
|
|
11
|
+
eventDelegation,
|
|
12
|
+
handlerRegistry,
|
|
13
|
+
wrapEvent
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
package/dist/hmr.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// src/hmr.js
|
|
2
|
+
throw new Error(
|
|
3
|
+
"Coherent.js 1.0: importing '@coherent.js/client/src/hmr.js' was removed. Import { hmrClient } from '@coherent.js/client' and call hmrClient.connect() instead. See https://coherentjs.dev/docs/migration/1.0#removed-client-hmr-shim"
|
|
4
|
+
);
|
|
5
|
+
//# sourceMappingURL=hmr.js.map
|
package/dist/hmr.js.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/hmr.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * Coherent.js HMR \u2014 legacy module entrypoint\n *\n * REMOVED in 1.0. This file existed in beta to auto-initialize HMR on import.\n * Direct imports of this path now throw immediately so callers see the\n * migration instruction instead of silent failures further down the call stack.\n *\n * @module @coherent.js/client/hmr\n */\n\nthrow new Error(\n \"Coherent.js 1.0: importing '@coherent.js/client/src/hmr.js' was removed. \" +\n \"Import { hmrClient } from '@coherent.js/client' and call hmrClient.connect() instead. \" +\n \"See https://coherentjs.dev/docs/migration/1.0#removed-client-hmr-shim\"\n);\n"],
|
|
5
|
+
"mappings": ";AAUA,MAAM,IAAI;AAAA,EACR;AAGF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,195 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* @param {string} handlerId - Unique identifier for the handler
|
|
9
|
-
* @param {Function} handler - The event handler function
|
|
10
|
-
* @param {object|null} componentRef - Optional component reference with state/setState
|
|
11
|
-
*/
|
|
12
|
-
register(handlerId, handler, componentRef = null) {
|
|
13
|
-
if (typeof handler !== "function") {
|
|
14
|
-
throw new Error(`Handler must be a function, received: ${typeof handler}`);
|
|
15
|
-
}
|
|
16
|
-
this.handlers.set(handlerId, { handler, componentRef });
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Unregister a handler by ID
|
|
20
|
-
* @param {string} handlerId - The handler ID to remove
|
|
21
|
-
* @returns {boolean} True if handler was removed, false if not found
|
|
22
|
-
*/
|
|
23
|
-
unregister(handlerId) {
|
|
24
|
-
return this.handlers.delete(handlerId);
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Get a handler entry by ID
|
|
28
|
-
* @param {string} handlerId - The handler ID to look up
|
|
29
|
-
* @returns {{handler: Function, componentRef: object|null}|undefined} Handler entry or undefined
|
|
30
|
-
*/
|
|
31
|
-
get(handlerId) {
|
|
32
|
-
return this.handlers.get(handlerId);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Check if a handler is registered
|
|
36
|
-
* @param {string} handlerId - The handler ID to check
|
|
37
|
-
* @returns {boolean} True if handler exists
|
|
38
|
-
*/
|
|
39
|
-
has(handlerId) {
|
|
40
|
-
return this.handlers.has(handlerId);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Clear all registered handlers
|
|
44
|
-
*/
|
|
45
|
-
clear() {
|
|
46
|
-
this.handlers.clear();
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Get all handler IDs registered for a specific component
|
|
50
|
-
* @param {object} componentRef - The component reference to search for
|
|
51
|
-
* @returns {string[]} Array of handler IDs belonging to this component
|
|
52
|
-
*/
|
|
53
|
-
getByComponent(componentRef) {
|
|
54
|
-
if (!componentRef) {
|
|
55
|
-
return [];
|
|
56
|
-
}
|
|
57
|
-
const handlerIds = [];
|
|
58
|
-
for (const [handlerId, entry] of this.handlers) {
|
|
59
|
-
if (entry.componentRef === componentRef) {
|
|
60
|
-
handlerIds.push(handlerId);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return handlerIds;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Get the number of registered handlers
|
|
67
|
-
* @returns {number} Count of registered handlers
|
|
68
|
-
*/
|
|
69
|
-
get size() {
|
|
70
|
-
return this.handlers.size;
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
var handlerRegistry = new HandlerRegistry();
|
|
74
|
-
|
|
75
|
-
// src/events/wrapper.js
|
|
76
|
-
function wrapEvent(originalEvent, target, componentRef = null) {
|
|
77
|
-
return {
|
|
78
|
-
// Native event access
|
|
79
|
-
originalEvent,
|
|
80
|
-
target,
|
|
81
|
-
// Delegate common methods
|
|
82
|
-
preventDefault() {
|
|
83
|
-
originalEvent.preventDefault();
|
|
84
|
-
},
|
|
85
|
-
stopPropagation() {
|
|
86
|
-
originalEvent.stopPropagation();
|
|
87
|
-
},
|
|
88
|
-
// Component context (null if no componentRef provided)
|
|
89
|
-
component: componentRef?.component ?? null,
|
|
90
|
-
state: componentRef?.state ?? null,
|
|
91
|
-
setState: componentRef?.setState ?? null,
|
|
92
|
-
props: componentRef?.props ?? null
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// src/events/delegation.js
|
|
97
|
-
var EventDelegation = class {
|
|
98
|
-
/**
|
|
99
|
-
* @param {import('./registry.js').HandlerRegistry} [registry] - Handler registry instance
|
|
100
|
-
*/
|
|
101
|
-
constructor(registry = handlerRegistry) {
|
|
102
|
-
this.registry = registry;
|
|
103
|
-
this.initialized = false;
|
|
104
|
-
this.root = null;
|
|
105
|
-
this.boundHandlers = /* @__PURE__ */ new Map();
|
|
106
|
-
this.eventTypes = [
|
|
107
|
-
"click",
|
|
108
|
-
"change",
|
|
109
|
-
"input",
|
|
110
|
-
"submit",
|
|
111
|
-
"focus",
|
|
112
|
-
"blur",
|
|
113
|
-
"keydown",
|
|
114
|
-
"keyup",
|
|
115
|
-
"keypress"
|
|
116
|
-
];
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Initialize event delegation by attaching listeners to the root element
|
|
120
|
-
* @param {Document|Element} [root=document] - Root element for event delegation
|
|
121
|
-
*/
|
|
122
|
-
initialize(root = typeof document !== "undefined" ? document : null) {
|
|
123
|
-
if (this.initialized) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
if (!root) {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
this.root = root;
|
|
130
|
-
for (const eventType of this.eventTypes) {
|
|
131
|
-
const handler = (event) => this.handleEvent(event, eventType);
|
|
132
|
-
const useCapture = eventType === "focus" || eventType === "blur";
|
|
133
|
-
const options = {
|
|
134
|
-
capture: useCapture,
|
|
135
|
-
passive: eventType !== "submit"
|
|
136
|
-
};
|
|
137
|
-
root.addEventListener(eventType, handler, options);
|
|
138
|
-
this.boundHandlers.set(eventType, { handler, options });
|
|
139
|
-
}
|
|
140
|
-
this.initialized = true;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Handle a delegated event
|
|
144
|
-
* @param {Event} event - The DOM event
|
|
145
|
-
* @param {string} eventType - The type of event (click, change, etc.)
|
|
146
|
-
*/
|
|
147
|
-
handleEvent(event, eventType) {
|
|
148
|
-
const target = event.target;
|
|
149
|
-
if (!target || typeof target.closest !== "function") {
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
const attrName = `data-coherent-${eventType}`;
|
|
153
|
-
const delegateTarget = target.closest(`[${attrName}]`);
|
|
154
|
-
if (!delegateTarget) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
const handlerId = delegateTarget.getAttribute(attrName);
|
|
158
|
-
if (!handlerId) {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
const entry = this.registry.get(handlerId);
|
|
162
|
-
if (!entry) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
const wrappedEvent = wrapEvent(event, delegateTarget, entry.componentRef);
|
|
166
|
-
entry.handler(wrappedEvent);
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Destroy the event delegation system
|
|
170
|
-
* Removes all listeners and clears the registry
|
|
171
|
-
*/
|
|
172
|
-
destroy() {
|
|
173
|
-
if (!this.initialized || !this.root) {
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
for (const [eventType, { handler, options }] of this.boundHandlers) {
|
|
177
|
-
this.root.removeEventListener(eventType, handler, options);
|
|
178
|
-
}
|
|
179
|
-
this.boundHandlers.clear();
|
|
180
|
-
this.registry.clear();
|
|
181
|
-
this.initialized = false;
|
|
182
|
-
this.root = null;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Check if the delegation system is initialized
|
|
186
|
-
* @returns {boolean} True if initialized
|
|
187
|
-
*/
|
|
188
|
-
isInitialized() {
|
|
189
|
-
return this.initialized;
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
var eventDelegation = new EventDelegation();
|
|
1
|
+
import {
|
|
2
|
+
EventDelegation,
|
|
3
|
+
HandlerRegistry,
|
|
4
|
+
eventDelegation,
|
|
5
|
+
handlerRegistry,
|
|
6
|
+
wrapEvent
|
|
7
|
+
} from "./chunk-N36BSMJU.js";
|
|
193
8
|
|
|
194
9
|
// src/hydration/state-serializer.js
|
|
195
10
|
function serializeState(state) {
|
|
@@ -512,6 +327,7 @@ function hydrate(component, container, options = {}) {
|
|
|
512
327
|
eventDelegation.initialize();
|
|
513
328
|
const {
|
|
514
329
|
initialState: providedState,
|
|
330
|
+
// eslint-disable-next-line no-restricted-globals -- statically replaced by esbuild `define` at build time
|
|
515
331
|
detectMismatch: shouldDetectMismatch = true,
|
|
516
332
|
strict = false,
|
|
517
333
|
onMismatch,
|