thunderous 2.4.3 → 2.4.5
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/index.cjs +125 -68
- package/dist/index.d.cts +54 -1
- package/dist/index.d.ts +54 -1
- package/dist/index.js +123 -68
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
clearRenderState: () => clearRenderState,
|
|
24
|
+
clearServerCss: () => clearServerCss,
|
|
23
25
|
clientOnlyCallback: () => clientOnlyCallback,
|
|
24
26
|
createEffect: () => createEffect,
|
|
25
27
|
createRegistry: () => createRegistry,
|
|
@@ -163,12 +165,6 @@ var createEffect = (fn, value) => {
|
|
|
163
165
|
|
|
164
166
|
// src/utilities.ts
|
|
165
167
|
var NOOP = () => void 0;
|
|
166
|
-
var queryComment = (node, comment) => {
|
|
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
168
|
var queryChildren = (children, selector) => {
|
|
173
169
|
for (const child of children) {
|
|
174
170
|
if (child instanceof Element && child.matches(selector)) {
|
|
@@ -184,6 +180,9 @@ var serverDefineFns = /* @__PURE__ */ new Set();
|
|
|
184
180
|
var onServerDefine = (fn) => {
|
|
185
181
|
serverDefineFns.add(fn);
|
|
186
182
|
};
|
|
183
|
+
var clearServerCss = () => {
|
|
184
|
+
serverCss.clear();
|
|
185
|
+
};
|
|
187
186
|
var serverDefine = ({
|
|
188
187
|
tagName,
|
|
189
188
|
serverRender,
|
|
@@ -321,7 +320,7 @@ var clientOnlyCallback = (fn) => {
|
|
|
321
320
|
// src/render.ts
|
|
322
321
|
var CALLBACK_BINDING_REGEX = /(\{\{callback:.+\}\})/;
|
|
323
322
|
var LEGACY_CALLBACK_BINDING_REGEX = /(this.getRootNode\(\).host.__customCallbackFns.get\('.+'\)\(event\))/;
|
|
324
|
-
var SIGNAL_BINDING_REGEX = /(\{\{signal
|
|
323
|
+
var SIGNAL_BINDING_REGEX = /(\{\{signal:.+?\}\})/;
|
|
325
324
|
var FRAGMENT_ATTRIBUTE = "___thunderous-fragment";
|
|
326
325
|
var renderState = {
|
|
327
326
|
currentShadowRoot: null,
|
|
@@ -332,6 +331,13 @@ var renderState = {
|
|
|
332
331
|
propertyMap: /* @__PURE__ */ new Map(),
|
|
333
332
|
registry: typeof customElements !== "undefined" ? customElements : {}
|
|
334
333
|
};
|
|
334
|
+
var clearRenderState = () => {
|
|
335
|
+
renderState.signalMap.clear();
|
|
336
|
+
renderState.callbackMap.clear();
|
|
337
|
+
renderState.propertyMap.clear();
|
|
338
|
+
renderState.fragmentMap.clear();
|
|
339
|
+
renderState.childrenMap.clear();
|
|
340
|
+
};
|
|
335
341
|
var logPropertyWarning = (propName, element) => {
|
|
336
342
|
console.warn(
|
|
337
343
|
`Property "${propName}" does not exist on element:`,
|
|
@@ -339,19 +345,34 @@ var logPropertyWarning = (propName, element) => {
|
|
|
339
345
|
"\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."
|
|
340
346
|
);
|
|
341
347
|
};
|
|
342
|
-
var asNodeList = (value, parent) => {
|
|
348
|
+
var asNodeList = (value, parent, autoKey) => {
|
|
349
|
+
if (value === null || value === void 0) return [];
|
|
343
350
|
if (typeof value === "string") return [new Text(value)];
|
|
344
|
-
if (value
|
|
351
|
+
if (typeof value === "number" || typeof value === "boolean") return [new Text(String(value))];
|
|
352
|
+
if (value instanceof DocumentFragment) {
|
|
353
|
+
const children = Array.from(value.children);
|
|
354
|
+
if (autoKey !== void 0 && children.length > 0) {
|
|
355
|
+
const child = children[0];
|
|
356
|
+
if (child instanceof Element && child.getAttribute("key") === null) {
|
|
357
|
+
child.setAttribute("key", String(autoKey));
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return children;
|
|
361
|
+
}
|
|
345
362
|
if (Array.isArray(value)) {
|
|
346
363
|
const nodeList = [];
|
|
347
364
|
let count = 0;
|
|
348
365
|
const keys = /* @__PURE__ */ new Set();
|
|
349
366
|
for (const item of value) {
|
|
350
367
|
const cachedItem = item instanceof DocumentFragment ? renderState.childrenMap.get(item) : void 0;
|
|
351
|
-
const children = cachedItem ?? asNodeList(item, parent);
|
|
368
|
+
const children = cachedItem ?? asNodeList(item, parent, item instanceof DocumentFragment ? count : void 0);
|
|
352
369
|
if (cachedItem === void 0 && item instanceof DocumentFragment) {
|
|
353
370
|
renderState.childrenMap.set(item, children);
|
|
354
371
|
}
|
|
372
|
+
if (!(item instanceof DocumentFragment)) {
|
|
373
|
+
nodeList.push(...children);
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
355
376
|
if (children.length > 1) {
|
|
356
377
|
console.error(
|
|
357
378
|
"When rendering arrays, fragments must contain only one top-level element at a time. Error occured in:",
|
|
@@ -404,73 +425,77 @@ var processValue = (value) => {
|
|
|
404
425
|
renderState.callbackMap.set(uniqueKey, value);
|
|
405
426
|
return isServer ? String(value()) : `{{callback:${uniqueKey}}}`;
|
|
406
427
|
}
|
|
407
|
-
return String(value);
|
|
428
|
+
return value === null || value === void 0 ? "" : String(value);
|
|
408
429
|
};
|
|
409
430
|
var evaluateBindings = (element, fragment) => {
|
|
410
|
-
for (const child of
|
|
431
|
+
for (const child of Array.from(element.childNodes)) {
|
|
411
432
|
if (child instanceof Text && SIGNAL_BINDING_REGEX.test(child.data)) {
|
|
412
433
|
const textList = child.data.split(SIGNAL_BINDING_REGEX);
|
|
413
|
-
const
|
|
414
|
-
const
|
|
415
|
-
|
|
434
|
+
const allInitialChildren = [];
|
|
435
|
+
const signalEntries = [];
|
|
436
|
+
let signalIndex = 0;
|
|
437
|
+
const totalSignals = textList.filter((t) => SIGNAL_BINDING_REGEX.test(t)).length;
|
|
438
|
+
textList.forEach((text) => {
|
|
416
439
|
const uniqueKey = SIGNAL_BINDING_REGEX.test(text) ? text.replace(/\{\{signal:(.+)\}\}/, "$1") : void 0;
|
|
417
440
|
const signal = uniqueKey !== void 0 ? renderState.signalMap.get(uniqueKey) : void 0;
|
|
418
441
|
const newValue = signal !== void 0 ? signal() : text;
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
if (endAnchor2 !== null) {
|
|
425
|
-
endAnchor2.before(...initialChildren);
|
|
426
|
-
} else {
|
|
427
|
-
element.append(...initialChildren);
|
|
428
|
-
}
|
|
442
|
+
const autoKey = signal !== void 0 && totalSignals > 1 ? signalIndex++ : void 0;
|
|
443
|
+
const initialChildren = asNodeList(newValue, element, autoKey);
|
|
444
|
+
allInitialChildren.push(...initialChildren);
|
|
445
|
+
if (uniqueKey !== void 0 && signal !== void 0) {
|
|
446
|
+
signalEntries.push({ uniqueKey, signal, initialChildren, autoKey });
|
|
429
447
|
}
|
|
430
|
-
|
|
448
|
+
});
|
|
449
|
+
child.replaceWith(...allInitialChildren);
|
|
450
|
+
signalEntries.forEach(({ uniqueKey, signal, initialChildren, autoKey }) => {
|
|
451
|
+
const firstChild = initialChildren[0];
|
|
452
|
+
const lastChild = initialChildren[initialChildren.length - 1];
|
|
453
|
+
if (uniqueKey === void 0 || firstChild === void 0) return;
|
|
431
454
|
const startAnchor = document.createComment(`${uniqueKey}:start`);
|
|
432
|
-
|
|
433
|
-
prevSibling.after(startAnchor);
|
|
434
|
-
} else {
|
|
435
|
-
element.prepend(startAnchor);
|
|
436
|
-
}
|
|
455
|
+
firstChild.before(startAnchor);
|
|
437
456
|
const endAnchor = document.createComment(`${uniqueKey}:end`);
|
|
438
|
-
if (
|
|
439
|
-
|
|
457
|
+
if (lastChild !== void 0) {
|
|
458
|
+
lastChild.after(endAnchor);
|
|
440
459
|
} else {
|
|
441
|
-
|
|
460
|
+
startAnchor.after(endAnchor);
|
|
442
461
|
}
|
|
443
462
|
const bindText = (node, signal2) => {
|
|
444
463
|
createEffect(({ destroy }) => {
|
|
445
464
|
const result = signal2();
|
|
446
465
|
if (Array.isArray(result)) {
|
|
447
466
|
destroy();
|
|
448
|
-
bindArray(signal2);
|
|
467
|
+
bindArray(signal2, autoKey);
|
|
449
468
|
return;
|
|
450
469
|
}
|
|
451
470
|
if (result instanceof DocumentFragment) {
|
|
452
471
|
destroy();
|
|
453
|
-
bindFragment(signal2);
|
|
472
|
+
bindFragment(signal2, initialChildren, autoKey);
|
|
454
473
|
return;
|
|
455
474
|
}
|
|
456
|
-
node.data = result === null ? "" : String(result);
|
|
475
|
+
node.data = result === null || result === void 0 ? "" : String(result);
|
|
457
476
|
});
|
|
458
477
|
};
|
|
459
|
-
const bindArray = (signal2) => {
|
|
478
|
+
const bindArray = (signal2, autoKey2) => {
|
|
460
479
|
createEffect(
|
|
461
480
|
({ lastValue: oldChildren, destroy }) => {
|
|
462
481
|
const result = signal2();
|
|
463
|
-
const newChildren = asNodeList(result, element);
|
|
464
|
-
const
|
|
465
|
-
if (!Array.isArray(result)
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
482
|
+
const newChildren = asNodeList(result, element, autoKey2);
|
|
483
|
+
const firstChild2 = newChildren[0];
|
|
484
|
+
if (!Array.isArray(result)) {
|
|
485
|
+
if (newChildren.length === 1 && firstChild2 instanceof DocumentFragment) {
|
|
486
|
+
destroy();
|
|
487
|
+
bindFragment(signal2, initialChildren, autoKey2);
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
if (newChildren.length === 1 && firstChild2 instanceof Text) {
|
|
491
|
+
while (startAnchor.nextSibling !== endAnchor) {
|
|
492
|
+
startAnchor.nextSibling?.remove();
|
|
493
|
+
}
|
|
494
|
+
startAnchor.after(firstChild2);
|
|
495
|
+
destroy();
|
|
496
|
+
bindText(firstChild2, signal2);
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
474
499
|
}
|
|
475
500
|
while (startAnchor.nextSibling !== endAnchor) {
|
|
476
501
|
startAnchor.nextSibling?.remove();
|
|
@@ -486,10 +511,10 @@ var evaluateBindings = (element, fragment) => {
|
|
|
486
511
|
persistedChild.remove();
|
|
487
512
|
continue;
|
|
488
513
|
}
|
|
489
|
-
for (const attr of
|
|
514
|
+
for (const attr of Array.from(persistedChild.attributes)) {
|
|
490
515
|
if (!newChild.hasAttribute(attr.name)) persistedChild.removeAttribute(attr.name);
|
|
491
516
|
}
|
|
492
|
-
for (const newAttr of
|
|
517
|
+
for (const newAttr of Array.from(newChild.attributes)) {
|
|
493
518
|
const oldAttrValue = persistedChild.getAttribute(newAttr.name);
|
|
494
519
|
if (oldAttrValue?.startsWith("this.__customCallbackFns")) continue;
|
|
495
520
|
persistedChild.setAttribute(newAttr.name, newAttr.value);
|
|
@@ -502,36 +527,50 @@ var evaluateBindings = (element, fragment) => {
|
|
|
502
527
|
null
|
|
503
528
|
);
|
|
504
529
|
};
|
|
505
|
-
const bindFragment = (signal2) => {
|
|
530
|
+
const bindFragment = (signal2, initialChildren2, autoKey2) => {
|
|
506
531
|
const initialFragment = signal2();
|
|
507
|
-
|
|
532
|
+
const firstInitialChild = initialChildren2[0];
|
|
533
|
+
if (firstInitialChild instanceof Element) {
|
|
534
|
+
renderState.childrenMap.set(initialFragment, initialChildren2);
|
|
535
|
+
}
|
|
508
536
|
createEffect(({ destroy }) => {
|
|
509
537
|
const result = signal2();
|
|
510
|
-
const cachedChildren = renderState.childrenMap.get(
|
|
511
|
-
const children = cachedChildren ?? asNodeList(result, element);
|
|
538
|
+
const cachedChildren = result instanceof DocumentFragment ? renderState.childrenMap.get(result) : void 0;
|
|
539
|
+
const children = cachedChildren ?? asNodeList(result, element, autoKey2);
|
|
540
|
+
if (result instanceof DocumentFragment && !renderState.childrenMap.has(result)) {
|
|
541
|
+
renderState.childrenMap.set(result, children);
|
|
542
|
+
}
|
|
512
543
|
if (Array.isArray(result)) {
|
|
513
544
|
destroy();
|
|
514
|
-
bindArray(signal2);
|
|
545
|
+
bindArray(signal2, autoKey2);
|
|
515
546
|
return;
|
|
516
547
|
}
|
|
517
|
-
if (result instanceof
|
|
518
|
-
|
|
519
|
-
|
|
548
|
+
if (!(result instanceof DocumentFragment) && result !== null && result !== void 0) {
|
|
549
|
+
while (startAnchor.nextSibling !== endAnchor) {
|
|
550
|
+
startAnchor.nextSibling?.remove();
|
|
551
|
+
}
|
|
552
|
+
const children2 = asNodeList(result, element, autoKey2);
|
|
553
|
+
const text = children2[0];
|
|
554
|
+
startAnchor.after(text);
|
|
520
555
|
destroy();
|
|
521
|
-
bindText(
|
|
556
|
+
bindText(text, signal2);
|
|
522
557
|
return;
|
|
523
558
|
}
|
|
524
559
|
while (startAnchor.nextSibling !== endAnchor) {
|
|
525
560
|
startAnchor.nextSibling?.remove();
|
|
526
561
|
}
|
|
562
|
+
if (result === null || result === void 0) {
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
527
565
|
startAnchor.after(...children);
|
|
528
566
|
});
|
|
529
567
|
};
|
|
530
568
|
if (signal !== void 0) {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
569
|
+
const currentValue = signal();
|
|
570
|
+
if (Array.isArray(currentValue)) {
|
|
571
|
+
bindArray(signal, autoKey);
|
|
572
|
+
} else if (currentValue instanceof DocumentFragment) {
|
|
573
|
+
bindFragment(signal, initialChildren, autoKey);
|
|
535
574
|
} else {
|
|
536
575
|
const initialChild = initialChildren[0];
|
|
537
576
|
bindText(initialChild, signal);
|
|
@@ -546,7 +585,7 @@ var evaluateBindings = (element, fragment) => {
|
|
|
546
585
|
child.replaceWith(childFragment);
|
|
547
586
|
}
|
|
548
587
|
} else if (child instanceof Element) {
|
|
549
|
-
for (const attr of
|
|
588
|
+
for (const attr of Array.from(child.attributes)) {
|
|
550
589
|
const attrName = attr.name;
|
|
551
590
|
if (SIGNAL_BINDING_REGEX.test(attr.value)) {
|
|
552
591
|
const textList = attr.value.split(SIGNAL_BINDING_REGEX);
|
|
@@ -804,7 +843,9 @@ var customElement = (render, options) => {
|
|
|
804
843
|
for (const mutation of mutations) {
|
|
805
844
|
const attrName = mutation.attributeName;
|
|
806
845
|
if (mutation.type !== "attributes" || attrName === null) continue;
|
|
807
|
-
if (!(attrName in this.#attrSignals))
|
|
846
|
+
if (!(attrName in this.#attrSignals)) {
|
|
847
|
+
this.#attrSignals[attrName] = createSignal(this.getAttribute(attrName));
|
|
848
|
+
}
|
|
808
849
|
const [getter, setter] = this.#attrSignals[attrName];
|
|
809
850
|
const oldValue = getter();
|
|
810
851
|
const newValue = this.getAttribute(attrName);
|
|
@@ -904,7 +945,9 @@ You must set an initial value before calling a property signal's getter.
|
|
|
904
945
|
{},
|
|
905
946
|
{
|
|
906
947
|
get: (_, prop) => {
|
|
907
|
-
if (!(prop in this.#attrSignals))
|
|
948
|
+
if (!(prop in this.#attrSignals)) {
|
|
949
|
+
this.#attrSignals[prop] = createSignal(this.getAttribute(prop));
|
|
950
|
+
}
|
|
908
951
|
const [getter] = this.#attrSignals[prop];
|
|
909
952
|
const setter = (newValue) => this.setAttribute(prop, newValue);
|
|
910
953
|
return [getter, setter];
|
|
@@ -991,7 +1034,9 @@ You must set an initial value before calling a property signal's getter.
|
|
|
991
1034
|
}
|
|
992
1035
|
connectedCallback() {
|
|
993
1036
|
for (const [attrName, attr] of this.#attributesAsPropertiesMap) {
|
|
994
|
-
if (!(attrName in this.#attrSignals))
|
|
1037
|
+
if (!(attrName in this.#attrSignals)) {
|
|
1038
|
+
this.#attrSignals[attrName] = createSignal(this.getAttribute(attrName));
|
|
1039
|
+
}
|
|
995
1040
|
const propName = attr.prop;
|
|
996
1041
|
const [getter] = this.#getPropSignal(propName, { allowUndefined: true });
|
|
997
1042
|
let busy = false;
|
|
@@ -1008,6 +1053,16 @@ You must set an initial value before calling a property signal's getter.
|
|
|
1008
1053
|
busy = false;
|
|
1009
1054
|
});
|
|
1010
1055
|
}
|
|
1056
|
+
for (const attrName of Object.keys(this.#attrSignals)) {
|
|
1057
|
+
const signal = this.#attrSignals[attrName];
|
|
1058
|
+
if (signal) {
|
|
1059
|
+
const [getter, setter] = signal;
|
|
1060
|
+
const currentValue = this.getAttribute(attrName);
|
|
1061
|
+
if (getter() !== currentValue) {
|
|
1062
|
+
setter(currentValue);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1011
1066
|
if (this.#observer !== null) {
|
|
1012
1067
|
this.#observer.observe(this, { attributes: true });
|
|
1013
1068
|
}
|
|
@@ -1176,6 +1231,8 @@ var createRegistry = (args) => {
|
|
|
1176
1231
|
};
|
|
1177
1232
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1178
1233
|
0 && (module.exports = {
|
|
1234
|
+
clearRenderState,
|
|
1235
|
+
clearServerCss,
|
|
1179
1236
|
clientOnlyCallback,
|
|
1180
1237
|
createEffect,
|
|
1181
1238
|
createRegistry,
|
package/dist/index.d.cts
CHANGED
|
@@ -143,7 +143,41 @@ declare const customElement: <Props extends CustomElementProps>(render: RenderFu
|
|
|
143
143
|
*/
|
|
144
144
|
declare const createRegistry: (args?: RegistryArgs) => RegistryResult;
|
|
145
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Add a callback to handle each call to `define()` on the server.
|
|
148
|
+
*
|
|
149
|
+
* This enables you to intercept those definitions and respond to them,
|
|
150
|
+
* for example to inject declarative shadow DOM templates.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts
|
|
154
|
+
* let response = originalResponse;
|
|
155
|
+
* onServerDefine((tagName, htmlString) => {
|
|
156
|
+
* // ...
|
|
157
|
+
* response = htmlString.replace(tagName, `my-${tagName}`);
|
|
158
|
+
* });
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
146
161
|
declare const onServerDefine: (fn: ServerDefineFn) => void;
|
|
162
|
+
/**
|
|
163
|
+
* Thunderous tracks its state using several maps to associate values with
|
|
164
|
+
* their respective elements.
|
|
165
|
+
*
|
|
166
|
+
* This function clears the map that tracks CSS on the server side, to prevent
|
|
167
|
+
* memory leaks and purge stale data from previous renders.
|
|
168
|
+
*
|
|
169
|
+
* If you are building a framework or plugin that depends on Thunderous, you
|
|
170
|
+
* should call this function before every render. Otherwise, the map will
|
|
171
|
+
* accumulate stale data and may create significant performance issues.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```ts
|
|
175
|
+
* import { clearServerCss } from 'thunderous'
|
|
176
|
+
*
|
|
177
|
+
* clearServerCss();
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
declare const clearServerCss: () => void;
|
|
147
181
|
declare const insertTemplates: (tagName: string, template: string, inputString: string) => string;
|
|
148
182
|
declare const clientOnlyCallback: (fn: (() => void) | (() => Promise<void>)) => void | Promise<void>;
|
|
149
183
|
|
|
@@ -178,10 +212,29 @@ declare const derived: <T>(fn: () => T, options?: SignalOptions) => SignalGetter
|
|
|
178
212
|
*/
|
|
179
213
|
declare const createEffect: <T = unknown>(fn: Effect<T>, value?: T) => void;
|
|
180
214
|
|
|
215
|
+
/**
|
|
216
|
+
* Thunderous tracks its state using several maps to associate values with
|
|
217
|
+
* their respective elements.
|
|
218
|
+
*
|
|
219
|
+
* This function clears the maps tracking render state, to prevent memory
|
|
220
|
+
* leaks and purge stale data from previous renders.
|
|
221
|
+
*
|
|
222
|
+
* If you are building a framework or plugin that depends on Thunderous, you
|
|
223
|
+
* should call this function before every render. Otherwise, the maps will
|
|
224
|
+
* accumulate stale data and may create significant performance issues.
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```ts
|
|
228
|
+
* import { clearRenderState } from 'thunderous'
|
|
229
|
+
*
|
|
230
|
+
* clearRenderState();
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
declare const clearRenderState: () => void;
|
|
181
234
|
/**
|
|
182
235
|
* A tagged template function for creating DocumentFragment instances.
|
|
183
236
|
*/
|
|
184
237
|
declare const html: (strings: TemplateStringsArray, ...values: unknown[]) => DocumentFragment;
|
|
185
238
|
declare const css: (strings: TemplateStringsArray, ...values: unknown[]) => Styles;
|
|
186
239
|
|
|
187
|
-
export { type ElementResult, type HTMLCustomElement, type RegistryResult, type RenderArgs, type RenderFunction, type Signal, type SignalGetter, type SignalSetter, clientOnlyCallback, createEffect, createRegistry, createSignal, css, customElement, derived, html, insertTemplates, onServerDefine };
|
|
240
|
+
export { type ElementResult, type HTMLCustomElement, type RegistryResult, type RenderArgs, type RenderFunction, type Signal, type SignalGetter, type SignalSetter, clearRenderState, clearServerCss, clientOnlyCallback, createEffect, createRegistry, createSignal, css, customElement, derived, html, insertTemplates, onServerDefine };
|
package/dist/index.d.ts
CHANGED
|
@@ -143,7 +143,41 @@ declare const customElement: <Props extends CustomElementProps>(render: RenderFu
|
|
|
143
143
|
*/
|
|
144
144
|
declare const createRegistry: (args?: RegistryArgs) => RegistryResult;
|
|
145
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Add a callback to handle each call to `define()` on the server.
|
|
148
|
+
*
|
|
149
|
+
* This enables you to intercept those definitions and respond to them,
|
|
150
|
+
* for example to inject declarative shadow DOM templates.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts
|
|
154
|
+
* let response = originalResponse;
|
|
155
|
+
* onServerDefine((tagName, htmlString) => {
|
|
156
|
+
* // ...
|
|
157
|
+
* response = htmlString.replace(tagName, `my-${tagName}`);
|
|
158
|
+
* });
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
146
161
|
declare const onServerDefine: (fn: ServerDefineFn) => void;
|
|
162
|
+
/**
|
|
163
|
+
* Thunderous tracks its state using several maps to associate values with
|
|
164
|
+
* their respective elements.
|
|
165
|
+
*
|
|
166
|
+
* This function clears the map that tracks CSS on the server side, to prevent
|
|
167
|
+
* memory leaks and purge stale data from previous renders.
|
|
168
|
+
*
|
|
169
|
+
* If you are building a framework or plugin that depends on Thunderous, you
|
|
170
|
+
* should call this function before every render. Otherwise, the map will
|
|
171
|
+
* accumulate stale data and may create significant performance issues.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```ts
|
|
175
|
+
* import { clearServerCss } from 'thunderous'
|
|
176
|
+
*
|
|
177
|
+
* clearServerCss();
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
declare const clearServerCss: () => void;
|
|
147
181
|
declare const insertTemplates: (tagName: string, template: string, inputString: string) => string;
|
|
148
182
|
declare const clientOnlyCallback: (fn: (() => void) | (() => Promise<void>)) => void | Promise<void>;
|
|
149
183
|
|
|
@@ -178,10 +212,29 @@ declare const derived: <T>(fn: () => T, options?: SignalOptions) => SignalGetter
|
|
|
178
212
|
*/
|
|
179
213
|
declare const createEffect: <T = unknown>(fn: Effect<T>, value?: T) => void;
|
|
180
214
|
|
|
215
|
+
/**
|
|
216
|
+
* Thunderous tracks its state using several maps to associate values with
|
|
217
|
+
* their respective elements.
|
|
218
|
+
*
|
|
219
|
+
* This function clears the maps tracking render state, to prevent memory
|
|
220
|
+
* leaks and purge stale data from previous renders.
|
|
221
|
+
*
|
|
222
|
+
* If you are building a framework or plugin that depends on Thunderous, you
|
|
223
|
+
* should call this function before every render. Otherwise, the maps will
|
|
224
|
+
* accumulate stale data and may create significant performance issues.
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```ts
|
|
228
|
+
* import { clearRenderState } from 'thunderous'
|
|
229
|
+
*
|
|
230
|
+
* clearRenderState();
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
declare const clearRenderState: () => void;
|
|
181
234
|
/**
|
|
182
235
|
* A tagged template function for creating DocumentFragment instances.
|
|
183
236
|
*/
|
|
184
237
|
declare const html: (strings: TemplateStringsArray, ...values: unknown[]) => DocumentFragment;
|
|
185
238
|
declare const css: (strings: TemplateStringsArray, ...values: unknown[]) => Styles;
|
|
186
239
|
|
|
187
|
-
export { type ElementResult, type HTMLCustomElement, type RegistryResult, type RenderArgs, type RenderFunction, type Signal, type SignalGetter, type SignalSetter, clientOnlyCallback, createEffect, createRegistry, createSignal, css, customElement, derived, html, insertTemplates, onServerDefine };
|
|
240
|
+
export { type ElementResult, type HTMLCustomElement, type RegistryResult, type RenderArgs, type RenderFunction, type Signal, type SignalGetter, type SignalSetter, clearRenderState, clearServerCss, clientOnlyCallback, createEffect, createRegistry, createSignal, css, customElement, derived, html, insertTemplates, onServerDefine };
|
package/dist/index.js
CHANGED
|
@@ -128,12 +128,6 @@ var createEffect = (fn, value) => {
|
|
|
128
128
|
|
|
129
129
|
// src/utilities.ts
|
|
130
130
|
var NOOP = () => void 0;
|
|
131
|
-
var queryComment = (node, comment) => {
|
|
132
|
-
const walker = document.createTreeWalker(node, NodeFilter.SHOW_COMMENT, {
|
|
133
|
-
acceptNode: (n) => n.nodeValue === comment ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
|
|
134
|
-
});
|
|
135
|
-
return walker.nextNode();
|
|
136
|
-
};
|
|
137
131
|
var queryChildren = (children, selector) => {
|
|
138
132
|
for (const child of children) {
|
|
139
133
|
if (child instanceof Element && child.matches(selector)) {
|
|
@@ -149,6 +143,9 @@ var serverDefineFns = /* @__PURE__ */ new Set();
|
|
|
149
143
|
var onServerDefine = (fn) => {
|
|
150
144
|
serverDefineFns.add(fn);
|
|
151
145
|
};
|
|
146
|
+
var clearServerCss = () => {
|
|
147
|
+
serverCss.clear();
|
|
148
|
+
};
|
|
152
149
|
var serverDefine = ({
|
|
153
150
|
tagName,
|
|
154
151
|
serverRender,
|
|
@@ -286,7 +283,7 @@ var clientOnlyCallback = (fn) => {
|
|
|
286
283
|
// src/render.ts
|
|
287
284
|
var CALLBACK_BINDING_REGEX = /(\{\{callback:.+\}\})/;
|
|
288
285
|
var LEGACY_CALLBACK_BINDING_REGEX = /(this.getRootNode\(\).host.__customCallbackFns.get\('.+'\)\(event\))/;
|
|
289
|
-
var SIGNAL_BINDING_REGEX = /(\{\{signal
|
|
286
|
+
var SIGNAL_BINDING_REGEX = /(\{\{signal:.+?\}\})/;
|
|
290
287
|
var FRAGMENT_ATTRIBUTE = "___thunderous-fragment";
|
|
291
288
|
var renderState = {
|
|
292
289
|
currentShadowRoot: null,
|
|
@@ -297,6 +294,13 @@ var renderState = {
|
|
|
297
294
|
propertyMap: /* @__PURE__ */ new Map(),
|
|
298
295
|
registry: typeof customElements !== "undefined" ? customElements : {}
|
|
299
296
|
};
|
|
297
|
+
var clearRenderState = () => {
|
|
298
|
+
renderState.signalMap.clear();
|
|
299
|
+
renderState.callbackMap.clear();
|
|
300
|
+
renderState.propertyMap.clear();
|
|
301
|
+
renderState.fragmentMap.clear();
|
|
302
|
+
renderState.childrenMap.clear();
|
|
303
|
+
};
|
|
300
304
|
var logPropertyWarning = (propName, element) => {
|
|
301
305
|
console.warn(
|
|
302
306
|
`Property "${propName}" does not exist on element:`,
|
|
@@ -304,19 +308,34 @@ var logPropertyWarning = (propName, element) => {
|
|
|
304
308
|
"\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."
|
|
305
309
|
);
|
|
306
310
|
};
|
|
307
|
-
var asNodeList = (value, parent) => {
|
|
311
|
+
var asNodeList = (value, parent, autoKey) => {
|
|
312
|
+
if (value === null || value === void 0) return [];
|
|
308
313
|
if (typeof value === "string") return [new Text(value)];
|
|
309
|
-
if (value
|
|
314
|
+
if (typeof value === "number" || typeof value === "boolean") return [new Text(String(value))];
|
|
315
|
+
if (value instanceof DocumentFragment) {
|
|
316
|
+
const children = Array.from(value.children);
|
|
317
|
+
if (autoKey !== void 0 && children.length > 0) {
|
|
318
|
+
const child = children[0];
|
|
319
|
+
if (child instanceof Element && child.getAttribute("key") === null) {
|
|
320
|
+
child.setAttribute("key", String(autoKey));
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return children;
|
|
324
|
+
}
|
|
310
325
|
if (Array.isArray(value)) {
|
|
311
326
|
const nodeList = [];
|
|
312
327
|
let count = 0;
|
|
313
328
|
const keys = /* @__PURE__ */ new Set();
|
|
314
329
|
for (const item of value) {
|
|
315
330
|
const cachedItem = item instanceof DocumentFragment ? renderState.childrenMap.get(item) : void 0;
|
|
316
|
-
const children = cachedItem ?? asNodeList(item, parent);
|
|
331
|
+
const children = cachedItem ?? asNodeList(item, parent, item instanceof DocumentFragment ? count : void 0);
|
|
317
332
|
if (cachedItem === void 0 && item instanceof DocumentFragment) {
|
|
318
333
|
renderState.childrenMap.set(item, children);
|
|
319
334
|
}
|
|
335
|
+
if (!(item instanceof DocumentFragment)) {
|
|
336
|
+
nodeList.push(...children);
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
320
339
|
if (children.length > 1) {
|
|
321
340
|
console.error(
|
|
322
341
|
"When rendering arrays, fragments must contain only one top-level element at a time. Error occured in:",
|
|
@@ -369,73 +388,77 @@ var processValue = (value) => {
|
|
|
369
388
|
renderState.callbackMap.set(uniqueKey, value);
|
|
370
389
|
return isServer ? String(value()) : `{{callback:${uniqueKey}}}`;
|
|
371
390
|
}
|
|
372
|
-
return String(value);
|
|
391
|
+
return value === null || value === void 0 ? "" : String(value);
|
|
373
392
|
};
|
|
374
393
|
var evaluateBindings = (element, fragment) => {
|
|
375
|
-
for (const child of
|
|
394
|
+
for (const child of Array.from(element.childNodes)) {
|
|
376
395
|
if (child instanceof Text && SIGNAL_BINDING_REGEX.test(child.data)) {
|
|
377
396
|
const textList = child.data.split(SIGNAL_BINDING_REGEX);
|
|
378
|
-
const
|
|
379
|
-
const
|
|
380
|
-
|
|
397
|
+
const allInitialChildren = [];
|
|
398
|
+
const signalEntries = [];
|
|
399
|
+
let signalIndex = 0;
|
|
400
|
+
const totalSignals = textList.filter((t) => SIGNAL_BINDING_REGEX.test(t)).length;
|
|
401
|
+
textList.forEach((text) => {
|
|
381
402
|
const uniqueKey = SIGNAL_BINDING_REGEX.test(text) ? text.replace(/\{\{signal:(.+)\}\}/, "$1") : void 0;
|
|
382
403
|
const signal = uniqueKey !== void 0 ? renderState.signalMap.get(uniqueKey) : void 0;
|
|
383
404
|
const newValue = signal !== void 0 ? signal() : text;
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
if (endAnchor2 !== null) {
|
|
390
|
-
endAnchor2.before(...initialChildren);
|
|
391
|
-
} else {
|
|
392
|
-
element.append(...initialChildren);
|
|
393
|
-
}
|
|
405
|
+
const autoKey = signal !== void 0 && totalSignals > 1 ? signalIndex++ : void 0;
|
|
406
|
+
const initialChildren = asNodeList(newValue, element, autoKey);
|
|
407
|
+
allInitialChildren.push(...initialChildren);
|
|
408
|
+
if (uniqueKey !== void 0 && signal !== void 0) {
|
|
409
|
+
signalEntries.push({ uniqueKey, signal, initialChildren, autoKey });
|
|
394
410
|
}
|
|
395
|
-
|
|
411
|
+
});
|
|
412
|
+
child.replaceWith(...allInitialChildren);
|
|
413
|
+
signalEntries.forEach(({ uniqueKey, signal, initialChildren, autoKey }) => {
|
|
414
|
+
const firstChild = initialChildren[0];
|
|
415
|
+
const lastChild = initialChildren[initialChildren.length - 1];
|
|
416
|
+
if (uniqueKey === void 0 || firstChild === void 0) return;
|
|
396
417
|
const startAnchor = document.createComment(`${uniqueKey}:start`);
|
|
397
|
-
|
|
398
|
-
prevSibling.after(startAnchor);
|
|
399
|
-
} else {
|
|
400
|
-
element.prepend(startAnchor);
|
|
401
|
-
}
|
|
418
|
+
firstChild.before(startAnchor);
|
|
402
419
|
const endAnchor = document.createComment(`${uniqueKey}:end`);
|
|
403
|
-
if (
|
|
404
|
-
|
|
420
|
+
if (lastChild !== void 0) {
|
|
421
|
+
lastChild.after(endAnchor);
|
|
405
422
|
} else {
|
|
406
|
-
|
|
423
|
+
startAnchor.after(endAnchor);
|
|
407
424
|
}
|
|
408
425
|
const bindText = (node, signal2) => {
|
|
409
426
|
createEffect(({ destroy }) => {
|
|
410
427
|
const result = signal2();
|
|
411
428
|
if (Array.isArray(result)) {
|
|
412
429
|
destroy();
|
|
413
|
-
bindArray(signal2);
|
|
430
|
+
bindArray(signal2, autoKey);
|
|
414
431
|
return;
|
|
415
432
|
}
|
|
416
433
|
if (result instanceof DocumentFragment) {
|
|
417
434
|
destroy();
|
|
418
|
-
bindFragment(signal2);
|
|
435
|
+
bindFragment(signal2, initialChildren, autoKey);
|
|
419
436
|
return;
|
|
420
437
|
}
|
|
421
|
-
node.data = result === null ? "" : String(result);
|
|
438
|
+
node.data = result === null || result === void 0 ? "" : String(result);
|
|
422
439
|
});
|
|
423
440
|
};
|
|
424
|
-
const bindArray = (signal2) => {
|
|
441
|
+
const bindArray = (signal2, autoKey2) => {
|
|
425
442
|
createEffect(
|
|
426
443
|
({ lastValue: oldChildren, destroy }) => {
|
|
427
444
|
const result = signal2();
|
|
428
|
-
const newChildren = asNodeList(result, element);
|
|
429
|
-
const
|
|
430
|
-
if (!Array.isArray(result)
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
445
|
+
const newChildren = asNodeList(result, element, autoKey2);
|
|
446
|
+
const firstChild2 = newChildren[0];
|
|
447
|
+
if (!Array.isArray(result)) {
|
|
448
|
+
if (newChildren.length === 1 && firstChild2 instanceof DocumentFragment) {
|
|
449
|
+
destroy();
|
|
450
|
+
bindFragment(signal2, initialChildren, autoKey2);
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
if (newChildren.length === 1 && firstChild2 instanceof Text) {
|
|
454
|
+
while (startAnchor.nextSibling !== endAnchor) {
|
|
455
|
+
startAnchor.nextSibling?.remove();
|
|
456
|
+
}
|
|
457
|
+
startAnchor.after(firstChild2);
|
|
458
|
+
destroy();
|
|
459
|
+
bindText(firstChild2, signal2);
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
439
462
|
}
|
|
440
463
|
while (startAnchor.nextSibling !== endAnchor) {
|
|
441
464
|
startAnchor.nextSibling?.remove();
|
|
@@ -451,10 +474,10 @@ var evaluateBindings = (element, fragment) => {
|
|
|
451
474
|
persistedChild.remove();
|
|
452
475
|
continue;
|
|
453
476
|
}
|
|
454
|
-
for (const attr of
|
|
477
|
+
for (const attr of Array.from(persistedChild.attributes)) {
|
|
455
478
|
if (!newChild.hasAttribute(attr.name)) persistedChild.removeAttribute(attr.name);
|
|
456
479
|
}
|
|
457
|
-
for (const newAttr of
|
|
480
|
+
for (const newAttr of Array.from(newChild.attributes)) {
|
|
458
481
|
const oldAttrValue = persistedChild.getAttribute(newAttr.name);
|
|
459
482
|
if (oldAttrValue?.startsWith("this.__customCallbackFns")) continue;
|
|
460
483
|
persistedChild.setAttribute(newAttr.name, newAttr.value);
|
|
@@ -467,36 +490,50 @@ var evaluateBindings = (element, fragment) => {
|
|
|
467
490
|
null
|
|
468
491
|
);
|
|
469
492
|
};
|
|
470
|
-
const bindFragment = (signal2) => {
|
|
493
|
+
const bindFragment = (signal2, initialChildren2, autoKey2) => {
|
|
471
494
|
const initialFragment = signal2();
|
|
472
|
-
|
|
495
|
+
const firstInitialChild = initialChildren2[0];
|
|
496
|
+
if (firstInitialChild instanceof Element) {
|
|
497
|
+
renderState.childrenMap.set(initialFragment, initialChildren2);
|
|
498
|
+
}
|
|
473
499
|
createEffect(({ destroy }) => {
|
|
474
500
|
const result = signal2();
|
|
475
|
-
const cachedChildren = renderState.childrenMap.get(
|
|
476
|
-
const children = cachedChildren ?? asNodeList(result, element);
|
|
501
|
+
const cachedChildren = result instanceof DocumentFragment ? renderState.childrenMap.get(result) : void 0;
|
|
502
|
+
const children = cachedChildren ?? asNodeList(result, element, autoKey2);
|
|
503
|
+
if (result instanceof DocumentFragment && !renderState.childrenMap.has(result)) {
|
|
504
|
+
renderState.childrenMap.set(result, children);
|
|
505
|
+
}
|
|
477
506
|
if (Array.isArray(result)) {
|
|
478
507
|
destroy();
|
|
479
|
-
bindArray(signal2);
|
|
508
|
+
bindArray(signal2, autoKey2);
|
|
480
509
|
return;
|
|
481
510
|
}
|
|
482
|
-
if (result instanceof
|
|
483
|
-
|
|
484
|
-
|
|
511
|
+
if (!(result instanceof DocumentFragment) && result !== null && result !== void 0) {
|
|
512
|
+
while (startAnchor.nextSibling !== endAnchor) {
|
|
513
|
+
startAnchor.nextSibling?.remove();
|
|
514
|
+
}
|
|
515
|
+
const children2 = asNodeList(result, element, autoKey2);
|
|
516
|
+
const text = children2[0];
|
|
517
|
+
startAnchor.after(text);
|
|
485
518
|
destroy();
|
|
486
|
-
bindText(
|
|
519
|
+
bindText(text, signal2);
|
|
487
520
|
return;
|
|
488
521
|
}
|
|
489
522
|
while (startAnchor.nextSibling !== endAnchor) {
|
|
490
523
|
startAnchor.nextSibling?.remove();
|
|
491
524
|
}
|
|
525
|
+
if (result === null || result === void 0) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
492
528
|
startAnchor.after(...children);
|
|
493
529
|
});
|
|
494
530
|
};
|
|
495
531
|
if (signal !== void 0) {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
532
|
+
const currentValue = signal();
|
|
533
|
+
if (Array.isArray(currentValue)) {
|
|
534
|
+
bindArray(signal, autoKey);
|
|
535
|
+
} else if (currentValue instanceof DocumentFragment) {
|
|
536
|
+
bindFragment(signal, initialChildren, autoKey);
|
|
500
537
|
} else {
|
|
501
538
|
const initialChild = initialChildren[0];
|
|
502
539
|
bindText(initialChild, signal);
|
|
@@ -511,7 +548,7 @@ var evaluateBindings = (element, fragment) => {
|
|
|
511
548
|
child.replaceWith(childFragment);
|
|
512
549
|
}
|
|
513
550
|
} else if (child instanceof Element) {
|
|
514
|
-
for (const attr of
|
|
551
|
+
for (const attr of Array.from(child.attributes)) {
|
|
515
552
|
const attrName = attr.name;
|
|
516
553
|
if (SIGNAL_BINDING_REGEX.test(attr.value)) {
|
|
517
554
|
const textList = attr.value.split(SIGNAL_BINDING_REGEX);
|
|
@@ -769,7 +806,9 @@ var customElement = (render, options) => {
|
|
|
769
806
|
for (const mutation of mutations) {
|
|
770
807
|
const attrName = mutation.attributeName;
|
|
771
808
|
if (mutation.type !== "attributes" || attrName === null) continue;
|
|
772
|
-
if (!(attrName in this.#attrSignals))
|
|
809
|
+
if (!(attrName in this.#attrSignals)) {
|
|
810
|
+
this.#attrSignals[attrName] = createSignal(this.getAttribute(attrName));
|
|
811
|
+
}
|
|
773
812
|
const [getter, setter] = this.#attrSignals[attrName];
|
|
774
813
|
const oldValue = getter();
|
|
775
814
|
const newValue = this.getAttribute(attrName);
|
|
@@ -869,7 +908,9 @@ You must set an initial value before calling a property signal's getter.
|
|
|
869
908
|
{},
|
|
870
909
|
{
|
|
871
910
|
get: (_, prop) => {
|
|
872
|
-
if (!(prop in this.#attrSignals))
|
|
911
|
+
if (!(prop in this.#attrSignals)) {
|
|
912
|
+
this.#attrSignals[prop] = createSignal(this.getAttribute(prop));
|
|
913
|
+
}
|
|
873
914
|
const [getter] = this.#attrSignals[prop];
|
|
874
915
|
const setter = (newValue) => this.setAttribute(prop, newValue);
|
|
875
916
|
return [getter, setter];
|
|
@@ -956,7 +997,9 @@ You must set an initial value before calling a property signal's getter.
|
|
|
956
997
|
}
|
|
957
998
|
connectedCallback() {
|
|
958
999
|
for (const [attrName, attr] of this.#attributesAsPropertiesMap) {
|
|
959
|
-
if (!(attrName in this.#attrSignals))
|
|
1000
|
+
if (!(attrName in this.#attrSignals)) {
|
|
1001
|
+
this.#attrSignals[attrName] = createSignal(this.getAttribute(attrName));
|
|
1002
|
+
}
|
|
960
1003
|
const propName = attr.prop;
|
|
961
1004
|
const [getter] = this.#getPropSignal(propName, { allowUndefined: true });
|
|
962
1005
|
let busy = false;
|
|
@@ -973,6 +1016,16 @@ You must set an initial value before calling a property signal's getter.
|
|
|
973
1016
|
busy = false;
|
|
974
1017
|
});
|
|
975
1018
|
}
|
|
1019
|
+
for (const attrName of Object.keys(this.#attrSignals)) {
|
|
1020
|
+
const signal = this.#attrSignals[attrName];
|
|
1021
|
+
if (signal) {
|
|
1022
|
+
const [getter, setter] = signal;
|
|
1023
|
+
const currentValue = this.getAttribute(attrName);
|
|
1024
|
+
if (getter() !== currentValue) {
|
|
1025
|
+
setter(currentValue);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
976
1029
|
if (this.#observer !== null) {
|
|
977
1030
|
this.#observer.observe(this, { attributes: true });
|
|
978
1031
|
}
|
|
@@ -1140,6 +1193,8 @@ var createRegistry = (args) => {
|
|
|
1140
1193
|
};
|
|
1141
1194
|
};
|
|
1142
1195
|
export {
|
|
1196
|
+
clearRenderState,
|
|
1197
|
+
clearServerCss,
|
|
1143
1198
|
clientOnlyCallback,
|
|
1144
1199
|
createEffect,
|
|
1145
1200
|
createRegistry,
|