olova 2.0.2 → 2.0.4

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/olova.js CHANGED
@@ -1,226 +1,291 @@
1
- let currentObserver = null;
2
- function diffProps(e = {}, t = {}, r) {
3
- for (const [n, o] of Object.entries(e))
4
- n in t ||
5
- (n.startsWith("on")
6
- ? r.removeEventListener(n.slice(2).toLowerCase(), o)
7
- : "style" === n
8
- ? (r.style.cssText = "")
9
- : r.removeAttribute(n));
10
- for (const [n, o] of Object.entries(t))
11
- if (null != o && e[n] !== o)
12
- if (n.startsWith("on")) {
13
- const t = n.slice(2).toLowerCase();
14
- e[n] && r.removeEventListener(t, e[n]), r.addEventListener(t, o);
15
- } else if ("ref" === n)
16
- o && "object" == typeof o && "current" in o
17
- ? (o.current = r)
18
- : "function" == typeof o && o(r);
19
- else if ("style" === n) {
20
- const e = r.style;
21
- "object" == typeof o ? Object.assign(e, o) : (e.cssText = o);
22
- } else r.setAttribute(n, o);
23
- }
24
- function diffChildren(e, t, r) {
25
- const n = Array.isArray(e) ? e.flat() : [e],
26
- o = Array.isArray(t) ? t.flat() : [t],
27
- s = Math.max(n.length, o.length);
28
- for (let e = 0; e < s; e++) {
29
- const t = n[e],
30
- s = o[e];
31
- if (!t || s)
32
- if (t || !s) {
33
- if (t instanceof Node && s instanceof Node)
34
- t.nodeType !== s.nodeType || t.nodeName !== s.nodeName
35
- ? r.replaceChild(s, t)
36
- : (diffProps(t.attributes, s.attributes, t),
37
- diffChildren(
38
- Array.from(t.childNodes),
39
- Array.from(s.childNodes),
40
- t
41
- ));
42
- else if (t !== s) {
43
- const t = r.childNodes[e];
44
- t && (t.textContent = String(s));
45
- }
46
- } else {
47
- const e = s instanceof Node ? s : document.createTextNode(String(s));
48
- r.appendChild(e);
49
- }
50
- else t instanceof Node && r.removeChild(t);
51
- }
52
- }
53
- class Signal {
54
- constructor(e) {
55
- (this._value = e), (this.observers = new Map());
56
- }
57
- get value() {
58
- return (
59
- currentObserver &&
60
- (this.observers.has("_root") || this.observers.set("_root", new Set()),
61
- this.observers.get("_root").add(currentObserver)),
62
- this._value
63
- );
64
- }
65
- set value(e) {
66
- if (this._value === e) return;
67
- const t = this._value;
68
- if (((this._value = e), this.observers.has("_root")))
69
- for (const e of this.observers.get("_root")) e();
70
- if ("object" == typeof t && "object" == typeof e) {
71
- const r = new Set([...Object.keys(t), ...Object.keys(e)]);
72
- for (const n of r)
73
- if (t[n] !== e[n] && this.observers.has(n))
74
- for (const e of this.observers.get(n)) e();
75
- }
76
- }
77
- observe(e, t) {
78
- this.observers.has(e) || this.observers.set(e, new Set()),
79
- this.observers.get(e).add(t);
80
- }
81
- unobserve(e, t) {
82
- this.observers.has(e) && this.observers.get(e).delete(t);
83
- }
84
- }
85
- function State(e) {
86
- const t = new Signal(e),
87
- r = () => t.value;
88
- return (
89
- (r.toString = () => t.value),
90
- (r.observe = (e, r) => t.observe(e, r)),
91
- (r.unobserve = (e, r) => t.unobserve(e, r)),
92
- [
93
- r,
94
- (e) => {
95
- t.value = "function" == typeof e ? e(t.value) : e;
96
- },
97
- ]
98
- );
99
- }
100
- function Effect(e) {
101
- const t = () => {
102
- (currentObserver = t), e(), (currentObserver = null);
103
- };
104
- t();
105
- }
106
- function Memo(e) {
107
- const [t, r] = State(e());
108
- return Effect(() => r(e())), t;
109
- }
110
- function Ref(e) {
111
- const [t, r] = State({
112
- current: e,
113
- toString() {
114
- return this.current;
115
- },
116
- valueOf() {
117
- return this.current;
118
- },
119
- });
120
- return {
121
- get current() {
122
- return t().current;
123
- },
124
- set current(e) {
125
- r((t) => (t.current === e ? t : { ...t, current: e }));
126
- },
127
- toString() {
128
- return this.current.toString();
129
- },
130
- valueOf() {
131
- return this.current;
132
- },
133
- };
134
- }
135
- function h(e, t, ...r) {
136
- if (e === Fragment || Array.isArray(e)) {
137
- const n = document.createDocumentFragment(),
138
- o = e === Fragment ? t?.children || r : e;
139
- if (Array.isArray(o)) {
140
- const e = document.createTextNode.bind(document);
141
- o.forEach((t) => {
142
- n.appendChild(t instanceof Node ? t : null != t ? e(String(t)) : null);
143
- });
144
- }
145
- return n;
146
- }
147
- if (!e) return null;
148
- const n = "function" == typeof e ? e(t) : document.createElement(e);
149
- if (("string" == typeof e && n && t && diffProps({}, t, n), r.length)) {
150
- const e = document.createDocumentFragment(),
151
- t = (r) => {
152
- if (null != r)
153
- if ("function" == typeof r) {
154
- const t = document.createTextNode("");
155
- Effect(() => (t.textContent = r())), e.appendChild(t);
156
- } else
157
- r instanceof Node
158
- ? e.appendChild(r)
159
- : Array.isArray(r)
160
- ? r.flat().forEach(t)
161
- : e.appendChild(document.createTextNode(String(r)));
162
- };
163
- r.forEach(t), n.appendChild(e);
164
- }
165
- return n;
166
- }
167
- const Component = (e, t) => {
168
- if ("function" != typeof e)
169
- throw new Error("Invalid Component: must be a function");
170
- return e(t);
171
- },
172
- Fragment = (e) => e.children;
173
- window.Fragment = Fragment;
174
- const Olova = {
175
- render(e, t) {
176
- const r = "function" == typeof e ? e() : e;
177
- return (
178
- t.firstChild ? diffChildren([t.firstChild], [r], t) : t.appendChild(r),
179
- r
180
- );
181
- },
182
- mount(e, t) {
183
- return this.render(e, t);
184
- },
185
- unmount(e) {
186
- e.innerHTML = "";
187
- },
188
- Fragment: Fragment,
189
- },
190
- contextRegistry = new Map();
191
- function Context(e) {
192
- const t = Symbol("context");
193
- return (
194
- contextRegistry.set(t, e),
195
- {
196
- Provider({ value: e, children: r }) {
197
- const n = contextRegistry.get(t);
198
- contextRegistry.set(t, e);
199
- const o = r;
200
- return contextRegistry.set(t, n), o;
201
- },
202
- use() {
203
- const r = contextRegistry.get(t);
204
- if (void 0 === r && void 0 === e)
205
- throw new Error("Context used outside of Provider");
206
- return r ?? e;
207
- },
208
- }
209
- );
210
- }
211
- function Callback(e, t) {
212
- const [r, n] = State(() => ({ fn: e, deps: t, memoized: (...t) => e(...t) }));
213
- return (
214
- Effect(() => {
215
- const o = r();
216
- t &&
217
- ((o.deps &&
218
- t.length === o.deps.length &&
219
- !t.some((e, t) => e !== o.deps[t])) ||
220
- n({ fn: e, deps: t, memoized: (...t) => e(...t) }));
221
- }),
222
- () => r().memoized
223
- );
224
- }
225
- export { State, Effect, Memo, Ref, Context, Callback, Component, h, Fragment };
226
- export default Olova;
1
+ const memoize = (e) => {
2
+ const t = new Map();
3
+ return (...n) => {
4
+ const r = JSON.stringify(n);
5
+ return t.has(r) || t.set(r, e(...n)), t.get(r);
6
+ };
7
+ };
8
+ let currentObserver = null;
9
+ function diffProps(e = {}, t = {}, n) {
10
+ void 0 !== t.className && ((t.class = t.className), delete t.className),
11
+ void 0 !== e.className && ((e.class = e.className), delete e.className);
12
+ for (const [r, o] of Object.entries(e))
13
+ r in t ||
14
+ (r.startsWith("on")
15
+ ? n.removeEventListener(r.slice(2).toLowerCase(), o)
16
+ : "style" === r
17
+ ? (n.style.cssText = "")
18
+ : n.removeAttribute(r));
19
+ for (const [r, o] of Object.entries(t))
20
+ if (null != o && e[r] !== o)
21
+ if (r.startsWith("on")) {
22
+ const t = r.slice(2).toLowerCase();
23
+ e[r] && n.removeEventListener(t, e[r]), n.addEventListener(t, o);
24
+ } else if ("ref" === r)
25
+ o && "object" == typeof o && "current" in o
26
+ ? (o.current = n)
27
+ : "function" == typeof o && o(n);
28
+ else if ("style" === r) {
29
+ const e = n.style;
30
+ "object" == typeof o ? Object.assign(e, o) : (e.cssText = o);
31
+ } else n.setAttribute(r, o);
32
+ }
33
+ const diffChildren = memoize((e, t, n) => {
34
+ const r = Array.isArray(e) ? e.flat() : [e],
35
+ o = Array.isArray(t) ? t.flat() : [t],
36
+ s = Math.max(r.length, o.length);
37
+ for (let e = 0; e < s; e++) {
38
+ const t = r[e],
39
+ s = o[e];
40
+ if (!t || s)
41
+ if (t || !s) {
42
+ if (t instanceof Node && s instanceof Node)
43
+ t.nodeType !== s.nodeType || t.nodeName !== s.nodeName
44
+ ? n.replaceChild(s, t)
45
+ : (diffProps(t.attributes, s.attributes, t),
46
+ diffChildren(
47
+ Array.from(t.childNodes),
48
+ Array.from(s.childNodes),
49
+ t
50
+ ));
51
+ else if (t !== s) {
52
+ const t = n.childNodes[e];
53
+ t && (t.textContent = String(s));
54
+ }
55
+ } else {
56
+ const e = s instanceof Node ? s : document.createTextNode(String(s));
57
+ n.appendChild(e);
58
+ }
59
+ else t instanceof Node && n.removeChild(t);
60
+ }
61
+ });
62
+ class Signal {
63
+ constructor(e) {
64
+ (this._value = e),
65
+ (this.observers = new Map()),
66
+ (this.pending = new Set()),
67
+ (this.isBatching = !1);
68
+ }
69
+ get value() {
70
+ return (
71
+ currentObserver &&
72
+ (this.observers.has("_root") || this.observers.set("_root", new Set()),
73
+ this.observers.get("_root").add(currentObserver)),
74
+ this._value
75
+ );
76
+ }
77
+ set value(e) {
78
+ if (this._value === e) return;
79
+ const t = this._value;
80
+ if (((this._value = e), this.observers.has("_root")))
81
+ for (const e of this.observers.get("_root")) this.pending.add(e);
82
+ if ("object" == typeof t && "object" == typeof e) {
83
+ const n = new Set([...Object.keys(t), ...Object.keys(e)]);
84
+ for (const r of n)
85
+ if (t[r] !== e[r] && this.observers.has(r))
86
+ for (const e of this.observers.get(r)) this.pending.add(e);
87
+ }
88
+ this.batchUpdate();
89
+ }
90
+ batchUpdate() {
91
+ this.isBatching ||
92
+ ((this.isBatching = !0),
93
+ Promise.resolve().then(() => {
94
+ this.pending.forEach((e) => e()),
95
+ this.pending.clear(),
96
+ (this.isBatching = !1);
97
+ }));
98
+ }
99
+ observe(e, t) {
100
+ this.observers.has(e) || this.observers.set(e, new Set()),
101
+ this.observers.get(e).add(t);
102
+ }
103
+ unobserve(e, t) {
104
+ this.observers.has(e) && this.observers.get(e).delete(t);
105
+ }
106
+ }
107
+ function $signal(e) {
108
+ const t = new Signal(e),
109
+ n = () => t.value;
110
+ return (
111
+ (n.toString = () => t.value),
112
+ (n.observe = (e, n) => t.observe(e, n)),
113
+ (n.unobserve = (e, n) => t.unobserve(e, n)),
114
+ [
115
+ n,
116
+ (e) => {
117
+ t.value = "function" == typeof e ? e(t.value) : e;
118
+ },
119
+ ]
120
+ );
121
+ }
122
+ function $effect(e, t) {
123
+ let n,
124
+ r = !0,
125
+ o = null;
126
+ const s = () => {
127
+ "function" == typeof n && (n(), (n = void 0)), (currentObserver = o);
128
+ const t = e();
129
+ (currentObserver = null), "function" == typeof t && (n = t);
130
+ };
131
+ return (
132
+ (o = () => {
133
+ if (r || !t) return s(), void (r = !1);
134
+ Array.isArray(t) && 0 === t.length ? r && (s(), (r = !1)) : s();
135
+ }),
136
+ o(),
137
+ () => {
138
+ n && n();
139
+ }
140
+ );
141
+ }
142
+ function $memo(e) {
143
+ const [t, n] = $signal(e());
144
+ return $effect(() => n(e())), t;
145
+ }
146
+ function $ref(e) {
147
+ const [t, n] = $signal({
148
+ current: e,
149
+ toString() {
150
+ return this.current;
151
+ },
152
+ valueOf() {
153
+ return this.current;
154
+ },
155
+ });
156
+ return {
157
+ get current() {
158
+ return t().current;
159
+ },
160
+ set current(e) {
161
+ n((t) => (t.current === e ? t : { ...t, current: e }));
162
+ },
163
+ toString() {
164
+ return this.current.toString();
165
+ },
166
+ valueOf() {
167
+ return this.current;
168
+ },
169
+ };
170
+ }
171
+ function h(e, t, ...n) {
172
+ if (e === Fragment || Array.isArray(e)) {
173
+ const r = document.createDocumentFragment(),
174
+ o = e === Fragment ? t?.children || n : e;
175
+ return (
176
+ Array.isArray(o) &&
177
+ o.flat().forEach((e) => {
178
+ null != e &&
179
+ r.appendChild(
180
+ e instanceof Node ? e : document.createTextNode(String(e))
181
+ );
182
+ }),
183
+ r
184
+ );
185
+ }
186
+ if (!e) return null;
187
+ const r = "function" == typeof e ? e(t) : document.createElement(e);
188
+ if (("string" == typeof e && r && t && diffProps({}, t, r), n.length)) {
189
+ const e = document.createDocumentFragment(),
190
+ t = (n) => {
191
+ if (null != n)
192
+ if ("function" == typeof n) {
193
+ const t = document.createTextNode("");
194
+ $effect(() => {
195
+ const e = n();
196
+ if (Array.isArray(e)) {
197
+ const n = document.createDocumentFragment();
198
+ e.forEach((e) => {
199
+ n.appendChild(
200
+ e instanceof Node ? e : document.createTextNode(String(e))
201
+ );
202
+ }),
203
+ t.parentNode && t.parentNode.replaceChild(n, t);
204
+ } else t.textContent = String(e);
205
+ }),
206
+ e.appendChild(t);
207
+ } else
208
+ n instanceof Node
209
+ ? e.appendChild(n)
210
+ : Array.isArray(n)
211
+ ? n.flat().forEach(t)
212
+ : e.appendChild(document.createTextNode(String(n)));
213
+ };
214
+ n.forEach(t), r.appendChild(e);
215
+ }
216
+ return r;
217
+ }
218
+ const Component = (e, t) => {
219
+ if ("function" != typeof e)
220
+ throw new Error("Invalid Component: must be a function");
221
+ return e(t);
222
+ },
223
+ Fragment = (e) => e.children;
224
+ window.Fragment = Fragment;
225
+ const Olova = {
226
+ render(e, t) {
227
+ const n = "function" == typeof e ? e() : e;
228
+ return (
229
+ t.firstChild ? diffChildren([t.firstChild], [n], t) : t.appendChild(n),
230
+ n
231
+ );
232
+ },
233
+ mount(e, t) {
234
+ return this.render(e, t);
235
+ },
236
+ unmount(e) {
237
+ e.innerHTML = "";
238
+ },
239
+ Fragment: Fragment,
240
+ },
241
+ contextRegistry = new Map();
242
+ function $context(e) {
243
+ const t = Symbol("context");
244
+ return (
245
+ contextRegistry.set(t, e),
246
+ {
247
+ Provider({ value: e, children: n }) {
248
+ const r = contextRegistry.get(t);
249
+ contextRegistry.set(t, e);
250
+ const o = n;
251
+ return contextRegistry.set(t, r), o;
252
+ },
253
+ use() {
254
+ const n = contextRegistry.get(t);
255
+ if (void 0 === n && void 0 === e)
256
+ throw new Error("Context used outside of Provider");
257
+ return n ?? e;
258
+ },
259
+ }
260
+ );
261
+ }
262
+ function $callback(e, t) {
263
+ const [n, r] = $signal(() => ({
264
+ fn: e,
265
+ deps: t,
266
+ memoized: (...t) => e(...t),
267
+ }));
268
+ return (
269
+ $effect(() => {
270
+ const o = n();
271
+ t &&
272
+ ((o.deps &&
273
+ t.length === o.deps.length &&
274
+ !t.some((e, t) => e !== o.deps[t])) ||
275
+ r({ fn: e, deps: t, memoized: (...t) => e(...t) }));
276
+ }),
277
+ () => n().memoized
278
+ );
279
+ }
280
+ export {
281
+ $signal,
282
+ $effect,
283
+ $memo,
284
+ $ref,
285
+ $context,
286
+ $callback,
287
+ Component,
288
+ h,
289
+ Fragment,
290
+ };
291
+ export default Olova;