thunderous 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/index.cjs +152 -99
- package/dist/index.d.cts +12 -7
- package/dist/index.d.ts +12 -7
- package/dist/index.js +152 -99
- package/package.json +1 -1
package/README.md
CHANGED
@@ -227,6 +227,27 @@ createEffect(() => {
|
|
227
227
|
});
|
228
228
|
```
|
229
229
|
|
230
|
+
##### Debugging Signals
|
231
|
+
|
232
|
+
If you're having a tough time tracing an issue, you can provide the `debugMode` option to any signal to log potentially helpful information to the console. For differentiating values, you can also provide an optional `label` property to easily associate logs with their respective sources. These options can be passed to signals themselves, or to specific calls to setters and getters.
|
233
|
+
|
234
|
+
```ts
|
235
|
+
const [count, setCount] = createSignal(0, {
|
236
|
+
debugMode: true,
|
237
|
+
label: 'count signal',
|
238
|
+
});
|
239
|
+
|
240
|
+
setCount(1, {
|
241
|
+
debugMode: true,
|
242
|
+
label: 'start count',
|
243
|
+
});
|
244
|
+
|
245
|
+
const newCount = count({
|
246
|
+
debugMode: true,
|
247
|
+
label: 'new count',
|
248
|
+
});
|
249
|
+
```
|
250
|
+
|
230
251
|
#### Refs
|
231
252
|
|
232
253
|
The refs property exists for convenience to avoid manually querying the DOM. Since the DOM is only available after rendering, refs will only work in and after the `connectedCallback` method.
|
package/dist/index.cjs
CHANGED
@@ -50,18 +50,33 @@ var setInnerHTML = (element, html2) => {
|
|
50
50
|
var subscriber = null;
|
51
51
|
var updateQueue = /* @__PURE__ */ new Set();
|
52
52
|
var isBatchingUpdates = false;
|
53
|
-
var createSignal = (initVal) => {
|
53
|
+
var createSignal = (initVal, options) => {
|
54
54
|
const subscribers = /* @__PURE__ */ new Set();
|
55
55
|
let value = initVal;
|
56
|
-
const getter = () => {
|
56
|
+
const getter = (getterOptions) => {
|
57
57
|
if (subscriber !== null) {
|
58
58
|
subscribers.add(subscriber);
|
59
59
|
}
|
60
|
+
if ((options == null ? void 0 : options.debugMode) || (getterOptions == null ? void 0 : getterOptions.debugMode)) {
|
61
|
+
requestAnimationFrame(() => {
|
62
|
+
let label = "anonymous signal";
|
63
|
+
if ((options == null ? void 0 : options.label) !== void 0) {
|
64
|
+
label = `(${options.label})`;
|
65
|
+
if ((getterOptions == null ? void 0 : getterOptions.label) !== void 0) {
|
66
|
+
label += ` ${getterOptions.label}`;
|
67
|
+
}
|
68
|
+
} else if ((getterOptions == null ? void 0 : getterOptions.label) !== void 0) {
|
69
|
+
label = getterOptions.label;
|
70
|
+
}
|
71
|
+
console.log("Signal retrieved:", { value, subscribers, label });
|
72
|
+
});
|
73
|
+
}
|
60
74
|
return value;
|
61
75
|
};
|
62
|
-
const setter = (newValue) => {
|
76
|
+
const setter = (newValue, setterOptions) => {
|
63
77
|
const isObject = typeof newValue === "object" && newValue !== null;
|
64
78
|
if (!isObject && value === newValue) return;
|
79
|
+
const oldValue = value;
|
65
80
|
value = newValue;
|
66
81
|
for (const fn of subscribers) {
|
67
82
|
updateQueue.add(fn);
|
@@ -69,9 +84,24 @@ var createSignal = (initVal) => {
|
|
69
84
|
if (!isBatchingUpdates) {
|
70
85
|
isBatchingUpdates = true;
|
71
86
|
requestAnimationFrame(() => {
|
72
|
-
console.log("next animation frame");
|
73
87
|
for (const fn of updateQueue) {
|
74
|
-
|
88
|
+
try {
|
89
|
+
fn();
|
90
|
+
} catch (error) {
|
91
|
+
console.error("Error in subscriber:", { error, oldValue, newValue, fn });
|
92
|
+
}
|
93
|
+
}
|
94
|
+
if ((options == null ? void 0 : options.debugMode) || (setterOptions == null ? void 0 : setterOptions.debugMode)) {
|
95
|
+
let label = "anonymous signal";
|
96
|
+
if ((options == null ? void 0 : options.label) !== void 0) {
|
97
|
+
label = `(${options.label})`;
|
98
|
+
if ((setterOptions == null ? void 0 : setterOptions.label) !== void 0) {
|
99
|
+
label += ` ${setterOptions.label}`;
|
100
|
+
}
|
101
|
+
} else if ((setterOptions == null ? void 0 : setterOptions.label) !== void 0) {
|
102
|
+
label = setterOptions.label;
|
103
|
+
}
|
104
|
+
console.log("Signal set:", { oldValue, newValue, subscribers, label });
|
75
105
|
}
|
76
106
|
updateQueue.clear();
|
77
107
|
isBatchingUpdates = false;
|
@@ -83,16 +113,124 @@ var createSignal = (initVal) => {
|
|
83
113
|
var derived = (fn) => {
|
84
114
|
const [getter, setter] = createSignal();
|
85
115
|
createEffect(() => {
|
86
|
-
|
116
|
+
try {
|
117
|
+
setter(fn());
|
118
|
+
} catch (error) {
|
119
|
+
console.error("Error in derived signal:", { error, fn });
|
120
|
+
}
|
87
121
|
});
|
88
122
|
return getter;
|
89
123
|
};
|
90
124
|
var createEffect = (fn) => {
|
91
125
|
subscriber = fn;
|
92
|
-
|
126
|
+
try {
|
127
|
+
fn();
|
128
|
+
} catch (error) {
|
129
|
+
console.error("Error in effect:", { error, fn });
|
130
|
+
}
|
93
131
|
subscriber = null;
|
94
132
|
};
|
95
133
|
|
134
|
+
// src/render.ts
|
135
|
+
var html = (strings, ...values) => {
|
136
|
+
let innerHTML = "";
|
137
|
+
const signalMap = /* @__PURE__ */ new Map();
|
138
|
+
strings.forEach((string, i) => {
|
139
|
+
let value = values[i] ?? "";
|
140
|
+
if (typeof value === "function") {
|
141
|
+
const uniqueKey = crypto.randomUUID();
|
142
|
+
signalMap.set(uniqueKey, value);
|
143
|
+
value = `{{signal:${uniqueKey}}}`;
|
144
|
+
}
|
145
|
+
innerHTML += string + String(value);
|
146
|
+
});
|
147
|
+
const fragment = parseFragment(innerHTML);
|
148
|
+
const callbackBindingRegex = /(\{\{callback:.+\}\})/;
|
149
|
+
const signalBindingRegex = /(\{\{signal:.+\}\})/;
|
150
|
+
const parseChildren = (element) => {
|
151
|
+
for (const child of element.childNodes) {
|
152
|
+
if (child instanceof Text && signalBindingRegex.test(child.data)) {
|
153
|
+
const textList = child.data.split(signalBindingRegex);
|
154
|
+
textList.forEach((text, i) => {
|
155
|
+
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
156
|
+
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
157
|
+
const newText = signal !== null ? signal() : text;
|
158
|
+
const newNode = new Text(newText);
|
159
|
+
if (i === 0) {
|
160
|
+
child.replaceWith(newNode);
|
161
|
+
} else {
|
162
|
+
element.insertBefore(newNode, child.nextSibling);
|
163
|
+
}
|
164
|
+
if (signal !== null) {
|
165
|
+
createEffect(() => {
|
166
|
+
newNode.data = signal();
|
167
|
+
});
|
168
|
+
}
|
169
|
+
});
|
170
|
+
}
|
171
|
+
if (child instanceof Element) {
|
172
|
+
for (const attr of child.attributes) {
|
173
|
+
if (signalBindingRegex.test(attr.value)) {
|
174
|
+
const textList = attr.value.split(signalBindingRegex);
|
175
|
+
createEffect(() => {
|
176
|
+
let newText = "";
|
177
|
+
for (const text of textList) {
|
178
|
+
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
179
|
+
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
180
|
+
newText += signal !== null ? signal() : text;
|
181
|
+
}
|
182
|
+
child.setAttribute(attr.name, newText);
|
183
|
+
});
|
184
|
+
} else if (callbackBindingRegex.test(attr.value)) {
|
185
|
+
const uniqueKey = attr.value.replace(/\{\{callback:(.+)\}\}/, "$1");
|
186
|
+
child.setAttribute(attr.name, `this.getRootNode().host.__customCallbackFns.get('${uniqueKey}')(event)`);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
parseChildren(child);
|
190
|
+
}
|
191
|
+
}
|
192
|
+
};
|
193
|
+
parseChildren(fragment);
|
194
|
+
return fragment;
|
195
|
+
};
|
196
|
+
var _a, _b;
|
197
|
+
var adoptedStylesSupported = typeof window !== "undefined" && ((_a = window.ShadowRoot) == null ? void 0 : _a.prototype.hasOwnProperty("adoptedStyleSheets")) && ((_b = window.CSSStyleSheet) == null ? void 0 : _b.prototype.hasOwnProperty("replace"));
|
198
|
+
var isCSSStyleSheet = (stylesheet) => {
|
199
|
+
return typeof CSSStyleSheet !== "undefined" && stylesheet instanceof CSSStyleSheet;
|
200
|
+
};
|
201
|
+
var css = (strings, ...values) => {
|
202
|
+
let cssText = "";
|
203
|
+
const signalMap = /* @__PURE__ */ new Map();
|
204
|
+
const signalBindingRegex = /(\{\{signal:.+\}\})/;
|
205
|
+
strings.forEach((string, i) => {
|
206
|
+
let value = values[i] ?? "";
|
207
|
+
if (typeof value === "function") {
|
208
|
+
const uniqueKey = crypto.randomUUID();
|
209
|
+
signalMap.set(uniqueKey, value);
|
210
|
+
value = `{{signal:${uniqueKey}}}`;
|
211
|
+
}
|
212
|
+
cssText += string + String(value);
|
213
|
+
});
|
214
|
+
let stylesheet = adoptedStylesSupported ? new CSSStyleSheet() : document.createElement("style");
|
215
|
+
const textList = cssText.split(signalBindingRegex);
|
216
|
+
createEffect(() => {
|
217
|
+
const newCSSTextList = [];
|
218
|
+
for (const text of textList) {
|
219
|
+
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
220
|
+
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
221
|
+
const newText = signal !== null ? signal() : text;
|
222
|
+
newCSSTextList.push(newText);
|
223
|
+
}
|
224
|
+
const newCSSText = newCSSTextList.join("");
|
225
|
+
if (isCSSStyleSheet(stylesheet)) {
|
226
|
+
stylesheet.replace(newCSSText);
|
227
|
+
} else {
|
228
|
+
stylesheet.textContent = newCSSText;
|
229
|
+
}
|
230
|
+
});
|
231
|
+
return stylesheet;
|
232
|
+
};
|
233
|
+
|
96
234
|
// src/custom-element.ts
|
97
235
|
var DEFAULT_RENDER_OPTIONS = {
|
98
236
|
formAssociated: false,
|
@@ -169,7 +307,13 @@ var customElement = (render, options) => {
|
|
169
307
|
}
|
170
308
|
),
|
171
309
|
adoptStyleSheet: (stylesheet) => {
|
172
|
-
|
310
|
+
if (isCSSStyleSheet(stylesheet)) {
|
311
|
+
this.#shadowRoot.adoptedStyleSheets.push(stylesheet);
|
312
|
+
} else {
|
313
|
+
requestAnimationFrame(() => {
|
314
|
+
this.#shadowRoot.appendChild(stylesheet);
|
315
|
+
});
|
316
|
+
}
|
173
317
|
}
|
174
318
|
});
|
175
319
|
setInnerHTML(this.#shadowRoot, fragment);
|
@@ -266,97 +410,6 @@ var createRegistry = () => {
|
|
266
410
|
getTagName: (element) => registry.get(element)
|
267
411
|
};
|
268
412
|
};
|
269
|
-
|
270
|
-
// src/render.ts
|
271
|
-
var html = (strings, ...values) => {
|
272
|
-
let innerHTML = "";
|
273
|
-
const signalMap = /* @__PURE__ */ new Map();
|
274
|
-
strings.forEach((string, i) => {
|
275
|
-
let value = values[i] ?? "";
|
276
|
-
if (typeof value === "function") {
|
277
|
-
const uniqueKey = crypto.randomUUID();
|
278
|
-
signalMap.set(uniqueKey, value);
|
279
|
-
value = `{{signal:${uniqueKey}}}`;
|
280
|
-
}
|
281
|
-
innerHTML += string + String(value);
|
282
|
-
});
|
283
|
-
const fragment = parseFragment(innerHTML);
|
284
|
-
const callbackBindingRegex = /(\{\{callback:.+\}\})/;
|
285
|
-
const signalBindingRegex = /(\{\{signal:.+\}\})/;
|
286
|
-
const parseChildren = (element) => {
|
287
|
-
for (const child of element.childNodes) {
|
288
|
-
if (child instanceof Text && signalBindingRegex.test(child.data)) {
|
289
|
-
const textList = child.data.split(signalBindingRegex);
|
290
|
-
textList.forEach((text, i) => {
|
291
|
-
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
292
|
-
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
293
|
-
const newText = signal !== null ? signal() : text;
|
294
|
-
const newNode = new Text(newText);
|
295
|
-
if (i === 0) {
|
296
|
-
child.replaceWith(newNode);
|
297
|
-
} else {
|
298
|
-
element.insertBefore(newNode, child.nextSibling);
|
299
|
-
}
|
300
|
-
if (signal !== null) {
|
301
|
-
createEffect(() => {
|
302
|
-
newNode.data = signal();
|
303
|
-
});
|
304
|
-
}
|
305
|
-
});
|
306
|
-
}
|
307
|
-
if (child instanceof Element) {
|
308
|
-
for (const attr of child.attributes) {
|
309
|
-
if (signalBindingRegex.test(attr.value)) {
|
310
|
-
const textList = attr.value.split(signalBindingRegex);
|
311
|
-
createEffect(() => {
|
312
|
-
let newText = "";
|
313
|
-
for (const text of textList) {
|
314
|
-
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
315
|
-
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
316
|
-
newText += signal !== null ? signal() : text;
|
317
|
-
}
|
318
|
-
child.setAttribute(attr.name, newText);
|
319
|
-
});
|
320
|
-
} else if (callbackBindingRegex.test(attr.value)) {
|
321
|
-
const uniqueKey = attr.value.replace(/\{\{callback:(.+)\}\}/, "$1");
|
322
|
-
child.setAttribute(attr.name, `this.getRootNode().host.__customCallbackFns.get('${uniqueKey}')(event)`);
|
323
|
-
}
|
324
|
-
}
|
325
|
-
parseChildren(child);
|
326
|
-
}
|
327
|
-
}
|
328
|
-
};
|
329
|
-
parseChildren(fragment);
|
330
|
-
return fragment;
|
331
|
-
};
|
332
|
-
var css = (strings, ...values) => {
|
333
|
-
let cssText = "";
|
334
|
-
const signalMap = /* @__PURE__ */ new Map();
|
335
|
-
const signalBindingRegex = /(\{\{signal:.+\}\})/;
|
336
|
-
strings.forEach((string, i) => {
|
337
|
-
let value = values[i] ?? "";
|
338
|
-
if (typeof value === "function") {
|
339
|
-
const uniqueKey = crypto.randomUUID();
|
340
|
-
signalMap.set(uniqueKey, value);
|
341
|
-
value = `{{signal:${uniqueKey}}}`;
|
342
|
-
}
|
343
|
-
cssText += string + String(value);
|
344
|
-
});
|
345
|
-
const stylesheet = new CSSStyleSheet();
|
346
|
-
const textList = cssText.split(signalBindingRegex);
|
347
|
-
createEffect(() => {
|
348
|
-
const newCSSTextList = [];
|
349
|
-
for (const text of textList) {
|
350
|
-
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
351
|
-
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
352
|
-
const newText = signal !== null ? signal() : text;
|
353
|
-
newCSSTextList.push(newText);
|
354
|
-
}
|
355
|
-
const newCSSText = newCSSTextList.join("");
|
356
|
-
stylesheet.replace(newCSSText);
|
357
|
-
});
|
358
|
-
return stylesheet;
|
359
|
-
};
|
360
413
|
// Annotate the CommonJS export names for ESM import in node:
|
361
414
|
0 && (module.exports = {
|
362
415
|
createEffect,
|
package/dist/index.d.cts
CHANGED
@@ -1,7 +1,15 @@
|
|
1
|
-
|
2
|
-
type
|
1
|
+
declare const html: (strings: TemplateStringsArray, ...values: unknown[]) => DocumentFragment;
|
2
|
+
type Styles = CSSStyleSheet | HTMLStyleElement;
|
3
|
+
declare const css: (strings: TemplateStringsArray, ...values: unknown[]) => Styles;
|
4
|
+
|
5
|
+
type SignalOptions = {
|
6
|
+
debugMode: boolean;
|
7
|
+
label?: string;
|
8
|
+
};
|
9
|
+
type SignalGetter<T> = (options?: SignalOptions) => T;
|
10
|
+
type SignalSetter<T> = (newValue: T, options?: SignalOptions) => void;
|
3
11
|
type Signal<T = unknown> = [SignalGetter<T>, SignalSetter<T>];
|
4
|
-
declare const createSignal: <T = undefined>(initVal?: T) => Signal<T>;
|
12
|
+
declare const createSignal: <T = undefined>(initVal?: T, options?: SignalOptions) => Signal<T>;
|
5
13
|
declare const derived: <T>(fn: () => T) => SignalGetter<T>;
|
6
14
|
declare const createEffect: (fn: () => void) => void;
|
7
15
|
|
@@ -25,7 +33,7 @@ type RenderProps = {
|
|
25
33
|
customCallback: (fn: () => void) => `{{callback:${string}}}`;
|
26
34
|
attrSignals: Record<string, Signal<string | null>>;
|
27
35
|
refs: Record<string, HTMLElement | null>;
|
28
|
-
adoptStyleSheet: (stylesheet:
|
36
|
+
adoptStyleSheet: (stylesheet: Styles) => void;
|
29
37
|
};
|
30
38
|
type RenderOptions = {
|
31
39
|
formAssociated: boolean;
|
@@ -39,7 +47,4 @@ type Registry = {
|
|
39
47
|
};
|
40
48
|
declare const createRegistry: () => Registry;
|
41
49
|
|
42
|
-
declare const html: (strings: TemplateStringsArray, ...values: unknown[]) => DocumentFragment;
|
43
|
-
declare const css: (strings: TemplateStringsArray, ...values: unknown[]) => CSSStyleSheet;
|
44
|
-
|
45
50
|
export { type RenderFunction, type RenderProps, type Signal, type SignalGetter, type SignalSetter, createEffect, createRegistry, createSignal, css, customElement, derived, html };
|
package/dist/index.d.ts
CHANGED
@@ -1,7 +1,15 @@
|
|
1
|
-
|
2
|
-
type
|
1
|
+
declare const html: (strings: TemplateStringsArray, ...values: unknown[]) => DocumentFragment;
|
2
|
+
type Styles = CSSStyleSheet | HTMLStyleElement;
|
3
|
+
declare const css: (strings: TemplateStringsArray, ...values: unknown[]) => Styles;
|
4
|
+
|
5
|
+
type SignalOptions = {
|
6
|
+
debugMode: boolean;
|
7
|
+
label?: string;
|
8
|
+
};
|
9
|
+
type SignalGetter<T> = (options?: SignalOptions) => T;
|
10
|
+
type SignalSetter<T> = (newValue: T, options?: SignalOptions) => void;
|
3
11
|
type Signal<T = unknown> = [SignalGetter<T>, SignalSetter<T>];
|
4
|
-
declare const createSignal: <T = undefined>(initVal?: T) => Signal<T>;
|
12
|
+
declare const createSignal: <T = undefined>(initVal?: T, options?: SignalOptions) => Signal<T>;
|
5
13
|
declare const derived: <T>(fn: () => T) => SignalGetter<T>;
|
6
14
|
declare const createEffect: (fn: () => void) => void;
|
7
15
|
|
@@ -25,7 +33,7 @@ type RenderProps = {
|
|
25
33
|
customCallback: (fn: () => void) => `{{callback:${string}}}`;
|
26
34
|
attrSignals: Record<string, Signal<string | null>>;
|
27
35
|
refs: Record<string, HTMLElement | null>;
|
28
|
-
adoptStyleSheet: (stylesheet:
|
36
|
+
adoptStyleSheet: (stylesheet: Styles) => void;
|
29
37
|
};
|
30
38
|
type RenderOptions = {
|
31
39
|
formAssociated: boolean;
|
@@ -39,7 +47,4 @@ type Registry = {
|
|
39
47
|
};
|
40
48
|
declare const createRegistry: () => Registry;
|
41
49
|
|
42
|
-
declare const html: (strings: TemplateStringsArray, ...values: unknown[]) => DocumentFragment;
|
43
|
-
declare const css: (strings: TemplateStringsArray, ...values: unknown[]) => CSSStyleSheet;
|
44
|
-
|
45
50
|
export { type RenderFunction, type RenderProps, type Signal, type SignalGetter, type SignalSetter, createEffect, createRegistry, createSignal, css, customElement, derived, html };
|
package/dist/index.js
CHANGED
@@ -19,18 +19,33 @@ var setInnerHTML = (element, html2) => {
|
|
19
19
|
var subscriber = null;
|
20
20
|
var updateQueue = /* @__PURE__ */ new Set();
|
21
21
|
var isBatchingUpdates = false;
|
22
|
-
var createSignal = (initVal) => {
|
22
|
+
var createSignal = (initVal, options) => {
|
23
23
|
const subscribers = /* @__PURE__ */ new Set();
|
24
24
|
let value = initVal;
|
25
|
-
const getter = () => {
|
25
|
+
const getter = (getterOptions) => {
|
26
26
|
if (subscriber !== null) {
|
27
27
|
subscribers.add(subscriber);
|
28
28
|
}
|
29
|
+
if ((options == null ? void 0 : options.debugMode) || (getterOptions == null ? void 0 : getterOptions.debugMode)) {
|
30
|
+
requestAnimationFrame(() => {
|
31
|
+
let label = "anonymous signal";
|
32
|
+
if ((options == null ? void 0 : options.label) !== void 0) {
|
33
|
+
label = `(${options.label})`;
|
34
|
+
if ((getterOptions == null ? void 0 : getterOptions.label) !== void 0) {
|
35
|
+
label += ` ${getterOptions.label}`;
|
36
|
+
}
|
37
|
+
} else if ((getterOptions == null ? void 0 : getterOptions.label) !== void 0) {
|
38
|
+
label = getterOptions.label;
|
39
|
+
}
|
40
|
+
console.log("Signal retrieved:", { value, subscribers, label });
|
41
|
+
});
|
42
|
+
}
|
29
43
|
return value;
|
30
44
|
};
|
31
|
-
const setter = (newValue) => {
|
45
|
+
const setter = (newValue, setterOptions) => {
|
32
46
|
const isObject = typeof newValue === "object" && newValue !== null;
|
33
47
|
if (!isObject && value === newValue) return;
|
48
|
+
const oldValue = value;
|
34
49
|
value = newValue;
|
35
50
|
for (const fn of subscribers) {
|
36
51
|
updateQueue.add(fn);
|
@@ -38,9 +53,24 @@ var createSignal = (initVal) => {
|
|
38
53
|
if (!isBatchingUpdates) {
|
39
54
|
isBatchingUpdates = true;
|
40
55
|
requestAnimationFrame(() => {
|
41
|
-
console.log("next animation frame");
|
42
56
|
for (const fn of updateQueue) {
|
43
|
-
|
57
|
+
try {
|
58
|
+
fn();
|
59
|
+
} catch (error) {
|
60
|
+
console.error("Error in subscriber:", { error, oldValue, newValue, fn });
|
61
|
+
}
|
62
|
+
}
|
63
|
+
if ((options == null ? void 0 : options.debugMode) || (setterOptions == null ? void 0 : setterOptions.debugMode)) {
|
64
|
+
let label = "anonymous signal";
|
65
|
+
if ((options == null ? void 0 : options.label) !== void 0) {
|
66
|
+
label = `(${options.label})`;
|
67
|
+
if ((setterOptions == null ? void 0 : setterOptions.label) !== void 0) {
|
68
|
+
label += ` ${setterOptions.label}`;
|
69
|
+
}
|
70
|
+
} else if ((setterOptions == null ? void 0 : setterOptions.label) !== void 0) {
|
71
|
+
label = setterOptions.label;
|
72
|
+
}
|
73
|
+
console.log("Signal set:", { oldValue, newValue, subscribers, label });
|
44
74
|
}
|
45
75
|
updateQueue.clear();
|
46
76
|
isBatchingUpdates = false;
|
@@ -52,16 +82,124 @@ var createSignal = (initVal) => {
|
|
52
82
|
var derived = (fn) => {
|
53
83
|
const [getter, setter] = createSignal();
|
54
84
|
createEffect(() => {
|
55
|
-
|
85
|
+
try {
|
86
|
+
setter(fn());
|
87
|
+
} catch (error) {
|
88
|
+
console.error("Error in derived signal:", { error, fn });
|
89
|
+
}
|
56
90
|
});
|
57
91
|
return getter;
|
58
92
|
};
|
59
93
|
var createEffect = (fn) => {
|
60
94
|
subscriber = fn;
|
61
|
-
|
95
|
+
try {
|
96
|
+
fn();
|
97
|
+
} catch (error) {
|
98
|
+
console.error("Error in effect:", { error, fn });
|
99
|
+
}
|
62
100
|
subscriber = null;
|
63
101
|
};
|
64
102
|
|
103
|
+
// src/render.ts
|
104
|
+
var html = (strings, ...values) => {
|
105
|
+
let innerHTML = "";
|
106
|
+
const signalMap = /* @__PURE__ */ new Map();
|
107
|
+
strings.forEach((string, i) => {
|
108
|
+
let value = values[i] ?? "";
|
109
|
+
if (typeof value === "function") {
|
110
|
+
const uniqueKey = crypto.randomUUID();
|
111
|
+
signalMap.set(uniqueKey, value);
|
112
|
+
value = `{{signal:${uniqueKey}}}`;
|
113
|
+
}
|
114
|
+
innerHTML += string + String(value);
|
115
|
+
});
|
116
|
+
const fragment = parseFragment(innerHTML);
|
117
|
+
const callbackBindingRegex = /(\{\{callback:.+\}\})/;
|
118
|
+
const signalBindingRegex = /(\{\{signal:.+\}\})/;
|
119
|
+
const parseChildren = (element) => {
|
120
|
+
for (const child of element.childNodes) {
|
121
|
+
if (child instanceof Text && signalBindingRegex.test(child.data)) {
|
122
|
+
const textList = child.data.split(signalBindingRegex);
|
123
|
+
textList.forEach((text, i) => {
|
124
|
+
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
125
|
+
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
126
|
+
const newText = signal !== null ? signal() : text;
|
127
|
+
const newNode = new Text(newText);
|
128
|
+
if (i === 0) {
|
129
|
+
child.replaceWith(newNode);
|
130
|
+
} else {
|
131
|
+
element.insertBefore(newNode, child.nextSibling);
|
132
|
+
}
|
133
|
+
if (signal !== null) {
|
134
|
+
createEffect(() => {
|
135
|
+
newNode.data = signal();
|
136
|
+
});
|
137
|
+
}
|
138
|
+
});
|
139
|
+
}
|
140
|
+
if (child instanceof Element) {
|
141
|
+
for (const attr of child.attributes) {
|
142
|
+
if (signalBindingRegex.test(attr.value)) {
|
143
|
+
const textList = attr.value.split(signalBindingRegex);
|
144
|
+
createEffect(() => {
|
145
|
+
let newText = "";
|
146
|
+
for (const text of textList) {
|
147
|
+
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
148
|
+
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
149
|
+
newText += signal !== null ? signal() : text;
|
150
|
+
}
|
151
|
+
child.setAttribute(attr.name, newText);
|
152
|
+
});
|
153
|
+
} else if (callbackBindingRegex.test(attr.value)) {
|
154
|
+
const uniqueKey = attr.value.replace(/\{\{callback:(.+)\}\}/, "$1");
|
155
|
+
child.setAttribute(attr.name, `this.getRootNode().host.__customCallbackFns.get('${uniqueKey}')(event)`);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
parseChildren(child);
|
159
|
+
}
|
160
|
+
}
|
161
|
+
};
|
162
|
+
parseChildren(fragment);
|
163
|
+
return fragment;
|
164
|
+
};
|
165
|
+
var _a, _b;
|
166
|
+
var adoptedStylesSupported = typeof window !== "undefined" && ((_a = window.ShadowRoot) == null ? void 0 : _a.prototype.hasOwnProperty("adoptedStyleSheets")) && ((_b = window.CSSStyleSheet) == null ? void 0 : _b.prototype.hasOwnProperty("replace"));
|
167
|
+
var isCSSStyleSheet = (stylesheet) => {
|
168
|
+
return typeof CSSStyleSheet !== "undefined" && stylesheet instanceof CSSStyleSheet;
|
169
|
+
};
|
170
|
+
var css = (strings, ...values) => {
|
171
|
+
let cssText = "";
|
172
|
+
const signalMap = /* @__PURE__ */ new Map();
|
173
|
+
const signalBindingRegex = /(\{\{signal:.+\}\})/;
|
174
|
+
strings.forEach((string, i) => {
|
175
|
+
let value = values[i] ?? "";
|
176
|
+
if (typeof value === "function") {
|
177
|
+
const uniqueKey = crypto.randomUUID();
|
178
|
+
signalMap.set(uniqueKey, value);
|
179
|
+
value = `{{signal:${uniqueKey}}}`;
|
180
|
+
}
|
181
|
+
cssText += string + String(value);
|
182
|
+
});
|
183
|
+
let stylesheet = adoptedStylesSupported ? new CSSStyleSheet() : document.createElement("style");
|
184
|
+
const textList = cssText.split(signalBindingRegex);
|
185
|
+
createEffect(() => {
|
186
|
+
const newCSSTextList = [];
|
187
|
+
for (const text of textList) {
|
188
|
+
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
189
|
+
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
190
|
+
const newText = signal !== null ? signal() : text;
|
191
|
+
newCSSTextList.push(newText);
|
192
|
+
}
|
193
|
+
const newCSSText = newCSSTextList.join("");
|
194
|
+
if (isCSSStyleSheet(stylesheet)) {
|
195
|
+
stylesheet.replace(newCSSText);
|
196
|
+
} else {
|
197
|
+
stylesheet.textContent = newCSSText;
|
198
|
+
}
|
199
|
+
});
|
200
|
+
return stylesheet;
|
201
|
+
};
|
202
|
+
|
65
203
|
// src/custom-element.ts
|
66
204
|
var DEFAULT_RENDER_OPTIONS = {
|
67
205
|
formAssociated: false,
|
@@ -138,7 +276,13 @@ var customElement = (render, options) => {
|
|
138
276
|
}
|
139
277
|
),
|
140
278
|
adoptStyleSheet: (stylesheet) => {
|
141
|
-
|
279
|
+
if (isCSSStyleSheet(stylesheet)) {
|
280
|
+
this.#shadowRoot.adoptedStyleSheets.push(stylesheet);
|
281
|
+
} else {
|
282
|
+
requestAnimationFrame(() => {
|
283
|
+
this.#shadowRoot.appendChild(stylesheet);
|
284
|
+
});
|
285
|
+
}
|
142
286
|
}
|
143
287
|
});
|
144
288
|
setInnerHTML(this.#shadowRoot, fragment);
|
@@ -235,97 +379,6 @@ var createRegistry = () => {
|
|
235
379
|
getTagName: (element) => registry.get(element)
|
236
380
|
};
|
237
381
|
};
|
238
|
-
|
239
|
-
// src/render.ts
|
240
|
-
var html = (strings, ...values) => {
|
241
|
-
let innerHTML = "";
|
242
|
-
const signalMap = /* @__PURE__ */ new Map();
|
243
|
-
strings.forEach((string, i) => {
|
244
|
-
let value = values[i] ?? "";
|
245
|
-
if (typeof value === "function") {
|
246
|
-
const uniqueKey = crypto.randomUUID();
|
247
|
-
signalMap.set(uniqueKey, value);
|
248
|
-
value = `{{signal:${uniqueKey}}}`;
|
249
|
-
}
|
250
|
-
innerHTML += string + String(value);
|
251
|
-
});
|
252
|
-
const fragment = parseFragment(innerHTML);
|
253
|
-
const callbackBindingRegex = /(\{\{callback:.+\}\})/;
|
254
|
-
const signalBindingRegex = /(\{\{signal:.+\}\})/;
|
255
|
-
const parseChildren = (element) => {
|
256
|
-
for (const child of element.childNodes) {
|
257
|
-
if (child instanceof Text && signalBindingRegex.test(child.data)) {
|
258
|
-
const textList = child.data.split(signalBindingRegex);
|
259
|
-
textList.forEach((text, i) => {
|
260
|
-
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
261
|
-
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
262
|
-
const newText = signal !== null ? signal() : text;
|
263
|
-
const newNode = new Text(newText);
|
264
|
-
if (i === 0) {
|
265
|
-
child.replaceWith(newNode);
|
266
|
-
} else {
|
267
|
-
element.insertBefore(newNode, child.nextSibling);
|
268
|
-
}
|
269
|
-
if (signal !== null) {
|
270
|
-
createEffect(() => {
|
271
|
-
newNode.data = signal();
|
272
|
-
});
|
273
|
-
}
|
274
|
-
});
|
275
|
-
}
|
276
|
-
if (child instanceof Element) {
|
277
|
-
for (const attr of child.attributes) {
|
278
|
-
if (signalBindingRegex.test(attr.value)) {
|
279
|
-
const textList = attr.value.split(signalBindingRegex);
|
280
|
-
createEffect(() => {
|
281
|
-
let newText = "";
|
282
|
-
for (const text of textList) {
|
283
|
-
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
284
|
-
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
285
|
-
newText += signal !== null ? signal() : text;
|
286
|
-
}
|
287
|
-
child.setAttribute(attr.name, newText);
|
288
|
-
});
|
289
|
-
} else if (callbackBindingRegex.test(attr.value)) {
|
290
|
-
const uniqueKey = attr.value.replace(/\{\{callback:(.+)\}\}/, "$1");
|
291
|
-
child.setAttribute(attr.name, `this.getRootNode().host.__customCallbackFns.get('${uniqueKey}')(event)`);
|
292
|
-
}
|
293
|
-
}
|
294
|
-
parseChildren(child);
|
295
|
-
}
|
296
|
-
}
|
297
|
-
};
|
298
|
-
parseChildren(fragment);
|
299
|
-
return fragment;
|
300
|
-
};
|
301
|
-
var css = (strings, ...values) => {
|
302
|
-
let cssText = "";
|
303
|
-
const signalMap = /* @__PURE__ */ new Map();
|
304
|
-
const signalBindingRegex = /(\{\{signal:.+\}\})/;
|
305
|
-
strings.forEach((string, i) => {
|
306
|
-
let value = values[i] ?? "";
|
307
|
-
if (typeof value === "function") {
|
308
|
-
const uniqueKey = crypto.randomUUID();
|
309
|
-
signalMap.set(uniqueKey, value);
|
310
|
-
value = `{{signal:${uniqueKey}}}`;
|
311
|
-
}
|
312
|
-
cssText += string + String(value);
|
313
|
-
});
|
314
|
-
const stylesheet = new CSSStyleSheet();
|
315
|
-
const textList = cssText.split(signalBindingRegex);
|
316
|
-
createEffect(() => {
|
317
|
-
const newCSSTextList = [];
|
318
|
-
for (const text of textList) {
|
319
|
-
const uniqueKey = text.replace(/\{\{signal:(.+)\}\}/, "$1");
|
320
|
-
const signal = uniqueKey !== text ? signalMap.get(uniqueKey) : null;
|
321
|
-
const newText = signal !== null ? signal() : text;
|
322
|
-
newCSSTextList.push(newText);
|
323
|
-
}
|
324
|
-
const newCSSText = newCSSTextList.join("");
|
325
|
-
stylesheet.replace(newCSSText);
|
326
|
-
});
|
327
|
-
return stylesheet;
|
328
|
-
};
|
329
382
|
export {
|
330
383
|
createEffect,
|
331
384
|
createRegistry,
|