defuss-morph 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -6
- package/dist/all.js +209 -253
- package/dist/all.js.map +7 -7
- package/dist/all.min.js +1 -1
- package/dist/all.min.js.map +1 -1
- package/dist/index.cjs +199 -249
- package/dist/index.d.ts +32 -4
- package/dist/index.mjs +197 -250
- package/dist/stats.json +9 -9
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -9,8 +9,7 @@ const CAPTURE_ONLY_EVENTS = /* @__PURE__ */ new Set([
|
|
|
9
9
|
// Note: focusin/focusout DO bubble, so they're not included here
|
|
10
10
|
]);
|
|
11
11
|
const elementHandlerMap = /* @__PURE__ */ new WeakMap();
|
|
12
|
-
const
|
|
13
|
-
const captureDispatched = /* @__PURE__ */ new WeakMap();
|
|
12
|
+
const slotListeners = /* @__PURE__ */ new WeakMap();
|
|
14
13
|
const activeDispatches = /* @__PURE__ */ new WeakMap();
|
|
15
14
|
const parseEventPropName = (propName) => {
|
|
16
15
|
if (!propName.startsWith("on")) return null;
|
|
@@ -29,147 +28,64 @@ const getOrCreateElementHandlers = (el) => {
|
|
|
29
28
|
elementHandlerMap.set(el, created);
|
|
30
29
|
return created;
|
|
31
30
|
};
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
35
|
-
const
|
|
36
|
-
let
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
const runSlot = (target, eventType, phase, event) => {
|
|
32
|
+
const handler = elementHandlerMap.get(target)?.get(eventType)?.[phase];
|
|
33
|
+
if (!handler) return;
|
|
34
|
+
const dispatchKey = `${eventType}:${phase}`;
|
|
35
|
+
let active = activeDispatches.get(target);
|
|
36
|
+
if (active?.has(dispatchKey)) return;
|
|
37
|
+
if (!active) {
|
|
38
|
+
active = /* @__PURE__ */ new Set();
|
|
39
|
+
activeDispatches.set(target, active);
|
|
40
|
+
}
|
|
41
|
+
active.add(dispatchKey);
|
|
42
|
+
try {
|
|
43
|
+
handler.call(target, event);
|
|
44
|
+
} finally {
|
|
45
|
+
active.delete(dispatchKey);
|
|
45
46
|
}
|
|
46
|
-
const doc = event.target?.ownerDocument;
|
|
47
|
-
if (doc && path[path.length - 1] !== doc) path.push(doc);
|
|
48
|
-
const win = doc?.defaultView;
|
|
49
|
-
if (win && path[path.length - 1] !== win) path.push(win);
|
|
50
|
-
return path;
|
|
51
47
|
};
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const entry = handlersByEvent.get(eventType);
|
|
63
|
-
if (!entry) continue;
|
|
64
|
-
let targets = dispatched.get(event);
|
|
65
|
-
if (targets?.has(target)) continue;
|
|
66
|
-
if (!targets) {
|
|
67
|
-
targets = /* @__PURE__ */ new WeakSet();
|
|
68
|
-
dispatched.set(event, targets);
|
|
69
|
-
}
|
|
70
|
-
targets.add(target);
|
|
71
|
-
const dispatchKey = `${eventType}:${phase}`;
|
|
72
|
-
let activeSet = activeDispatches.get(target);
|
|
73
|
-
if (activeSet?.has(dispatchKey)) continue;
|
|
74
|
-
if (!activeSet) {
|
|
75
|
-
activeSet = /* @__PURE__ */ new Set();
|
|
76
|
-
activeDispatches.set(target, activeSet);
|
|
77
|
-
}
|
|
78
|
-
activeSet.add(dispatchKey);
|
|
79
|
-
try {
|
|
80
|
-
if (phase === "capture") {
|
|
81
|
-
if (entry.capture) {
|
|
82
|
-
entry.capture.call(target, event);
|
|
83
|
-
if (event.cancelBubble)
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
if (entry.captureSet) {
|
|
87
|
-
for (const handler of entry.captureSet) {
|
|
88
|
-
handler.call(target, event);
|
|
89
|
-
if (event.cancelBubble)
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
} else {
|
|
94
|
-
if (entry.bubble) {
|
|
95
|
-
entry.bubble.call(target, event);
|
|
96
|
-
if (event.cancelBubble)
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
if (entry.bubbleSet) {
|
|
100
|
-
for (const handler of entry.bubbleSet) {
|
|
101
|
-
handler.call(target, event);
|
|
102
|
-
if (event.cancelBubble)
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
} finally {
|
|
108
|
-
activeSet.delete(dispatchKey);
|
|
109
|
-
}
|
|
48
|
+
const setSlot = (target, eventType, phase, entry, handler) => {
|
|
49
|
+
entry[phase] = handler;
|
|
50
|
+
const key = `${eventType}:${phase}`;
|
|
51
|
+
const capture = phase === "capture";
|
|
52
|
+
let byKey = slotListeners.get(target);
|
|
53
|
+
const installed = byKey?.get(key);
|
|
54
|
+
if (handler && !installed) {
|
|
55
|
+
if (!byKey) {
|
|
56
|
+
byKey = /* @__PURE__ */ new Map();
|
|
57
|
+
slotListeners.set(target, byKey);
|
|
110
58
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const captureKey = `${eventType}:capture`;
|
|
118
|
-
if (!installed.has(captureKey)) {
|
|
119
|
-
root.addEventListener(
|
|
120
|
-
eventType,
|
|
121
|
-
createPhaseHandler(eventType, "capture"),
|
|
122
|
-
true
|
|
123
|
-
);
|
|
124
|
-
installed.add(captureKey);
|
|
125
|
-
}
|
|
126
|
-
const bubbleKey = `${eventType}:bubble`;
|
|
127
|
-
if (!installed.has(bubbleKey)) {
|
|
128
|
-
root.addEventListener(
|
|
129
|
-
eventType,
|
|
130
|
-
createPhaseHandler(eventType, "bubble"),
|
|
131
|
-
false
|
|
132
|
-
);
|
|
133
|
-
installed.add(bubbleKey);
|
|
59
|
+
const trampoline = (event) => runSlot(target, eventType, phase, event);
|
|
60
|
+
byKey.set(key, trampoline);
|
|
61
|
+
target.addEventListener(eventType, trampoline, capture);
|
|
62
|
+
} else if (!handler && installed) {
|
|
63
|
+
byKey.delete(key);
|
|
64
|
+
target.removeEventListener(eventType, installed, capture);
|
|
134
65
|
}
|
|
135
66
|
};
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return root;
|
|
143
|
-
}
|
|
144
|
-
return null;
|
|
67
|
+
const clearPhase = (target, eventType, entry, phase) => {
|
|
68
|
+
setSlot(target, eventType, phase, entry, void 0);
|
|
69
|
+
const setKey = phase === "capture" ? "captureSet" : "bubbleSet";
|
|
70
|
+
for (const handler of entry[setKey] ?? [])
|
|
71
|
+
target.removeEventListener(eventType, handler, phase === "capture");
|
|
72
|
+
entry[setKey] = void 0;
|
|
145
73
|
};
|
|
146
74
|
const registerDelegatedEvent = (element, eventType, handler, options = {}) => {
|
|
147
|
-
const root = getEventRoot(element);
|
|
148
75
|
const capture = options.capture || CAPTURE_ONLY_EVENTS.has(eventType);
|
|
149
|
-
|
|
150
|
-
ensureRootListener(root, eventType);
|
|
151
|
-
} else if (element.ownerDocument) {
|
|
152
|
-
ensureRootListener(element.ownerDocument, eventType);
|
|
153
|
-
} else {
|
|
154
|
-
element.addEventListener(eventType, handler, capture);
|
|
155
|
-
}
|
|
76
|
+
const phase = capture ? "capture" : "bubble";
|
|
156
77
|
const byEvent = getOrCreateElementHandlers(element);
|
|
157
78
|
const entry = byEvent.get(eventType) ?? {};
|
|
158
79
|
byEvent.set(eventType, entry);
|
|
159
80
|
if (options.multi) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
entry.bubbleSet.add(handler);
|
|
81
|
+
const setKey = capture ? "captureSet" : "bubbleSet";
|
|
82
|
+
const set = entry[setKey] ??= /* @__PURE__ */ new Set();
|
|
83
|
+
if (!set.has(handler)) {
|
|
84
|
+
set.add(handler);
|
|
85
|
+
element.addEventListener(eventType, handler, capture);
|
|
166
86
|
}
|
|
167
87
|
} else {
|
|
168
|
-
|
|
169
|
-
entry.capture = handler;
|
|
170
|
-
} else {
|
|
171
|
-
entry.bubble = handler;
|
|
172
|
-
}
|
|
88
|
+
setSlot(element, eventType, phase, entry, handler);
|
|
173
89
|
}
|
|
174
90
|
};
|
|
175
91
|
const isEntryEmpty = (entry) => !entry.capture && !entry.bubble && (!entry.captureSet || entry.captureSet.size === 0) && (!entry.bubbleSet || entry.bubbleSet.size === 0);
|
|
@@ -179,34 +95,38 @@ const removeDelegatedEvent = (target, eventType, handler, _options = {}) => {
|
|
|
179
95
|
const entry = byEvent.get(eventType);
|
|
180
96
|
if (!entry) return;
|
|
181
97
|
if (handler) {
|
|
182
|
-
|
|
183
|
-
entry.captureSet.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
entry
|
|
187
|
-
|
|
188
|
-
if (entry.capture === handler) {
|
|
189
|
-
entry.capture = void 0;
|
|
190
|
-
}
|
|
191
|
-
if (entry.bubble === handler) {
|
|
192
|
-
entry.bubble = void 0;
|
|
98
|
+
for (const phase of ["capture", "bubble"]) {
|
|
99
|
+
const set = phase === "capture" ? entry.captureSet : entry.bubbleSet;
|
|
100
|
+
if (set?.delete(handler))
|
|
101
|
+
target.removeEventListener(eventType, handler, phase === "capture");
|
|
102
|
+
if (entry[phase] === handler)
|
|
103
|
+
setSlot(target, eventType, phase, entry, void 0);
|
|
193
104
|
}
|
|
194
|
-
target.removeEventListener(eventType, handler, true);
|
|
195
|
-
target.removeEventListener(eventType, handler, false);
|
|
196
105
|
} else {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
entry.captureSet = void 0;
|
|
200
|
-
entry.bubbleSet = void 0;
|
|
106
|
+
clearPhase(target, eventType, entry, "capture");
|
|
107
|
+
clearPhase(target, eventType, entry, "bubble");
|
|
201
108
|
}
|
|
202
109
|
if (isEntryEmpty(entry)) {
|
|
203
110
|
byEvent.delete(eventType);
|
|
204
111
|
}
|
|
205
112
|
};
|
|
113
|
+
const clearHooks = /* @__PURE__ */ new Set();
|
|
114
|
+
const onClearDelegatedEvents = (hook) => {
|
|
115
|
+
clearHooks.add(hook);
|
|
116
|
+
return () => {
|
|
117
|
+
clearHooks.delete(hook);
|
|
118
|
+
};
|
|
119
|
+
};
|
|
206
120
|
const clearDelegatedEvents = (target) => {
|
|
207
121
|
const byEvent = elementHandlerMap.get(target);
|
|
208
|
-
if (
|
|
209
|
-
|
|
122
|
+
if (byEvent) {
|
|
123
|
+
for (const [eventType, entry] of byEvent) {
|
|
124
|
+
clearPhase(target, eventType, entry, "capture");
|
|
125
|
+
clearPhase(target, eventType, entry, "bubble");
|
|
126
|
+
}
|
|
127
|
+
byEvent.clear();
|
|
128
|
+
}
|
|
129
|
+
for (const hook of clearHooks) hook(target);
|
|
210
130
|
};
|
|
211
131
|
const clearDelegatedEventsDeep = (root) => {
|
|
212
132
|
clearDelegatedEvents(root);
|
|
@@ -244,16 +164,109 @@ const removeDelegatedEventByKey = (element, eventType, phase) => {
|
|
|
244
164
|
if (!byEvent) return;
|
|
245
165
|
const entry = byEvent.get(eventType);
|
|
246
166
|
if (!entry) return;
|
|
247
|
-
|
|
248
|
-
entry.capture = void 0;
|
|
249
|
-
entry.captureSet = void 0;
|
|
250
|
-
} else {
|
|
251
|
-
entry.bubble = void 0;
|
|
252
|
-
entry.bubbleSet = void 0;
|
|
253
|
-
}
|
|
167
|
+
clearPhase(element, eventType, entry, phase);
|
|
254
168
|
if (isEntryEmpty(entry)) byEvent.delete(eventType);
|
|
255
169
|
};
|
|
256
170
|
|
|
171
|
+
const FROM_DOM_MARKER = Symbol("defuss-morph.from-dom");
|
|
172
|
+
const COMMENT_TYPE = "#comment";
|
|
173
|
+
const isCommentVNode = (value) => !!value && typeof value === "object" && value.type === COMMENT_TYPE;
|
|
174
|
+
const HTML_BOOLEAN_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
175
|
+
"allowfullscreen",
|
|
176
|
+
"async",
|
|
177
|
+
"autofocus",
|
|
178
|
+
"autoplay",
|
|
179
|
+
"checked",
|
|
180
|
+
"controls",
|
|
181
|
+
"default",
|
|
182
|
+
"defer",
|
|
183
|
+
"disabled",
|
|
184
|
+
"formnovalidate",
|
|
185
|
+
"hidden",
|
|
186
|
+
"inert",
|
|
187
|
+
"ismap",
|
|
188
|
+
"itemscope",
|
|
189
|
+
"loop",
|
|
190
|
+
"multiple",
|
|
191
|
+
"muted",
|
|
192
|
+
"nomodule",
|
|
193
|
+
"novalidate",
|
|
194
|
+
"open",
|
|
195
|
+
"playsinline",
|
|
196
|
+
"readonly",
|
|
197
|
+
"required",
|
|
198
|
+
"reversed",
|
|
199
|
+
"selected"
|
|
200
|
+
]);
|
|
201
|
+
const domAttributeToVNodeValue = (attr) => HTML_BOOLEAN_ATTRIBUTES.has(attr.name.toLowerCase()) ? true : attr.value;
|
|
202
|
+
function parseDOM(input, type, Parser) {
|
|
203
|
+
return new Parser().parseFromString(input, type);
|
|
204
|
+
}
|
|
205
|
+
function isSVG(input, Parser) {
|
|
206
|
+
const doc = parseDOM(input, "image/svg+xml", Parser);
|
|
207
|
+
if (!doc.documentElement) return false;
|
|
208
|
+
return doc.documentElement.nodeName.toLowerCase() === "svg";
|
|
209
|
+
}
|
|
210
|
+
function isHTML(input, Parser) {
|
|
211
|
+
const doc = parseDOM(input, "text/html", Parser);
|
|
212
|
+
return doc.documentElement.querySelectorAll("*").length > 2;
|
|
213
|
+
}
|
|
214
|
+
const isMarkup = (input, Parser) => input.indexOf("<") > -1 && input.indexOf(">") > -1 && (isHTML(input, Parser) || isSVG(input, Parser));
|
|
215
|
+
function renderMarkup(markup, Parser, doc) {
|
|
216
|
+
const parsed = doc ? doc : parseDOM(markup, getMimeType(markup, Parser), Parser);
|
|
217
|
+
if (parsed.body) return Array.from(parsed.body.childNodes);
|
|
218
|
+
return parsed.documentElement ? [parsed.documentElement] : [];
|
|
219
|
+
}
|
|
220
|
+
function getMimeType(input, Parser) {
|
|
221
|
+
if (isSVG(input, Parser)) {
|
|
222
|
+
return "image/svg+xml";
|
|
223
|
+
}
|
|
224
|
+
return "text/html";
|
|
225
|
+
}
|
|
226
|
+
function domNodeToVNode(node) {
|
|
227
|
+
if (node.nodeType === 3) {
|
|
228
|
+
return node.textContent || "";
|
|
229
|
+
}
|
|
230
|
+
if (node.nodeType === 1) {
|
|
231
|
+
const element = node;
|
|
232
|
+
const attributes = {};
|
|
233
|
+
for (let i = 0; i < element.attributes.length; i++) {
|
|
234
|
+
const attr = element.attributes[i];
|
|
235
|
+
attributes[attr.name] = domAttributeToVNodeValue(attr);
|
|
236
|
+
}
|
|
237
|
+
const children = [];
|
|
238
|
+
for (let i = 0; i < element.childNodes.length; i++) {
|
|
239
|
+
const childVNode = domNodeToVNode(element.childNodes[i]);
|
|
240
|
+
children.push(childVNode);
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
type: element.tagName.toLowerCase(),
|
|
244
|
+
attributes: { ...attributes, [FROM_DOM_MARKER]: true },
|
|
245
|
+
children
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
if (node.nodeType === 8) {
|
|
249
|
+
return { type: COMMENT_TYPE, value: node.nodeValue ?? "" };
|
|
250
|
+
}
|
|
251
|
+
return "";
|
|
252
|
+
}
|
|
253
|
+
const DOCUMENT_START = /^\s*(?:<!--[\s\S]*?-->\s*)*<(?:!doctype|html|head|body)[\s>/]/i;
|
|
254
|
+
function htmlStringToVNodes(html, Parser) {
|
|
255
|
+
const parser = new Parser();
|
|
256
|
+
const doc = parser.parseFromString(
|
|
257
|
+
DOCUMENT_START.test(html) ? html : `<body>${html}`,
|
|
258
|
+
"text/html"
|
|
259
|
+
);
|
|
260
|
+
const vNodes = [];
|
|
261
|
+
for (let i = 0; i < doc.body.childNodes.length; i++) {
|
|
262
|
+
const vnode = domNodeToVNode(doc.body.childNodes[i]);
|
|
263
|
+
if (vnode !== "") {
|
|
264
|
+
vNodes.push(vnode);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return vNodes;
|
|
268
|
+
}
|
|
269
|
+
|
|
257
270
|
const CLASS_ATTRIBUTE_NAME = "class";
|
|
258
271
|
const XLINK_ATTRIBUTE_NAME = "xlink";
|
|
259
272
|
const XMLNS_ATTRIBUTE_NAME = "xmlns";
|
|
@@ -327,6 +340,11 @@ const getRenderer = (document) => {
|
|
|
327
340
|
},
|
|
328
341
|
createElement: (virtualNode, parentDomElement) => {
|
|
329
342
|
let newEl;
|
|
343
|
+
if (isCommentVNode(virtualNode)) {
|
|
344
|
+
const comment = document.createComment(virtualNode.value ?? "");
|
|
345
|
+
parentDomElement?.appendChild(comment);
|
|
346
|
+
return comment;
|
|
347
|
+
}
|
|
330
348
|
try {
|
|
331
349
|
if (typeof virtualNode === "function" && virtualNode.constructor.name === "AsyncFunction") {
|
|
332
350
|
newEl = document.createElement("div");
|
|
@@ -517,96 +535,6 @@ const getRenderer = (document) => {
|
|
|
517
535
|
return renderer;
|
|
518
536
|
};
|
|
519
537
|
|
|
520
|
-
const FROM_DOM_MARKER = Symbol("defuss-morph.from-dom");
|
|
521
|
-
const HTML_BOOLEAN_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
522
|
-
"allowfullscreen",
|
|
523
|
-
"async",
|
|
524
|
-
"autofocus",
|
|
525
|
-
"autoplay",
|
|
526
|
-
"checked",
|
|
527
|
-
"controls",
|
|
528
|
-
"default",
|
|
529
|
-
"defer",
|
|
530
|
-
"disabled",
|
|
531
|
-
"formnovalidate",
|
|
532
|
-
"hidden",
|
|
533
|
-
"inert",
|
|
534
|
-
"ismap",
|
|
535
|
-
"itemscope",
|
|
536
|
-
"loop",
|
|
537
|
-
"multiple",
|
|
538
|
-
"muted",
|
|
539
|
-
"nomodule",
|
|
540
|
-
"novalidate",
|
|
541
|
-
"open",
|
|
542
|
-
"playsinline",
|
|
543
|
-
"readonly",
|
|
544
|
-
"required",
|
|
545
|
-
"reversed",
|
|
546
|
-
"selected"
|
|
547
|
-
]);
|
|
548
|
-
const domAttributeToVNodeValue = (attr) => HTML_BOOLEAN_ATTRIBUTES.has(attr.name.toLowerCase()) ? true : attr.value;
|
|
549
|
-
function parseDOM(input, type, Parser) {
|
|
550
|
-
return new Parser().parseFromString(input, type);
|
|
551
|
-
}
|
|
552
|
-
function isSVG(input, Parser) {
|
|
553
|
-
const doc = parseDOM(input, "image/svg+xml", Parser);
|
|
554
|
-
if (!doc.documentElement) return false;
|
|
555
|
-
return doc.documentElement.nodeName.toLowerCase() === "svg";
|
|
556
|
-
}
|
|
557
|
-
function isHTML(input, Parser) {
|
|
558
|
-
const doc = parseDOM(input, "text/html", Parser);
|
|
559
|
-
return doc.documentElement.querySelectorAll("*").length > 2;
|
|
560
|
-
}
|
|
561
|
-
const isMarkup = (input, Parser) => input.indexOf("<") > -1 && input.indexOf(">") > -1 && (isHTML(input, Parser) || isSVG(input, Parser));
|
|
562
|
-
function renderMarkup(markup, Parser, doc) {
|
|
563
|
-
const parsed = doc ? doc : parseDOM(markup, getMimeType(markup, Parser), Parser);
|
|
564
|
-
if (parsed.body) return Array.from(parsed.body.childNodes);
|
|
565
|
-
return parsed.documentElement ? [parsed.documentElement] : [];
|
|
566
|
-
}
|
|
567
|
-
function getMimeType(input, Parser) {
|
|
568
|
-
if (isSVG(input, Parser)) {
|
|
569
|
-
return "image/svg+xml";
|
|
570
|
-
}
|
|
571
|
-
return "text/html";
|
|
572
|
-
}
|
|
573
|
-
function domNodeToVNode(node) {
|
|
574
|
-
if (node.nodeType === 3) {
|
|
575
|
-
return node.textContent || "";
|
|
576
|
-
}
|
|
577
|
-
if (node.nodeType === 1) {
|
|
578
|
-
const element = node;
|
|
579
|
-
const attributes = {};
|
|
580
|
-
for (let i = 0; i < element.attributes.length; i++) {
|
|
581
|
-
const attr = element.attributes[i];
|
|
582
|
-
attributes[attr.name] = domAttributeToVNodeValue(attr);
|
|
583
|
-
}
|
|
584
|
-
const children = [];
|
|
585
|
-
for (let i = 0; i < element.childNodes.length; i++) {
|
|
586
|
-
const childVNode = domNodeToVNode(element.childNodes[i]);
|
|
587
|
-
children.push(childVNode);
|
|
588
|
-
}
|
|
589
|
-
return {
|
|
590
|
-
type: element.tagName.toLowerCase(),
|
|
591
|
-
attributes: { ...attributes, [FROM_DOM_MARKER]: true },
|
|
592
|
-
children
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
return "";
|
|
596
|
-
}
|
|
597
|
-
function htmlStringToVNodes(html, Parser) {
|
|
598
|
-
const parser = new Parser();
|
|
599
|
-
const doc = parser.parseFromString(html, "text/html");
|
|
600
|
-
const vNodes = [];
|
|
601
|
-
for (let i = 0; i < doc.body.childNodes.length; i++) {
|
|
602
|
-
const vnode = domNodeToVNode(doc.body.childNodes[i]);
|
|
603
|
-
if (vnode !== "") {
|
|
604
|
-
vNodes.push(vnode);
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
return vNodes;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
538
|
const areDomNodesEqual = (oldNode, newNode) => {
|
|
611
539
|
if (oldNode === newNode) return true;
|
|
612
540
|
if (oldNode.nodeType !== newNode.nodeType) return false;
|
|
@@ -623,8 +551,8 @@ const areDomNodesEqual = (oldNode, newNode) => {
|
|
|
623
551
|
if (oldAttr.value !== newAttrValue) return false;
|
|
624
552
|
}
|
|
625
553
|
}
|
|
626
|
-
if (oldNode.nodeType === 3) {
|
|
627
|
-
if (oldNode.
|
|
554
|
+
if (oldNode.nodeType === 3 || oldNode.nodeType === 8) {
|
|
555
|
+
if (oldNode.nodeValue !== newNode.nodeValue) return false;
|
|
628
556
|
}
|
|
629
557
|
return true;
|
|
630
558
|
};
|
|
@@ -711,6 +639,7 @@ function areNodeAndChildMatching(domNode, child) {
|
|
|
711
639
|
if (typeof child === "string" || typeof child === "number" || typeof child === "boolean") {
|
|
712
640
|
return domNode.nodeType === 3;
|
|
713
641
|
}
|
|
642
|
+
if (isCommentVNode(child)) return domNode.nodeType === 8;
|
|
714
643
|
if (child && typeof child === "object") {
|
|
715
644
|
if (domNode.nodeType !== 1) return false;
|
|
716
645
|
const el = domNode;
|
|
@@ -796,6 +725,11 @@ function patchElementInPlace(el, vnode, globals, mergeAttributes = false) {
|
|
|
796
725
|
return;
|
|
797
726
|
morphDomDirect(el, vnode.children ?? [], globals);
|
|
798
727
|
}
|
|
728
|
+
function replaceNode(old, next) {
|
|
729
|
+
if (old.nodeType === 1)
|
|
730
|
+
clearDelegatedEventsDeep(old);
|
|
731
|
+
old.parentNode?.replaceChild(next, old);
|
|
732
|
+
}
|
|
799
733
|
function morphNode(domNode, child, globals, mergeAttributes = false) {
|
|
800
734
|
if (typeof child === "string" || typeof child === "number" || typeof child === "boolean") {
|
|
801
735
|
const text = String(child);
|
|
@@ -804,7 +738,17 @@ function morphNode(domNode, child, globals, mergeAttributes = false) {
|
|
|
804
738
|
return domNode;
|
|
805
739
|
}
|
|
806
740
|
const next = globals.window.document.createTextNode(text);
|
|
807
|
-
domNode
|
|
741
|
+
replaceNode(domNode, next);
|
|
742
|
+
return next;
|
|
743
|
+
}
|
|
744
|
+
if (isCommentVNode(child)) {
|
|
745
|
+
const data = child.value ?? "";
|
|
746
|
+
if (domNode.nodeType === 8) {
|
|
747
|
+
if (domNode.nodeValue !== data) domNode.nodeValue = data;
|
|
748
|
+
return domNode;
|
|
749
|
+
}
|
|
750
|
+
const next = globals.window.document.createComment(data);
|
|
751
|
+
replaceNode(domNode, next);
|
|
808
752
|
return next;
|
|
809
753
|
}
|
|
810
754
|
if (child && typeof child === "object") {
|
|
@@ -825,13 +769,15 @@ function morphNode(domNode, child, globals, mergeAttributes = false) {
|
|
|
825
769
|
const created = createDomFromChild(child, globals);
|
|
826
770
|
const first = Array.isArray(created) ? created[0] : created;
|
|
827
771
|
if (!first) return null;
|
|
828
|
-
el
|
|
772
|
+
replaceNode(el, first);
|
|
829
773
|
handleLifecycleEventsForOnMount(first);
|
|
830
774
|
return first;
|
|
831
775
|
}
|
|
832
776
|
patchElementInPlace(el, child, globals, mergeAttributes);
|
|
833
777
|
return el;
|
|
834
778
|
}
|
|
779
|
+
if (domNode.nodeType === 1)
|
|
780
|
+
clearDelegatedEventsDeep(domNode);
|
|
835
781
|
domNode.parentNode?.removeChild(domNode);
|
|
836
782
|
return null;
|
|
837
783
|
}
|
|
@@ -886,6 +832,7 @@ function morphDiff(targetRoot, patchItems, globals) {
|
|
|
886
832
|
}
|
|
887
833
|
for (const item of patchItems) {
|
|
888
834
|
if (typeof item === "string" && item.trim() === "") continue;
|
|
835
|
+
if (isCommentVNode(item)) continue;
|
|
889
836
|
const key = getVNodeMatchKey(item);
|
|
890
837
|
if (!key) {
|
|
891
838
|
throw new Error(
|
|
@@ -1201,4 +1148,4 @@ const morph = (el, newContent, options = {}) => {
|
|
|
1201
1148
|
apply(newContent);
|
|
1202
1149
|
};
|
|
1203
1150
|
|
|
1204
|
-
export { CAPTURE_ONLY_EVENTS, CLASS_ATTRIBUTE_NAME, DANGEROUSLY_SET_INNER_HTML_ATTRIBUTE, DEFAULT_TRANSITION_CONFIG, FROM_DOM_MARKER, REF_ATTRIBUTE_NAME, XLINK_ATTRIBUTE_NAME, XMLNS_ATTRIBUTE_NAME, applyStyles, areDomNodesEqual, clearDelegatedEvents, clearDelegatedEventsDeep, domNodeToVNode, getMimeType, getRegisteredEventKeys, getRegisteredEventTypes, getRenderer, getTransitionStyles, handleLifecycleEventsForOnMount, htmlStringToVNodes, isHTML, isMarkup, isSVG, morph, nsMap, observeUnmount, parseDOM, parseEventPropName, performTransition, queueCallback, registerDelegatedEvent, removeDelegatedEvent, removeDelegatedEventByKey, renderMarkup, replaceDomWithVdom, resolveGlobals, updateDomWithVdom };
|
|
1151
|
+
export { CAPTURE_ONLY_EVENTS, CLASS_ATTRIBUTE_NAME, COMMENT_TYPE, DANGEROUSLY_SET_INNER_HTML_ATTRIBUTE, DEFAULT_TRANSITION_CONFIG, FROM_DOM_MARKER, REF_ATTRIBUTE_NAME, XLINK_ATTRIBUTE_NAME, XMLNS_ATTRIBUTE_NAME, applyStyles, areDomNodesEqual, clearDelegatedEvents, clearDelegatedEventsDeep, domNodeToVNode, getMimeType, getRegisteredEventKeys, getRegisteredEventTypes, getRenderer, getTransitionStyles, handleLifecycleEventsForOnMount, htmlStringToVNodes, isCommentVNode, isHTML, isMarkup, isSVG, morph, nsMap, observeUnmount, onClearDelegatedEvents, parseDOM, parseEventPropName, performTransition, queueCallback, registerDelegatedEvent, removeDelegatedEvent, removeDelegatedEventByKey, renderMarkup, replaceDomWithVdom, resolveGlobals, updateDomWithVdom };
|
package/dist/stats.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "defuss-morph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"files": {
|
|
5
5
|
"dist/index.mjs": {
|
|
6
|
-
"bytes":
|
|
7
|
-
"gzip":
|
|
6
|
+
"bytes": 40246,
|
|
7
|
+
"gzip": 9801
|
|
8
8
|
},
|
|
9
9
|
"dist/index.cjs": {
|
|
10
|
-
"bytes":
|
|
11
|
-
"gzip":
|
|
10
|
+
"bytes": 41358,
|
|
11
|
+
"gzip": 9959
|
|
12
12
|
},
|
|
13
13
|
"dist/all.js": {
|
|
14
|
-
"bytes":
|
|
15
|
-
"gzip":
|
|
14
|
+
"bytes": 41865,
|
|
15
|
+
"gzip": 10117
|
|
16
16
|
},
|
|
17
17
|
"dist/all.min.js": {
|
|
18
|
-
"bytes":
|
|
19
|
-
"gzip":
|
|
18
|
+
"bytes": 19193,
|
|
19
|
+
"gzip": 6986
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
}
|