thunderous 2.3.12 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__test__/custom-element.test.js +48 -0
- package/dist/__test__/registry.test.js +60 -0
- package/dist/__test__/render.test.js +48 -0
- package/dist/__test__/server-side.test.js +196 -0
- package/dist/__test__/signals.test.js +247 -0
- package/dist/__test__/utilities.test.js +8 -0
- package/dist/constants.js +13 -0
- package/dist/custom-element.js +391 -0
- package/dist/index.cjs +239 -91
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +239 -91
- package/dist/registry.js +95 -0
- package/dist/render.js +350 -0
- package/dist/server-side.js +136 -0
- package/dist/signals.js +115 -0
- package/dist/utilities.js +9 -0
- package/package.json +7 -5
package/dist/index.cjs
CHANGED
|
@@ -49,13 +49,14 @@ var DEFAULT_RENDER_OPTIONS = {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
// src/signals.ts
|
|
52
|
-
var
|
|
52
|
+
var sym = null;
|
|
53
|
+
var effects = /* @__PURE__ */ new WeakMap();
|
|
53
54
|
var createSignal = (initVal, options) => {
|
|
54
55
|
const subscribers = /* @__PURE__ */ new Set();
|
|
55
56
|
let value = initVal;
|
|
56
57
|
const getter = (getterOptions) => {
|
|
57
|
-
if (
|
|
58
|
-
subscribers.add(
|
|
58
|
+
if (sym !== null) {
|
|
59
|
+
subscribers.add(sym);
|
|
59
60
|
}
|
|
60
61
|
if (options?.debugMode === true || getterOptions?.debugMode === true) {
|
|
61
62
|
let label = "anonymous signal";
|
|
@@ -67,7 +68,11 @@ var createSignal = (initVal, options) => {
|
|
|
67
68
|
} else if (getterOptions?.label !== void 0) {
|
|
68
69
|
label = getterOptions.label;
|
|
69
70
|
}
|
|
70
|
-
console.log("Signal retrieved:", {
|
|
71
|
+
console.log("Signal retrieved:", {
|
|
72
|
+
value,
|
|
73
|
+
subscribers: Array.from(subscribers).map((sym2) => effects.get(sym2)),
|
|
74
|
+
label
|
|
75
|
+
});
|
|
71
76
|
}
|
|
72
77
|
return value;
|
|
73
78
|
};
|
|
@@ -84,15 +89,29 @@ var createSignal = (initVal, options) => {
|
|
|
84
89
|
const isObject = typeof newValue === "object" && newValue !== null;
|
|
85
90
|
if (!isObject && value === newValue) return;
|
|
86
91
|
if (isObject && typeof value === "object" && value !== null) {
|
|
87
|
-
|
|
92
|
+
const isPlainObject = (obj) => typeof obj === "object" && obj !== null && Object.getPrototypeOf(obj) === Object.prototype;
|
|
93
|
+
if (isPlainObject(value) && isPlainObject(newValue)) {
|
|
94
|
+
if (JSON.stringify(value) === JSON.stringify(newValue)) return;
|
|
95
|
+
}
|
|
88
96
|
}
|
|
89
97
|
const oldValue = value;
|
|
90
98
|
value = newValue;
|
|
91
|
-
for (const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
for (const sym2 of subscribers) {
|
|
100
|
+
const effectRef = effects.get(sym2);
|
|
101
|
+
if (effectRef !== void 0) {
|
|
102
|
+
try {
|
|
103
|
+
effectRef.fn({
|
|
104
|
+
lastValue: effectRef.value,
|
|
105
|
+
destroy: () => {
|
|
106
|
+
effects.delete(sym2);
|
|
107
|
+
queueMicrotask(() => subscribers.delete(sym2));
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.error("Error in subscriber:", { error, oldValue, newValue, fn: effectRef.fn });
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
queueMicrotask(() => subscribers.delete(sym2));
|
|
96
115
|
}
|
|
97
116
|
}
|
|
98
117
|
if (options?.debugMode === true || setterOptions?.debugMode === true) {
|
|
@@ -105,7 +124,12 @@ var createSignal = (initVal, options) => {
|
|
|
105
124
|
} else if (setterOptions?.label !== void 0) {
|
|
106
125
|
label = setterOptions.label;
|
|
107
126
|
}
|
|
108
|
-
console.log("Signal set:", {
|
|
127
|
+
console.log("Signal set:", {
|
|
128
|
+
oldValue,
|
|
129
|
+
newValue,
|
|
130
|
+
subscribers: Array.from(subscribers).map((sym2) => effects.get(sym2)),
|
|
131
|
+
label
|
|
132
|
+
});
|
|
109
133
|
}
|
|
110
134
|
};
|
|
111
135
|
return [getter, setter];
|
|
@@ -121,21 +145,33 @@ var derived = (fn, options) => {
|
|
|
121
145
|
});
|
|
122
146
|
return getter;
|
|
123
147
|
};
|
|
124
|
-
var createEffect = (fn) => {
|
|
125
|
-
|
|
148
|
+
var createEffect = (fn, value) => {
|
|
149
|
+
const privateSym = sym = Symbol();
|
|
150
|
+
effects.set(sym, { fn, value });
|
|
126
151
|
try {
|
|
127
|
-
fn(
|
|
152
|
+
fn({
|
|
153
|
+
lastValue: value,
|
|
154
|
+
destroy: () => {
|
|
155
|
+
effects.delete(privateSym);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
128
158
|
} catch (error) {
|
|
129
159
|
console.error("Error in effect:", { error, fn });
|
|
130
160
|
}
|
|
131
|
-
|
|
161
|
+
sym = null;
|
|
132
162
|
};
|
|
133
163
|
|
|
134
164
|
// src/utilities.ts
|
|
135
165
|
var NOOP = () => void 0;
|
|
136
166
|
var queryComment = (node, comment) => {
|
|
137
|
-
|
|
138
|
-
|
|
167
|
+
const walker = document.createTreeWalker(node, NodeFilter.SHOW_COMMENT, {
|
|
168
|
+
acceptNode: (n) => n.nodeValue === comment ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
|
|
169
|
+
});
|
|
170
|
+
return walker.nextNode();
|
|
171
|
+
};
|
|
172
|
+
var queryChildren = (children, selector) => {
|
|
173
|
+
for (const child of children) {
|
|
174
|
+
if (child instanceof Element && child.matches(selector)) {
|
|
139
175
|
return child;
|
|
140
176
|
}
|
|
141
177
|
}
|
|
@@ -291,6 +327,8 @@ var renderState = {
|
|
|
291
327
|
signalMap: /* @__PURE__ */ new Map(),
|
|
292
328
|
callbackMap: /* @__PURE__ */ new Map(),
|
|
293
329
|
fragmentMap: /* @__PURE__ */ new Map(),
|
|
330
|
+
childrenMap: /* @__PURE__ */ new Map(),
|
|
331
|
+
propertyMap: /* @__PURE__ */ new Map(),
|
|
294
332
|
registry: typeof customElements !== "undefined" ? customElements : {}
|
|
295
333
|
};
|
|
296
334
|
var logPropertyWarning = (propName, element) => {
|
|
@@ -300,21 +338,27 @@ var logPropertyWarning = (propName, element) => {
|
|
|
300
338
|
"\n\nThunderous will attempt to set the property anyway, but this may result in unexpected behavior. Please make sure the property exists on the element prior to setting it."
|
|
301
339
|
);
|
|
302
340
|
};
|
|
303
|
-
var
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
341
|
+
var asNodeList = (value, parent) => {
|
|
342
|
+
if (typeof value === "string") return [new Text(value)];
|
|
343
|
+
if (value instanceof DocumentFragment) return [...value.children];
|
|
344
|
+
if (Array.isArray(value)) {
|
|
345
|
+
const nodeList = [];
|
|
346
|
+
let count = 0;
|
|
347
|
+
const keys = /* @__PURE__ */ new Set();
|
|
348
|
+
for (const item of value) {
|
|
349
|
+
const cachedItem = item instanceof DocumentFragment ? renderState.childrenMap.get(item) : void 0;
|
|
350
|
+
const children = cachedItem ?? asNodeList(item, parent);
|
|
351
|
+
if (cachedItem === void 0 && item instanceof DocumentFragment) {
|
|
352
|
+
renderState.childrenMap.set(item, children);
|
|
353
|
+
}
|
|
354
|
+
if (children.length > 1) {
|
|
312
355
|
console.error(
|
|
313
356
|
"When rendering arrays, fragments must contain only one top-level element at a time. Error occured in:",
|
|
314
357
|
parent
|
|
315
358
|
);
|
|
316
359
|
}
|
|
317
|
-
|
|
360
|
+
const child = children[0];
|
|
361
|
+
if (child === null || !(child instanceof Element)) continue;
|
|
318
362
|
let key = child.getAttribute("key");
|
|
319
363
|
if (key === null) {
|
|
320
364
|
console.warn(
|
|
@@ -332,18 +376,11 @@ var arrayToDocumentFragment = (array, parent, uniqueKey) => {
|
|
|
332
376
|
}
|
|
333
377
|
keys.add(key);
|
|
334
378
|
count++;
|
|
379
|
+
nodeList.push(...children);
|
|
335
380
|
}
|
|
336
|
-
|
|
381
|
+
return nodeList;
|
|
337
382
|
}
|
|
338
|
-
|
|
339
|
-
documentFragment.append(comment);
|
|
340
|
-
return documentFragment;
|
|
341
|
-
};
|
|
342
|
-
var createNewNode = (value, parent, uniqueKey) => {
|
|
343
|
-
if (typeof value === "string") return new Text(value);
|
|
344
|
-
if (Array.isArray(value)) return arrayToDocumentFragment(value, parent, uniqueKey);
|
|
345
|
-
if (value instanceof DocumentFragment) return value;
|
|
346
|
-
return new Text("");
|
|
383
|
+
return [new Text()];
|
|
347
384
|
};
|
|
348
385
|
var processValue = (value) => {
|
|
349
386
|
if (!isServer && value instanceof DocumentFragment) {
|
|
@@ -369,62 +406,139 @@ var processValue = (value) => {
|
|
|
369
406
|
return String(value);
|
|
370
407
|
};
|
|
371
408
|
var evaluateBindings = (element, fragment) => {
|
|
372
|
-
for (const child of element.childNodes) {
|
|
409
|
+
for (const child of [...element.childNodes]) {
|
|
373
410
|
if (child instanceof Text && SIGNAL_BINDING_REGEX.test(child.data)) {
|
|
374
411
|
const textList = child.data.split(SIGNAL_BINDING_REGEX);
|
|
375
|
-
const
|
|
412
|
+
const nextSibling = child.nextSibling;
|
|
413
|
+
const prevSibling = child.previousSibling;
|
|
376
414
|
textList.forEach((text, i) => {
|
|
377
|
-
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
|
378
|
-
const signal = uniqueKey !==
|
|
415
|
+
const uniqueKey = SIGNAL_BINDING_REGEX.test(text) ? text.replace(/\{\{signal:(.+)\}\}/, "$1") : void 0;
|
|
416
|
+
const signal = uniqueKey !== void 0 ? renderState.signalMap.get(uniqueKey) : void 0;
|
|
379
417
|
const newValue = signal !== void 0 ? signal() : text;
|
|
380
|
-
const
|
|
418
|
+
const initialChildren = asNodeList(newValue, element);
|
|
381
419
|
if (i === 0) {
|
|
382
|
-
child.replaceWith(
|
|
420
|
+
child.replaceWith(...initialChildren);
|
|
383
421
|
} else {
|
|
384
|
-
element
|
|
422
|
+
const endAnchor2 = queryComment(element, `${uniqueKey}:end`) ?? nextSibling;
|
|
423
|
+
if (endAnchor2 !== null) {
|
|
424
|
+
endAnchor2.before(...initialChildren);
|
|
425
|
+
} else {
|
|
426
|
+
element.append(...initialChildren);
|
|
427
|
+
}
|
|
385
428
|
}
|
|
386
|
-
if (
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
} else
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
429
|
+
if (uniqueKey === void 0) return;
|
|
430
|
+
const startAnchor = document.createComment(`${uniqueKey}:start`);
|
|
431
|
+
if (prevSibling !== null) {
|
|
432
|
+
prevSibling.after(startAnchor);
|
|
433
|
+
} else {
|
|
434
|
+
element.prepend(startAnchor);
|
|
435
|
+
}
|
|
436
|
+
const endAnchor = document.createComment(`${uniqueKey}:end`);
|
|
437
|
+
if (nextSibling !== null) {
|
|
438
|
+
nextSibling.before(endAnchor);
|
|
439
|
+
} else {
|
|
440
|
+
element.append(endAnchor);
|
|
441
|
+
}
|
|
442
|
+
const bindText = (node, signal2) => {
|
|
443
|
+
createEffect(({ destroy }) => {
|
|
444
|
+
const result = signal2();
|
|
445
|
+
if (Array.isArray(result)) {
|
|
446
|
+
destroy();
|
|
447
|
+
bindArray(signal2);
|
|
448
|
+
return;
|
|
401
449
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
if (init && matchingNode === null) {
|
|
407
|
-
child2.remove();
|
|
408
|
-
}
|
|
450
|
+
if (result instanceof DocumentFragment) {
|
|
451
|
+
destroy();
|
|
452
|
+
bindFragment(signal2);
|
|
453
|
+
return;
|
|
409
454
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
455
|
+
node.data = result === null ? "" : String(result);
|
|
456
|
+
});
|
|
457
|
+
};
|
|
458
|
+
const bindArray = (signal2) => {
|
|
459
|
+
createEffect(
|
|
460
|
+
({ lastValue: oldChildren, destroy }) => {
|
|
461
|
+
const result = signal2();
|
|
462
|
+
console.trace("Binding array:", {
|
|
463
|
+
result: result.map((node) => node.cloneNode(true)),
|
|
464
|
+
oldChildren
|
|
465
|
+
});
|
|
466
|
+
const newChildren = asNodeList(result, element);
|
|
467
|
+
const firstChild = newChildren[0];
|
|
468
|
+
if (!Array.isArray(result) && newChildren.length === 1 && firstChild instanceof DocumentFragment) {
|
|
469
|
+
destroy();
|
|
470
|
+
bindFragment(signal2);
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
if (newChildren.length === 1 && firstChild instanceof Text) {
|
|
474
|
+
destroy();
|
|
475
|
+
bindText(firstChild, signal2);
|
|
476
|
+
return;
|
|
418
477
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
478
|
+
while (startAnchor.nextSibling !== endAnchor) {
|
|
479
|
+
startAnchor.nextSibling?.remove();
|
|
480
|
+
}
|
|
481
|
+
startAnchor.after(...newChildren);
|
|
482
|
+
if (oldChildren === null) return newChildren;
|
|
483
|
+
for (const persistedChild of oldChildren) {
|
|
484
|
+
if (persistedChild instanceof Element) {
|
|
485
|
+
const key = persistedChild.getAttribute("key");
|
|
486
|
+
if (key === null) continue;
|
|
487
|
+
const newChild = queryChildren(newChildren, `[key="${key}"]`);
|
|
488
|
+
if (newChild === null) {
|
|
489
|
+
persistedChild.remove();
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
for (const attr of [...persistedChild.attributes]) {
|
|
493
|
+
if (!newChild.hasAttribute(attr.name)) persistedChild.removeAttribute(attr.name);
|
|
494
|
+
}
|
|
495
|
+
for (const newAttr of [...newChild.attributes]) {
|
|
496
|
+
const oldAttrValue = persistedChild.getAttribute(newAttr.name);
|
|
497
|
+
if (oldAttrValue?.startsWith("this.__customCallbackFns")) continue;
|
|
498
|
+
persistedChild.setAttribute(newAttr.name, newAttr.value);
|
|
499
|
+
}
|
|
500
|
+
newChild.replaceWith(persistedChild);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return newChildren;
|
|
504
|
+
},
|
|
505
|
+
null
|
|
506
|
+
);
|
|
507
|
+
};
|
|
508
|
+
const bindFragment = (signal2) => {
|
|
509
|
+
const initialFragment = signal2();
|
|
510
|
+
renderState.childrenMap.set(initialFragment, [...initialFragment.childNodes]);
|
|
511
|
+
createEffect(({ destroy }) => {
|
|
512
|
+
const result = signal2();
|
|
513
|
+
const cachedChildren = renderState.childrenMap.get(initialFragment);
|
|
514
|
+
const children = cachedChildren ?? asNodeList(result, element);
|
|
515
|
+
if (Array.isArray(result)) {
|
|
516
|
+
destroy();
|
|
517
|
+
bindArray(signal2);
|
|
518
|
+
return;
|
|
422
519
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
520
|
+
if (result instanceof Text) {
|
|
521
|
+
const children2 = asNodeList(result, element);
|
|
522
|
+
const text2 = children2[0];
|
|
523
|
+
destroy();
|
|
524
|
+
bindText(text2, signal2);
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
while (startAnchor.nextSibling !== endAnchor) {
|
|
528
|
+
startAnchor.nextSibling?.remove();
|
|
529
|
+
}
|
|
530
|
+
startAnchor.after(...children);
|
|
427
531
|
});
|
|
532
|
+
};
|
|
533
|
+
if (signal !== void 0) {
|
|
534
|
+
if (Array.isArray(newValue)) {
|
|
535
|
+
bindArray(signal);
|
|
536
|
+
} else if (initialChildren instanceof DocumentFragment) {
|
|
537
|
+
bindFragment(signal);
|
|
538
|
+
} else {
|
|
539
|
+
const initialChild = initialChildren[0];
|
|
540
|
+
bindText(initialChild, signal);
|
|
541
|
+
}
|
|
428
542
|
}
|
|
429
543
|
});
|
|
430
544
|
}
|
|
@@ -455,14 +569,22 @@ var evaluateBindings = (element, fragment) => {
|
|
|
455
569
|
newText += text;
|
|
456
570
|
}
|
|
457
571
|
}
|
|
458
|
-
if (hasNull && newText === "null" || attrName.startsWith("prop:")) {
|
|
572
|
+
if (hasNull && newText === "null" || attrName.startsWith("prop-id:")) {
|
|
459
573
|
if (child.hasAttribute(attrName)) child.removeAttribute(attrName);
|
|
460
574
|
} else {
|
|
461
575
|
if (newText !== prevText) child.setAttribute(attrName, newText);
|
|
462
576
|
}
|
|
463
|
-
if (attrName.startsWith("prop:")) {
|
|
577
|
+
if (attrName.startsWith("prop-id:")) {
|
|
464
578
|
if (child.hasAttribute(attrName)) child.removeAttribute(attrName);
|
|
465
|
-
const
|
|
579
|
+
const propId = attrName.replace("prop-id:", "");
|
|
580
|
+
const propName = renderState.propertyMap.get(propId);
|
|
581
|
+
if (propName === void 0) {
|
|
582
|
+
console.error(
|
|
583
|
+
`BRANCH:SIGNAL; Property ID "${propId}" does not exist in the property map. This is likely a problem with Thunderous. Report a bug if you see this message. https://github.com/Thunder-Solutions/Thunderous/issues`,
|
|
584
|
+
child
|
|
585
|
+
);
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
466
588
|
const newValue = hasNull && newText === "null" ? null : newText;
|
|
467
589
|
if (!(propName in child)) logPropertyWarning(propName, child);
|
|
468
590
|
child[propName] = signal !== void 0 ? signal() : newValue;
|
|
@@ -488,18 +610,34 @@ var evaluateBindings = (element, fragment) => {
|
|
|
488
610
|
child.__customCallbackFns.set(uniqueKey, callback);
|
|
489
611
|
}
|
|
490
612
|
}
|
|
491
|
-
if (uniqueKey !== "" && !attrName.startsWith("prop:")) {
|
|
613
|
+
if (uniqueKey !== "" && !attrName.startsWith("prop-id:")) {
|
|
492
614
|
child.setAttribute(attrName, `this.__customCallbackFns.get('${uniqueKey}')(event)`);
|
|
493
|
-
} else if (attrName.startsWith("prop:")) {
|
|
615
|
+
} else if (attrName.startsWith("prop-id:")) {
|
|
494
616
|
child.removeAttribute(attrName);
|
|
495
|
-
const
|
|
617
|
+
const propId = attrName.replace("prop-id:", "");
|
|
618
|
+
const propName = renderState.propertyMap.get(propId);
|
|
619
|
+
if (propName === void 0) {
|
|
620
|
+
console.error(
|
|
621
|
+
`BRANCH:CALLBACK; Property ID "${propId}" does not exist in the property map. This is likely a problem with Thunderous. Report a bug if you see this message. https://github.com/Thunder-Solutions/Thunderous/issues`,
|
|
622
|
+
child
|
|
623
|
+
);
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
496
626
|
if (!(propName in child)) logPropertyWarning(propName, child);
|
|
497
627
|
child[propName] = child.__customCallbackFns.get(uniqueKey);
|
|
498
628
|
}
|
|
499
629
|
});
|
|
500
|
-
} else if (attrName.startsWith("prop:")) {
|
|
630
|
+
} else if (attrName.startsWith("prop-id:")) {
|
|
501
631
|
child.removeAttribute(attrName);
|
|
502
|
-
const
|
|
632
|
+
const propId = attrName.replace("prop-id:", "");
|
|
633
|
+
const propName = renderState.propertyMap.get(propId);
|
|
634
|
+
if (propName === void 0) {
|
|
635
|
+
console.error(
|
|
636
|
+
`BRANCH:PROP; Property ID "${propId}" does not exist in the property map. This is likely a problem with Thunderous. Report a bug if you see this message. https://github.com/Thunder-Solutions/Thunderous/issues`,
|
|
637
|
+
child
|
|
638
|
+
);
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
503
641
|
if (!(propName in child)) logPropertyWarning(propName, child);
|
|
504
642
|
child[propName] = attr.value;
|
|
505
643
|
}
|
|
@@ -509,7 +647,7 @@ var evaluateBindings = (element, fragment) => {
|
|
|
509
647
|
}
|
|
510
648
|
};
|
|
511
649
|
var html = (strings, ...values) => {
|
|
512
|
-
|
|
650
|
+
let innerHTML = strings.reduce((innerHTML2, str, i) => {
|
|
513
651
|
let value = values[i] ?? "";
|
|
514
652
|
if (Array.isArray(value)) {
|
|
515
653
|
value = value.map((item) => processValue(item)).join("");
|
|
@@ -520,6 +658,16 @@ var html = (strings, ...values) => {
|
|
|
520
658
|
return innerHTML2;
|
|
521
659
|
}, "");
|
|
522
660
|
if (isServer) return innerHTML;
|
|
661
|
+
const props = innerHTML.match(/prop:([^=]+)/g);
|
|
662
|
+
if (props !== null) {
|
|
663
|
+
for (const prop of props) {
|
|
664
|
+
const name = prop.split(":")[1].trim();
|
|
665
|
+
const id = crypto.randomUUID();
|
|
666
|
+
const newProp = `prop-id:${id}`;
|
|
667
|
+
renderState.propertyMap.set(id, name);
|
|
668
|
+
innerHTML = innerHTML.replace(`prop:${name}`, newProp);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
523
671
|
const template = document.createElement("template");
|
|
524
672
|
template.innerHTML = innerHTML;
|
|
525
673
|
const fragment = renderState.currentShadowRoot?.importNode?.(template.content, true) ?? document.importNode(template.content, true);
|
|
@@ -633,7 +781,7 @@ var customElement = (render, options) => {
|
|
|
633
781
|
observedAttributesSet.add(attrName);
|
|
634
782
|
attributesAsPropertiesMap.set(attrName, {
|
|
635
783
|
// convert kebab-case attribute names to camelCase property names
|
|
636
|
-
prop: attrName.replace(
|
|
784
|
+
prop: attrName.replace(/(?<=-|_)([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/(-|_)/g, ""),
|
|
637
785
|
coerce,
|
|
638
786
|
value: null
|
|
639
787
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -112,6 +112,10 @@ type AnyFn = (...args: any[]) => any;
|
|
|
112
112
|
|
|
113
113
|
type HTMLCustomElement<T extends Record<PropertyKey, unknown>> = Omit<HTMLElement, keyof T> & T;
|
|
114
114
|
|
|
115
|
+
// Again, flexible typing is necessary to support these generics
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
117
|
+
type Effect<T = any> = (args: { lastValue: T; destroy: () => void }) => T | void;
|
|
118
|
+
|
|
115
119
|
/**
|
|
116
120
|
* Create a custom element that can be defined for use in the DOM.
|
|
117
121
|
* @example
|
|
@@ -174,7 +178,7 @@ declare const derived: <T>(fn: () => T, options?: SignalOptions) => SignalGetter
|
|
|
174
178
|
* });
|
|
175
179
|
* ```
|
|
176
180
|
*/
|
|
177
|
-
declare const createEffect: (fn:
|
|
181
|
+
declare const createEffect: <T = unknown>(fn: Effect<T>, value?: T) => void;
|
|
178
182
|
|
|
179
183
|
/**
|
|
180
184
|
* A tagged template function for creating DocumentFragment instances.
|
package/dist/index.d.ts
CHANGED
|
@@ -112,6 +112,10 @@ type AnyFn = (...args: any[]) => any;
|
|
|
112
112
|
|
|
113
113
|
type HTMLCustomElement<T extends Record<PropertyKey, unknown>> = Omit<HTMLElement, keyof T> & T;
|
|
114
114
|
|
|
115
|
+
// Again, flexible typing is necessary to support these generics
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
117
|
+
type Effect<T = any> = (args: { lastValue: T; destroy: () => void }) => T | void;
|
|
118
|
+
|
|
115
119
|
/**
|
|
116
120
|
* Create a custom element that can be defined for use in the DOM.
|
|
117
121
|
* @example
|
|
@@ -174,7 +178,7 @@ declare const derived: <T>(fn: () => T, options?: SignalOptions) => SignalGetter
|
|
|
174
178
|
* });
|
|
175
179
|
* ```
|
|
176
180
|
*/
|
|
177
|
-
declare const createEffect: (fn:
|
|
181
|
+
declare const createEffect: <T = unknown>(fn: Effect<T>, value?: T) => void;
|
|
178
182
|
|
|
179
183
|
/**
|
|
180
184
|
* A tagged template function for creating DocumentFragment instances.
|