agentgui 1.0.971 → 1.0.973
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/AGENTS.md +13 -20
- package/PUNCHLIST-DESIGN-15.md +37 -0
- package/lib/asset-server.js +17 -5
- package/lib/http-handler.js +100 -27
- package/lib/ws-handlers-util.js +24 -11
- package/lib/ws-setup.js +15 -2
- package/package.json +2 -2
- package/server.js +2 -2
- package/site/app/js/app.js +10 -9
- package/site/app/vendor/anentrypoint-design/247420.css +185 -73
- package/site/app/vendor/anentrypoint-design/247420.js +13 -13
- package/scripts/build-rippleui.mjs +0 -84
- package/scripts/copy-vendor.js +0 -50
- package/static/lib/webjsx.js +0 -700
- package/static/lib/xstate.umd.min.js +0 -2
package/static/lib/webjsx.js
DELETED
|
@@ -1,700 +0,0 @@
|
|
|
1
|
-
(function(window) {
|
|
2
|
-
"use strict";
|
|
3
|
-
|
|
4
|
-
// === constants.js ===
|
|
5
|
-
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
|
6
|
-
const MATH_NAMESPACE = "http://www.w3.org/1998/Math/MathML";
|
|
7
|
-
const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
8
|
-
|
|
9
|
-
// === elementTags.js ===
|
|
10
|
-
// Create a Map for faster lookups
|
|
11
|
-
const KNOWN_ELEMENTS = new Map(Object.entries({
|
|
12
|
-
a: "A",
|
|
13
|
-
abbr: "ABBR",
|
|
14
|
-
address: "ADDRESS",
|
|
15
|
-
area: "AREA",
|
|
16
|
-
article: "ARTICLE",
|
|
17
|
-
aside: "ASIDE",
|
|
18
|
-
audio: "AUDIO",
|
|
19
|
-
b: "B",
|
|
20
|
-
base: "BASE",
|
|
21
|
-
bdi: "BDI",
|
|
22
|
-
bdo: "BDO",
|
|
23
|
-
blockquote: "BLOCKQUOTE",
|
|
24
|
-
body: "BODY",
|
|
25
|
-
br: "BR",
|
|
26
|
-
button: "BUTTON",
|
|
27
|
-
canvas: "CANVAS",
|
|
28
|
-
caption: "CAPTION",
|
|
29
|
-
cite: "CITE",
|
|
30
|
-
code: "CODE",
|
|
31
|
-
col: "COL",
|
|
32
|
-
colgroup: "COLGROUP",
|
|
33
|
-
data: "DATA",
|
|
34
|
-
datalist: "DATALIST",
|
|
35
|
-
dd: "DD",
|
|
36
|
-
del: "DEL",
|
|
37
|
-
details: "DETAILS",
|
|
38
|
-
dfn: "DFN",
|
|
39
|
-
dialog: "DIALOG",
|
|
40
|
-
div: "DIV",
|
|
41
|
-
dl: "DL",
|
|
42
|
-
dt: "DT",
|
|
43
|
-
em: "EM",
|
|
44
|
-
embed: "EMBED",
|
|
45
|
-
fieldset: "FIELDSET",
|
|
46
|
-
figcaption: "FIGCAPTION",
|
|
47
|
-
figure: "FIGURE",
|
|
48
|
-
footer: "FOOTER",
|
|
49
|
-
form: "FORM",
|
|
50
|
-
h1: "H1",
|
|
51
|
-
h2: "H2",
|
|
52
|
-
h3: "H3",
|
|
53
|
-
h4: "H4",
|
|
54
|
-
h5: "H5",
|
|
55
|
-
h6: "H6",
|
|
56
|
-
head: "HEAD",
|
|
57
|
-
header: "HEADER",
|
|
58
|
-
hgroup: "HGROUP",
|
|
59
|
-
hr: "HR",
|
|
60
|
-
html: "HTML",
|
|
61
|
-
i: "I",
|
|
62
|
-
iframe: "IFRAME",
|
|
63
|
-
img: "IMG",
|
|
64
|
-
input: "INPUT",
|
|
65
|
-
ins: "INS",
|
|
66
|
-
kbd: "KBD",
|
|
67
|
-
label: "LABEL",
|
|
68
|
-
legend: "LEGEND",
|
|
69
|
-
li: "LI",
|
|
70
|
-
link: "LINK",
|
|
71
|
-
main: "MAIN",
|
|
72
|
-
map: "MAP",
|
|
73
|
-
mark: "MARK",
|
|
74
|
-
menu: "MENU",
|
|
75
|
-
meta: "META",
|
|
76
|
-
meter: "METER",
|
|
77
|
-
nav: "NAV",
|
|
78
|
-
noscript: "NOSCRIPT",
|
|
79
|
-
object: "OBJECT",
|
|
80
|
-
ol: "OL",
|
|
81
|
-
optgroup: "OPTGROUP",
|
|
82
|
-
option: "OPTION",
|
|
83
|
-
output: "OUTPUT",
|
|
84
|
-
p: "P",
|
|
85
|
-
picture: "PICTURE",
|
|
86
|
-
pre: "PRE",
|
|
87
|
-
progress: "PROGRESS",
|
|
88
|
-
q: "Q",
|
|
89
|
-
rp: "RP",
|
|
90
|
-
rt: "RT",
|
|
91
|
-
ruby: "RUBY",
|
|
92
|
-
s: "S",
|
|
93
|
-
samp: "SAMP",
|
|
94
|
-
script: "SCRIPT",
|
|
95
|
-
section: "SECTION",
|
|
96
|
-
select: "SELECT",
|
|
97
|
-
slot: "SLOT",
|
|
98
|
-
small: "SMALL",
|
|
99
|
-
source: "SOURCE",
|
|
100
|
-
span: "SPAN",
|
|
101
|
-
strong: "STRONG",
|
|
102
|
-
style: "STYLE",
|
|
103
|
-
sub: "SUB",
|
|
104
|
-
summary: "SUMMARY",
|
|
105
|
-
sup: "SUP",
|
|
106
|
-
table: "TABLE",
|
|
107
|
-
tbody: "TBODY",
|
|
108
|
-
td: "TD",
|
|
109
|
-
template: "TEMPLATE",
|
|
110
|
-
textarea: "TEXTAREA",
|
|
111
|
-
tfoot: "TFOOT",
|
|
112
|
-
th: "TH",
|
|
113
|
-
thead: "THEAD",
|
|
114
|
-
time: "TIME",
|
|
115
|
-
title: "TITLE",
|
|
116
|
-
tr: "TR",
|
|
117
|
-
track: "TRACK",
|
|
118
|
-
u: "U",
|
|
119
|
-
ul: "UL",
|
|
120
|
-
var: "VAR",
|
|
121
|
-
video: "VIDEO",
|
|
122
|
-
wbr: "WBR",
|
|
123
|
-
}));
|
|
124
|
-
|
|
125
|
-
// === utils.js ===
|
|
126
|
-
/**
|
|
127
|
-
* Flattens nested virtual nodes by replacing Fragments with their children.
|
|
128
|
-
* @param vnodes Virtual nodes to flatten
|
|
129
|
-
* @returns Array of flattened virtual nodes
|
|
130
|
-
*/
|
|
131
|
-
function flattenVNodes(vnodes, result = []) {
|
|
132
|
-
if (Array.isArray(vnodes)) {
|
|
133
|
-
for (const vnode of vnodes) {
|
|
134
|
-
flattenVNodes(vnode, result);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
else if (isValidVNode(vnodes)) {
|
|
138
|
-
result.push(vnodes);
|
|
139
|
-
}
|
|
140
|
-
return result;
|
|
141
|
-
}
|
|
142
|
-
function isValidVNode(vnode) {
|
|
143
|
-
const typeofVNode = typeof vnode;
|
|
144
|
-
return (vnode !== null &&
|
|
145
|
-
vnode !== undefined &&
|
|
146
|
-
(typeofVNode === "string" ||
|
|
147
|
-
typeofVNode === "object" ||
|
|
148
|
-
typeofVNode === "number" ||
|
|
149
|
-
typeofVNode === "bigint"));
|
|
150
|
-
}
|
|
151
|
-
/* Get Child Nodes Efficiently */
|
|
152
|
-
function getChildNodes(parent) {
|
|
153
|
-
const nodes = [];
|
|
154
|
-
let current = parent.firstChild;
|
|
155
|
-
while (current) {
|
|
156
|
-
nodes.push(current);
|
|
157
|
-
current = current.nextSibling;
|
|
158
|
-
}
|
|
159
|
-
return nodes;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Assigns a ref to a DOM node.
|
|
163
|
-
* @param node Target DOM node
|
|
164
|
-
* @param ref Reference to assign (function or object with current property)
|
|
165
|
-
*/
|
|
166
|
-
function assignRef(node, ref) {
|
|
167
|
-
if (typeof ref === "function") {
|
|
168
|
-
ref(node);
|
|
169
|
-
}
|
|
170
|
-
else if (ref && typeof ref === "object") {
|
|
171
|
-
ref.current = node;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function isVElement(vnode) {
|
|
175
|
-
const typeofVNode = typeof vnode;
|
|
176
|
-
return (typeofVNode !== "string" &&
|
|
177
|
-
typeofVNode !== "number" &&
|
|
178
|
-
typeofVNode !== "bigint");
|
|
179
|
-
}
|
|
180
|
-
function isNonBooleanPrimitive(vnode) {
|
|
181
|
-
const typeofVNode = typeof vnode;
|
|
182
|
-
return (typeofVNode === "string" ||
|
|
183
|
-
typeofVNode === "number" ||
|
|
184
|
-
typeofVNode === "bigint");
|
|
185
|
-
}
|
|
186
|
-
function getNamespaceURI(node) {
|
|
187
|
-
return node instanceof Element && node.namespaceURI !== HTML_NAMESPACE
|
|
188
|
-
? node.namespaceURI ?? undefined
|
|
189
|
-
: undefined;
|
|
190
|
-
}
|
|
191
|
-
function setWebJSXProps(element, props) {
|
|
192
|
-
element.__webjsx_props = props;
|
|
193
|
-
}
|
|
194
|
-
function getWebJSXProps(element) {
|
|
195
|
-
let props = element.__webjsx_props;
|
|
196
|
-
if (!props) {
|
|
197
|
-
props = {};
|
|
198
|
-
element.__webjsx_props = props;
|
|
199
|
-
}
|
|
200
|
-
return props;
|
|
201
|
-
}
|
|
202
|
-
function setWebJSXChildNodeCache(element, childNodes) {
|
|
203
|
-
element.__webjsx_childNodes = childNodes;
|
|
204
|
-
}
|
|
205
|
-
function getWebJSXChildNodeCache(element) {
|
|
206
|
-
return element.__webjsx_childNodes;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// === renderSuspension.js ===
|
|
210
|
-
function definesRenderSuspension(el) {
|
|
211
|
-
return !!el.__webjsx_suspendRendering;
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Executes a callback with render suspension handling.
|
|
215
|
-
* @param el Element that may have render suspension
|
|
216
|
-
* @param callback Function to execute during suspension
|
|
217
|
-
* @returns Result of the callback
|
|
218
|
-
*/
|
|
219
|
-
function withRenderSuspension(el, callback) {
|
|
220
|
-
const isRenderingSuspended = !!el
|
|
221
|
-
.__webjsx_suspendRendering;
|
|
222
|
-
if (isRenderingSuspended) {
|
|
223
|
-
el.__webjsx_suspendRendering();
|
|
224
|
-
}
|
|
225
|
-
try {
|
|
226
|
-
return callback();
|
|
227
|
-
}
|
|
228
|
-
finally {
|
|
229
|
-
if (isRenderingSuspended) {
|
|
230
|
-
el.__webjsx_resumeRendering();
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// === attributes.js ===
|
|
236
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Updates an event listener on an element.
|
|
240
|
-
* @param el Target element
|
|
241
|
-
* @param eventName Name of the event (without 'on' prefix)
|
|
242
|
-
* @param newHandler New event handler function
|
|
243
|
-
* @param oldHandler Previous event handler function
|
|
244
|
-
*/
|
|
245
|
-
function updateEventListener(el, eventName, newHandler, oldHandler) {
|
|
246
|
-
if (oldHandler && oldHandler !== newHandler) {
|
|
247
|
-
el.removeEventListener(eventName, oldHandler);
|
|
248
|
-
}
|
|
249
|
-
if (newHandler && oldHandler !== newHandler) {
|
|
250
|
-
el.addEventListener(eventName, newHandler);
|
|
251
|
-
el.__webjsx_listeners =
|
|
252
|
-
el.__webjsx_listeners ?? {};
|
|
253
|
-
el.__webjsx_listeners[eventName] = newHandler;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Updates a single property or attribute on an element.
|
|
258
|
-
* @param el Target element
|
|
259
|
-
* @param key Property or attribute name
|
|
260
|
-
* @param value New value to set
|
|
261
|
-
*/
|
|
262
|
-
function updatePropOrAttr(el, key, value) {
|
|
263
|
-
if (el instanceof HTMLElement) {
|
|
264
|
-
if (key in el) {
|
|
265
|
-
// Fast path: property exists on HTMLElement
|
|
266
|
-
el[key] = value;
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
if (typeof value === "string") {
|
|
270
|
-
el.setAttribute(key, value);
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
// Fallback for non-string values on HTMLElement
|
|
274
|
-
el[key] = value;
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
// SVG/Other namespace elements
|
|
278
|
-
const isSVG = el.namespaceURI === "http://www.w3.org/2000/svg";
|
|
279
|
-
if (isSVG) {
|
|
280
|
-
if (value !== undefined && value !== null) {
|
|
281
|
-
el.setAttribute(key, `${value}`);
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
el.removeAttribute(key);
|
|
285
|
-
}
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
// Fallback for other element types
|
|
289
|
-
if (typeof value === "string") {
|
|
290
|
-
el.setAttribute(key, value);
|
|
291
|
-
}
|
|
292
|
-
else {
|
|
293
|
-
el[key] = value;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Updates all attributes and properties on a DOM element.
|
|
298
|
-
* @param el Target element
|
|
299
|
-
* @param newProps New properties to apply
|
|
300
|
-
* @param oldProps Previous properties for comparison (default empty object)
|
|
301
|
-
*/
|
|
302
|
-
function updateAttributesCore(el, newProps, oldProps = {}) {
|
|
303
|
-
// Handle new/updated props
|
|
304
|
-
for (const key of Object.keys(newProps)) {
|
|
305
|
-
const value = newProps[key];
|
|
306
|
-
if (key === "children" ||
|
|
307
|
-
key === "key" ||
|
|
308
|
-
key === "dangerouslySetInnerHTML" ||
|
|
309
|
-
key === "nodes")
|
|
310
|
-
continue;
|
|
311
|
-
if (key.startsWith("on") && typeof value === "function") {
|
|
312
|
-
const eventName = key.substring(2).toLowerCase();
|
|
313
|
-
updateEventListener(el, eventName, value, el.__webjsx_listeners?.[eventName]);
|
|
314
|
-
}
|
|
315
|
-
else if (value !== oldProps[key]) {
|
|
316
|
-
updatePropOrAttr(el, key, value);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
// Handle dangerouslySetInnerHTML
|
|
320
|
-
if (newProps.dangerouslySetInnerHTML) {
|
|
321
|
-
if (!oldProps.dangerouslySetInnerHTML ||
|
|
322
|
-
newProps.dangerouslySetInnerHTML.__html !==
|
|
323
|
-
oldProps.dangerouslySetInnerHTML.__html) {
|
|
324
|
-
const html = newProps.dangerouslySetInnerHTML?.__html || "";
|
|
325
|
-
el.innerHTML = html;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
else {
|
|
329
|
-
if (oldProps.dangerouslySetInnerHTML) {
|
|
330
|
-
el.innerHTML = "";
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
// Remove old props/attributes
|
|
334
|
-
for (const key of Object.keys(oldProps)) {
|
|
335
|
-
if (!(key in newProps) &&
|
|
336
|
-
key !== "children" &&
|
|
337
|
-
key !== "key" &&
|
|
338
|
-
key !== "dangerouslySetInnerHTML" &&
|
|
339
|
-
key !== "nodes") {
|
|
340
|
-
if (key.startsWith("on")) {
|
|
341
|
-
const eventName = key.substring(2).toLowerCase();
|
|
342
|
-
const existingListener = el
|
|
343
|
-
.__webjsx_listeners?.[eventName];
|
|
344
|
-
if (existingListener) {
|
|
345
|
-
el.removeEventListener(eventName, existingListener);
|
|
346
|
-
delete el.__webjsx_listeners[eventName];
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
else if (key in el) {
|
|
350
|
-
el[key] = undefined;
|
|
351
|
-
}
|
|
352
|
-
else {
|
|
353
|
-
el.removeAttribute(key);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* Sets initial attributes and properties on a DOM element.
|
|
360
|
-
* @param el Target element
|
|
361
|
-
* @param props Properties to apply
|
|
362
|
-
*/
|
|
363
|
-
function setAttributes(el, props) {
|
|
364
|
-
if (definesRenderSuspension(el)) {
|
|
365
|
-
withRenderSuspension(el, () => {
|
|
366
|
-
updateAttributesCore(el, props);
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
else {
|
|
370
|
-
updateAttributesCore(el, props);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
/**
|
|
374
|
-
* Updates existing attributes and properties on a DOM element.
|
|
375
|
-
* @param el Target element
|
|
376
|
-
* @param newProps New properties to apply
|
|
377
|
-
* @param oldProps Previous properties for comparison
|
|
378
|
-
*/
|
|
379
|
-
function updateAttributes(el, newProps, oldProps) {
|
|
380
|
-
if (definesRenderSuspension(el)) {
|
|
381
|
-
withRenderSuspension(el, () => {
|
|
382
|
-
updateAttributesCore(el, newProps, oldProps);
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
else {
|
|
386
|
-
updateAttributesCore(el, newProps, oldProps);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// === createDOMElement.js ===
|
|
391
|
-
/**
|
|
392
|
-
* Creates a real DOM node from a virtual node representation.
|
|
393
|
-
* @param velement Virtual node to convert
|
|
394
|
-
* @param parentNamespaceURI Namespace URI from parent element, if any
|
|
395
|
-
* @returns Created DOM node
|
|
396
|
-
*/
|
|
397
|
-
function createDOMElement(velement, parentNamespaceURI) {
|
|
398
|
-
const namespaceURI = velement.props.xmlns !== undefined
|
|
399
|
-
? velement.props.xmlns
|
|
400
|
-
: velement.type === "svg"
|
|
401
|
-
? SVG_NAMESPACE
|
|
402
|
-
: parentNamespaceURI ?? undefined;
|
|
403
|
-
const el = velement.props.is !== undefined
|
|
404
|
-
? namespaceURI !== undefined
|
|
405
|
-
? document.createElementNS(namespaceURI, velement.type, {
|
|
406
|
-
is: velement.props.is,
|
|
407
|
-
})
|
|
408
|
-
: document.createElement(velement.type, {
|
|
409
|
-
is: velement.props.is,
|
|
410
|
-
})
|
|
411
|
-
: namespaceURI !== undefined
|
|
412
|
-
? document.createElementNS(namespaceURI, velement.type)
|
|
413
|
-
: document.createElement(velement.type);
|
|
414
|
-
if (velement.props) {
|
|
415
|
-
setAttributes(el, velement.props);
|
|
416
|
-
}
|
|
417
|
-
if (velement.props.key !== undefined) {
|
|
418
|
-
el.__webjsx_key = velement.props.key;
|
|
419
|
-
}
|
|
420
|
-
if (velement.props.ref) {
|
|
421
|
-
assignRef(el, velement.props.ref);
|
|
422
|
-
}
|
|
423
|
-
if (velement.props.children && !velement.props.dangerouslySetInnerHTML) {
|
|
424
|
-
const children = velement.props.children;
|
|
425
|
-
const nodes = [];
|
|
426
|
-
for (let i = 0; i < children.length; i++) {
|
|
427
|
-
const child = children[i];
|
|
428
|
-
const node = isVElement(child)
|
|
429
|
-
? createDOMElement(child, namespaceURI)
|
|
430
|
-
: document.createTextNode(`${child}`);
|
|
431
|
-
nodes.push(node);
|
|
432
|
-
el.appendChild(node);
|
|
433
|
-
}
|
|
434
|
-
setWebJSXProps(el, velement.props);
|
|
435
|
-
setWebJSXChildNodeCache(el, nodes);
|
|
436
|
-
}
|
|
437
|
-
return el;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// === createElement.js ===
|
|
441
|
-
/**
|
|
442
|
-
* Creates a virtual element representing a DOM node or Fragment.
|
|
443
|
-
* @param type Element type (tag name) or Fragment
|
|
444
|
-
* @param props Properties and attributes for the element
|
|
445
|
-
* @param children Child elements or content
|
|
446
|
-
* @returns Virtual element representation
|
|
447
|
-
*/
|
|
448
|
-
function createElement(type, props, ...children) {
|
|
449
|
-
if (typeof type === "string") {
|
|
450
|
-
const normalizedProps = props ? props : {};
|
|
451
|
-
const flatChildren = flattenVNodes(children);
|
|
452
|
-
if (flatChildren.length > 0) {
|
|
453
|
-
// Set children property only if dangerouslySetInnerHTML is not present
|
|
454
|
-
if (!normalizedProps.dangerouslySetInnerHTML) {
|
|
455
|
-
normalizedProps.children = flatChildren;
|
|
456
|
-
}
|
|
457
|
-
else {
|
|
458
|
-
normalizedProps.children = [];
|
|
459
|
-
console.warn("WebJSX: Ignoring children since dangerouslySetInnerHTML is set.");
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
else {
|
|
463
|
-
normalizedProps.children = [];
|
|
464
|
-
}
|
|
465
|
-
const result = {
|
|
466
|
-
type,
|
|
467
|
-
tagName: KNOWN_ELEMENTS.get(type) ?? type.toUpperCase(),
|
|
468
|
-
props: normalizedProps ?? {},
|
|
469
|
-
};
|
|
470
|
-
return result;
|
|
471
|
-
}
|
|
472
|
-
else {
|
|
473
|
-
return flattenVNodes(children);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
// As called from jsx-runtime.jsx function.
|
|
477
|
-
function createElementJSX(type, props, key) {
|
|
478
|
-
if (typeof type === "string") {
|
|
479
|
-
props = props || {};
|
|
480
|
-
const flatChildren = props
|
|
481
|
-
? flattenVNodes(props.children)
|
|
482
|
-
: [];
|
|
483
|
-
if (key !== undefined) {
|
|
484
|
-
props.key = key;
|
|
485
|
-
}
|
|
486
|
-
if (flatChildren.length > 0) {
|
|
487
|
-
// Set children property only if dangerouslySetInnerHTML is not present
|
|
488
|
-
if (!props.dangerouslySetInnerHTML) {
|
|
489
|
-
props.children = flatChildren;
|
|
490
|
-
}
|
|
491
|
-
else {
|
|
492
|
-
props.children = [];
|
|
493
|
-
console.warn("WebJSX: Ignoring children since dangerouslySetInnerHTML is set.");
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
else {
|
|
497
|
-
props.children = [];
|
|
498
|
-
}
|
|
499
|
-
const result = {
|
|
500
|
-
type,
|
|
501
|
-
tagName: KNOWN_ELEMENTS.get(type) ?? type.toUpperCase(),
|
|
502
|
-
props: props ?? {},
|
|
503
|
-
};
|
|
504
|
-
return result;
|
|
505
|
-
}
|
|
506
|
-
else {
|
|
507
|
-
const flatChildren = props
|
|
508
|
-
? flattenVNodes(props.children)
|
|
509
|
-
: [];
|
|
510
|
-
return flatChildren;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
// === applyDiff.js ===
|
|
515
|
-
function applyDiff(parent, vnodes) {
|
|
516
|
-
const newVNodes = flattenVNodes(vnodes);
|
|
517
|
-
const newNodes = diffChildren(parent, newVNodes);
|
|
518
|
-
const props = getWebJSXProps(parent);
|
|
519
|
-
props.children = newVNodes;
|
|
520
|
-
setWebJSXChildNodeCache(parent, newNodes);
|
|
521
|
-
}
|
|
522
|
-
function diffChildren(parent, newVNodes) {
|
|
523
|
-
const parentProps = getWebJSXProps(parent);
|
|
524
|
-
const oldVNodes = parentProps.children ?? [];
|
|
525
|
-
if (newVNodes.length === 0) {
|
|
526
|
-
if (oldVNodes.length > 0) {
|
|
527
|
-
parent.innerHTML = "";
|
|
528
|
-
return [];
|
|
529
|
-
}
|
|
530
|
-
else {
|
|
531
|
-
// If the parent
|
|
532
|
-
// a) never had any nodes
|
|
533
|
-
// b) OR was managing content via dangerouslySetInnerHTML
|
|
534
|
-
// we must not set parent.innerHTML = "";
|
|
535
|
-
return [];
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
const changes = [];
|
|
539
|
-
let keyedMap = null;
|
|
540
|
-
const originalChildNodes = getWebJSXChildNodeCache(parent) ?? getChildNodes(parent);
|
|
541
|
-
let hasKeyedNodes = false;
|
|
542
|
-
let nodeOrderUnchanged = true;
|
|
543
|
-
for (let i = 0; i < newVNodes.length; i++) {
|
|
544
|
-
const newVNode = newVNodes[i];
|
|
545
|
-
const oldVNode = oldVNodes[i];
|
|
546
|
-
const currentNode = originalChildNodes[i];
|
|
547
|
-
const newKey = isVElement(newVNode) ? newVNode.props.key : undefined;
|
|
548
|
-
if (newKey !== undefined) {
|
|
549
|
-
if (!keyedMap) {
|
|
550
|
-
hasKeyedNodes = true;
|
|
551
|
-
keyedMap = new Map();
|
|
552
|
-
for (let j = 0; j < oldVNodes.length; j++) {
|
|
553
|
-
const matchingVNode = oldVNodes[j];
|
|
554
|
-
const key = matchingVNode.props.key;
|
|
555
|
-
if (key !== undefined) {
|
|
556
|
-
const node = originalChildNodes[j];
|
|
557
|
-
keyedMap.set(key, { node, oldVNode: matchingVNode });
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
const keyedNode = keyedMap.get(newKey);
|
|
562
|
-
if (keyedNode) {
|
|
563
|
-
if (keyedNode.oldVNode !== oldVNode) {
|
|
564
|
-
nodeOrderUnchanged = false;
|
|
565
|
-
}
|
|
566
|
-
changes.push({
|
|
567
|
-
type: "update",
|
|
568
|
-
node: keyedNode.node,
|
|
569
|
-
newVNode,
|
|
570
|
-
oldVNode: keyedNode.oldVNode,
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
else {
|
|
574
|
-
nodeOrderUnchanged = false;
|
|
575
|
-
changes.push({ type: "create", vnode: newVNode });
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
else {
|
|
579
|
-
if (!hasKeyedNodes &&
|
|
580
|
-
canUpdateVNodes(newVNode, oldVNode) &&
|
|
581
|
-
currentNode) {
|
|
582
|
-
changes.push({
|
|
583
|
-
type: "update",
|
|
584
|
-
node: currentNode,
|
|
585
|
-
newVNode,
|
|
586
|
-
oldVNode,
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
else {
|
|
590
|
-
nodeOrderUnchanged = false;
|
|
591
|
-
changes.push({ type: "create", vnode: newVNode });
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
if (changes.length) {
|
|
596
|
-
const { nodes, lastNode: lastPlacedNode } = applyChanges(parent, changes, originalChildNodes, nodeOrderUnchanged);
|
|
597
|
-
// Remove any remaining nodes
|
|
598
|
-
while (lastPlacedNode?.nextSibling) {
|
|
599
|
-
parent.removeChild(lastPlacedNode.nextSibling);
|
|
600
|
-
}
|
|
601
|
-
return nodes;
|
|
602
|
-
}
|
|
603
|
-
else {
|
|
604
|
-
return originalChildNodes;
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
function canUpdateVNodes(newVNode, oldVNode) {
|
|
608
|
-
if (oldVNode === undefined)
|
|
609
|
-
return false;
|
|
610
|
-
if (isNonBooleanPrimitive(newVNode) && isNonBooleanPrimitive(oldVNode)) {
|
|
611
|
-
return true;
|
|
612
|
-
}
|
|
613
|
-
else {
|
|
614
|
-
if (isVElement(oldVNode) && isVElement(newVNode)) {
|
|
615
|
-
const oldKey = oldVNode.props.key;
|
|
616
|
-
const newKey = newVNode.props.key;
|
|
617
|
-
return (oldVNode.tagName === newVNode.tagName &&
|
|
618
|
-
((oldKey === undefined && newKey === undefined) ||
|
|
619
|
-
(oldKey !== undefined && newKey !== undefined && oldKey === newKey)));
|
|
620
|
-
}
|
|
621
|
-
else {
|
|
622
|
-
return false;
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
function applyChanges(parent, changes, originalNodes, nodeOrderUnchanged) {
|
|
627
|
-
const nodes = [];
|
|
628
|
-
let lastPlacedNode = null;
|
|
629
|
-
for (const change of changes) {
|
|
630
|
-
if (change.type === "create") {
|
|
631
|
-
let node = undefined;
|
|
632
|
-
if (isVElement(change.vnode)) {
|
|
633
|
-
node = createDOMElement(change.vnode, getNamespaceURI(parent));
|
|
634
|
-
}
|
|
635
|
-
else {
|
|
636
|
-
node = document.createTextNode(`${change.vnode}`);
|
|
637
|
-
}
|
|
638
|
-
if (!lastPlacedNode) {
|
|
639
|
-
parent.prepend(node);
|
|
640
|
-
}
|
|
641
|
-
else {
|
|
642
|
-
parent.insertBefore(node, lastPlacedNode.nextSibling ?? null);
|
|
643
|
-
}
|
|
644
|
-
lastPlacedNode = node;
|
|
645
|
-
nodes.push(node);
|
|
646
|
-
}
|
|
647
|
-
else {
|
|
648
|
-
const { node, newVNode, oldVNode } = change;
|
|
649
|
-
if (isVElement(newVNode)) {
|
|
650
|
-
const oldProps = oldVNode?.props || {};
|
|
651
|
-
const newProps = newVNode.props;
|
|
652
|
-
updateAttributes(node, newProps, oldProps);
|
|
653
|
-
if (newVNode.props.key !== undefined) {
|
|
654
|
-
node.__webjsx_key = newVNode.props.key;
|
|
655
|
-
}
|
|
656
|
-
else {
|
|
657
|
-
if (oldVNode.props?.key) {
|
|
658
|
-
delete node.__webjsx_key;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
if (newVNode.props.ref) {
|
|
662
|
-
assignRef(node, newVNode.props.ref);
|
|
663
|
-
}
|
|
664
|
-
if (!newProps.dangerouslySetInnerHTML && newProps.children != null) {
|
|
665
|
-
const childNodes = diffChildren(node, newProps.children);
|
|
666
|
-
setWebJSXProps(node, newProps);
|
|
667
|
-
setWebJSXChildNodeCache(node, childNodes);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
else {
|
|
671
|
-
if (newVNode !== oldVNode) {
|
|
672
|
-
node.textContent = `${newVNode}`;
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
if (!nodeOrderUnchanged) {
|
|
676
|
-
if (!lastPlacedNode) {
|
|
677
|
-
if (node !== originalNodes[0]) {
|
|
678
|
-
parent.prepend(node);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
else {
|
|
682
|
-
if (lastPlacedNode.nextSibling !== node) {
|
|
683
|
-
parent.insertBefore(node, lastPlacedNode.nextSibling ?? null);
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
lastPlacedNode = node;
|
|
688
|
-
nodes.push(node);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
return { nodes, lastNode: lastPlacedNode };
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
// === types.js ===
|
|
695
|
-
const Fragment = (props) => {
|
|
696
|
-
return flattenVNodes(props.children);
|
|
697
|
-
};
|
|
698
|
-
|
|
699
|
-
window.webjsx = { createElement, applyDiff, createDOMElement, Fragment };
|
|
700
|
-
})(typeof window !== 'undefined' ? window : globalThis);
|