thunderous 1.1.1 → 2.0.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/dist/index.cjs CHANGED
@@ -18,8 +18,8 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
20
  // src/index.ts
21
- var src_exports = {};
22
- __export(src_exports, {
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
23
  clientOnlyCallback: () => clientOnlyCallback,
24
24
  createEffect: () => createEffect,
25
25
  createRegistry: () => createRegistry,
@@ -31,441 +31,7 @@ __export(src_exports, {
31
31
  insertTemplates: () => insertTemplates,
32
32
  onServerDefine: () => onServerDefine
33
33
  });
34
- module.exports = __toCommonJS(src_exports);
35
-
36
- // vendor/@webcomponents/scoped-custom-element-registry/src/scoped-custom-element-registry.js
37
- if (typeof window !== "undefined") {
38
- if (!ShadowRoot.prototype.createElement) {
39
- const NativeHTMLElement = window.HTMLElement;
40
- const nativeDefine = window.customElements.define;
41
- const nativeGet = window.customElements.get;
42
- const nativeRegistry = window.customElements;
43
- const definitionForElement = /* @__PURE__ */ new WeakMap();
44
- const pendingRegistryForElement = /* @__PURE__ */ new WeakMap();
45
- const globalDefinitionForConstructor = /* @__PURE__ */ new WeakMap();
46
- const scopeForElement = /* @__PURE__ */ new WeakMap();
47
- window.CustomElementRegistry = class {
48
- constructor() {
49
- this._definitionsByTag = /* @__PURE__ */ new Map();
50
- this._definitionsByClass = /* @__PURE__ */ new Map();
51
- this._whenDefinedPromises = /* @__PURE__ */ new Map();
52
- this._awaitingUpgrade = /* @__PURE__ */ new Map();
53
- }
54
- define(tagName, elementClass) {
55
- tagName = tagName.toLowerCase();
56
- if (this._getDefinition(tagName) !== void 0) {
57
- throw new DOMException(
58
- `Failed to execute 'define' on 'CustomElementRegistry': the name "${tagName}" has already been used with this registry`
59
- );
60
- }
61
- if (this._definitionsByClass.get(elementClass) !== void 0) {
62
- throw new DOMException(
63
- `Failed to execute 'define' on 'CustomElementRegistry': this constructor has already been used with this registry`
64
- );
65
- }
66
- const attributeChangedCallback = elementClass.prototype.attributeChangedCallback;
67
- const observedAttributes = new Set(elementClass.observedAttributes || []);
68
- patchAttributes(
69
- elementClass,
70
- observedAttributes,
71
- attributeChangedCallback
72
- );
73
- const definition = {
74
- elementClass,
75
- connectedCallback: elementClass.prototype.connectedCallback,
76
- disconnectedCallback: elementClass.prototype.disconnectedCallback,
77
- adoptedCallback: elementClass.prototype.adoptedCallback,
78
- attributeChangedCallback,
79
- "formAssociated": elementClass["formAssociated"],
80
- "formAssociatedCallback": elementClass.prototype["formAssociatedCallback"],
81
- "formDisabledCallback": elementClass.prototype["formDisabledCallback"],
82
- "formResetCallback": elementClass.prototype["formResetCallback"],
83
- "formStateRestoreCallback": elementClass.prototype["formStateRestoreCallback"],
84
- observedAttributes
85
- };
86
- this._definitionsByTag.set(tagName, definition);
87
- this._definitionsByClass.set(elementClass, definition);
88
- let standInClass = nativeGet.call(nativeRegistry, tagName);
89
- if (!standInClass) {
90
- standInClass = createStandInElement(tagName);
91
- nativeDefine.call(nativeRegistry, tagName, standInClass);
92
- }
93
- if (this === window.customElements) {
94
- globalDefinitionForConstructor.set(elementClass, definition);
95
- definition.standInClass = standInClass;
96
- }
97
- const awaiting = this._awaitingUpgrade.get(tagName);
98
- if (awaiting) {
99
- this._awaitingUpgrade.delete(tagName);
100
- for (const element of awaiting) {
101
- pendingRegistryForElement.delete(element);
102
- customize(element, definition, true);
103
- }
104
- }
105
- const info = this._whenDefinedPromises.get(tagName);
106
- if (info !== void 0) {
107
- info.resolve(elementClass);
108
- this._whenDefinedPromises.delete(tagName);
109
- }
110
- return elementClass;
111
- }
112
- upgrade() {
113
- creationContext.push(this);
114
- nativeRegistry.upgrade.apply(nativeRegistry, arguments);
115
- creationContext.pop();
116
- }
117
- get(tagName) {
118
- const definition = this._definitionsByTag.get(tagName);
119
- return definition?.elementClass;
120
- }
121
- _getDefinition(tagName) {
122
- return this._definitionsByTag.get(tagName);
123
- }
124
- whenDefined(tagName) {
125
- const definition = this._getDefinition(tagName);
126
- if (definition !== void 0) {
127
- return Promise.resolve(definition.elementClass);
128
- }
129
- let info = this._whenDefinedPromises.get(tagName);
130
- if (info === void 0) {
131
- info = {};
132
- info.promise = new Promise((r) => info.resolve = r);
133
- this._whenDefinedPromises.set(tagName, info);
134
- }
135
- return info.promise;
136
- }
137
- _upgradeWhenDefined(element, tagName, shouldUpgrade) {
138
- let awaiting = this._awaitingUpgrade.get(tagName);
139
- if (!awaiting) {
140
- this._awaitingUpgrade.set(tagName, awaiting = /* @__PURE__ */ new Set());
141
- }
142
- if (shouldUpgrade) {
143
- awaiting.add(element);
144
- } else {
145
- awaiting.delete(element);
146
- }
147
- }
148
- };
149
- let upgradingInstance;
150
- window.HTMLElement = function HTMLElement2() {
151
- let instance = upgradingInstance;
152
- if (instance) {
153
- upgradingInstance = void 0;
154
- return instance;
155
- }
156
- const definition = globalDefinitionForConstructor.get(this.constructor);
157
- if (!definition) {
158
- throw new TypeError(
159
- "Illegal constructor (custom element class must be registered with global customElements registry to be newable)"
160
- );
161
- }
162
- instance = Reflect.construct(
163
- NativeHTMLElement,
164
- [],
165
- definition.standInClass
166
- );
167
- Object.setPrototypeOf(instance, this.constructor.prototype);
168
- definitionForElement.set(instance, definition);
169
- return instance;
170
- };
171
- window.HTMLElement.prototype = NativeHTMLElement.prototype;
172
- const isValidScope = (node) => node === document || node instanceof ShadowRoot;
173
- const registryForNode = (node) => {
174
- let scope = node.getRootNode();
175
- if (!isValidScope(scope)) {
176
- const context = creationContext[creationContext.length - 1];
177
- if (context instanceof CustomElementRegistry) {
178
- return context;
179
- }
180
- scope = context.getRootNode();
181
- if (!isValidScope(scope)) {
182
- scope = scopeForElement.get(scope)?.getRootNode() || document;
183
- }
184
- }
185
- return scope.customElements;
186
- };
187
- const createStandInElement = (tagName) => {
188
- return class ScopedCustomElementBase {
189
- static get ["formAssociated"]() {
190
- return true;
191
- }
192
- constructor() {
193
- const instance = Reflect.construct(
194
- NativeHTMLElement,
195
- [],
196
- this.constructor
197
- );
198
- Object.setPrototypeOf(instance, HTMLElement.prototype);
199
- const registry = registryForNode(instance) || window.customElements;
200
- const definition = registry._getDefinition(tagName);
201
- if (definition) {
202
- customize(instance, definition);
203
- } else {
204
- pendingRegistryForElement.set(instance, registry);
205
- }
206
- return instance;
207
- }
208
- connectedCallback() {
209
- const definition = definitionForElement.get(this);
210
- if (definition) {
211
- definition.connectedCallback && definition.connectedCallback.apply(this, arguments);
212
- } else {
213
- pendingRegistryForElement.get(this)._upgradeWhenDefined(this, tagName, true);
214
- }
215
- }
216
- disconnectedCallback() {
217
- const definition = definitionForElement.get(this);
218
- if (definition) {
219
- definition.disconnectedCallback && definition.disconnectedCallback.apply(this, arguments);
220
- } else {
221
- pendingRegistryForElement.get(this)._upgradeWhenDefined(this, tagName, false);
222
- }
223
- }
224
- adoptedCallback() {
225
- const definition = definitionForElement.get(this);
226
- definition?.adoptedCallback?.apply(this, arguments);
227
- }
228
- // Form-associated custom elements lifecycle methods
229
- ["formAssociatedCallback"]() {
230
- const definition = definitionForElement.get(this);
231
- if (definition && definition["formAssociated"]) {
232
- definition?.["formAssociatedCallback"]?.apply(this, arguments);
233
- }
234
- }
235
- ["formDisabledCallback"]() {
236
- const definition = definitionForElement.get(this);
237
- if (definition?.["formAssociated"]) {
238
- definition?.["formDisabledCallback"]?.apply(this, arguments);
239
- }
240
- }
241
- ["formResetCallback"]() {
242
- const definition = definitionForElement.get(this);
243
- if (definition?.["formAssociated"]) {
244
- definition?.["formResetCallback"]?.apply(this, arguments);
245
- }
246
- }
247
- ["formStateRestoreCallback"]() {
248
- const definition = definitionForElement.get(this);
249
- if (definition?.["formAssociated"]) {
250
- definition?.["formStateRestoreCallback"]?.apply(this, arguments);
251
- }
252
- }
253
- // no attributeChangedCallback or observedAttributes since these
254
- // are simulated via setAttribute/removeAttribute patches
255
- };
256
- };
257
- const patchAttributes = (elementClass, observedAttributes, attributeChangedCallback) => {
258
- if (observedAttributes.size === 0 || attributeChangedCallback === void 0) {
259
- return;
260
- }
261
- const setAttribute = elementClass.prototype.setAttribute;
262
- if (setAttribute) {
263
- elementClass.prototype.setAttribute = function(n, value) {
264
- const name = n.toLowerCase();
265
- if (observedAttributes.has(name)) {
266
- const old = this.getAttribute(name);
267
- setAttribute.call(this, name, value);
268
- attributeChangedCallback.call(this, name, old, value);
269
- } else {
270
- setAttribute.call(this, name, value);
271
- }
272
- };
273
- }
274
- const removeAttribute = elementClass.prototype.removeAttribute;
275
- if (removeAttribute) {
276
- elementClass.prototype.removeAttribute = function(n) {
277
- const name = n.toLowerCase();
278
- if (observedAttributes.has(name)) {
279
- const old = this.getAttribute(name);
280
- removeAttribute.call(this, name);
281
- attributeChangedCallback.call(this, name, old, null);
282
- } else {
283
- removeAttribute.call(this, name);
284
- }
285
- };
286
- }
287
- const toggleAttribute = elementClass.prototype.toggleAttribute;
288
- if (toggleAttribute) {
289
- elementClass.prototype.toggleAttribute = function(n, force) {
290
- const name = n.toLowerCase();
291
- if (observedAttributes.has(name)) {
292
- const old = this.getAttribute(name);
293
- toggleAttribute.call(this, name, force);
294
- const newValue = this.getAttribute(name);
295
- attributeChangedCallback.call(this, name, old, newValue);
296
- } else {
297
- toggleAttribute.call(this, name, force);
298
- }
299
- };
300
- }
301
- };
302
- const patchHTMLElement = (elementClass) => {
303
- const parentClass = Object.getPrototypeOf(elementClass);
304
- if (parentClass !== window.HTMLElement) {
305
- if (parentClass === NativeHTMLElement) {
306
- return Object.setPrototypeOf(elementClass, window.HTMLElement);
307
- }
308
- return patchHTMLElement(parentClass);
309
- }
310
- };
311
- const customize = (instance, definition, isUpgrade = false) => {
312
- Object.setPrototypeOf(instance, definition.elementClass.prototype);
313
- definitionForElement.set(instance, definition);
314
- upgradingInstance = instance;
315
- try {
316
- new definition.elementClass();
317
- } catch (_) {
318
- patchHTMLElement(definition.elementClass);
319
- new definition.elementClass();
320
- }
321
- if (definition.attributeChangedCallback) {
322
- definition.observedAttributes.forEach((attr) => {
323
- if (instance.hasAttribute(attr)) {
324
- definition.attributeChangedCallback.call(
325
- instance,
326
- attr,
327
- null,
328
- instance.getAttribute(attr)
329
- );
330
- }
331
- });
332
- }
333
- if (isUpgrade && definition.connectedCallback && instance.isConnected) {
334
- definition.connectedCallback.call(instance);
335
- }
336
- };
337
- const nativeAttachShadow = Element.prototype.attachShadow;
338
- Element.prototype.attachShadow = function(init) {
339
- const shadowRoot = nativeAttachShadow.apply(this, arguments);
340
- if (init.customElements) {
341
- shadowRoot.customElements = init.customElements;
342
- }
343
- return shadowRoot;
344
- };
345
- let creationContext = [document];
346
- const installScopedCreationMethod = (ctor, method, from = void 0) => {
347
- const native = (from ? Object.getPrototypeOf(from) : ctor.prototype)[method];
348
- ctor.prototype[method] = function() {
349
- creationContext.push(this);
350
- const ret = native.apply(from || this, arguments);
351
- if (ret !== void 0) {
352
- scopeForElement.set(ret, this);
353
- }
354
- creationContext.pop();
355
- return ret;
356
- };
357
- };
358
- installScopedCreationMethod(ShadowRoot, "createElement", document);
359
- installScopedCreationMethod(ShadowRoot, "importNode", document);
360
- installScopedCreationMethod(Element, "insertAdjacentHTML");
361
- const installScopedCreationSetter = (ctor, name) => {
362
- const descriptor = Object.getOwnPropertyDescriptor(ctor.prototype, name);
363
- Object.defineProperty(ctor.prototype, name, {
364
- ...descriptor,
365
- set(value) {
366
- creationContext.push(this);
367
- descriptor.set.call(this, value);
368
- creationContext.pop();
369
- }
370
- });
371
- };
372
- installScopedCreationSetter(Element, "innerHTML");
373
- installScopedCreationSetter(ShadowRoot, "innerHTML");
374
- Object.defineProperty(window, "customElements", {
375
- value: new CustomElementRegistry(),
376
- configurable: true,
377
- writable: true
378
- });
379
- if (!!window["ElementInternals"] && !!window["ElementInternals"].prototype["setFormValue"]) {
380
- const internalsToHostMap = /* @__PURE__ */ new WeakMap();
381
- const attachInternals = HTMLElement.prototype["attachInternals"];
382
- const methods = [
383
- "setFormValue",
384
- "setValidity",
385
- "checkValidity",
386
- "reportValidity"
387
- ];
388
- HTMLElement.prototype["attachInternals"] = function(...args) {
389
- const internals = attachInternals.call(this, ...args);
390
- internalsToHostMap.set(internals, this);
391
- return internals;
392
- };
393
- methods.forEach((method) => {
394
- const proto = window["ElementInternals"].prototype;
395
- const originalMethod = proto[method];
396
- proto[method] = function(...args) {
397
- const host = internalsToHostMap.get(this);
398
- const definition = definitionForElement.get(host);
399
- if (definition["formAssociated"] === true) {
400
- return originalMethod?.call(this, ...args);
401
- } else {
402
- throw new DOMException(
403
- `Failed to execute ${originalMethod} on 'ElementInternals': The target element is not a form-associated custom element.`
404
- );
405
- }
406
- };
407
- });
408
- class RadioNodeList extends Array {
409
- constructor(elements) {
410
- super(...elements);
411
- this._elements = elements;
412
- }
413
- get ["value"]() {
414
- return this._elements.find((element) => element["checked"] === true)?.value || "";
415
- }
416
- }
417
- class HTMLFormControlsCollection {
418
- constructor(elements) {
419
- const entries = /* @__PURE__ */ new Map();
420
- elements.forEach((element, index) => {
421
- const name = element.getAttribute("name");
422
- const nameReference = entries.get(name) || [];
423
- this[+index] = element;
424
- nameReference.push(element);
425
- entries.set(name, nameReference);
426
- });
427
- this["length"] = elements.length;
428
- entries.forEach((value, key) => {
429
- if (!value) return;
430
- if (value.length === 1) {
431
- this[key] = value[0];
432
- } else {
433
- this[key] = new RadioNodeList(value);
434
- }
435
- });
436
- }
437
- ["namedItem"](key) {
438
- return this[key];
439
- }
440
- }
441
- const formElementsDescriptor = Object.getOwnPropertyDescriptor(
442
- HTMLFormElement.prototype,
443
- "elements"
444
- );
445
- Object.defineProperty(HTMLFormElement.prototype, "elements", {
446
- get: function() {
447
- const nativeElements = formElementsDescriptor.get.call(this, []);
448
- const include = [];
449
- for (const element of nativeElements) {
450
- const definition = definitionForElement.get(element);
451
- if (!definition || definition["formAssociated"] === true) {
452
- include.push(element);
453
- }
454
- }
455
- return new HTMLFormControlsCollection(include);
456
- }
457
- });
458
- }
459
- }
460
- class TrackableCustomElementRegistry extends window.CustomElementRegistry {
461
- __tagNames = /* @__PURE__ */ new Set();
462
- define(tagName, constructor, options) {
463
- super.define(tagName, constructor, options);
464
- this.__tagNames.add(tagName);
465
- }
466
- }
467
- window.CustomElementRegistry = TrackableCustomElementRegistry;
468
- }
34
+ module.exports = __toCommonJS(index_exports);
469
35
 
470
36
  // src/constants.ts
471
37
  var DEFAULT_RENDER_OPTIONS = {
@@ -509,6 +75,7 @@ var createSignal = (initVal, options) => {
509
75
  }
510
76
  return value;
511
77
  };
78
+ getter.getter = true;
512
79
  const setter = (newValue, setterOptions) => {
513
80
  const isObject = typeof newValue === "object" && newValue !== null;
514
81
  if (!isObject && value === newValue) return;
@@ -645,7 +212,12 @@ var getServerRenderArgs = (tagName, registry) => ({
645
212
  formStateRestoreCallback: NOOP,
646
213
  formAssociatedCallback: NOOP,
647
214
  clientOnlyCallback: NOOP,
648
- customCallback: () => `{{callback:unavailable-on-server}}`,
215
+ customCallback: () => "",
216
+ getter: (fn) => {
217
+ const _fn = () => fn();
218
+ _fn.getter = true;
219
+ return _fn;
220
+ },
649
221
  attrSignals: new Proxy({}, { get: (_, attr) => createSignal(`{{attr:${String(attr)}}}`) }),
650
222
  propSignals: new Proxy({}, { get: () => createSignal(null) }),
651
223
  refs: {},
@@ -765,13 +337,14 @@ var getNewNode = (value, parent) => {
765
337
  var html = (strings, ...values) => {
766
338
  let innerHTML = "";
767
339
  const signalMap = /* @__PURE__ */ new Map();
340
+ const callbackMap = /* @__PURE__ */ new Map();
768
341
  const processValue = (value) => {
769
342
  if (!isServer && value instanceof DocumentFragment) {
770
343
  const tempDiv = document.createElement("div");
771
344
  tempDiv.append(value.cloneNode(true));
772
345
  return tempDiv.innerHTML;
773
346
  }
774
- if (typeof value === "function") {
347
+ if (typeof value === "function" && "getter" in value && value.getter === true) {
775
348
  const getter = value;
776
349
  const uniqueKey = crypto.randomUUID();
777
350
  signalMap.set(uniqueKey, getter);
@@ -781,6 +354,11 @@ var html = (strings, ...values) => {
781
354
  }
782
355
  return isServer ? String(result) : `{{signal:${uniqueKey}}}`;
783
356
  }
357
+ if (typeof value === "function") {
358
+ const uniqueKey = crypto.randomUUID();
359
+ callbackMap.set(uniqueKey, value);
360
+ return isServer ? String(value()) : `{{callback:${uniqueKey}}}`;
361
+ }
784
362
  if (typeof value === "object" && value !== null) {
785
363
  logValueError(value);
786
364
  return "";
@@ -801,6 +379,7 @@ var html = (strings, ...values) => {
801
379
  }
802
380
  const fragment = parseFragment(innerHTML);
803
381
  const callbackBindingRegex = /(\{\{callback:.+\}\})/;
382
+ const legacyCallbackBindingRegex = /(this.getRootNode\(\).host.__customCallbackFns.get\('.+'\)\(event\))/;
804
383
  const signalBindingRegex = /(\{\{signal:.+\}\})/;
805
384
  const parseChildren = (element) => {
806
385
  for (const child of element.childNodes) {
@@ -863,14 +442,29 @@ var html = (strings, ...values) => {
863
442
  child.setAttribute(attr.name, newText);
864
443
  }
865
444
  });
866
- } else if (callbackBindingRegex.test(attr.value)) {
445
+ } else if (legacyCallbackBindingRegex.test(attr.value)) {
867
446
  const getRootNode = child.getRootNode.bind(child);
868
447
  child.getRootNode = () => {
869
448
  const rootNode = getRootNode();
870
449
  return rootNode instanceof ShadowRoot ? rootNode : fragment;
871
450
  };
872
- const uniqueKey = attr.value.replace(/\{\{callback:(.+)\}\}/, "$1");
873
- child.setAttribute(attr.name, `this.getRootNode().host.__customCallbackFns.get('${uniqueKey}')(event)`);
451
+ } else if (callbackBindingRegex.test(attr.value)) {
452
+ const textList = attr.value.split(callbackBindingRegex);
453
+ createEffect(() => {
454
+ child.__customCallbackFns = child.__customCallbackFns ?? /* @__PURE__ */ new Map();
455
+ let uniqueKey = "";
456
+ for (const text of textList) {
457
+ const _uniqueKey = text.replace(/\{\{callback:(.+)\}\}/, "$1");
458
+ if (_uniqueKey !== text) uniqueKey = _uniqueKey;
459
+ const callback = uniqueKey !== text ? callbackMap.get(uniqueKey) : void 0;
460
+ if (callback !== void 0) {
461
+ child.__customCallbackFns.set(uniqueKey, callback);
462
+ }
463
+ }
464
+ if (uniqueKey !== "") {
465
+ child.setAttribute(attr.name, `this.__customCallbackFns.get('${uniqueKey}')(event)`);
466
+ }
467
+ });
874
468
  }
875
469
  }
876
470
  parseChildren(child);
@@ -1035,10 +629,15 @@ var customElement = (render, options) => {
1035
629
  formResetCallback: (fn) => this.#formResetCallbackFns.add(fn),
1036
630
  formStateRestoreCallback: (fn) => this.#formStateRestoreCallbackFns.add(fn),
1037
631
  clientOnlyCallback: (fn) => this.#clientOnlyCallbackFns.add(fn),
632
+ getter: (fn) => {
633
+ const _fn = () => fn();
634
+ _fn.getter = true;
635
+ return _fn;
636
+ },
1038
637
  customCallback: (fn) => {
1039
638
  const key = crypto.randomUUID();
1040
639
  this.__customCallbackFns.set(key, fn);
1041
- return `{{callback:${key}}}`;
640
+ return `this.getRootNode().host.__customCallbackFns.get('${key}')(event)`;
1042
641
  },
1043
642
  attrSignals: new Proxy(
1044
643
  {},
@@ -1076,6 +675,7 @@ You must set an initial value before calling a property signal's getter.
1076
675
  );
1077
676
  return value;
1078
677
  };
678
+ getter.getter = true;
1079
679
  return [getter, setter];
1080
680
  },
1081
681
  set: () => {
@@ -1322,16 +922,3 @@ var createRegistry = (args) => {
1322
922
  insertTemplates,
1323
923
  onServerDefine
1324
924
  });
1325
- /**
1326
- * @license
1327
- * Copyright (c) 2020 The Polymer Project Authors. All rights reserved.
1328
- * This code may only be used under the BSD style license found at
1329
- * http://polymer.github.io/LICENSE.txt
1330
- * The complete set of authors may be found at
1331
- * http://polymer.github.io/AUTHORS.txt
1332
- * The complete set of contributors may be found at
1333
- * http://polymer.github.io/CONTRIBUTORS.txt
1334
- * Code distributed by Google as part of the polymer project is also
1335
- * subject to an additional IP rights grant found at
1336
- * http://polymer.github.io/PATENTS.txt
1337
- */