@manyducks.co/dolla 2.0.0-alpha.39 → 2.0.0-alpha.40
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.js +838 -1234
- package/dist/index.js.map +1 -1
- package/dist/jsx-dev-runtime.js +14 -20
- package/dist/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx-runtime.js +16 -27
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/markup-DIfh0nwz.js +1442 -0
- package/dist/markup-DIfh0nwz.js.map +1 -0
- package/package.json +1 -1
- package/vite.config.js +4 -4
- package/dist/markup-PXJjYgl3.js +0 -1506
- package/dist/markup-PXJjYgl3.js.map +0 -1
package/dist/markup-PXJjYgl3.js
DELETED
|
@@ -1,1506 +0,0 @@
|
|
|
1
|
-
import htm from 'htm/mini';
|
|
2
|
-
import { SubscriberFlags, createReactiveSystem } from 'alien-signals';
|
|
3
|
-
|
|
4
|
-
function typeOf(value) {
|
|
5
|
-
const type = typeof value;
|
|
6
|
-
switch (type) {
|
|
7
|
-
case "undefined":
|
|
8
|
-
return type;
|
|
9
|
-
case "number":
|
|
10
|
-
if (isNaN(value)) return "NaN";
|
|
11
|
-
return type;
|
|
12
|
-
case "function":
|
|
13
|
-
if (/^\s*class\s+/.test(value.toString())) return "class";
|
|
14
|
-
return type;
|
|
15
|
-
case "object":
|
|
16
|
-
if (value === null) return "null";
|
|
17
|
-
if (value instanceof Promise) return "promise";
|
|
18
|
-
if (value instanceof Map) return "map";
|
|
19
|
-
if (value instanceof Set) return "set";
|
|
20
|
-
if (Array.isArray(value)) return "array";
|
|
21
|
-
return type;
|
|
22
|
-
default:
|
|
23
|
-
return type;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
function isArray(value) {
|
|
27
|
-
return Array.isArray(value);
|
|
28
|
-
}
|
|
29
|
-
function isArrayOf(check, value) {
|
|
30
|
-
return isArray(value) && value.every((item) => check(item));
|
|
31
|
-
}
|
|
32
|
-
function assertArrayOf(check, value, errorMessage) {
|
|
33
|
-
if (isArrayOf(check, value)) {
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
throw new TypeError(formatError(value, errorMessage));
|
|
37
|
-
}
|
|
38
|
-
function isString(value) {
|
|
39
|
-
return typeof value === "string";
|
|
40
|
-
}
|
|
41
|
-
function assertString(value, errorMessage) {
|
|
42
|
-
if (isString(value)) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
throw new TypeError(formatError(value, errorMessage ?? "Expected a string. Got type: %t, value: %v"));
|
|
46
|
-
}
|
|
47
|
-
function isFunction(value) {
|
|
48
|
-
return typeOf(value) === "function";
|
|
49
|
-
}
|
|
50
|
-
function isNumber(value) {
|
|
51
|
-
return typeof value === "number" && !isNaN(value);
|
|
52
|
-
}
|
|
53
|
-
function assertInstanceOf(...args) {
|
|
54
|
-
const constructor = args[0];
|
|
55
|
-
const errorMessage = isString(args[2]) ? args[2] : `Expected instance of ${constructor.name}. Got type: %t, value: %v`;
|
|
56
|
-
const test = (value) => {
|
|
57
|
-
if (value instanceof constructor) {
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
throw new TypeError(formatError(value, errorMessage));
|
|
61
|
-
};
|
|
62
|
-
if (args.length < 2) {
|
|
63
|
-
return test;
|
|
64
|
-
} else {
|
|
65
|
-
return test(args[1]);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
function isObject(value) {
|
|
69
|
-
return value != null && typeof value === "object" && !isArray(value);
|
|
70
|
-
}
|
|
71
|
-
function assertObject(value, errorMessage) {
|
|
72
|
-
if (isObject(value)) {
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
throw new TypeError(formatError(value, errorMessage));
|
|
76
|
-
}
|
|
77
|
-
function formatError(value, message) {
|
|
78
|
-
const typeName = typeOf(value);
|
|
79
|
-
const valueString = value?.toString?.() || String(value);
|
|
80
|
-
return message.replaceAll("%t", typeName).replaceAll("%v", valueString);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const DEPENDENCY = Symbol("dependency");
|
|
84
|
-
const {
|
|
85
|
-
link,
|
|
86
|
-
propagate,
|
|
87
|
-
updateDirtyFlag,
|
|
88
|
-
startTracking,
|
|
89
|
-
endTracking,
|
|
90
|
-
processEffectNotifications,
|
|
91
|
-
processComputedUpdate,
|
|
92
|
-
processPendingInnerEffects
|
|
93
|
-
} = createReactiveSystem({
|
|
94
|
-
updateComputed(computed) {
|
|
95
|
-
const prevSub = activeSub;
|
|
96
|
-
activeSub = computed;
|
|
97
|
-
startTracking(computed);
|
|
98
|
-
try {
|
|
99
|
-
const oldValue = computed.currentValue;
|
|
100
|
-
const newValue = computed.getter(oldValue);
|
|
101
|
-
if (!computed.equals(oldValue, newValue)) {
|
|
102
|
-
computed.currentValue = newValue;
|
|
103
|
-
return true;
|
|
104
|
-
}
|
|
105
|
-
return false;
|
|
106
|
-
} finally {
|
|
107
|
-
activeSub = prevSub;
|
|
108
|
-
endTracking(computed);
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
notifyEffect(e) {
|
|
112
|
-
const flags = e.flags;
|
|
113
|
-
if (flags & SubscriberFlags.Dirty || flags & SubscriberFlags.PendingComputed && updateDirtyFlag(e, flags)) {
|
|
114
|
-
queueEffect(e);
|
|
115
|
-
} else {
|
|
116
|
-
processPendingInnerEffects(e, e.flags);
|
|
117
|
-
}
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
let activeSub;
|
|
122
|
-
const PENDING_EFFECTS = [];
|
|
123
|
-
let flushPending = false;
|
|
124
|
-
function flushEffects() {
|
|
125
|
-
if (!flushPending) {
|
|
126
|
-
flushPending = true;
|
|
127
|
-
queueMicrotask(() => {
|
|
128
|
-
flushPending = false;
|
|
129
|
-
for (let i = 0; i < PENDING_EFFECTS.length; i++) {
|
|
130
|
-
const e = PENDING_EFFECTS[i];
|
|
131
|
-
const prevSub = activeSub;
|
|
132
|
-
activeSub = e;
|
|
133
|
-
startTracking(e);
|
|
134
|
-
try {
|
|
135
|
-
e.fn();
|
|
136
|
-
} finally {
|
|
137
|
-
activeSub = prevSub;
|
|
138
|
-
endTracking(e);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
PENDING_EFFECTS.length = 0;
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
function queueEffect(e) {
|
|
146
|
-
PENDING_EFFECTS.push(e);
|
|
147
|
-
flushEffects();
|
|
148
|
-
}
|
|
149
|
-
function stopEffect() {
|
|
150
|
-
startTracking(this);
|
|
151
|
-
endTracking(this);
|
|
152
|
-
queueMicrotask(() => {
|
|
153
|
-
PENDING_EFFECTS.splice(PENDING_EFFECTS.indexOf(this), 1);
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
class Atom {
|
|
157
|
-
#signal;
|
|
158
|
-
#equals;
|
|
159
|
-
name;
|
|
160
|
-
constructor(signal, options) {
|
|
161
|
-
this.#signal = signal;
|
|
162
|
-
this.#equals = options?.equals ?? Object.is;
|
|
163
|
-
if (options?.name) {
|
|
164
|
-
this.name = options.name;
|
|
165
|
-
}
|
|
166
|
-
Object.defineProperty(this, DEPENDENCY, {
|
|
167
|
-
value: signal,
|
|
168
|
-
configurable: false,
|
|
169
|
-
enumerable: false,
|
|
170
|
-
writable: false
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
get value() {
|
|
174
|
-
return this.#signal.currentValue;
|
|
175
|
-
}
|
|
176
|
-
set value(next) {
|
|
177
|
-
if (!this.#equals(this.#signal.currentValue, next)) {
|
|
178
|
-
this.#signal.currentValue = next;
|
|
179
|
-
const subs = this.#signal.subs;
|
|
180
|
-
if (subs !== void 0) {
|
|
181
|
-
propagate(subs);
|
|
182
|
-
processEffectNotifications();
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
class Composed {
|
|
188
|
-
computed;
|
|
189
|
-
constructor(computed) {
|
|
190
|
-
this.computed = computed;
|
|
191
|
-
Object.defineProperty(this, DEPENDENCY, {
|
|
192
|
-
value: computed,
|
|
193
|
-
configurable: false,
|
|
194
|
-
enumerable: false,
|
|
195
|
-
writable: false
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
get value() {
|
|
199
|
-
const computed = this.computed;
|
|
200
|
-
const flags = computed.flags;
|
|
201
|
-
if (flags & (SubscriberFlags.Dirty | SubscriberFlags.PendingComputed)) {
|
|
202
|
-
processComputedUpdate(computed, flags);
|
|
203
|
-
}
|
|
204
|
-
return computed.currentValue;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
function isReactive(value) {
|
|
208
|
-
return value != null && value[DEPENDENCY] != null;
|
|
209
|
-
}
|
|
210
|
-
function atom(value, options) {
|
|
211
|
-
return new Atom({ currentValue: value, subs: void 0, subsTail: void 0 }, options);
|
|
212
|
-
}
|
|
213
|
-
function compose(fn, options) {
|
|
214
|
-
return new Composed({
|
|
215
|
-
currentValue: void 0,
|
|
216
|
-
equals: options?.equals ?? Object.is,
|
|
217
|
-
subs: void 0,
|
|
218
|
-
subsTail: void 0,
|
|
219
|
-
deps: void 0,
|
|
220
|
-
depsTail: void 0,
|
|
221
|
-
flags: SubscriberFlags.Computed | SubscriberFlags.Dirty,
|
|
222
|
-
getter: (cachedValue) => {
|
|
223
|
-
let returned = fn(cachedValue);
|
|
224
|
-
returned = get(returned);
|
|
225
|
-
return returned;
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
function set(atom2, next) {
|
|
230
|
-
if (isFunction(next)) {
|
|
231
|
-
atom2.value = next(atom2.value);
|
|
232
|
-
} else if (arguments.length > 1) {
|
|
233
|
-
atom2.value = next;
|
|
234
|
-
} else {
|
|
235
|
-
return (next2) => set(atom2, next2);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
function get(value) {
|
|
239
|
-
if (isReactive(value)) {
|
|
240
|
-
if (activeSub !== void 0) {
|
|
241
|
-
const dep = value[DEPENDENCY];
|
|
242
|
-
link(dep, activeSub);
|
|
243
|
-
}
|
|
244
|
-
return value.value;
|
|
245
|
-
} else {
|
|
246
|
-
return value;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
function peek(value) {
|
|
250
|
-
if (isReactive(value)) {
|
|
251
|
-
return value.value;
|
|
252
|
-
} else {
|
|
253
|
-
return value;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
function effect(fn) {
|
|
257
|
-
const e = {
|
|
258
|
-
fn,
|
|
259
|
-
subs: void 0,
|
|
260
|
-
subsTail: void 0,
|
|
261
|
-
deps: void 0,
|
|
262
|
-
depsTail: void 0,
|
|
263
|
-
flags: SubscriberFlags.Effect
|
|
264
|
-
};
|
|
265
|
-
if (activeSub !== void 0) {
|
|
266
|
-
link(e, activeSub);
|
|
267
|
-
}
|
|
268
|
-
queueEffect(e);
|
|
269
|
-
return stopEffect.bind(e);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const noOp = () => {
|
|
273
|
-
};
|
|
274
|
-
let idCounter = 1;
|
|
275
|
-
function getUniqueId() {
|
|
276
|
-
idCounter = idCounter % Number.MAX_SAFE_INTEGER + 1;
|
|
277
|
-
return idCounter.toString(36) + Date.now().toString(36);
|
|
278
|
-
}
|
|
279
|
-
function strictEqual(a, b) {
|
|
280
|
-
return Object.is(a, b);
|
|
281
|
-
}
|
|
282
|
-
function shallowEqual(a, b) {
|
|
283
|
-
if (Object.is(a, b)) return true;
|
|
284
|
-
const t = typeOf(a);
|
|
285
|
-
if (t !== typeOf(b)) {
|
|
286
|
-
return false;
|
|
287
|
-
}
|
|
288
|
-
switch (t) {
|
|
289
|
-
case "object":
|
|
290
|
-
let size = 0;
|
|
291
|
-
for (const key in a) {
|
|
292
|
-
if (a[key] !== b[key]) return false;
|
|
293
|
-
size++;
|
|
294
|
-
}
|
|
295
|
-
return Object.keys(b).length === size;
|
|
296
|
-
case "array":
|
|
297
|
-
if (a.length !== b.length) return false;
|
|
298
|
-
for (let i = 0; i < a.length; i++) {
|
|
299
|
-
if (a[i] !== b[i]) return false;
|
|
300
|
-
}
|
|
301
|
-
return true;
|
|
302
|
-
case "map":
|
|
303
|
-
if (a.size !== b.size) return false;
|
|
304
|
-
for (const key of a.keys()) {
|
|
305
|
-
if (a[key] !== b[key]) return false;
|
|
306
|
-
}
|
|
307
|
-
return true;
|
|
308
|
-
case "set":
|
|
309
|
-
if (isFunction(a.symmetricDifference)) {
|
|
310
|
-
return a.symmetricDifference(b).size === 0;
|
|
311
|
-
} else {
|
|
312
|
-
for (const key of a.keys()) {
|
|
313
|
-
if (a[key] !== b.get(key)) return false;
|
|
314
|
-
}
|
|
315
|
-
return true;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
return false;
|
|
319
|
-
}
|
|
320
|
-
function deepEqual(a, b) {
|
|
321
|
-
if (a === b) return true;
|
|
322
|
-
if (a && b && typeof a == "object" && typeof b == "object") {
|
|
323
|
-
if (a.constructor !== b.constructor) return false;
|
|
324
|
-
var length, i, keys;
|
|
325
|
-
if (Array.isArray(a)) {
|
|
326
|
-
length = a.length;
|
|
327
|
-
if (length != b.length) return false;
|
|
328
|
-
for (i = length; i-- !== 0; ) if (!deepEqual(a[i], b[i])) return false;
|
|
329
|
-
return true;
|
|
330
|
-
}
|
|
331
|
-
if (a instanceof Map && b instanceof Map) {
|
|
332
|
-
if (a.size !== b.size) return false;
|
|
333
|
-
for (i of a.entries()) if (!b.has(i[0])) return false;
|
|
334
|
-
for (i of a.entries()) if (!deepEqual(i[1], b.get(i[0]))) return false;
|
|
335
|
-
return true;
|
|
336
|
-
}
|
|
337
|
-
if (a instanceof Set && b instanceof Set) {
|
|
338
|
-
if (a.size !== b.size) return false;
|
|
339
|
-
for (i of a.entries()) if (!b.has(i[0])) return false;
|
|
340
|
-
return true;
|
|
341
|
-
}
|
|
342
|
-
if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
|
|
343
|
-
length = a.length;
|
|
344
|
-
if (length != b.length) return false;
|
|
345
|
-
for (i = length; i-- !== 0; ) if (a[i] !== b[i]) return false;
|
|
346
|
-
return true;
|
|
347
|
-
}
|
|
348
|
-
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
|
|
349
|
-
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
|
|
350
|
-
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
|
|
351
|
-
keys = Object.keys(a);
|
|
352
|
-
length = keys.length;
|
|
353
|
-
if (length !== Object.keys(b).length) return false;
|
|
354
|
-
for (i = length; i-- !== 0; ) if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
|
|
355
|
-
for (i = length; i-- !== 0; ) {
|
|
356
|
-
var key = keys[i];
|
|
357
|
-
if (!deepEqual(a[key], b[key])) return false;
|
|
358
|
-
}
|
|
359
|
-
return true;
|
|
360
|
-
}
|
|
361
|
-
return a !== a && b !== b;
|
|
362
|
-
}
|
|
363
|
-
function omit(keys, object) {
|
|
364
|
-
const process = (object2) => {
|
|
365
|
-
const newObject = {};
|
|
366
|
-
for (const key in object2) {
|
|
367
|
-
if (!keys.includes(key)) {
|
|
368
|
-
newObject[key] = object2[key];
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
return newObject;
|
|
372
|
-
};
|
|
373
|
-
if (object == null) {
|
|
374
|
-
return process;
|
|
375
|
-
}
|
|
376
|
-
return process(object);
|
|
377
|
-
}
|
|
378
|
-
function okhash(value) {
|
|
379
|
-
let hue = 0;
|
|
380
|
-
for (let i = 0; i < value.length; i++) {
|
|
381
|
-
hue = (hue + value.charCodeAt(i) * 10) % 360;
|
|
382
|
-
}
|
|
383
|
-
return `oklch(0.68 0.15 ${hue}deg)`;
|
|
384
|
-
}
|
|
385
|
-
function createMatcher(pattern) {
|
|
386
|
-
if (pattern instanceof RegExp) {
|
|
387
|
-
return (value) => pattern.test(value);
|
|
388
|
-
}
|
|
389
|
-
const matchers = {
|
|
390
|
-
positive: [],
|
|
391
|
-
negative: []
|
|
392
|
-
};
|
|
393
|
-
const parts = pattern.split(",").map((p) => p.trim()).filter((p) => p !== "");
|
|
394
|
-
for (let part of parts) {
|
|
395
|
-
let section = "positive";
|
|
396
|
-
if (part.startsWith("-")) {
|
|
397
|
-
section = "negative";
|
|
398
|
-
part = part.slice(1);
|
|
399
|
-
}
|
|
400
|
-
if (part === "*") {
|
|
401
|
-
matchers[section].push(function() {
|
|
402
|
-
return true;
|
|
403
|
-
});
|
|
404
|
-
} else if (part.endsWith("*")) {
|
|
405
|
-
matchers[section].push(function(value) {
|
|
406
|
-
return value.startsWith(part.slice(0, part.length - 1));
|
|
407
|
-
});
|
|
408
|
-
} else {
|
|
409
|
-
matchers[section].push(function(value) {
|
|
410
|
-
return value === part;
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
return function(name) {
|
|
415
|
-
const { positive, negative } = matchers;
|
|
416
|
-
if (negative.some((fn) => fn(name))) {
|
|
417
|
-
return false;
|
|
418
|
-
}
|
|
419
|
-
if (positive.length > 0 && !positive.some((fn) => fn(name))) {
|
|
420
|
-
return false;
|
|
421
|
-
}
|
|
422
|
-
return true;
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
const IS_MARKUP_ELEMENT = Symbol.for("DollaMarkupElement");
|
|
427
|
-
const IS_ROUTER = Symbol.for("DollaRouter");
|
|
428
|
-
|
|
429
|
-
function Passthrough(_, ctx) {
|
|
430
|
-
return ctx.outlet();
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
class DOMNode {
|
|
434
|
-
[IS_MARKUP_ELEMENT] = true;
|
|
435
|
-
node;
|
|
436
|
-
get isMounted() {
|
|
437
|
-
return this.node.parentNode != null;
|
|
438
|
-
}
|
|
439
|
-
constructor(node) {
|
|
440
|
-
this.node = node;
|
|
441
|
-
}
|
|
442
|
-
mount(parent, after) {
|
|
443
|
-
parent.insertBefore(this.node, after?.nextSibling ?? null);
|
|
444
|
-
}
|
|
445
|
-
unmount(parentIsUnmounting = false) {
|
|
446
|
-
if (this.node.parentNode && !parentIsUnmounting) {
|
|
447
|
-
this.node.parentNode.removeChild(this.node);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
class Dynamic {
|
|
453
|
-
[IS_MARKUP_ELEMENT] = true;
|
|
454
|
-
node = document.createTextNode("");
|
|
455
|
-
children = [];
|
|
456
|
-
elementContext;
|
|
457
|
-
source;
|
|
458
|
-
unsubscribe;
|
|
459
|
-
get isMounted() {
|
|
460
|
-
return this.node.parentNode != null;
|
|
461
|
-
}
|
|
462
|
-
constructor(options) {
|
|
463
|
-
this.source = options.source;
|
|
464
|
-
this.elementContext = options.elementContext;
|
|
465
|
-
}
|
|
466
|
-
mount(parent, after) {
|
|
467
|
-
if (!this.isMounted) {
|
|
468
|
-
parent.insertBefore(this.node, after?.nextSibling ?? null);
|
|
469
|
-
this.unsubscribe = effect(() => {
|
|
470
|
-
const content = get(this.source);
|
|
471
|
-
if (!isRenderable(content)) {
|
|
472
|
-
console.error(content);
|
|
473
|
-
throw new TypeError(
|
|
474
|
-
`Dynamic received invalid value to render. Got type: ${typeOf(content)}, value: ${content}`
|
|
475
|
-
);
|
|
476
|
-
}
|
|
477
|
-
this.update(isArray(content) ? content : [content]);
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
unmount(parentIsUnmounting = false) {
|
|
482
|
-
this.unsubscribe?.();
|
|
483
|
-
if (this.isMounted) {
|
|
484
|
-
this.cleanup(parentIsUnmounting);
|
|
485
|
-
this.node.parentNode?.removeChild(this.node);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
cleanup(parentIsUnmounting) {
|
|
489
|
-
for (const element of this.children) {
|
|
490
|
-
element.unmount(parentIsUnmounting);
|
|
491
|
-
}
|
|
492
|
-
this.children = [];
|
|
493
|
-
}
|
|
494
|
-
update(children) {
|
|
495
|
-
this.cleanup(false);
|
|
496
|
-
if (children == null || children.length === 0 || !this.isMounted) {
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
const newElements = children.flatMap((c) => {
|
|
500
|
-
if (isMarkupElement(c)) {
|
|
501
|
-
return c;
|
|
502
|
-
} else {
|
|
503
|
-
return constructMarkup(this.elementContext, toMarkup(c));
|
|
504
|
-
}
|
|
505
|
-
});
|
|
506
|
-
for (const element of newElements) {
|
|
507
|
-
const previous = this.children.at(-1)?.node || this.node;
|
|
508
|
-
element.mount(this.node.parentNode, previous);
|
|
509
|
-
this.children.push(element);
|
|
510
|
-
}
|
|
511
|
-
const parent = this.node.parentNode;
|
|
512
|
-
const lastChildNextSibling = this.children.at(-1)?.node?.nextSibling ?? null;
|
|
513
|
-
parent.insertBefore(this.node, lastChildNextSibling);
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
const isCamelCaseEventName = (key) => /^on[A-Z]/.test(key);
|
|
518
|
-
class HTML {
|
|
519
|
-
[IS_MARKUP_ELEMENT] = true;
|
|
520
|
-
node;
|
|
521
|
-
props;
|
|
522
|
-
childMarkup = [];
|
|
523
|
-
children = [];
|
|
524
|
-
unsubscribers = [];
|
|
525
|
-
elementContext;
|
|
526
|
-
// Track the ref so we can nullify it on unmount.
|
|
527
|
-
ref;
|
|
528
|
-
// Prevents 'onClickOutside' handlers from firing in the same cycle in which the element is connected.
|
|
529
|
-
canClickAway = false;
|
|
530
|
-
get isMounted() {
|
|
531
|
-
return this.node.parentNode != null;
|
|
532
|
-
}
|
|
533
|
-
constructor({ tag, props, children, elementContext }) {
|
|
534
|
-
if (tag.toLowerCase() === "svg") {
|
|
535
|
-
elementContext = {
|
|
536
|
-
...elementContext,
|
|
537
|
-
isSVG: true
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
if (elementContext.isSVG) {
|
|
541
|
-
this.node = document.createElementNS("http://www.w3.org/2000/svg", tag);
|
|
542
|
-
} else {
|
|
543
|
-
this.node = document.createElement(tag);
|
|
544
|
-
}
|
|
545
|
-
if (elementContext.root.getEnv() === "development" && elementContext.viewName) {
|
|
546
|
-
this.node.dataset.view = elementContext.viewName;
|
|
547
|
-
}
|
|
548
|
-
if (props.ref) {
|
|
549
|
-
if (isFunction(props.ref)) {
|
|
550
|
-
this.ref = props.ref;
|
|
551
|
-
this.ref(this.node);
|
|
552
|
-
} else {
|
|
553
|
-
throw new Error("Expected ref to be a function. Got: " + props.ref);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
this.props = {
|
|
557
|
-
...omit(["ref", "class", "className"], props),
|
|
558
|
-
class: props.className ?? props.class
|
|
559
|
-
};
|
|
560
|
-
if (children) {
|
|
561
|
-
this.childMarkup = children;
|
|
562
|
-
}
|
|
563
|
-
this.elementContext = elementContext;
|
|
564
|
-
}
|
|
565
|
-
mount(parent, after) {
|
|
566
|
-
if (parent == null) {
|
|
567
|
-
throw new Error(`HTML element requires a parent element as the first argument to connect. Got: ${parent}`);
|
|
568
|
-
}
|
|
569
|
-
if (!this.isMounted) {
|
|
570
|
-
if (this.childMarkup.length > 0) {
|
|
571
|
-
this.children = constructMarkup(this.elementContext, this.childMarkup);
|
|
572
|
-
}
|
|
573
|
-
for (let i = 0; i < this.children.length; i++) {
|
|
574
|
-
const child = this.children[i];
|
|
575
|
-
const previous = i > 0 ? this.children[i - 1].node : void 0;
|
|
576
|
-
child.mount(this.node, previous);
|
|
577
|
-
}
|
|
578
|
-
this.applyProps(this.node, this.props);
|
|
579
|
-
if (this.props.style) this.applyStyles(this.node, this.props.style, this.unsubscribers);
|
|
580
|
-
if (this.props.class) this.applyClasses(this.node, this.props.class, this.unsubscribers);
|
|
581
|
-
}
|
|
582
|
-
parent.insertBefore(this.node, after?.nextSibling ?? null);
|
|
583
|
-
setTimeout(() => {
|
|
584
|
-
this.canClickAway = true;
|
|
585
|
-
}, 0);
|
|
586
|
-
}
|
|
587
|
-
unmount(parentIsUnmounting = false) {
|
|
588
|
-
if (this.isMounted) {
|
|
589
|
-
if (!parentIsUnmounting) {
|
|
590
|
-
this.node.parentNode?.removeChild(this.node);
|
|
591
|
-
}
|
|
592
|
-
for (const child of this.children) {
|
|
593
|
-
child.unmount(true);
|
|
594
|
-
}
|
|
595
|
-
if (this.ref) {
|
|
596
|
-
this.ref(void 0);
|
|
597
|
-
}
|
|
598
|
-
this.canClickAway = false;
|
|
599
|
-
for (const unsubscribe of this.unsubscribers) {
|
|
600
|
-
unsubscribe();
|
|
601
|
-
}
|
|
602
|
-
this.unsubscribers.length = 0;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
attachProp(value, callback) {
|
|
606
|
-
if (isReactive(value)) {
|
|
607
|
-
this.unsubscribers.push(effect(() => callback(get(value))));
|
|
608
|
-
} else {
|
|
609
|
-
callback(value);
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
applyProps(element, props) {
|
|
613
|
-
for (const key in props) {
|
|
614
|
-
const value = props[key];
|
|
615
|
-
if (key === "attributes") {
|
|
616
|
-
const values = value;
|
|
617
|
-
for (const name in values) {
|
|
618
|
-
this.attachProp(values[name], (current) => {
|
|
619
|
-
if (current == null) {
|
|
620
|
-
element.removeAttribute(name);
|
|
621
|
-
} else {
|
|
622
|
-
element.setAttribute(name, String(current));
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
} else if (key === "onClickOutside" || key === "onclickoutside") {
|
|
627
|
-
const listener = (e) => {
|
|
628
|
-
if (this.canClickAway && !element.contains(e.target)) {
|
|
629
|
-
if (isReactive(value)) {
|
|
630
|
-
value.value(e);
|
|
631
|
-
} else {
|
|
632
|
-
value(e);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
};
|
|
636
|
-
const options = { capture: true };
|
|
637
|
-
window.addEventListener("click", listener, options);
|
|
638
|
-
this.unsubscribers.push(() => {
|
|
639
|
-
window.removeEventListener("click", listener, options);
|
|
640
|
-
});
|
|
641
|
-
} else if (isCamelCaseEventName(key)) {
|
|
642
|
-
const eventName = key.slice(2).toLowerCase();
|
|
643
|
-
const listener = isReactive(value) ? (e) => value.value(e) : value;
|
|
644
|
-
element.addEventListener(eventName, listener);
|
|
645
|
-
this.unsubscribers.push(() => {
|
|
646
|
-
element.removeEventListener(eventName, listener);
|
|
647
|
-
});
|
|
648
|
-
} else if (key.includes("-")) {
|
|
649
|
-
this.attachProp(value, (current) => {
|
|
650
|
-
if (current == null) {
|
|
651
|
-
element.removeAttribute(key);
|
|
652
|
-
} else {
|
|
653
|
-
element.setAttribute(key, String(current));
|
|
654
|
-
}
|
|
655
|
-
});
|
|
656
|
-
} else if (!privateProps.includes(key)) {
|
|
657
|
-
if (this.elementContext.isSVG) {
|
|
658
|
-
this.attachProp(value, (current) => {
|
|
659
|
-
if (current != null) {
|
|
660
|
-
element.setAttribute(key, String(props[key]));
|
|
661
|
-
} else {
|
|
662
|
-
element.removeAttribute(key);
|
|
663
|
-
}
|
|
664
|
-
});
|
|
665
|
-
} else {
|
|
666
|
-
switch (key) {
|
|
667
|
-
case "contentEditable":
|
|
668
|
-
case "value":
|
|
669
|
-
this.attachProp(value, (current) => {
|
|
670
|
-
element[key] = String(current);
|
|
671
|
-
});
|
|
672
|
-
break;
|
|
673
|
-
case "for":
|
|
674
|
-
this.attachProp(value, (current) => {
|
|
675
|
-
element.htmlFor = current;
|
|
676
|
-
});
|
|
677
|
-
break;
|
|
678
|
-
case "checked":
|
|
679
|
-
this.attachProp(value, (current) => {
|
|
680
|
-
element.checked = current;
|
|
681
|
-
if (current) {
|
|
682
|
-
element.setAttribute("checked", "");
|
|
683
|
-
} else {
|
|
684
|
-
element.removeAttribute("checked");
|
|
685
|
-
}
|
|
686
|
-
});
|
|
687
|
-
break;
|
|
688
|
-
// Attribute-aliased props
|
|
689
|
-
case "exportParts":
|
|
690
|
-
case "part":
|
|
691
|
-
case "translate":
|
|
692
|
-
case "type":
|
|
693
|
-
case "title": {
|
|
694
|
-
const _key = key.toLowerCase();
|
|
695
|
-
this.attachProp(value, (current) => {
|
|
696
|
-
if (current == void 0) {
|
|
697
|
-
element.removeAttribute(_key);
|
|
698
|
-
} else {
|
|
699
|
-
element.setAttribute(_key, String(current));
|
|
700
|
-
}
|
|
701
|
-
});
|
|
702
|
-
break;
|
|
703
|
-
}
|
|
704
|
-
case "autocomplete":
|
|
705
|
-
case "autocapitalize":
|
|
706
|
-
this.attachProp(value, (current) => {
|
|
707
|
-
if (typeof current === "string") {
|
|
708
|
-
element.autocomplete = current;
|
|
709
|
-
} else if (current) {
|
|
710
|
-
element.autocomplete = "on";
|
|
711
|
-
} else {
|
|
712
|
-
element.autocomplete = "off";
|
|
713
|
-
}
|
|
714
|
-
});
|
|
715
|
-
break;
|
|
716
|
-
default: {
|
|
717
|
-
this.attachProp(value, (current) => {
|
|
718
|
-
element[key] = current;
|
|
719
|
-
});
|
|
720
|
-
break;
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
applyStyles(element, styles, unsubscribers) {
|
|
728
|
-
const propUnsubscribers = [];
|
|
729
|
-
if (isReactive(styles)) {
|
|
730
|
-
let unapply;
|
|
731
|
-
const unsubscribe = effect(() => {
|
|
732
|
-
if (isFunction(unapply)) {
|
|
733
|
-
unapply();
|
|
734
|
-
}
|
|
735
|
-
element.style.cssText = "";
|
|
736
|
-
unapply = this.applyStyles(element, get(styles), unsubscribers);
|
|
737
|
-
});
|
|
738
|
-
unsubscribers.push(unsubscribe);
|
|
739
|
-
propUnsubscribers.push(unsubscribe);
|
|
740
|
-
} else {
|
|
741
|
-
const mapped = getStyleMap(styles);
|
|
742
|
-
for (const name in mapped) {
|
|
743
|
-
const { value, priority } = mapped[name];
|
|
744
|
-
if (isReactive(value)) {
|
|
745
|
-
const unsubscribe = effect(() => {
|
|
746
|
-
if (get(value)) {
|
|
747
|
-
element.style.setProperty(name, String(value.value), priority);
|
|
748
|
-
} else {
|
|
749
|
-
element.style.removeProperty(name);
|
|
750
|
-
}
|
|
751
|
-
});
|
|
752
|
-
unsubscribers.push(unsubscribe);
|
|
753
|
-
propUnsubscribers.push(unsubscribe);
|
|
754
|
-
} else if (value != void 0) {
|
|
755
|
-
element.style.setProperty(name, String(value));
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
return function unapply() {
|
|
760
|
-
for (const unsubscribe of propUnsubscribers) {
|
|
761
|
-
unsubscribe();
|
|
762
|
-
unsubscribers.splice(unsubscribers.indexOf(unsubscribe), 1);
|
|
763
|
-
}
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
applyClasses(element, classes, unsubscribers) {
|
|
767
|
-
const classUnsubscribers = [];
|
|
768
|
-
if (isReactive(classes)) {
|
|
769
|
-
let unapply;
|
|
770
|
-
const unsubscribe = effect(() => {
|
|
771
|
-
if (isFunction(unapply)) {
|
|
772
|
-
unapply();
|
|
773
|
-
}
|
|
774
|
-
element.removeAttribute("class");
|
|
775
|
-
unapply = this.applyClasses(element, get(classes), unsubscribers);
|
|
776
|
-
});
|
|
777
|
-
unsubscribers.push(unsubscribe);
|
|
778
|
-
classUnsubscribers.push(unsubscribe);
|
|
779
|
-
} else {
|
|
780
|
-
const mapped = getClassMap(classes);
|
|
781
|
-
for (const name in mapped) {
|
|
782
|
-
const value = mapped[name];
|
|
783
|
-
if (isReactive(value)) {
|
|
784
|
-
const unsubscribe = effect(() => {
|
|
785
|
-
if (get(value)) {
|
|
786
|
-
element.classList.add(name);
|
|
787
|
-
} else {
|
|
788
|
-
element.classList.remove(name);
|
|
789
|
-
}
|
|
790
|
-
});
|
|
791
|
-
unsubscribers.push(unsubscribe);
|
|
792
|
-
classUnsubscribers.push(unsubscribe);
|
|
793
|
-
} else if (value) {
|
|
794
|
-
element.classList.add(name);
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
return function unapply() {
|
|
799
|
-
for (const unsubscribe of classUnsubscribers) {
|
|
800
|
-
unsubscribe();
|
|
801
|
-
unsubscribers.splice(unsubscribers.indexOf(unsubscribe), 1);
|
|
802
|
-
}
|
|
803
|
-
};
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
function getClassMap(classes) {
|
|
807
|
-
let mapped = {};
|
|
808
|
-
if (isString(classes)) {
|
|
809
|
-
const names = classes.split(" ");
|
|
810
|
-
for (const name of names) {
|
|
811
|
-
mapped[name] = true;
|
|
812
|
-
}
|
|
813
|
-
} else if (isObject(classes)) {
|
|
814
|
-
Object.assign(mapped, classes);
|
|
815
|
-
} else if (Array.isArray(classes)) {
|
|
816
|
-
Array.from(classes).filter(Boolean).forEach((item) => {
|
|
817
|
-
Object.assign(mapped, getClassMap(item));
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
delete mapped["undefined"];
|
|
821
|
-
return mapped;
|
|
822
|
-
}
|
|
823
|
-
function getStyleMap(styles) {
|
|
824
|
-
let mapped = {};
|
|
825
|
-
if (isString(styles)) {
|
|
826
|
-
const lines = styles.split(";").filter((line) => line.trim() !== "");
|
|
827
|
-
for (const line of lines) {
|
|
828
|
-
const [key, _value] = line.split(":");
|
|
829
|
-
const entry = {
|
|
830
|
-
value: _value
|
|
831
|
-
};
|
|
832
|
-
if (_value.includes("!important")) {
|
|
833
|
-
entry.priority = "important";
|
|
834
|
-
entry.value = _value.replace("!important", "").trim();
|
|
835
|
-
} else {
|
|
836
|
-
entry.value = _value.trim();
|
|
837
|
-
}
|
|
838
|
-
mapped[camelToKebab(key.trim())] = entry;
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
if (isObject(styles)) {
|
|
842
|
-
for (const key in styles) {
|
|
843
|
-
if (key.startsWith("--")) {
|
|
844
|
-
mapped[key] = { value: styles[key] };
|
|
845
|
-
} else {
|
|
846
|
-
mapped[camelToKebab(key)] = { value: styles[key] };
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
} else if (Array.isArray(styles)) {
|
|
850
|
-
Array.from(styles).filter((item) => item != null).forEach((item) => {
|
|
851
|
-
Object.assign(mapped, getStyleMap(item));
|
|
852
|
-
});
|
|
853
|
-
}
|
|
854
|
-
return mapped;
|
|
855
|
-
}
|
|
856
|
-
function camelToKebab(value) {
|
|
857
|
-
return value.replace(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? "-" : "") + $.toLowerCase());
|
|
858
|
-
}
|
|
859
|
-
const privateProps = ["ref", "children", "class", "style", "data"];
|
|
860
|
-
|
|
861
|
-
let Context$1 = class Context {
|
|
862
|
-
store;
|
|
863
|
-
constructor(store) {
|
|
864
|
-
this.store = store;
|
|
865
|
-
const descriptors = Object.getOwnPropertyDescriptors(this.store.logger);
|
|
866
|
-
for (const key in descriptors) {
|
|
867
|
-
if (key !== "setName") {
|
|
868
|
-
Object.defineProperty(this, key, descriptors[key]);
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
get isMounted() {
|
|
873
|
-
return this.store.isMounted;
|
|
874
|
-
}
|
|
875
|
-
get name() {
|
|
876
|
-
return this.store.name || this.store.id;
|
|
877
|
-
}
|
|
878
|
-
set name(value) {
|
|
879
|
-
this.store.name = value;
|
|
880
|
-
this.store.logger.setName(value);
|
|
881
|
-
}
|
|
882
|
-
get(store) {
|
|
883
|
-
if (isFunction(store)) {
|
|
884
|
-
let context = this.store.elementContext;
|
|
885
|
-
let instance;
|
|
886
|
-
while (true) {
|
|
887
|
-
instance = context.stores.get(store);
|
|
888
|
-
if (instance == null && context.parent != null) {
|
|
889
|
-
context = context.parent;
|
|
890
|
-
} else {
|
|
891
|
-
break;
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
if (instance == null) {
|
|
895
|
-
throw new StoreError(`Store '${store.name}' is not provided on this context.`);
|
|
896
|
-
} else {
|
|
897
|
-
return instance.value;
|
|
898
|
-
}
|
|
899
|
-
} else {
|
|
900
|
-
throw new StoreError(`Invalid store.`);
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
onMount(callback) {
|
|
904
|
-
this.store.lifecycleListeners.mount.push(callback);
|
|
905
|
-
}
|
|
906
|
-
onUnmount(callback) {
|
|
907
|
-
this.store.lifecycleListeners.unmount.push(callback);
|
|
908
|
-
}
|
|
909
|
-
effect(callback) {
|
|
910
|
-
const store = this.store;
|
|
911
|
-
if (store.isMounted) {
|
|
912
|
-
const unsubscribe = effect(callback);
|
|
913
|
-
store.lifecycleListeners.unmount.push(unsubscribe);
|
|
914
|
-
return unsubscribe;
|
|
915
|
-
} else {
|
|
916
|
-
let unsubscribe;
|
|
917
|
-
let disposed = false;
|
|
918
|
-
store.lifecycleListeners.mount.push(() => {
|
|
919
|
-
if (!disposed) {
|
|
920
|
-
unsubscribe = effect(callback);
|
|
921
|
-
store.lifecycleListeners.unmount.push(unsubscribe);
|
|
922
|
-
}
|
|
923
|
-
});
|
|
924
|
-
return () => {
|
|
925
|
-
if (unsubscribe != null) {
|
|
926
|
-
disposed = true;
|
|
927
|
-
unsubscribe();
|
|
928
|
-
}
|
|
929
|
-
};
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
};
|
|
933
|
-
class Store {
|
|
934
|
-
fn;
|
|
935
|
-
_options;
|
|
936
|
-
/**
|
|
937
|
-
* Value is guaranteed to be set after `attach` is called.
|
|
938
|
-
*/
|
|
939
|
-
value;
|
|
940
|
-
isMounted = false;
|
|
941
|
-
elementContext;
|
|
942
|
-
lifecycleListeners = { mount: [], unmount: [] };
|
|
943
|
-
logger;
|
|
944
|
-
id = getUniqueId();
|
|
945
|
-
name;
|
|
946
|
-
constructor(fn, options) {
|
|
947
|
-
this.fn = fn;
|
|
948
|
-
this.name = fn.name;
|
|
949
|
-
this._options = options;
|
|
950
|
-
}
|
|
951
|
-
/**
|
|
952
|
-
* Attaches this Store to the elementContext.
|
|
953
|
-
* Returns false if there was already an instance attached, and true otherwise.
|
|
954
|
-
*/
|
|
955
|
-
attach(elementContext) {
|
|
956
|
-
if (elementContext.stores.has(this.fn)) {
|
|
957
|
-
return false;
|
|
958
|
-
}
|
|
959
|
-
this.elementContext = elementContext;
|
|
960
|
-
this.logger = elementContext.root.createLogger(this.name);
|
|
961
|
-
const context = new Context$1(this);
|
|
962
|
-
try {
|
|
963
|
-
this.value = this.fn.call(context, this._options, context);
|
|
964
|
-
} catch (error) {
|
|
965
|
-
this.logger.crash(error);
|
|
966
|
-
throw error;
|
|
967
|
-
}
|
|
968
|
-
elementContext.stores.set(this.fn, this);
|
|
969
|
-
return true;
|
|
970
|
-
}
|
|
971
|
-
handleMount() {
|
|
972
|
-
this.isMounted = true;
|
|
973
|
-
for (const listener of this.lifecycleListeners.mount) {
|
|
974
|
-
listener();
|
|
975
|
-
}
|
|
976
|
-
this.lifecycleListeners.mount.length = 0;
|
|
977
|
-
}
|
|
978
|
-
handleUnmount() {
|
|
979
|
-
this.isMounted = false;
|
|
980
|
-
for (const listener of this.lifecycleListeners.unmount) {
|
|
981
|
-
listener();
|
|
982
|
-
}
|
|
983
|
-
this.lifecycleListeners.unmount.length = 0;
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
class StoreError extends Error {
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
class Context {
|
|
990
|
-
view;
|
|
991
|
-
constructor(view) {
|
|
992
|
-
this.view = view;
|
|
993
|
-
const descriptors = Object.getOwnPropertyDescriptors(this.view.logger);
|
|
994
|
-
for (const key in descriptors) {
|
|
995
|
-
if (key !== "setName") {
|
|
996
|
-
Object.defineProperty(this, key, descriptors[key]);
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
get uid() {
|
|
1001
|
-
return this.view.uniqueId;
|
|
1002
|
-
}
|
|
1003
|
-
get isMounted() {
|
|
1004
|
-
return this.view.isMounted;
|
|
1005
|
-
}
|
|
1006
|
-
get name() {
|
|
1007
|
-
return this.view.elementContext.viewName || this.uid;
|
|
1008
|
-
}
|
|
1009
|
-
set name(value) {
|
|
1010
|
-
this.view.elementContext.viewName = value;
|
|
1011
|
-
this.view.logger.setName(value);
|
|
1012
|
-
}
|
|
1013
|
-
provide(store, options) {
|
|
1014
|
-
const instance = new Store(store, options);
|
|
1015
|
-
const attached = instance.attach(this.view.elementContext);
|
|
1016
|
-
if (attached) {
|
|
1017
|
-
this.view.lifecycleListeners.mount.push(() => {
|
|
1018
|
-
instance.handleMount();
|
|
1019
|
-
});
|
|
1020
|
-
this.view.lifecycleListeners.unmount.push(() => {
|
|
1021
|
-
instance.handleUnmount();
|
|
1022
|
-
});
|
|
1023
|
-
return instance.value;
|
|
1024
|
-
} else {
|
|
1025
|
-
let name = store.name ? `'${store.name}'` : "this store";
|
|
1026
|
-
this.view.logger.warn(`An instance of ${name} was already attached to this context.`);
|
|
1027
|
-
return this.get(store);
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
get(store) {
|
|
1031
|
-
if (isFunction(store)) {
|
|
1032
|
-
let context = this.view.elementContext;
|
|
1033
|
-
let instance;
|
|
1034
|
-
while (true) {
|
|
1035
|
-
instance = context.stores.get(store);
|
|
1036
|
-
if (instance == null && context.parent != null) {
|
|
1037
|
-
context = context.parent;
|
|
1038
|
-
} else {
|
|
1039
|
-
break;
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
if (instance == null) {
|
|
1043
|
-
throw new StoreError(`Store '${store.name}' is not provided on this context.`);
|
|
1044
|
-
} else {
|
|
1045
|
-
return instance.value;
|
|
1046
|
-
}
|
|
1047
|
-
} else {
|
|
1048
|
-
throw new StoreError(`Invalid store.`);
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
beforeMount(callback) {
|
|
1052
|
-
this.view.lifecycleListeners.beforeMount.push(callback);
|
|
1053
|
-
}
|
|
1054
|
-
onMount(callback) {
|
|
1055
|
-
this.view.lifecycleListeners.mount.push(callback);
|
|
1056
|
-
}
|
|
1057
|
-
beforeUnmount(callback) {
|
|
1058
|
-
this.view.lifecycleListeners.beforeUnmount.push(callback);
|
|
1059
|
-
}
|
|
1060
|
-
onUnmount(callback) {
|
|
1061
|
-
this.view.lifecycleListeners.unmount.push(callback);
|
|
1062
|
-
}
|
|
1063
|
-
effect(callback) {
|
|
1064
|
-
if (this.view.isMounted) {
|
|
1065
|
-
const unsubscribe = effect(callback);
|
|
1066
|
-
this.view.lifecycleListeners.unmount.push(unsubscribe);
|
|
1067
|
-
return unsubscribe;
|
|
1068
|
-
} else {
|
|
1069
|
-
let unsubscribe;
|
|
1070
|
-
let disposed = false;
|
|
1071
|
-
this.view.lifecycleListeners.mount.push(() => {
|
|
1072
|
-
if (!disposed) {
|
|
1073
|
-
unsubscribe = effect(callback);
|
|
1074
|
-
this.view.lifecycleListeners.unmount.push(unsubscribe);
|
|
1075
|
-
}
|
|
1076
|
-
});
|
|
1077
|
-
return () => {
|
|
1078
|
-
if (unsubscribe != null) {
|
|
1079
|
-
disposed = true;
|
|
1080
|
-
unsubscribe();
|
|
1081
|
-
}
|
|
1082
|
-
};
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
outlet() {
|
|
1086
|
-
return createMarkup("$outlet", { children: this.view.children });
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
class View {
|
|
1090
|
-
[IS_MARKUP_ELEMENT] = true;
|
|
1091
|
-
uniqueId = getUniqueId();
|
|
1092
|
-
elementContext;
|
|
1093
|
-
logger;
|
|
1094
|
-
props;
|
|
1095
|
-
fn;
|
|
1096
|
-
element;
|
|
1097
|
-
childMarkup;
|
|
1098
|
-
children = atom([]);
|
|
1099
|
-
lifecycleListeners = { beforeMount: [], mount: [], beforeUnmount: [], unmount: [] };
|
|
1100
|
-
constructor(elementContext, fn, props, children = []) {
|
|
1101
|
-
this.elementContext = {
|
|
1102
|
-
...elementContext,
|
|
1103
|
-
parent: elementContext,
|
|
1104
|
-
viewName: fn.name,
|
|
1105
|
-
stores: /* @__PURE__ */ new Map()
|
|
1106
|
-
};
|
|
1107
|
-
this.logger = elementContext.root.createLogger(fn.name || "🌇 anonymous view", { uid: this.uniqueId });
|
|
1108
|
-
this.props = props;
|
|
1109
|
-
this.fn = fn;
|
|
1110
|
-
this.childMarkup = children;
|
|
1111
|
-
}
|
|
1112
|
-
/*===============================*\
|
|
1113
|
-
|| "Public" API ||
|
|
1114
|
-
\*===============================*/
|
|
1115
|
-
get node() {
|
|
1116
|
-
return this.element?.node;
|
|
1117
|
-
}
|
|
1118
|
-
isMounted = false;
|
|
1119
|
-
mount(parent, after) {
|
|
1120
|
-
const wasConnected = this.isMounted;
|
|
1121
|
-
if (!wasConnected) {
|
|
1122
|
-
this._initialize();
|
|
1123
|
-
for (const listener of this.lifecycleListeners.beforeMount) {
|
|
1124
|
-
listener();
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
if (this.element) {
|
|
1128
|
-
this.element.mount(parent, after);
|
|
1129
|
-
}
|
|
1130
|
-
if (!wasConnected) {
|
|
1131
|
-
this.isMounted = true;
|
|
1132
|
-
requestAnimationFrame(() => {
|
|
1133
|
-
for (const listener of this.lifecycleListeners.mount) {
|
|
1134
|
-
listener();
|
|
1135
|
-
}
|
|
1136
|
-
});
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
unmount(parentIsUnmounting = false) {
|
|
1140
|
-
for (const listener of this.lifecycleListeners.beforeUnmount) {
|
|
1141
|
-
listener();
|
|
1142
|
-
}
|
|
1143
|
-
if (this.element) {
|
|
1144
|
-
this.element.unmount(parentIsUnmounting);
|
|
1145
|
-
}
|
|
1146
|
-
this.isMounted = false;
|
|
1147
|
-
for (const listener of this.lifecycleListeners.unmount) {
|
|
1148
|
-
listener();
|
|
1149
|
-
}
|
|
1150
|
-
this.lifecycleListeners.beforeMount.length = 0;
|
|
1151
|
-
this.lifecycleListeners.mount.length = 0;
|
|
1152
|
-
this.lifecycleListeners.beforeUnmount.length = 0;
|
|
1153
|
-
this.lifecycleListeners.unmount.length = 0;
|
|
1154
|
-
}
|
|
1155
|
-
setChildView(fn) {
|
|
1156
|
-
this.childMarkup = [];
|
|
1157
|
-
const node = new View(this.elementContext, fn, {});
|
|
1158
|
-
this.children.value = [node];
|
|
1159
|
-
return node;
|
|
1160
|
-
}
|
|
1161
|
-
/*===============================*\
|
|
1162
|
-
|| Internal ||
|
|
1163
|
-
\*===============================*/
|
|
1164
|
-
_initialize() {
|
|
1165
|
-
const context = new Context(this);
|
|
1166
|
-
let result;
|
|
1167
|
-
try {
|
|
1168
|
-
result = this.fn.call(context, this.props, context);
|
|
1169
|
-
if (this.childMarkup.length) {
|
|
1170
|
-
this.children.value = constructMarkup(this.elementContext, this.childMarkup);
|
|
1171
|
-
}
|
|
1172
|
-
} catch (error) {
|
|
1173
|
-
if (error instanceof Error) {
|
|
1174
|
-
this.logger.crash(error);
|
|
1175
|
-
}
|
|
1176
|
-
throw error;
|
|
1177
|
-
}
|
|
1178
|
-
if (result === null) ; else if (result instanceof Node) {
|
|
1179
|
-
this.element = groupElements(constructMarkup(this.elementContext, createMarkup("$node", { value: result })));
|
|
1180
|
-
} else if (isReactive(result)) {
|
|
1181
|
-
this.element = groupElements(
|
|
1182
|
-
constructMarkup(this.elementContext, createMarkup("$dynamic", { source: result }))
|
|
1183
|
-
);
|
|
1184
|
-
} else if (isMarkup(result) || isArrayOf(isMarkup, result)) {
|
|
1185
|
-
this.element = groupElements(constructMarkup(this.elementContext, result));
|
|
1186
|
-
} else {
|
|
1187
|
-
const error = new TypeError(
|
|
1188
|
-
`Expected '${this.fn.name}' function to return a DOM node, Markup element, Readable or null. Got: ${typeOf(result)}`
|
|
1189
|
-
);
|
|
1190
|
-
this.logger.crash(error);
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
|
-
class List {
|
|
1196
|
-
[IS_MARKUP_ELEMENT] = true;
|
|
1197
|
-
node = document.createTextNode("");
|
|
1198
|
-
items;
|
|
1199
|
-
unsubscribe = null;
|
|
1200
|
-
connectedItems = [];
|
|
1201
|
-
elementContext;
|
|
1202
|
-
renderFn;
|
|
1203
|
-
keyFn;
|
|
1204
|
-
get isMounted() {
|
|
1205
|
-
return this.node.parentNode != null;
|
|
1206
|
-
}
|
|
1207
|
-
constructor({ elementContext, items, renderFn, keyFn }) {
|
|
1208
|
-
this.elementContext = elementContext;
|
|
1209
|
-
this.items = items;
|
|
1210
|
-
this.renderFn = renderFn;
|
|
1211
|
-
this.keyFn = keyFn;
|
|
1212
|
-
}
|
|
1213
|
-
mount(parent, after) {
|
|
1214
|
-
if (!this.isMounted) {
|
|
1215
|
-
parent.insertBefore(this.node, after?.nextSibling ?? null);
|
|
1216
|
-
this.unsubscribe = effect(() => {
|
|
1217
|
-
let value = get(this.items);
|
|
1218
|
-
if (value == null) {
|
|
1219
|
-
value = [];
|
|
1220
|
-
console.log("list received empty value", value, this);
|
|
1221
|
-
}
|
|
1222
|
-
this._update(Array.from(value));
|
|
1223
|
-
});
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
unmount(parentIsUnmounting = false) {
|
|
1227
|
-
if (this.unsubscribe) {
|
|
1228
|
-
this.unsubscribe();
|
|
1229
|
-
this.unsubscribe = null;
|
|
1230
|
-
}
|
|
1231
|
-
if (!parentIsUnmounting && this.isMounted) {
|
|
1232
|
-
this.node.parentNode?.removeChild(this.node);
|
|
1233
|
-
}
|
|
1234
|
-
this._cleanup(parentIsUnmounting);
|
|
1235
|
-
}
|
|
1236
|
-
_cleanup(parentIsUnmounting) {
|
|
1237
|
-
for (const item of this.connectedItems) {
|
|
1238
|
-
item.element.unmount(parentIsUnmounting);
|
|
1239
|
-
}
|
|
1240
|
-
this.connectedItems = [];
|
|
1241
|
-
}
|
|
1242
|
-
_update(value) {
|
|
1243
|
-
if (value.length === 0 || !this.isMounted) {
|
|
1244
|
-
return this._cleanup(false);
|
|
1245
|
-
}
|
|
1246
|
-
const potentialItems = [];
|
|
1247
|
-
let index = 0;
|
|
1248
|
-
for (const item of value) {
|
|
1249
|
-
potentialItems.push({
|
|
1250
|
-
key: this.keyFn(item, index),
|
|
1251
|
-
value: item,
|
|
1252
|
-
index: index++
|
|
1253
|
-
});
|
|
1254
|
-
}
|
|
1255
|
-
const newItems = [];
|
|
1256
|
-
for (const connected of this.connectedItems) {
|
|
1257
|
-
const potentialItem = potentialItems.find((p) => p.key === connected.key);
|
|
1258
|
-
if (!potentialItem) {
|
|
1259
|
-
connected.element.unmount(false);
|
|
1260
|
-
}
|
|
1261
|
-
}
|
|
1262
|
-
for (const potential of potentialItems) {
|
|
1263
|
-
const connected = this.connectedItems.find((item) => item.key === potential.key);
|
|
1264
|
-
if (connected) {
|
|
1265
|
-
connected.item.value = potential.value;
|
|
1266
|
-
connected.index.value = potential.index;
|
|
1267
|
-
newItems[potential.index] = connected;
|
|
1268
|
-
} else {
|
|
1269
|
-
const item = atom(potential.value);
|
|
1270
|
-
const index2 = atom(potential.index);
|
|
1271
|
-
newItems[potential.index] = {
|
|
1272
|
-
key: potential.key,
|
|
1273
|
-
item,
|
|
1274
|
-
index: index2,
|
|
1275
|
-
element: new View(this.elementContext, ListItemView, {
|
|
1276
|
-
item: compose(() => item.value),
|
|
1277
|
-
index: index2,
|
|
1278
|
-
renderFn: this.renderFn
|
|
1279
|
-
})
|
|
1280
|
-
};
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
for (let i = 0; i < newItems.length; i++) {
|
|
1284
|
-
const item = newItems[i];
|
|
1285
|
-
const previous = newItems[i - 1]?.element.node ?? this.node;
|
|
1286
|
-
item.element.mount(this.node.parentNode, previous);
|
|
1287
|
-
}
|
|
1288
|
-
this.connectedItems = newItems;
|
|
1289
|
-
const lastItem = newItems.at(-1)?.element.node ?? this.node;
|
|
1290
|
-
this.node.parentNode?.insertBefore(this.node, lastItem.nextSibling);
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
function ListItemView(props, context) {
|
|
1294
|
-
context.name = "@ListItem";
|
|
1295
|
-
return props.renderFn.call(context, props.item, props.index, context);
|
|
1296
|
-
}
|
|
1297
|
-
|
|
1298
|
-
class Outlet {
|
|
1299
|
-
[IS_MARKUP_ELEMENT] = true;
|
|
1300
|
-
node = document.createTextNode("");
|
|
1301
|
-
isMounted = false;
|
|
1302
|
-
source;
|
|
1303
|
-
elements = [];
|
|
1304
|
-
unsubscribe;
|
|
1305
|
-
constructor(source) {
|
|
1306
|
-
this.source = source;
|
|
1307
|
-
}
|
|
1308
|
-
mount(parent, after) {
|
|
1309
|
-
if (!this.isMounted) {
|
|
1310
|
-
this.isMounted = true;
|
|
1311
|
-
parent.insertBefore(this.node, after?.nextSibling ?? null);
|
|
1312
|
-
if (isReactive(this.source)) {
|
|
1313
|
-
this.unsubscribe = effect(() => {
|
|
1314
|
-
this.update(get(this.source));
|
|
1315
|
-
});
|
|
1316
|
-
} else {
|
|
1317
|
-
this.update(this.elements);
|
|
1318
|
-
}
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
unmount(parentIsUnmounting = false) {
|
|
1322
|
-
if (this.unsubscribe) {
|
|
1323
|
-
this.unsubscribe();
|
|
1324
|
-
this.unsubscribe = void 0;
|
|
1325
|
-
}
|
|
1326
|
-
if (this.isMounted) {
|
|
1327
|
-
this.cleanup(parentIsUnmounting);
|
|
1328
|
-
this.isMounted = false;
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
cleanup(parentIsUnmounting) {
|
|
1332
|
-
for (const element of this.elements) {
|
|
1333
|
-
element.unmount(parentIsUnmounting);
|
|
1334
|
-
}
|
|
1335
|
-
this.elements = [];
|
|
1336
|
-
}
|
|
1337
|
-
update(newElements) {
|
|
1338
|
-
this.cleanup(false);
|
|
1339
|
-
if (newElements.length > 0) {
|
|
1340
|
-
for (let i = 0; i < newElements.length; i++) {
|
|
1341
|
-
const element = newElements[i];
|
|
1342
|
-
const previous = i > 0 ? this.elements[i - 1] : void 0;
|
|
1343
|
-
element.mount(this.node.parentElement, previous?.node);
|
|
1344
|
-
this.elements.push(element);
|
|
1345
|
-
}
|
|
1346
|
-
this.node.parentNode?.insertBefore(this.node, this.elements.at(-1)?.node ?? null);
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
|
-
class Portal {
|
|
1352
|
-
[IS_MARKUP_ELEMENT] = true;
|
|
1353
|
-
config;
|
|
1354
|
-
element;
|
|
1355
|
-
get isMounted() {
|
|
1356
|
-
if (!this.element) {
|
|
1357
|
-
return false;
|
|
1358
|
-
}
|
|
1359
|
-
return this.element.isMounted;
|
|
1360
|
-
}
|
|
1361
|
-
constructor(config) {
|
|
1362
|
-
this.config = config;
|
|
1363
|
-
}
|
|
1364
|
-
mount(_parent, _after) {
|
|
1365
|
-
const { content, parent } = this.config;
|
|
1366
|
-
if (isMarkupElement(content)) {
|
|
1367
|
-
this.element = content;
|
|
1368
|
-
} else {
|
|
1369
|
-
this.element = groupElements(constructMarkup(this.config.elementContext, toMarkup(content)));
|
|
1370
|
-
}
|
|
1371
|
-
this.element.mount(parent);
|
|
1372
|
-
}
|
|
1373
|
-
unmount(parentIsUnmounting = false) {
|
|
1374
|
-
if (this.element?.isMounted) {
|
|
1375
|
-
this.element.unmount(parentIsUnmounting);
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
|
|
1380
|
-
function isMarkup(value) {
|
|
1381
|
-
return value instanceof VNode;
|
|
1382
|
-
}
|
|
1383
|
-
function isMarkupElement(value) {
|
|
1384
|
-
return value?.[IS_MARKUP_ELEMENT] === true;
|
|
1385
|
-
}
|
|
1386
|
-
function toMarkup(renderables) {
|
|
1387
|
-
if (!isArray(renderables)) {
|
|
1388
|
-
renderables = [renderables];
|
|
1389
|
-
}
|
|
1390
|
-
return renderables.flat(Infinity).filter((x) => x !== null && x !== void 0 && x !== false).map((x) => {
|
|
1391
|
-
if (isMarkup(x)) {
|
|
1392
|
-
return x;
|
|
1393
|
-
}
|
|
1394
|
-
if (x instanceof Node) {
|
|
1395
|
-
return createMarkup("$node", { value: x });
|
|
1396
|
-
}
|
|
1397
|
-
if (isReactive(x)) {
|
|
1398
|
-
return createMarkup("$dynamic", { source: x });
|
|
1399
|
-
}
|
|
1400
|
-
return createMarkup("$text", { value: x });
|
|
1401
|
-
});
|
|
1402
|
-
}
|
|
1403
|
-
function createMarkup(type, props, ...children) {
|
|
1404
|
-
return new VNode(type, props, ...children);
|
|
1405
|
-
}
|
|
1406
|
-
class VNode {
|
|
1407
|
-
type;
|
|
1408
|
-
props;
|
|
1409
|
-
children;
|
|
1410
|
-
constructor(type, props, ...children) {
|
|
1411
|
-
this.type = type;
|
|
1412
|
-
this.props = props;
|
|
1413
|
-
this.children = toMarkup(children);
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
const html = htm.bind(createMarkup);
|
|
1417
|
-
function cond(condition, thenContent, elseContent) {
|
|
1418
|
-
return createMarkup("$dynamic", {
|
|
1419
|
-
source: compose(() => {
|
|
1420
|
-
const value = get(condition);
|
|
1421
|
-
if (value && thenContent) {
|
|
1422
|
-
return thenContent;
|
|
1423
|
-
} else if (!value && elseContent) {
|
|
1424
|
-
return elseContent;
|
|
1425
|
-
}
|
|
1426
|
-
return null;
|
|
1427
|
-
})
|
|
1428
|
-
});
|
|
1429
|
-
}
|
|
1430
|
-
function list(items, keyFn, renderFn) {
|
|
1431
|
-
return createMarkup("$list", { items: compose(() => items), keyFn, renderFn });
|
|
1432
|
-
}
|
|
1433
|
-
function portal(parent, content) {
|
|
1434
|
-
return createMarkup("$portal", { parent, content });
|
|
1435
|
-
}
|
|
1436
|
-
function constructMarkup(elementContext, markup) {
|
|
1437
|
-
const items = isArray(markup) ? markup : [markup];
|
|
1438
|
-
return items.map((item) => {
|
|
1439
|
-
if (isFunction(item.type)) {
|
|
1440
|
-
return new View(elementContext, item.type, item.props, item.children);
|
|
1441
|
-
} else if (isString(item.type)) {
|
|
1442
|
-
switch (item.type) {
|
|
1443
|
-
case "$node": {
|
|
1444
|
-
const attrs = item.props;
|
|
1445
|
-
return new DOMNode(attrs.value);
|
|
1446
|
-
}
|
|
1447
|
-
case "$text": {
|
|
1448
|
-
const attrs = item.props;
|
|
1449
|
-
return new DOMNode(document.createTextNode(String(attrs.value)));
|
|
1450
|
-
}
|
|
1451
|
-
case "$list": {
|
|
1452
|
-
const attrs = item.props;
|
|
1453
|
-
return new List({
|
|
1454
|
-
items: attrs.items,
|
|
1455
|
-
keyFn: attrs.keyFn,
|
|
1456
|
-
renderFn: attrs.renderFn,
|
|
1457
|
-
elementContext
|
|
1458
|
-
});
|
|
1459
|
-
}
|
|
1460
|
-
case "$dynamic": {
|
|
1461
|
-
const attrs = item.props;
|
|
1462
|
-
return new Dynamic({
|
|
1463
|
-
source: attrs.source,
|
|
1464
|
-
elementContext
|
|
1465
|
-
});
|
|
1466
|
-
}
|
|
1467
|
-
case "$outlet": {
|
|
1468
|
-
const attrs = item.props;
|
|
1469
|
-
return new Outlet(attrs.children);
|
|
1470
|
-
}
|
|
1471
|
-
case "$portal": {
|
|
1472
|
-
const attrs = item.props;
|
|
1473
|
-
return new Portal({
|
|
1474
|
-
content: attrs.content,
|
|
1475
|
-
parent: attrs.parent,
|
|
1476
|
-
elementContext
|
|
1477
|
-
});
|
|
1478
|
-
}
|
|
1479
|
-
default:
|
|
1480
|
-
if (item.type.startsWith("$")) {
|
|
1481
|
-
throw new Error(`Unknown markup type: ${item.type}`);
|
|
1482
|
-
}
|
|
1483
|
-
return new HTML({
|
|
1484
|
-
tag: item.type,
|
|
1485
|
-
props: item.props ?? {},
|
|
1486
|
-
children: item.children,
|
|
1487
|
-
elementContext
|
|
1488
|
-
});
|
|
1489
|
-
}
|
|
1490
|
-
} else {
|
|
1491
|
-
throw new TypeError(`Expected a string or view function. Got: ${item.type}`);
|
|
1492
|
-
}
|
|
1493
|
-
});
|
|
1494
|
-
}
|
|
1495
|
-
function groupElements(elements) {
|
|
1496
|
-
if (elements.length === 1) {
|
|
1497
|
-
return elements[0];
|
|
1498
|
-
}
|
|
1499
|
-
return new Outlet(elements);
|
|
1500
|
-
}
|
|
1501
|
-
function isRenderable(value) {
|
|
1502
|
-
return value == null || value === false || isString(value) || isNumber(value) || isMarkup(value) || isReactive(value) || isArrayOf(isRenderable, value);
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
export { portal as A, list as B, IS_ROUTER as I, Passthrough as P, Store as S, View as V, assertArrayOf as a, assertString as b, atom as c, compose as d, assertObject as e, isString as f, get as g, isObject as h, isFunction as i, deepEqual as j, cond as k, html as l, createMatcher as m, StoreError as n, assertInstanceOf as o, createMarkup as p, groupElements as q, constructMarkup as r, shallowEqual as s, typeOf as t, noOp as u, okhash as v, effect as w, set as x, peek as y, strictEqual as z };
|
|
1506
|
-
//# sourceMappingURL=markup-PXJjYgl3.js.map
|