@oscarpalmer/abydon 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abydon.full.mjs +1443 -0
- package/dist/constants.d.mts +20 -0
- package/dist/constants.mjs +27 -0
- package/dist/fragment-9qTBAvtR.d.mts +82 -0
- package/dist/fragment.d.mts +2 -0
- package/dist/{fragment.js → fragment.mjs} +41 -14
- package/dist/fragments.d.mts +16 -0
- package/dist/{fragments.js → fragments.mjs} +10 -4
- package/dist/helpers/dom.d.mts +6 -0
- package/dist/helpers/{dom.js → dom.mjs} +4 -12
- package/dist/helpers/index.d.mts +9 -0
- package/dist/helpers/index.mjs +23 -0
- package/dist/index.d.mts +21 -0
- package/dist/index.mjs +24 -0
- package/dist/models.d.mts +2 -0
- package/dist/models.mjs +1 -0
- package/dist/node/attribute/index.d.mts +6 -0
- package/dist/node/attribute/index.mjs +41 -0
- package/dist/node/attribute/value.d.mts +6 -0
- package/dist/node/attribute/value.mjs +65 -0
- package/dist/node/event.d.mts +4 -0
- package/dist/node/event.mjs +25 -0
- package/dist/node/index.d.mts +6 -0
- package/dist/node/{index.js → index.mjs} +10 -8
- package/dist/node/value.d.mts +7 -0
- package/dist/node/{value.js → value.mjs} +12 -10
- package/dist/parse.d.mts +6 -0
- package/dist/{parse.js → parse.mjs} +11 -1
- package/package.json +42 -42
- package/src/constants.ts +30 -10
- package/src/fragment.ts +12 -24
- package/src/fragments.ts +3 -5
- package/src/helpers/dom.ts +1 -20
- package/src/helpers/index.ts +18 -15
- package/src/index.ts +14 -10
- package/src/models.ts +10 -1
- package/src/node/attribute/index.ts +22 -21
- package/src/node/attribute/value.ts +47 -37
- package/src/node/event.ts +26 -33
- package/src/node/index.ts +6 -18
- package/src/node/value.ts +15 -46
- package/src/parse.ts +15 -17
- package/dist/abydon.full.js +0 -1274
- package/dist/constants.js +0 -10
- package/dist/helpers/index.js +0 -14
- package/dist/index.js +0 -11
- package/dist/models.js +0 -0
- package/dist/node/attribute/index.js +0 -39
- package/dist/node/attribute/value.js +0 -56
- package/dist/node/event.js +0 -30
- package/types/constants.d.ts +0 -9
- package/types/fragment.d.ts +0 -38
- package/types/fragments.d.ts +0 -13
- package/types/helpers/dom.d.ts +0 -3
- package/types/helpers/index.d.ts +0 -5
- package/types/index.d.ts +0 -9
- package/types/models.d.ts +0 -32
- package/types/node/attribute/index.d.ts +0 -3
- package/types/node/attribute/value.d.ts +0 -3
- package/types/node/event.d.ts +0 -3
- package/types/node/index.d.ts +0 -2
- package/types/node/value.d.ts +0 -3
- package/types/parse.d.ts +0 -2
|
@@ -0,0 +1,1443 @@
|
|
|
1
|
+
//#region node_modules/@oscarpalmer/mora/dist/constants.js
|
|
2
|
+
const ACTIVE = {};
|
|
3
|
+
const BATCH = {
|
|
4
|
+
depth: 0,
|
|
5
|
+
handlers: /* @__PURE__ */ new Set()
|
|
6
|
+
};
|
|
7
|
+
const METHODS_AFFECTING_LENGTH = new Set([
|
|
8
|
+
"pop",
|
|
9
|
+
"push",
|
|
10
|
+
"shift",
|
|
11
|
+
"unshift"
|
|
12
|
+
]);
|
|
13
|
+
const METHODS_UPDATE = new Set([
|
|
14
|
+
...METHODS_AFFECTING_LENGTH,
|
|
15
|
+
"copyWithin",
|
|
16
|
+
"fill",
|
|
17
|
+
"reverse",
|
|
18
|
+
"sort",
|
|
19
|
+
"splice"
|
|
20
|
+
]);
|
|
21
|
+
const NAME_ARRAY = "array";
|
|
22
|
+
const NAME_COMPUTED = "computed";
|
|
23
|
+
const NAME_EFFECT = "effect";
|
|
24
|
+
const NAME_MORA = "$mora";
|
|
25
|
+
const NAME_SIGNAL = "signal";
|
|
26
|
+
const NAME_STORE = "store";
|
|
27
|
+
const NAME_ALL = new Set([
|
|
28
|
+
NAME_ARRAY,
|
|
29
|
+
NAME_COMPUTED,
|
|
30
|
+
NAME_SIGNAL,
|
|
31
|
+
NAME_STORE
|
|
32
|
+
]);
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region node_modules/@oscarpalmer/mora/dist/effect.js
|
|
35
|
+
var Effect = class {
|
|
36
|
+
constructor(callback) {
|
|
37
|
+
Object.defineProperty(this, NAME_MORA, { value: NAME_EFFECT });
|
|
38
|
+
this.state = { callback };
|
|
39
|
+
runEffect(this);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
function runEffect(effect$1) {
|
|
43
|
+
const previousEffect = ACTIVE.effect;
|
|
44
|
+
ACTIVE.effect = effect$1;
|
|
45
|
+
try {
|
|
46
|
+
effect$1.state.callback();
|
|
47
|
+
} finally {
|
|
48
|
+
ACTIVE.effect = previousEffect;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function effect(callback) {
|
|
52
|
+
return typeof callback === "function" ? new Effect(callback) : void 0;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region node_modules/@oscarpalmer/mora/dist/helpers/is.js
|
|
56
|
+
function isArray(value) {
|
|
57
|
+
return isMora(value, NAME_ARRAY);
|
|
58
|
+
}
|
|
59
|
+
function isComputed(value) {
|
|
60
|
+
return isMora(value, NAME_COMPUTED);
|
|
61
|
+
}
|
|
62
|
+
function isEffect(value) {
|
|
63
|
+
return isMora(value, NAME_EFFECT);
|
|
64
|
+
}
|
|
65
|
+
function isMora(value, name) {
|
|
66
|
+
return typeof value === "object" && value != null && "$mora" in value && (typeof name === "string" ? value["$mora"] === name : name.has(value["$mora"]));
|
|
67
|
+
}
|
|
68
|
+
function isReactive(value) {
|
|
69
|
+
return isMora(value, NAME_ALL);
|
|
70
|
+
}
|
|
71
|
+
function isSignal(value) {
|
|
72
|
+
return isMora(value, NAME_SIGNAL);
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region node_modules/@oscarpalmer/mora/dist/batch.js
|
|
76
|
+
function flushHandlers() {
|
|
77
|
+
while (BATCH.depth === 0 && BATCH.handlers.size > 0) {
|
|
78
|
+
const handlers = [...BATCH.handlers];
|
|
79
|
+
BATCH.handlers.clear();
|
|
80
|
+
for (const handler of handlers) if (isEffect(handler)) runEffect(handler);
|
|
81
|
+
else handler.callback(handler.state.value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function startBatch() {
|
|
85
|
+
BATCH.depth += 1;
|
|
86
|
+
}
|
|
87
|
+
function stopBatch() {
|
|
88
|
+
if (BATCH.depth > 0) BATCH.depth -= 1;
|
|
89
|
+
flushHandlers();
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region node_modules/@oscarpalmer/mora/dist/subscription.js
|
|
93
|
+
var Subscription = class {
|
|
94
|
+
callback;
|
|
95
|
+
state;
|
|
96
|
+
constructor(state, callback) {
|
|
97
|
+
this.state = state;
|
|
98
|
+
this.callback = callback;
|
|
99
|
+
callback(state.value);
|
|
100
|
+
}
|
|
101
|
+
destroy() {
|
|
102
|
+
this.callback = noop$1;
|
|
103
|
+
this.state = void 0;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
function noop$1() {}
|
|
107
|
+
function subscribe(state, callback) {
|
|
108
|
+
if (typeof callback !== "function" || state.subscriptions.has(callback)) return noop$1;
|
|
109
|
+
state.subscriptions.set(callback, new Subscription(state, callback));
|
|
110
|
+
return () => {
|
|
111
|
+
unsubscribe(state, callback);
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function unsubscribe(state, callback) {
|
|
115
|
+
state.subscriptions.get(callback)?.destroy();
|
|
116
|
+
state.subscriptions.delete(callback);
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
//#region node_modules/@oscarpalmer/mora/dist/value/reactive.js
|
|
120
|
+
var Reactive = class {
|
|
121
|
+
state = {
|
|
122
|
+
computeds: /* @__PURE__ */ new Set(),
|
|
123
|
+
effects: /* @__PURE__ */ new Set(),
|
|
124
|
+
equal: Object.is,
|
|
125
|
+
subscriptions: /* @__PURE__ */ new Map(),
|
|
126
|
+
value: void 0
|
|
127
|
+
};
|
|
128
|
+
constructor(name, value, options) {
|
|
129
|
+
this.state.value = value;
|
|
130
|
+
if (typeof options === "object" && typeof options.equal === "function") this.state.equal = options.equal;
|
|
131
|
+
Object.defineProperty(this, NAME_MORA, { value: name });
|
|
132
|
+
}
|
|
133
|
+
peek() {
|
|
134
|
+
return this.state.value;
|
|
135
|
+
}
|
|
136
|
+
subscribe(callback) {
|
|
137
|
+
return subscribe(this.state, callback);
|
|
138
|
+
}
|
|
139
|
+
toJSON() {
|
|
140
|
+
return this.get();
|
|
141
|
+
}
|
|
142
|
+
toString() {
|
|
143
|
+
return String(this.get());
|
|
144
|
+
}
|
|
145
|
+
unsubscribe(callback) {
|
|
146
|
+
unsubscribe(this.state, callback);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region node_modules/@oscarpalmer/mora/dist/value/computed.js
|
|
151
|
+
var Computed = class extends Reactive {
|
|
152
|
+
effect = {
|
|
153
|
+
dirty: true,
|
|
154
|
+
instance: void 0
|
|
155
|
+
};
|
|
156
|
+
constructor(callback, options) {
|
|
157
|
+
super(NAME_COMPUTED, void 0, options);
|
|
158
|
+
this.effect.instance = effect(() => {
|
|
159
|
+
if (!this.effect.dirty) return;
|
|
160
|
+
const previousComputed = ACTIVE.computed;
|
|
161
|
+
ACTIVE.computed = this;
|
|
162
|
+
const value = callback();
|
|
163
|
+
ACTIVE.computed = previousComputed;
|
|
164
|
+
if (!this.state.equal(this.state.value, value)) {
|
|
165
|
+
this.state.value = value;
|
|
166
|
+
for (const computed$1 of this.state.computeds) computed$1.effect.dirty = true;
|
|
167
|
+
for (const effect$1 of this.state.effects) BATCH.handlers.add(effect$1);
|
|
168
|
+
for (const [, subscription] of this.state.subscriptions) subscription.callback(value);
|
|
169
|
+
}
|
|
170
|
+
this.effect.dirty = false;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
get() {
|
|
174
|
+
if (ACTIVE.computed != null && this !== ACTIVE.computed) this.state.computeds.add(ACTIVE.computed);
|
|
175
|
+
if (ACTIVE.effect != null && ACTIVE.effect !== this.effect.instance) this.state.effects.add(ACTIVE.effect);
|
|
176
|
+
if (this.effect.dirty && BATCH.depth === 0) runEffect(this.effect.instance);
|
|
177
|
+
return this.state.value;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
function computed(callback, options) {
|
|
181
|
+
return new Computed(callback, options);
|
|
182
|
+
}
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region node_modules/@oscarpalmer/mora/dist/helpers/value.js
|
|
185
|
+
function emitValue(state) {
|
|
186
|
+
for (const computed of state.computeds) computed.effect.dirty = true;
|
|
187
|
+
for (const effect of state.effects) BATCH.handlers.add(effect);
|
|
188
|
+
for (const [, subscription] of state.subscriptions) BATCH.handlers.add(subscription);
|
|
189
|
+
if (BATCH.depth === 0) flushHandlers();
|
|
190
|
+
}
|
|
191
|
+
function equalArrays(state, first, second) {
|
|
192
|
+
let { length } = first;
|
|
193
|
+
if (length !== second.length) return false;
|
|
194
|
+
let offset = 0;
|
|
195
|
+
if (length >= 100) {
|
|
196
|
+
offset = Math.round(length / 10);
|
|
197
|
+
offset = offset > 25 ? 25 : offset;
|
|
198
|
+
for (let index = 0; index < offset; index += 1) if (!state.equal(first[index], second[index])) return false;
|
|
199
|
+
}
|
|
200
|
+
length -= offset;
|
|
201
|
+
for (let index = offset; index < length; index += 1) if (!state.equal(first[index], second[index])) return false;
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
function getValue$1(state) {
|
|
205
|
+
if (ACTIVE.computed != null) state.computeds.add(ACTIVE.computed);
|
|
206
|
+
if (ACTIVE.effect != null) state.effects.add(ACTIVE.effect);
|
|
207
|
+
return state.value;
|
|
208
|
+
}
|
|
209
|
+
//#endregion
|
|
210
|
+
//#region node_modules/@oscarpalmer/mora/dist/value/signal.js
|
|
211
|
+
var Signal = class extends Reactive {
|
|
212
|
+
constructor(value, options) {
|
|
213
|
+
super(NAME_SIGNAL, value, options);
|
|
214
|
+
}
|
|
215
|
+
get() {
|
|
216
|
+
return getValue$1(this.state);
|
|
217
|
+
}
|
|
218
|
+
set(value) {
|
|
219
|
+
if (!this.state.equal(this.state.value, value)) {
|
|
220
|
+
this.state.value = value;
|
|
221
|
+
emitValue(this.state);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
update(callback) {
|
|
225
|
+
this.set(callback(this.state.value));
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
function signal(value, options) {
|
|
229
|
+
return new Signal(value, options);
|
|
230
|
+
}
|
|
231
|
+
//#endregion
|
|
232
|
+
//#region node_modules/@oscarpalmer/mora/dist/helpers/proxy.js
|
|
233
|
+
function emityProxyValues(state, mapped) {
|
|
234
|
+
const values = [...mapped.values()];
|
|
235
|
+
const { length } = values;
|
|
236
|
+
for (let index = 0; index < length; index += 1) values[index].effect.dirty = true;
|
|
237
|
+
emitValue(state);
|
|
238
|
+
}
|
|
239
|
+
function getReactiveValueInProxy(reactive, mapped, key, isArray) {
|
|
240
|
+
let item = mapped.get(key);
|
|
241
|
+
if (item == null) {
|
|
242
|
+
item = computed(() => isArray ? reactive.get().at(key) : reactive.get()[key]);
|
|
243
|
+
mapped.set(key, item);
|
|
244
|
+
}
|
|
245
|
+
return item;
|
|
246
|
+
}
|
|
247
|
+
function setProxyValue(proxy, value) {
|
|
248
|
+
startBatch();
|
|
249
|
+
const proxyKeys = Object.keys(proxy);
|
|
250
|
+
const valueKeys = Object.keys(value);
|
|
251
|
+
let { length } = proxyKeys;
|
|
252
|
+
for (let index = 0; index < length; index += 1) {
|
|
253
|
+
const key = proxyKeys[index];
|
|
254
|
+
proxy[key] = valueKeys.includes(key) ? value[key] : void 0;
|
|
255
|
+
}
|
|
256
|
+
length = valueKeys.length;
|
|
257
|
+
for (let index = 0; index < length; index += 1) {
|
|
258
|
+
const key = valueKeys[index];
|
|
259
|
+
if (!proxyKeys.includes(key)) proxy[key] = value[key];
|
|
260
|
+
}
|
|
261
|
+
stopBatch();
|
|
262
|
+
}
|
|
263
|
+
function setValueInProxy(parameters) {
|
|
264
|
+
const { isArray, length, property, state, target, value } = parameters;
|
|
265
|
+
if (isArray) {
|
|
266
|
+
if (!(!Number.isNaN(Number(property)) || property === "length")) return Reflect.set(target, property, value);
|
|
267
|
+
}
|
|
268
|
+
const previous = Reflect.get(target, property);
|
|
269
|
+
if (!state.equal(previous, value)) {
|
|
270
|
+
Reflect.set(target, property, value);
|
|
271
|
+
emitValue(state);
|
|
272
|
+
if (isArray) length?.set(target.length);
|
|
273
|
+
}
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
//#endregion
|
|
277
|
+
//#region node_modules/@oscarpalmer/mora/dist/value/array.js
|
|
278
|
+
var ReactiveArray = class extends Reactive {
|
|
279
|
+
#indiced = /* @__PURE__ */ new Map();
|
|
280
|
+
#size = signal(0);
|
|
281
|
+
get length() {
|
|
282
|
+
return this.#size.get();
|
|
283
|
+
}
|
|
284
|
+
set length(value) {
|
|
285
|
+
if (typeof value === "number" && value >= 0 && value !== this.state.value.length) this.get().length = value;
|
|
286
|
+
}
|
|
287
|
+
constructor(value, options) {
|
|
288
|
+
super(NAME_ARRAY, new Proxy(value, {
|
|
289
|
+
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, this.state, this.#size) : Reflect.get(target, property),
|
|
290
|
+
set: (target, property, value$1) => setValueInProxy({
|
|
291
|
+
property,
|
|
292
|
+
target,
|
|
293
|
+
value: value$1,
|
|
294
|
+
isArray: true,
|
|
295
|
+
state: this.state,
|
|
296
|
+
length: this.#size
|
|
297
|
+
})
|
|
298
|
+
}), options);
|
|
299
|
+
this.#size.set(value.length);
|
|
300
|
+
}
|
|
301
|
+
clear() {
|
|
302
|
+
this.length = 0;
|
|
303
|
+
}
|
|
304
|
+
filter(callback) {
|
|
305
|
+
return computed(() => this.get().filter(callback));
|
|
306
|
+
}
|
|
307
|
+
get(first) {
|
|
308
|
+
if (typeof first === "number") return getReactiveValueInProxy(this, this.#indiced, first, true).get();
|
|
309
|
+
return first === "length" ? this.length : getValue$1(this.state);
|
|
310
|
+
}
|
|
311
|
+
map(callback) {
|
|
312
|
+
return computed(() => this.get().map(callback));
|
|
313
|
+
}
|
|
314
|
+
notify() {
|
|
315
|
+
emityProxyValues(this.state, this.#indiced);
|
|
316
|
+
}
|
|
317
|
+
peek(value) {
|
|
318
|
+
if (value === "length") return this.#size.peek();
|
|
319
|
+
return typeof value === "number" ? this.state.value.at(value) : [...this.state.value];
|
|
320
|
+
}
|
|
321
|
+
pop() {
|
|
322
|
+
return this.state.value.pop();
|
|
323
|
+
}
|
|
324
|
+
push(...items) {
|
|
325
|
+
return this.state.value.push(...items);
|
|
326
|
+
}
|
|
327
|
+
set(first, second) {
|
|
328
|
+
if (first == null || Array.isArray(first)) this.state.value.splice(0, this.state.value.length, ...first ?? []);
|
|
329
|
+
else if (first === "length") this.length = second;
|
|
330
|
+
else if (typeof first === "number" && !Number.isNaN(first)) setAtIndex(this.state.value, first, second);
|
|
331
|
+
}
|
|
332
|
+
shift() {
|
|
333
|
+
return this.state.value.shift();
|
|
334
|
+
}
|
|
335
|
+
splice(from, to, ...items) {
|
|
336
|
+
return this.state.value.splice(from, to ?? this.state.value.length, ...items);
|
|
337
|
+
}
|
|
338
|
+
subscribe(first, second) {
|
|
339
|
+
if (typeof first === "number" && typeof second === "function") return getReactiveValueInProxy(this, this.#indiced, first, true).subscribe(second);
|
|
340
|
+
return typeof first === "function" ? subscribe(this.state, first) : noop$1;
|
|
341
|
+
}
|
|
342
|
+
unshift(...items) {
|
|
343
|
+
return this.state.value.unshift(...items);
|
|
344
|
+
}
|
|
345
|
+
update(callback) {
|
|
346
|
+
const updated = callback(this.state.value);
|
|
347
|
+
if (updated == null || Array.isArray(updated)) this.set(updated);
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
function array(value, options) {
|
|
351
|
+
return new ReactiveArray(Array.isArray(value) ? value : [], options);
|
|
352
|
+
}
|
|
353
|
+
function updateArray(type, array$1, state, length) {
|
|
354
|
+
const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
|
|
355
|
+
const previousArray = affectsLength ? [] : [...array$1];
|
|
356
|
+
const previousLength = array$1.length;
|
|
357
|
+
return (...args) => {
|
|
358
|
+
const result = array$1[type](...args);
|
|
359
|
+
if (affectsLength ? array$1.length !== previousLength : !equalArrays(state, previousArray, array$1)) {
|
|
360
|
+
emitValue(state);
|
|
361
|
+
length.set(array$1.length);
|
|
362
|
+
}
|
|
363
|
+
return result;
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
function setAtIndex(array$1, index, value) {
|
|
367
|
+
const actual = index < 0 ? array$1.length + index : index;
|
|
368
|
+
if (actual > -1) array$1[actual] = value;
|
|
369
|
+
}
|
|
370
|
+
//#endregion
|
|
371
|
+
//#region node_modules/@oscarpalmer/mora/node_modules/@oscarpalmer/atoms/dist/internal/is.js
|
|
372
|
+
function isKey(value) {
|
|
373
|
+
return typeof value === "number" || typeof value === "string";
|
|
374
|
+
}
|
|
375
|
+
function isPlainObject$1(value) {
|
|
376
|
+
if (value === null || typeof value !== "object") return false;
|
|
377
|
+
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
378
|
+
const prototype = Object.getPrototypeOf(value);
|
|
379
|
+
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
380
|
+
}
|
|
381
|
+
//#endregion
|
|
382
|
+
//#region node_modules/@oscarpalmer/mora/dist/value/store.js
|
|
383
|
+
var Store = class extends Reactive {
|
|
384
|
+
#keyed = /* @__PURE__ */ new Map();
|
|
385
|
+
constructor(value, options) {
|
|
386
|
+
super(NAME_STORE, new Proxy(value, { set: (target, property, value$1) => setValueInProxy({
|
|
387
|
+
target,
|
|
388
|
+
property,
|
|
389
|
+
value: value$1,
|
|
390
|
+
isArray: false,
|
|
391
|
+
state: this.state
|
|
392
|
+
}) }), options);
|
|
393
|
+
}
|
|
394
|
+
get(key) {
|
|
395
|
+
return isKey(key) ? getReactiveValueInProxy(this, this.#keyed, key, false).get() : getValue$1(this.state);
|
|
396
|
+
}
|
|
397
|
+
notify() {
|
|
398
|
+
emityProxyValues(this.state, this.#keyed);
|
|
399
|
+
}
|
|
400
|
+
peek(key) {
|
|
401
|
+
return isKey(key) ? this.state.value[key] : { ...this.state.value };
|
|
402
|
+
}
|
|
403
|
+
set(first, second) {
|
|
404
|
+
if (isKey(first)) this.state.value[first] = second;
|
|
405
|
+
else if (first == null || isPlainObject$1(first)) setProxyValue(this.state.value, first ?? {});
|
|
406
|
+
}
|
|
407
|
+
subscribe(first, second) {
|
|
408
|
+
if (isKey(first) && typeof second === "function") return getReactiveValueInProxy(this, this.#keyed, first, false).subscribe(second);
|
|
409
|
+
return typeof first === "function" ? subscribe(this.state, first) : noop$1;
|
|
410
|
+
}
|
|
411
|
+
update(callback) {
|
|
412
|
+
const updated = callback({ ...this.state.value });
|
|
413
|
+
if (updated == null || isPlainObject$1(updated)) setProxyValue(this.state.value, updated ?? {});
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
function store(value, options) {
|
|
417
|
+
return new Store(isPlainObject$1(value) ? value : {}, options);
|
|
418
|
+
}
|
|
419
|
+
//#endregion
|
|
420
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
|
|
421
|
+
/**
|
|
422
|
+
* Is the value a plain object?
|
|
423
|
+
* @param value Value to check
|
|
424
|
+
* @returns `true` if the value is a plain object, otherwise `false`
|
|
425
|
+
*/
|
|
426
|
+
function isPlainObject(value) {
|
|
427
|
+
if (value === null || typeof value !== "object") return false;
|
|
428
|
+
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
429
|
+
const prototype = Object.getPrototypeOf(value);
|
|
430
|
+
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
431
|
+
}
|
|
432
|
+
//#endregion
|
|
433
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/string.mjs
|
|
434
|
+
/**
|
|
435
|
+
* Get the string value from any value
|
|
436
|
+
* @param value Original value
|
|
437
|
+
* @returns String representation of the value
|
|
438
|
+
*/
|
|
439
|
+
function getString(value) {
|
|
440
|
+
if (typeof value === "string") return value;
|
|
441
|
+
if (value == null) return "";
|
|
442
|
+
if (typeof value === "function") return getString(value());
|
|
443
|
+
if (typeof value !== "object") return String(value);
|
|
444
|
+
const asString = String(value.valueOf?.() ?? value);
|
|
445
|
+
return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
|
|
446
|
+
}
|
|
447
|
+
//#endregion
|
|
448
|
+
//#region node_modules/@oscarpalmer/atoms/dist/is.mjs
|
|
449
|
+
/**
|
|
450
|
+
* Is the value `undefined`, `null`, or a whitespace-only string?
|
|
451
|
+
* @param value Value to check
|
|
452
|
+
* @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
|
|
453
|
+
*/
|
|
454
|
+
function isNullableOrWhitespace(value) {
|
|
455
|
+
return value == null || EXPRESSION_WHITESPACE$1.test(getString(value));
|
|
456
|
+
}
|
|
457
|
+
const EXPRESSION_WHITESPACE$1 = /^\s*$/;
|
|
458
|
+
//#endregion
|
|
459
|
+
//#region node_modules/@oscarpalmer/toretto/dist/internal/is.mjs
|
|
460
|
+
/**
|
|
461
|
+
* Is the value an event target?
|
|
462
|
+
* @param value Value to check
|
|
463
|
+
* @returns `true` if it's an event target, otherwise `false`
|
|
464
|
+
*/
|
|
465
|
+
function isEventTarget(value) {
|
|
466
|
+
return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Is the value an HTML or SVG element?
|
|
470
|
+
* @param value Value to check
|
|
471
|
+
* @returns `true` if it's an HTML or SVG element, otherwise `false`
|
|
472
|
+
*/
|
|
473
|
+
function isHTMLOrSVGElement(value) {
|
|
474
|
+
return value instanceof HTMLElement || value instanceof SVGElement;
|
|
475
|
+
}
|
|
476
|
+
//#endregion
|
|
477
|
+
//#region node_modules/@oscarpalmer/toretto/dist/is.mjs
|
|
478
|
+
/**
|
|
479
|
+
* Is the value a child node?
|
|
480
|
+
* @param value Value to check
|
|
481
|
+
* @returns `true` if it's a child node, otherwise `false`
|
|
482
|
+
*/
|
|
483
|
+
function isChildNode(value) {
|
|
484
|
+
return value instanceof Node && CHILD_NODE_TYPES.has(value.nodeType);
|
|
485
|
+
}
|
|
486
|
+
const CHILD_NODE_TYPES = new Set([
|
|
487
|
+
Node.ELEMENT_NODE,
|
|
488
|
+
Node.TEXT_NODE,
|
|
489
|
+
Node.PROCESSING_INSTRUCTION_NODE,
|
|
490
|
+
Node.COMMENT_NODE,
|
|
491
|
+
Node.DOCUMENT_TYPE_NODE
|
|
492
|
+
]);
|
|
493
|
+
//#endregion
|
|
494
|
+
//#region node_modules/@oscarpalmer/toretto/dist/internal/element-value.mjs
|
|
495
|
+
function setElementValue(element, first, second, third, callback) {
|
|
496
|
+
if (!isHTMLOrSVGElement(element)) return;
|
|
497
|
+
if (typeof first === "string") setElementValues(element, first, second, third, callback);
|
|
498
|
+
else if (isAttribute(first)) setElementValues(element, first.name, first.value, third, callback);
|
|
499
|
+
}
|
|
500
|
+
function setElementValues(element, first, second, third, callback) {
|
|
501
|
+
if (!isHTMLOrSVGElement(element)) return;
|
|
502
|
+
if (typeof first === "string") {
|
|
503
|
+
callback(element, first, second, third);
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
const isArray = Array.isArray(first);
|
|
507
|
+
if (!isArray && !(typeof first === "object" && first !== null)) return;
|
|
508
|
+
const entries = isArray ? first : Object.entries(first).map(([name, value]) => ({
|
|
509
|
+
name,
|
|
510
|
+
value
|
|
511
|
+
}));
|
|
512
|
+
const { length } = entries;
|
|
513
|
+
for (let index = 0; index < length; index += 1) {
|
|
514
|
+
const entry = entries[index];
|
|
515
|
+
if (typeof entry === "object" && typeof entry?.name === "string") callback(element, entry.name, entry.value, third);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
function updateElementValue(element, key, value, set, remove, isBoolean, json) {
|
|
519
|
+
if (isBoolean ? value == null : isNullableOrWhitespace(value)) remove.call(element, key);
|
|
520
|
+
else set.call(element, key, json ? JSON.stringify(value) : String(value));
|
|
521
|
+
}
|
|
522
|
+
//#endregion
|
|
523
|
+
//#region node_modules/@oscarpalmer/toretto/dist/internal/attribute.mjs
|
|
524
|
+
function badAttributeHandler(name, value) {
|
|
525
|
+
if (typeof name !== "string" || name.trim().length === 0 || typeof value !== "string") return true;
|
|
526
|
+
if (EXPRESSION_CLOBBERED_NAME.test(name) && (value in document || value in formElement) || EXPRESSION_EVENT_NAME$1.test(name)) return true;
|
|
527
|
+
if (EXPRESSION_SKIP_NAME.test(name) || EXPRESSION_URI_VALUE.test(value) || isValidSourceAttribute(name, value)) return false;
|
|
528
|
+
return EXPRESSION_DATA_OR_SCRIPT.test(value);
|
|
529
|
+
}
|
|
530
|
+
function booleanAttributeHandler(name, value) {
|
|
531
|
+
if (typeof name !== "string" || name.trim().length === 0 || typeof value !== "string") return true;
|
|
532
|
+
const normalizedName = name.toLowerCase();
|
|
533
|
+
if (!booleanAttributesSet.has(normalizedName)) return false;
|
|
534
|
+
const normalized = value.toLowerCase();
|
|
535
|
+
return !(normalized.length === 0 || normalized === normalizedName);
|
|
536
|
+
}
|
|
537
|
+
function decodeAttribute(value) {
|
|
538
|
+
textArea ??= document.createElement("textarea");
|
|
539
|
+
textArea.innerHTML = value;
|
|
540
|
+
return decodeURIComponent(textArea.value);
|
|
541
|
+
}
|
|
542
|
+
function handleAttribute(callback, decode, first, second) {
|
|
543
|
+
let name;
|
|
544
|
+
let value;
|
|
545
|
+
if (isAttribute(first)) {
|
|
546
|
+
name = first.name;
|
|
547
|
+
value = String(first.value);
|
|
548
|
+
} else if (typeof first === "string" && typeof second === "string") {
|
|
549
|
+
name = first;
|
|
550
|
+
value = second;
|
|
551
|
+
}
|
|
552
|
+
if (decode && value != null) value = decodeAttribute(value);
|
|
553
|
+
return callback(name, value?.replace(EXPRESSION_WHITESPACE, ""));
|
|
554
|
+
}
|
|
555
|
+
function isAttribute(value) {
|
|
556
|
+
return value instanceof Attr || isPlainObject(value) && typeof value.name === "string" && "value" in value;
|
|
557
|
+
}
|
|
558
|
+
function _isBadAttribute(first, second, decode) {
|
|
559
|
+
return handleAttribute(badAttributeHandler, decode, first, second);
|
|
560
|
+
}
|
|
561
|
+
function _isBooleanAttribute(first, decode) {
|
|
562
|
+
return handleAttribute((name) => booleanAttributesSet.has(name?.toLowerCase()), decode, first, "");
|
|
563
|
+
}
|
|
564
|
+
function _isEmptyNonBooleanAttribute(first, second, decode) {
|
|
565
|
+
return handleAttribute((name, value) => name != null && value != null && !booleanAttributesSet.has(name) && value.trim().length === 0, decode, first, second);
|
|
566
|
+
}
|
|
567
|
+
function _isInvalidBooleanAttribute(first, second, decode) {
|
|
568
|
+
return handleAttribute(booleanAttributeHandler, decode, first, second);
|
|
569
|
+
}
|
|
570
|
+
function isValidSourceAttribute(name, value) {
|
|
571
|
+
return EXPRESSION_SOURCE_NAME.test(name) && EXPRESSION_SOURCE_VALUE.test(value);
|
|
572
|
+
}
|
|
573
|
+
function updateAttribute(element, name, value, dispatch) {
|
|
574
|
+
const normalizedName = name.toLowerCase();
|
|
575
|
+
const isBoolean = booleanAttributesSet.has(normalizedName);
|
|
576
|
+
const next = isBoolean ? value === true || typeof value === "string" && (value === "" || value.toLowerCase() === normalizedName) : value == null ? "" : value;
|
|
577
|
+
if (name in element) updateProperty$1(element, normalizedName, next, dispatch);
|
|
578
|
+
updateElementValue(element, name, isBoolean ? next ? "" : null : value, element.setAttribute, element.removeAttribute, isBoolean, false);
|
|
579
|
+
}
|
|
580
|
+
function updateProperty$1(element, name, value, dispatch) {
|
|
581
|
+
if (Object.is(element[name], value)) return;
|
|
582
|
+
element[name] = value;
|
|
583
|
+
const event = dispatch !== false && elementEvents[element.tagName]?.[name];
|
|
584
|
+
if (typeof event === "string") element.dispatchEvent(new Event(event, { bubbles: true }));
|
|
585
|
+
}
|
|
586
|
+
const EXPRESSION_CLOBBERED_NAME = /^(id|name)$/i;
|
|
587
|
+
const EXPRESSION_DATA_OR_SCRIPT = /^(?:data|\w+script):/i;
|
|
588
|
+
const EXPRESSION_EVENT_NAME$1 = /^on/i;
|
|
589
|
+
const EXPRESSION_SKIP_NAME = /^(aria-[-\w]+|data-[-\w.\u00B7-\uFFFF]+)$/i;
|
|
590
|
+
const EXPRESSION_SOURCE_NAME = /^src$/i;
|
|
591
|
+
const EXPRESSION_SOURCE_VALUE = /^data:/i;
|
|
592
|
+
const EXPRESSION_URI_VALUE = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i;
|
|
593
|
+
const EXPRESSION_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g;
|
|
594
|
+
/**
|
|
595
|
+
* List of boolean attributes
|
|
596
|
+
*/
|
|
597
|
+
const booleanAttributes = Object.freeze([
|
|
598
|
+
"async",
|
|
599
|
+
"autofocus",
|
|
600
|
+
"autoplay",
|
|
601
|
+
"checked",
|
|
602
|
+
"controls",
|
|
603
|
+
"default",
|
|
604
|
+
"defer",
|
|
605
|
+
"disabled",
|
|
606
|
+
"formnovalidate",
|
|
607
|
+
"hidden",
|
|
608
|
+
"inert",
|
|
609
|
+
"ismap",
|
|
610
|
+
"itemscope",
|
|
611
|
+
"loop",
|
|
612
|
+
"multiple",
|
|
613
|
+
"muted",
|
|
614
|
+
"nomodule",
|
|
615
|
+
"novalidate",
|
|
616
|
+
"open",
|
|
617
|
+
"playsinline",
|
|
618
|
+
"readonly",
|
|
619
|
+
"required",
|
|
620
|
+
"reversed",
|
|
621
|
+
"selected"
|
|
622
|
+
]);
|
|
623
|
+
const booleanAttributesSet = new Set(booleanAttributes);
|
|
624
|
+
const elementEvents = {
|
|
625
|
+
DETAILS: { open: "toggle" },
|
|
626
|
+
INPUT: {
|
|
627
|
+
checked: "change",
|
|
628
|
+
value: "input"
|
|
629
|
+
},
|
|
630
|
+
SELECT: { value: "change" },
|
|
631
|
+
TEXTAREA: { value: "input" }
|
|
632
|
+
};
|
|
633
|
+
const formElement = document.createElement("form");
|
|
634
|
+
let textArea;
|
|
635
|
+
//#endregion
|
|
636
|
+
//#region node_modules/@oscarpalmer/toretto/dist/attribute/set.mjs
|
|
637
|
+
function setAttribute$1(element, first, second, third) {
|
|
638
|
+
setElementValue(element, first, second, third, updateAttribute);
|
|
639
|
+
}
|
|
640
|
+
//#endregion
|
|
641
|
+
//#region node_modules/@oscarpalmer/toretto/dist/html/sanitize.mjs
|
|
642
|
+
function handleElement(element, depth) {
|
|
643
|
+
if (depth === 0) {
|
|
644
|
+
const removable = element.querySelectorAll(REMOVE_SELECTOR);
|
|
645
|
+
for (const item of removable) item.remove();
|
|
646
|
+
}
|
|
647
|
+
sanitizeAttributes(element, [...element.attributes]);
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Is the element clobbered?
|
|
651
|
+
*
|
|
652
|
+
* Thanks, DOMPurify _(https://github.com/cure53/DOMPurify)_
|
|
653
|
+
*/
|
|
654
|
+
function isClobbered(value) {
|
|
655
|
+
return value instanceof HTMLFormElement && (typeof value.nodeName !== "string" || typeof value.textContent !== "string" || typeof value.removeChild !== "function" || !(value.attributes instanceof NamedNodeMap) || typeof value.removeAttribute !== "function" || typeof value.setAttribute !== "function" || typeof value.namespaceURI !== "string" || typeof value.insertBefore !== "function" || typeof value.hasChildNodes !== "function");
|
|
656
|
+
}
|
|
657
|
+
function removeNode(node) {
|
|
658
|
+
if (typeof node.remove === "function") node.remove();
|
|
659
|
+
}
|
|
660
|
+
function sanitizeAttributes(element, attributes) {
|
|
661
|
+
const { length } = attributes;
|
|
662
|
+
for (let index = 0; index < length; index += 1) {
|
|
663
|
+
const { name, value } = attributes[index];
|
|
664
|
+
if (_isBadAttribute(name, value, false) || _isEmptyNonBooleanAttribute(name, value, false)) element.removeAttribute(name);
|
|
665
|
+
else if (_isInvalidBooleanAttribute(name, value, false)) setAttribute$1(element, name, true);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
function sanitizeNodes(nodes, depth) {
|
|
669
|
+
const actual = nodes.filter((node) => node instanceof Node);
|
|
670
|
+
let { length } = nodes;
|
|
671
|
+
for (let index = 0; index < length; index += 1) {
|
|
672
|
+
const node = actual[index];
|
|
673
|
+
let remove = isClobbered(node);
|
|
674
|
+
if (!remove) switch (node.nodeType) {
|
|
675
|
+
case Node.ELEMENT_NODE:
|
|
676
|
+
handleElement(node, depth);
|
|
677
|
+
break;
|
|
678
|
+
case Node.COMMENT_NODE:
|
|
679
|
+
remove = COMMENT_HARMFUL.test(node.data);
|
|
680
|
+
break;
|
|
681
|
+
case Node.DOCUMENT_TYPE_NODE:
|
|
682
|
+
case Node.PROCESSING_INSTRUCTION_NODE:
|
|
683
|
+
remove = true;
|
|
684
|
+
break;
|
|
685
|
+
}
|
|
686
|
+
if (remove) {
|
|
687
|
+
removeNode(node);
|
|
688
|
+
actual.splice(index, 1);
|
|
689
|
+
index -= 1;
|
|
690
|
+
length -= 1;
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
if (node.hasChildNodes()) sanitizeNodes([...node.childNodes], depth + 1);
|
|
694
|
+
}
|
|
695
|
+
return nodes;
|
|
696
|
+
}
|
|
697
|
+
const COMMENT_HARMFUL = /<[/\w]/g;
|
|
698
|
+
const REMOVE_SELECTOR = "script, toretto-temporary";
|
|
699
|
+
//#endregion
|
|
700
|
+
//#region node_modules/@oscarpalmer/toretto/dist/html/index.mjs
|
|
701
|
+
function createHtml(value) {
|
|
702
|
+
const parsed = getParser().parseFromString(getHtml(value), PARSE_TYPE_HTML);
|
|
703
|
+
parsed.body.normalize();
|
|
704
|
+
sanitizeNodes([parsed.body], 0);
|
|
705
|
+
return parsed.body.innerHTML;
|
|
706
|
+
}
|
|
707
|
+
function createTemplate(value, options) {
|
|
708
|
+
const template = document.createElement(TEMPLATE_TAG);
|
|
709
|
+
template.innerHTML = createHtml(value);
|
|
710
|
+
if (typeof value === "string" && options.cache) templates[value] = template;
|
|
711
|
+
return template;
|
|
712
|
+
}
|
|
713
|
+
function getHtml(value) {
|
|
714
|
+
return `${TEMPORARY_ELEMENT}${typeof value === "string" ? value : value.innerHTML}${TEMPORARY_ELEMENT}`;
|
|
715
|
+
}
|
|
716
|
+
function getNodes(value, options) {
|
|
717
|
+
if (typeof value !== "string" && !(value instanceof HTMLTemplateElement)) return [];
|
|
718
|
+
const template = getTemplate(value, options);
|
|
719
|
+
return template == null ? [] : [...template.content.cloneNode(true).childNodes];
|
|
720
|
+
}
|
|
721
|
+
function getOptions$1(input) {
|
|
722
|
+
const options = isPlainObject(input) ? input : {};
|
|
723
|
+
options.cache = typeof options.cache === "boolean" ? options.cache : true;
|
|
724
|
+
return options;
|
|
725
|
+
}
|
|
726
|
+
function getParser() {
|
|
727
|
+
parser ??= new DOMParser();
|
|
728
|
+
return parser;
|
|
729
|
+
}
|
|
730
|
+
function getTemplate(value, options) {
|
|
731
|
+
if (value instanceof HTMLTemplateElement) return createTemplate(value, options);
|
|
732
|
+
if (value.trim().length === 0) return;
|
|
733
|
+
let template = templates[value];
|
|
734
|
+
if (template != null) return template;
|
|
735
|
+
const element = EXPRESSION_ID.test(value) ? document.querySelector(`#${value}`) : null;
|
|
736
|
+
return createTemplate(element instanceof HTMLTemplateElement ? element : value, options);
|
|
737
|
+
}
|
|
738
|
+
const html$1 = ((value, options) => {
|
|
739
|
+
return getNodes(value, getOptions$1(options));
|
|
740
|
+
});
|
|
741
|
+
html$1.clear = () => {
|
|
742
|
+
templates = {};
|
|
743
|
+
};
|
|
744
|
+
html$1.remove = (template) => {
|
|
745
|
+
if (typeof template !== "string" || templates[template] == null) return;
|
|
746
|
+
const keys = Object.keys(templates);
|
|
747
|
+
const { length } = keys;
|
|
748
|
+
const updated = {};
|
|
749
|
+
for (let index = 0; index < length; index += 1) {
|
|
750
|
+
const key = keys[index];
|
|
751
|
+
if (key !== template) updated[key] = templates[key];
|
|
752
|
+
}
|
|
753
|
+
templates = updated;
|
|
754
|
+
};
|
|
755
|
+
const EXPRESSION_ID = /^[a-z][\w-]*$/i;
|
|
756
|
+
const PARSE_TYPE_HTML = "text/html";
|
|
757
|
+
const TEMPLATE_TAG = "template";
|
|
758
|
+
const TEMPORARY_ELEMENT = "<toretto-temporary></toretto-temporary>";
|
|
759
|
+
let parser;
|
|
760
|
+
let templates = {};
|
|
761
|
+
//#endregion
|
|
762
|
+
//#region src/constants.ts
|
|
763
|
+
const EVENT_DEFAULTS = {
|
|
764
|
+
A: "click",
|
|
765
|
+
BUTTON: "click",
|
|
766
|
+
DETAILS: "toggle",
|
|
767
|
+
FORM: "submit",
|
|
768
|
+
SELECT: "change",
|
|
769
|
+
TEXTAREA: "input"
|
|
770
|
+
};
|
|
771
|
+
const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?\w+)="<!--abydon.(\d+)-->"/g;
|
|
772
|
+
const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX = /^_/;
|
|
773
|
+
const EXPRESSION_ABYDON_CONTENT = /^@?abydon\.(\d+)@?$/;
|
|
774
|
+
const EXPRESSION_ATTRIBUTE_CLASS = /^class\./;
|
|
775
|
+
const EXPRESSION_ATTRIBUTE_STYLE_FULL = /^style\.([\w-]+)(?:\.([\w-]+))?$/;
|
|
776
|
+
const EXPRESSION_ATTRIBUTE_STYLE_PREFIX = /^style\./;
|
|
777
|
+
const EXPRESSION_EVENT_CHANGE_TYPES = /^(checkbox|radio)$/;
|
|
778
|
+
const EXPRESSION_EVENT_NAME = /^@([\w-]+)(?::([a-z:]+))?$/i;
|
|
779
|
+
const EXPRESSION_EVENT_OPTIONS_ACTIVE = /^a(ctive)$/i;
|
|
780
|
+
const EXPRESSION_EVENT_OPTIONS_CAPTURE = /^c(apture)$/i;
|
|
781
|
+
const EXPRESSION_EVENT_OPTIONS_ONCE = /^o(nce)$/i;
|
|
782
|
+
const EXPRESSION_EVENT_PREFIX = /^@/;
|
|
783
|
+
const EXPRESSION_PERIOD = /\./;
|
|
784
|
+
const NAME_FRAGMENT = "$fragment";
|
|
785
|
+
const NAME_FRAGMENTS = "$fragments";
|
|
786
|
+
//#endregion
|
|
787
|
+
//#region src/helpers/index.ts
|
|
788
|
+
function compareArrays(first, second) {
|
|
789
|
+
const firstIsLarger = first.length > second.length;
|
|
790
|
+
const from = firstIsLarger ? first : second;
|
|
791
|
+
const to = firstIsLarger ? second : first;
|
|
792
|
+
if (!from.filter((key) => to.includes(key)).every((key, index) => to[index] === key)) return COMPARISON_DISSIMILAR;
|
|
793
|
+
return firstIsLarger ? COMPARISON_REMOVED : COMPARISON_ADDED;
|
|
794
|
+
}
|
|
795
|
+
function isFragment(value) {
|
|
796
|
+
return isNamed(value, NAME_FRAGMENT);
|
|
797
|
+
}
|
|
798
|
+
function isFragments(value) {
|
|
799
|
+
return isNamed(value, NAME_FRAGMENTS);
|
|
800
|
+
}
|
|
801
|
+
function isNamed(value, name) {
|
|
802
|
+
return typeof value === "object" && value != null && name in value && value[name] === true;
|
|
803
|
+
}
|
|
804
|
+
const COMPARISON_ADDED = "added";
|
|
805
|
+
const COMPARISON_DISSIMILAR = "dissimilar";
|
|
806
|
+
const COMPARISON_REMOVED = "removed";
|
|
807
|
+
//#endregion
|
|
808
|
+
//#region src/fragments.ts
|
|
809
|
+
var Fragments = class {
|
|
810
|
+
#state;
|
|
811
|
+
/**
|
|
812
|
+
* Fragment items
|
|
813
|
+
*/
|
|
814
|
+
get items() {
|
|
815
|
+
return this.#state.mapped;
|
|
816
|
+
}
|
|
817
|
+
constructor(items, identify, fragment) {
|
|
818
|
+
Object.defineProperty(this, NAME_FRAGMENTS, { value: true });
|
|
819
|
+
this.#state = {
|
|
820
|
+
fragment,
|
|
821
|
+
identify,
|
|
822
|
+
array: items,
|
|
823
|
+
instances: {},
|
|
824
|
+
mapped: array([]),
|
|
825
|
+
subscriber: void 0
|
|
826
|
+
};
|
|
827
|
+
states.set(this, this.#state);
|
|
828
|
+
initializeFragments(this.#state);
|
|
829
|
+
}
|
|
830
|
+
};
|
|
831
|
+
function handleFragments(item, remove) {
|
|
832
|
+
const state = isFragments(item) ? states.get(item) : item;
|
|
833
|
+
if (state != null) (remove ? removeFragments$1 : initializeFragments)(state);
|
|
834
|
+
}
|
|
835
|
+
function handleItems(state, items) {
|
|
836
|
+
const keys = /* @__PURE__ */ new Set();
|
|
837
|
+
const mapped = [];
|
|
838
|
+
const { length } = items;
|
|
839
|
+
for (let index = 0; index < length; index += 1) {
|
|
840
|
+
const item = items[index];
|
|
841
|
+
const identifier = state.identify(item);
|
|
842
|
+
if (identifier == null) throw new Error("Identifier cannot be null or undefined");
|
|
843
|
+
const key = getString(identifier);
|
|
844
|
+
if (keys.has(key)) throw new Error(`Duplicate identifier found: "${key}"`);
|
|
845
|
+
let instance = state.instances[key];
|
|
846
|
+
if (instance == null) {
|
|
847
|
+
instance = state.fragment(item);
|
|
848
|
+
if (!isFragment(instance)) throw new Error("Fragment function must return a Fragment instance");
|
|
849
|
+
}
|
|
850
|
+
instance.identify(key);
|
|
851
|
+
state.instances[key] = instance;
|
|
852
|
+
keys.add(key);
|
|
853
|
+
mapped.push(instance);
|
|
854
|
+
}
|
|
855
|
+
state.mapped.set(mapped);
|
|
856
|
+
updateFragments(state, keys);
|
|
857
|
+
}
|
|
858
|
+
function initializeFragments(state) {
|
|
859
|
+
state.subscriber ??= state.array.subscribe((items) => {
|
|
860
|
+
handleItems(state, items);
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
function removeFragments$1(state) {
|
|
864
|
+
state.subscriber?.();
|
|
865
|
+
updateFragments(state);
|
|
866
|
+
state.subscriber = void 0;
|
|
867
|
+
}
|
|
868
|
+
function updateFragments(state, active) {
|
|
869
|
+
const next = {};
|
|
870
|
+
const previous = { ...state.instances };
|
|
871
|
+
const keys = Object.keys(previous);
|
|
872
|
+
const { length } = keys;
|
|
873
|
+
for (let index = 0; index < length; index += 1) {
|
|
874
|
+
const key = keys[index];
|
|
875
|
+
if (active?.has(key)) next[key] = previous[key];
|
|
876
|
+
else previous[key].remove();
|
|
877
|
+
}
|
|
878
|
+
state.instances = next;
|
|
879
|
+
active?.clear();
|
|
880
|
+
}
|
|
881
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
882
|
+
//#endregion
|
|
883
|
+
//#region src/helpers/dom.ts
|
|
884
|
+
function createNodes(value) {
|
|
885
|
+
if (isFragment(value)) return value.get();
|
|
886
|
+
if (isChildNode(value)) return [value];
|
|
887
|
+
return [new Text(getString(value))];
|
|
888
|
+
}
|
|
889
|
+
function removeNodes(nodes) {
|
|
890
|
+
const { length } = nodes;
|
|
891
|
+
for (let index = 0; index < length; index += 1) nodes[index].remove();
|
|
892
|
+
}
|
|
893
|
+
function replaceNodes(from, to) {
|
|
894
|
+
from[0]?.replaceWith(...to);
|
|
895
|
+
const { length } = from;
|
|
896
|
+
for (let index = 1; index < length; index += 1) from[index].remove();
|
|
897
|
+
}
|
|
898
|
+
//#endregion
|
|
899
|
+
//#region node_modules/@oscarpalmer/toretto/dist/internal/get-value.mjs
|
|
900
|
+
function getBoolean(value, defaultValue) {
|
|
901
|
+
return typeof value === "boolean" ? value : defaultValue ?? false;
|
|
902
|
+
}
|
|
903
|
+
//#endregion
|
|
904
|
+
//#region node_modules/@oscarpalmer/toretto/dist/event/delegation.mjs
|
|
905
|
+
function addDelegatedHandler(doc, type, name, passive) {
|
|
906
|
+
if (DELEGATED.has(name)) return;
|
|
907
|
+
DELEGATED.add(name);
|
|
908
|
+
doc.addEventListener(type, passive ? HANDLER_PASSIVE : HANDLER_ACTIVE, { passive });
|
|
909
|
+
}
|
|
910
|
+
function addDelegatedListener(target, type, name, listener, passive) {
|
|
911
|
+
target[name] ??= /* @__PURE__ */ new Set();
|
|
912
|
+
target[name].add(listener);
|
|
913
|
+
addDelegatedHandler(document, type, name, passive);
|
|
914
|
+
return () => {
|
|
915
|
+
removeDelegatedListener(target, name, listener);
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
function delegatedEventHandler(event) {
|
|
919
|
+
const key = `${EVENT_PREFIX}${event.type}${this ? EVENT_SUFFIX_PASSIVE : EVENT_SUFFIX_ACTIVE}`;
|
|
920
|
+
const items = event.composedPath();
|
|
921
|
+
const { length } = items;
|
|
922
|
+
let target = items[0];
|
|
923
|
+
Object.defineProperties(event, {
|
|
924
|
+
currentTarget: {
|
|
925
|
+
configurable: true,
|
|
926
|
+
get() {
|
|
927
|
+
return target;
|
|
928
|
+
}
|
|
929
|
+
},
|
|
930
|
+
target: {
|
|
931
|
+
configurable: true,
|
|
932
|
+
value: target
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
for (let index = 0; index < length; index += 1) {
|
|
936
|
+
const item = items[index];
|
|
937
|
+
const listeners = item[key];
|
|
938
|
+
if (item.disabled || listeners == null) continue;
|
|
939
|
+
target = item;
|
|
940
|
+
for (const listener of listeners) {
|
|
941
|
+
listener.call(item, event);
|
|
942
|
+
if (event.cancelBubble) return;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
function getDelegatedName(target, type, options) {
|
|
947
|
+
if (isEventTarget(target) && EVENT_TYPES.has(type) && !options.capture && !options.once && options.signal == null) return `${EVENT_PREFIX}${type}${options.passive ? EVENT_SUFFIX_PASSIVE : EVENT_SUFFIX_ACTIVE}`;
|
|
948
|
+
}
|
|
949
|
+
function removeDelegatedListener(target, name, listener) {
|
|
950
|
+
const handlers = target[name];
|
|
951
|
+
if (handlers == null || !handlers.has(listener)) return false;
|
|
952
|
+
handlers.delete(listener);
|
|
953
|
+
if (handlers.size === 0) target[name] = void 0;
|
|
954
|
+
return true;
|
|
955
|
+
}
|
|
956
|
+
const DELEGATED = /* @__PURE__ */ new Set();
|
|
957
|
+
const EVENT_PREFIX = "@";
|
|
958
|
+
const EVENT_SUFFIX_ACTIVE = ":active";
|
|
959
|
+
const EVENT_SUFFIX_PASSIVE = ":passive";
|
|
960
|
+
const EVENT_TYPES = new Set([
|
|
961
|
+
"beforeinput",
|
|
962
|
+
"click",
|
|
963
|
+
"dblclick",
|
|
964
|
+
"contextmenu",
|
|
965
|
+
"focusin",
|
|
966
|
+
"focusout",
|
|
967
|
+
"input",
|
|
968
|
+
"keydown",
|
|
969
|
+
"keyup",
|
|
970
|
+
"mousedown",
|
|
971
|
+
"mousemove",
|
|
972
|
+
"mouseout",
|
|
973
|
+
"mouseover",
|
|
974
|
+
"mouseup",
|
|
975
|
+
"pointerdown",
|
|
976
|
+
"pointermove",
|
|
977
|
+
"pointerout",
|
|
978
|
+
"pointerover",
|
|
979
|
+
"pointerup",
|
|
980
|
+
"touchend",
|
|
981
|
+
"touchmove",
|
|
982
|
+
"touchstart"
|
|
983
|
+
]);
|
|
984
|
+
const HANDLER_ACTIVE = delegatedEventHandler.bind(false);
|
|
985
|
+
const HANDLER_PASSIVE = delegatedEventHandler.bind(true);
|
|
986
|
+
//#endregion
|
|
987
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/function/misc.mjs
|
|
988
|
+
/**
|
|
989
|
+
* A function that does nothing, which can be useful, I guess…
|
|
990
|
+
*/
|
|
991
|
+
function noop() {}
|
|
992
|
+
//#endregion
|
|
993
|
+
//#region node_modules/@oscarpalmer/toretto/dist/event/index.mjs
|
|
994
|
+
function createEventOptions(options) {
|
|
995
|
+
return {
|
|
996
|
+
capture: getBoolean(options?.capture),
|
|
997
|
+
once: getBoolean(options?.once),
|
|
998
|
+
passive: getBoolean(options?.passive, true),
|
|
999
|
+
signal: options?.signal instanceof AbortSignal ? options.signal : void 0
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
function on(target, type, listener, options) {
|
|
1003
|
+
if (!isEventTarget(target) || typeof type !== "string" || typeof listener !== "function") return noop;
|
|
1004
|
+
const extended = createEventOptions(options);
|
|
1005
|
+
const delegated = getDelegatedName(target, type, extended);
|
|
1006
|
+
if (delegated != null) return addDelegatedListener(target, type, delegated, listener, extended.passive);
|
|
1007
|
+
target.addEventListener(type, listener, extended);
|
|
1008
|
+
if (extended.once) return noop;
|
|
1009
|
+
return () => {
|
|
1010
|
+
target.removeEventListener(type, listener, extended);
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
//#endregion
|
|
1014
|
+
//#region src/node/event.ts
|
|
1015
|
+
function getOptions(options) {
|
|
1016
|
+
const parts = options.split(":");
|
|
1017
|
+
return {
|
|
1018
|
+
capture: parts.some((part) => EXPRESSION_EVENT_OPTIONS_CAPTURE.test(part)),
|
|
1019
|
+
once: parts.some((part) => EXPRESSION_EVENT_OPTIONS_ONCE.test(part)),
|
|
1020
|
+
passive: !parts.some((part) => EXPRESSION_EVENT_OPTIONS_ACTIVE.test(part))
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
function getType(element, type) {
|
|
1024
|
+
if (type !== "on") return type;
|
|
1025
|
+
if (element instanceof HTMLInputElement) {
|
|
1026
|
+
if (EXPRESSION_EVENT_CHANGE_TYPES.test(element.type)) return "change";
|
|
1027
|
+
return element.type === "submit" ? "submit" : "input";
|
|
1028
|
+
}
|
|
1029
|
+
return EVENT_DEFAULTS[element.tagName] ?? type;
|
|
1030
|
+
}
|
|
1031
|
+
function mapEvent(element, name, value) {
|
|
1032
|
+
const [, type, options] = EXPRESSION_EVENT_NAME.exec(name) ?? [];
|
|
1033
|
+
if (type != null && typeof value === "function") on(element, getType(element, type), value, getOptions(options ?? ""));
|
|
1034
|
+
}
|
|
1035
|
+
//#endregion
|
|
1036
|
+
//#region node_modules/@oscarpalmer/toretto/dist/attribute/index.mjs
|
|
1037
|
+
function isBooleanAttribute(first) {
|
|
1038
|
+
return _isBooleanAttribute(first, true);
|
|
1039
|
+
}
|
|
1040
|
+
//#endregion
|
|
1041
|
+
//#region src/node/attribute/value.ts
|
|
1042
|
+
function getCallback(element, name) {
|
|
1043
|
+
if (isBooleanAttribute(name) && name in element) return name === "checked" ? updateChecked : updateProperty;
|
|
1044
|
+
return name === "value" ? updateValue : setAttribute$1;
|
|
1045
|
+
}
|
|
1046
|
+
function setAttribute(data, element, name, value) {
|
|
1047
|
+
switch (true) {
|
|
1048
|
+
case EXPRESSION_ATTRIBUTE_CLASS.test(name):
|
|
1049
|
+
setClasses(data, element, name, value);
|
|
1050
|
+
return;
|
|
1051
|
+
case EXPRESSION_ATTRIBUTE_STYLE_PREFIX.test(name):
|
|
1052
|
+
setStyle(data, element, name, value);
|
|
1053
|
+
return;
|
|
1054
|
+
default:
|
|
1055
|
+
setValue(data, element, name, value);
|
|
1056
|
+
break;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
function setClasses(data, element, name, value) {
|
|
1060
|
+
function update(value) {
|
|
1061
|
+
if (value === true) element.classList.add(...classes);
|
|
1062
|
+
else element.classList.remove(...classes);
|
|
1063
|
+
}
|
|
1064
|
+
const classes = name.slice(6).split(".");
|
|
1065
|
+
if (isReactive(value)) data.mora.subscribers.add(value.subscribe(update));
|
|
1066
|
+
else update(value);
|
|
1067
|
+
}
|
|
1068
|
+
function setStyle(data, element, name, value) {
|
|
1069
|
+
const [, property, unit] = EXPRESSION_ATTRIBUTE_STYLE_FULL.exec(name) ?? [];
|
|
1070
|
+
if (property == null) return;
|
|
1071
|
+
function update(value) {
|
|
1072
|
+
if (value == null || value === false || value === true && unit == null) element.style.removeProperty(property);
|
|
1073
|
+
else element.style.setProperty(property, value === true ? unit : String(value));
|
|
1074
|
+
}
|
|
1075
|
+
if (isReactive(value)) data.mora.subscribers.add(value.subscribe(update));
|
|
1076
|
+
else update(value);
|
|
1077
|
+
}
|
|
1078
|
+
function setValue(data, element, name, value) {
|
|
1079
|
+
const callback = getCallback(element, name);
|
|
1080
|
+
if (isReactive(value)) data.mora.subscribers.add(value.subscribe((next) => {
|
|
1081
|
+
callback(element, name, next);
|
|
1082
|
+
}));
|
|
1083
|
+
else callback(element, name, value);
|
|
1084
|
+
}
|
|
1085
|
+
function updateChecked(element, name, value) {
|
|
1086
|
+
updateElement("change", "checked", element, name, value, value === true);
|
|
1087
|
+
}
|
|
1088
|
+
function updateElement(event, property, element, name, value, next) {
|
|
1089
|
+
if (!(property in element) || element[property] === next) return;
|
|
1090
|
+
setAttribute$1(element, name, value);
|
|
1091
|
+
if (element[property] === next) return;
|
|
1092
|
+
element[property] = next;
|
|
1093
|
+
element.dispatchEvent(new Event(event, { bubbles: true }));
|
|
1094
|
+
}
|
|
1095
|
+
function updateProperty(element, name, value) {
|
|
1096
|
+
setAttribute$1(element, name, value === true);
|
|
1097
|
+
}
|
|
1098
|
+
function updateValue(element, name, value) {
|
|
1099
|
+
updateElement(element instanceof HTMLSelectElement ? "change" : "input", "value", element, name, value, String(value));
|
|
1100
|
+
}
|
|
1101
|
+
//#endregion
|
|
1102
|
+
//#region src/node/attribute/index.ts
|
|
1103
|
+
function getValue(data, original) {
|
|
1104
|
+
const matches = EXPRESSION_ABYDON_CONTENT.exec(original ?? "");
|
|
1105
|
+
return matches == null ? original : data.values[+matches[1]];
|
|
1106
|
+
}
|
|
1107
|
+
function mapAttributes(data, element) {
|
|
1108
|
+
const attributes = [...element.attributes];
|
|
1109
|
+
const { length } = attributes;
|
|
1110
|
+
for (let index = 0; index < length; index += 1) {
|
|
1111
|
+
const { name, value } = attributes[index];
|
|
1112
|
+
const actualName = name.replace(EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, "");
|
|
1113
|
+
const actualValue = getValue(data, value);
|
|
1114
|
+
if (actualName !== name) element.removeAttribute(name);
|
|
1115
|
+
switch (true) {
|
|
1116
|
+
case EXPRESSION_EVENT_PREFIX.test(actualName):
|
|
1117
|
+
mapEvent(element, actualName, actualValue);
|
|
1118
|
+
break;
|
|
1119
|
+
case EXPRESSION_PERIOD.test(actualName):
|
|
1120
|
+
case typeof actualValue === "function":
|
|
1121
|
+
case isReactive(actualValue):
|
|
1122
|
+
mapValue$1(data, element, actualName, actualValue);
|
|
1123
|
+
break;
|
|
1124
|
+
default: break;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
function mapValue$1(data, element, name, value) {
|
|
1129
|
+
if (typeof value === "function") setComputedAttribute(data, element, name, value);
|
|
1130
|
+
else setAttribute(data, element, name, value);
|
|
1131
|
+
}
|
|
1132
|
+
function setComputedAttribute(data, element, name, callback) {
|
|
1133
|
+
const value = computed(callback);
|
|
1134
|
+
data.mora.values.add(value);
|
|
1135
|
+
setAttribute(data, element, name, value);
|
|
1136
|
+
}
|
|
1137
|
+
//#endregion
|
|
1138
|
+
//#region src/node/value.ts
|
|
1139
|
+
function addToArray(identifiers, items, nodes, added) {
|
|
1140
|
+
let position = nodes[0];
|
|
1141
|
+
const before = added && !identifiers.previous.has(items.templates[0].identifier);
|
|
1142
|
+
const next = items.next.flatMap((fragment) => fragment.get().flatMap((node) => ({
|
|
1143
|
+
identifier: fragment.identifier,
|
|
1144
|
+
value: node
|
|
1145
|
+
})));
|
|
1146
|
+
const { length } = next;
|
|
1147
|
+
for (let index = 0; index < length; index += 1) {
|
|
1148
|
+
const node = next[index];
|
|
1149
|
+
if (!(added && identifiers.previous.has(node.identifier))) if (index === 0 && before) position.before(node.value);
|
|
1150
|
+
else position.after(node.value);
|
|
1151
|
+
position = node.value;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
function handleArray(identifiers, items, nodes) {
|
|
1155
|
+
const next = items.templates.map((template) => items.fragments?.find((fragment) => fragment.identifier === template.identifier) ?? template);
|
|
1156
|
+
const comparison = compareArrays(items.fragments ?? [], items.templates);
|
|
1157
|
+
if (comparison !== "removed") addToArray(identifiers, {
|
|
1158
|
+
...items,
|
|
1159
|
+
next
|
|
1160
|
+
}, nodes, comparison === "added");
|
|
1161
|
+
const toRemove = items.fragments?.filter((fragment) => !identifiers.next.has(fragment.identifier)) ?? [];
|
|
1162
|
+
const { length } = toRemove;
|
|
1163
|
+
for (let index = 0; index < length; index += 1) toRemove[index].remove();
|
|
1164
|
+
return {
|
|
1165
|
+
fragments: next,
|
|
1166
|
+
nodes: next.flatMap((fragment) => fragment.get())
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
function removeFragments(fragments) {
|
|
1170
|
+
if (fragments != null) {
|
|
1171
|
+
const { length } = fragments;
|
|
1172
|
+
for (let index = 0; index < length; index += 1) fragments[index].remove();
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
function replaceText(item, comment, isNullable) {
|
|
1176
|
+
let to;
|
|
1177
|
+
if (isNullable) to = [comment];
|
|
1178
|
+
else to = item.text == null ? [] : [item.text];
|
|
1179
|
+
replaceNodes(item.nodes ?? [], to);
|
|
1180
|
+
}
|
|
1181
|
+
function setArray(item, comment, value) {
|
|
1182
|
+
if (value.length === 0) return { nodes: setText(item, comment, value) };
|
|
1183
|
+
let templates = value.filter((item) => isFragment(item) && item.identifier != null);
|
|
1184
|
+
const next = templates.map((fragment) => fragment.identifier);
|
|
1185
|
+
const previous = item.fragments?.map((fragment) => fragment.identifier) ?? [];
|
|
1186
|
+
if (new Set(next).size !== templates.length) templates = [];
|
|
1187
|
+
const noTemplates = templates.length === 0;
|
|
1188
|
+
if (noTemplates || item.nodes == null || previous.some((identifier) => identifier == null)) return {
|
|
1189
|
+
fragments: noTemplates ? void 0 : templates,
|
|
1190
|
+
nodes: setNodes(item, comment, noTemplates ? value.flatMap((item) => createNodes(item)) : templates.flatMap((template) => template.get()))
|
|
1191
|
+
};
|
|
1192
|
+
return handleArray({
|
|
1193
|
+
next: new Set(next),
|
|
1194
|
+
previous: new Set(previous)
|
|
1195
|
+
}, {
|
|
1196
|
+
templates,
|
|
1197
|
+
fragments: item.fragments ?? []
|
|
1198
|
+
}, item.nodes);
|
|
1199
|
+
}
|
|
1200
|
+
function setNodes(item, comment, next) {
|
|
1201
|
+
if (item.nodes == null) {
|
|
1202
|
+
if (comment.parentNode != null) replaceNodes([comment], next);
|
|
1203
|
+
else if (item.text?.parentNode != null) replaceNodes([item.text], next);
|
|
1204
|
+
} else replaceNodes(item.nodes, next);
|
|
1205
|
+
removeFragments(item.fragments);
|
|
1206
|
+
return next;
|
|
1207
|
+
}
|
|
1208
|
+
function setReactiveValue(data, comment, reactive) {
|
|
1209
|
+
let item = data.items.find((item) => item.nodes?.includes(comment));
|
|
1210
|
+
item ??= {};
|
|
1211
|
+
item.text = new Text();
|
|
1212
|
+
data.mora.subscribers.add(reactive.subscribe((value) => {
|
|
1213
|
+
if (Array.isArray(value)) setReactiveValueForArray(item, comment, value);
|
|
1214
|
+
else setReactiveValueForSingle(item, comment, value);
|
|
1215
|
+
item.nodes = [...item.nodes ?? [comment]];
|
|
1216
|
+
}));
|
|
1217
|
+
}
|
|
1218
|
+
function setReactiveValueForArray(item, comment, value) {
|
|
1219
|
+
const result = setArray(item, comment, value);
|
|
1220
|
+
item.fragments = typeof result === "boolean" ? void 0 : result?.fragments;
|
|
1221
|
+
if (typeof result === "boolean") if (result) item.nodes = item.text == null ? [] : [item.text];
|
|
1222
|
+
else item.nodes = void 0;
|
|
1223
|
+
else item.nodes = result?.nodes;
|
|
1224
|
+
}
|
|
1225
|
+
function setReactiveValueForSingle(item, comment, value) {
|
|
1226
|
+
const valueIsFragment = isFragment(value);
|
|
1227
|
+
item.fragments = valueIsFragment ? [value] : void 0;
|
|
1228
|
+
if (valueIsFragment || isChildNode(value)) item.nodes = setNodes(item, comment, createNodes(value));
|
|
1229
|
+
else item.nodes = setText(item, comment, value);
|
|
1230
|
+
}
|
|
1231
|
+
function setText(item, comment, value) {
|
|
1232
|
+
const isNullable = isNullableOrWhitespace(value);
|
|
1233
|
+
if (item.text != null) item.text.textContent = isNullable ? "" : getString(value);
|
|
1234
|
+
let result = false;
|
|
1235
|
+
if (item.nodes != null) {
|
|
1236
|
+
replaceText(item, comment, isNullable);
|
|
1237
|
+
result = !isNullable;
|
|
1238
|
+
} else if (isNullable && comment.parentNode == null) item.text?.replaceWith(comment);
|
|
1239
|
+
else if (!isNullable && item?.text?.parentNode == null) {
|
|
1240
|
+
if (item.text != null) comment.replaceWith(item.text);
|
|
1241
|
+
result = true;
|
|
1242
|
+
}
|
|
1243
|
+
removeFragments(item.fragments);
|
|
1244
|
+
if (result) return item.text == null ? [] : [item.text];
|
|
1245
|
+
}
|
|
1246
|
+
//#endregion
|
|
1247
|
+
//#region src/node/index.ts
|
|
1248
|
+
function mapNode(data, comment) {
|
|
1249
|
+
const matches = EXPRESSION_ABYDON_CONTENT.exec(comment.textContent ?? "");
|
|
1250
|
+
const value = matches == null ? null : data.values[+matches[1]];
|
|
1251
|
+
if (value != null) mapValue(data, comment, value);
|
|
1252
|
+
}
|
|
1253
|
+
function mapNodes(data, nodes) {
|
|
1254
|
+
const { length } = nodes;
|
|
1255
|
+
for (let index = 0; index < length; index += 1) {
|
|
1256
|
+
const node = nodes[index];
|
|
1257
|
+
if (node instanceof Comment) {
|
|
1258
|
+
mapNode(data, node);
|
|
1259
|
+
continue;
|
|
1260
|
+
}
|
|
1261
|
+
if (isHTMLOrSVGElement(node)) mapAttributes(data, node);
|
|
1262
|
+
if (node.hasChildNodes()) mapNodes(data, [...node.childNodes]);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
function mapValue(data, comment, value) {
|
|
1266
|
+
switch (true) {
|
|
1267
|
+
case typeof value === "function":
|
|
1268
|
+
setComputedValue(data, comment, value);
|
|
1269
|
+
break;
|
|
1270
|
+
case isFragments(value):
|
|
1271
|
+
handleFragments(value, false);
|
|
1272
|
+
setReactiveValue(data, comment, value.items);
|
|
1273
|
+
break;
|
|
1274
|
+
case isReactive(value):
|
|
1275
|
+
setReactiveValue(data, comment, value);
|
|
1276
|
+
break;
|
|
1277
|
+
default:
|
|
1278
|
+
replaceComment(data, comment, value);
|
|
1279
|
+
break;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
function replaceComment(data, comment, value) {
|
|
1283
|
+
const item = data.items.find((item) => item.nodes?.includes(comment));
|
|
1284
|
+
const nodes = createNodes(value);
|
|
1285
|
+
if (item != null) {
|
|
1286
|
+
item.fragments = isFragment(value) ? [value] : void 0;
|
|
1287
|
+
item.nodes = nodes;
|
|
1288
|
+
}
|
|
1289
|
+
comment.replaceWith(...nodes);
|
|
1290
|
+
}
|
|
1291
|
+
function setComputedValue(data, comment, callback) {
|
|
1292
|
+
const value = computed(callback);
|
|
1293
|
+
data.mora.values.add(value);
|
|
1294
|
+
setReactiveValue(data, comment, value);
|
|
1295
|
+
}
|
|
1296
|
+
//#endregion
|
|
1297
|
+
//#region src/parse.ts
|
|
1298
|
+
function handleExpression(data, prefix, expression) {
|
|
1299
|
+
if (Array.isArray(expression)) {
|
|
1300
|
+
const { length } = expression;
|
|
1301
|
+
let expressions = "";
|
|
1302
|
+
for (let index = 0; index < length; index += 1) expressions += handleExpression(data, "", expression[index]);
|
|
1303
|
+
return `${prefix}${expressions}`;
|
|
1304
|
+
}
|
|
1305
|
+
if (typeof expression === "function" || typeof expression === "object" && expression != null) return transformExpression(prefix, data.values.push(expression) - 1);
|
|
1306
|
+
return isNullableOrWhitespace(expression) ? prefix : `${prefix}${expression}`;
|
|
1307
|
+
}
|
|
1308
|
+
function parse(data) {
|
|
1309
|
+
if (data.template != null) return data.template;
|
|
1310
|
+
const { length } = data.strings;
|
|
1311
|
+
data.template = "";
|
|
1312
|
+
for (let index = 0; index < length; index += 1) data.template += handleExpression(data, data.strings[index], data.expressions[index]);
|
|
1313
|
+
data.template = data.template.replaceAll(EXPRESSION_ABYDON_ATTRIBUTE_FULL, transformAttribute);
|
|
1314
|
+
data.expressions = [];
|
|
1315
|
+
data.strings = [];
|
|
1316
|
+
return data.template;
|
|
1317
|
+
}
|
|
1318
|
+
function transformAttribute(_, name, index) {
|
|
1319
|
+
return `_${name}="@abydon.${index}@"`;
|
|
1320
|
+
}
|
|
1321
|
+
function transformExpression(prefix, index) {
|
|
1322
|
+
return `${prefix}<!--abydon.${index}-->`;
|
|
1323
|
+
}
|
|
1324
|
+
//#endregion
|
|
1325
|
+
//#region src/fragment.ts
|
|
1326
|
+
var Fragment = class {
|
|
1327
|
+
#data;
|
|
1328
|
+
#configuration = {
|
|
1329
|
+
identifier: void 0,
|
|
1330
|
+
cache: true
|
|
1331
|
+
};
|
|
1332
|
+
/**
|
|
1333
|
+
* Fragment identifier
|
|
1334
|
+
*/
|
|
1335
|
+
get identifier() {
|
|
1336
|
+
return this.#configuration.identifier;
|
|
1337
|
+
}
|
|
1338
|
+
constructor(strings, expressions) {
|
|
1339
|
+
Object.defineProperty(this, NAME_FRAGMENT, { value: true });
|
|
1340
|
+
this.#data = {
|
|
1341
|
+
expressions,
|
|
1342
|
+
strings,
|
|
1343
|
+
items: [],
|
|
1344
|
+
mora: {
|
|
1345
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
1346
|
+
values: /* @__PURE__ */ new Set()
|
|
1347
|
+
},
|
|
1348
|
+
values: []
|
|
1349
|
+
};
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1352
|
+
* Append the fragment to the given element
|
|
1353
|
+
* @param element Element to append to
|
|
1354
|
+
*/
|
|
1355
|
+
appendTo(element) {
|
|
1356
|
+
element.append(...this.get());
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* Configure the fragment
|
|
1360
|
+
* @param configuration Configuration options
|
|
1361
|
+
* @returns Fragment
|
|
1362
|
+
*/
|
|
1363
|
+
configure(configuration) {
|
|
1364
|
+
const actual = isPlainObject(configuration) ? configuration : {};
|
|
1365
|
+
if ("identifier" in actual) this.#configuration.identifier = actual.identifier;
|
|
1366
|
+
if (typeof actual.cache === "boolean") this.#configuration.cache = actual.cache;
|
|
1367
|
+
return this;
|
|
1368
|
+
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Get a list of the fragment's nodes
|
|
1371
|
+
* @returns List of nodes
|
|
1372
|
+
*/
|
|
1373
|
+
get() {
|
|
1374
|
+
const data = this.#data;
|
|
1375
|
+
if (data.items.length === 0) {
|
|
1376
|
+
const templated = html$1(parse(data), { cache: this.#configuration.cache });
|
|
1377
|
+
data.items.splice(0, data.items.length, ...templated.map((node) => ({ nodes: [node] })));
|
|
1378
|
+
mapNodes(data, data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes ?? []));
|
|
1379
|
+
}
|
|
1380
|
+
return data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes ?? []);
|
|
1381
|
+
}
|
|
1382
|
+
/**
|
|
1383
|
+
* Set an identifier for the fragment
|
|
1384
|
+
*
|
|
1385
|
+
* _An identifier can be used to uniquely identify a fragment,
|
|
1386
|
+
* which helps prevent re-rendering in certain scenarios._
|
|
1387
|
+
* @param identifier Identifier
|
|
1388
|
+
* @returns Fragment
|
|
1389
|
+
*/
|
|
1390
|
+
identify(identifier) {
|
|
1391
|
+
this.#configuration.identifier = identifier;
|
|
1392
|
+
return this;
|
|
1393
|
+
}
|
|
1394
|
+
/**
|
|
1395
|
+
* Remove the fragment from the DOM
|
|
1396
|
+
*/
|
|
1397
|
+
remove() {
|
|
1398
|
+
removeFragment(this.#data);
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
1401
|
+
function removeFragment(data) {
|
|
1402
|
+
removeMora(data);
|
|
1403
|
+
let { length } = data.items;
|
|
1404
|
+
for (let index = 0; index < length; index += 1) {
|
|
1405
|
+
const { fragments, nodes } = data.items[index];
|
|
1406
|
+
const fragmentsLength = fragments?.length ?? 0;
|
|
1407
|
+
for (let fragmentIndex = 0; fragmentIndex < fragmentsLength; fragmentIndex += 1) fragments?.[fragmentIndex]?.remove();
|
|
1408
|
+
removeNodes(nodes ?? []);
|
|
1409
|
+
}
|
|
1410
|
+
data.items.length = 0;
|
|
1411
|
+
length = data.values.length;
|
|
1412
|
+
for (let index = 0; index < length; index += 1) {
|
|
1413
|
+
const value = data.values[index];
|
|
1414
|
+
if (isFragments(value)) handleFragments(value, true);
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
function removeMora(data) {
|
|
1418
|
+
const unsubscribers = [...data.mora.subscribers];
|
|
1419
|
+
data.mora.subscribers.clear();
|
|
1420
|
+
data.mora.values.clear();
|
|
1421
|
+
for (const unsubscribe of unsubscribers) unsubscribe();
|
|
1422
|
+
}
|
|
1423
|
+
//#endregion
|
|
1424
|
+
//#region src/index.ts
|
|
1425
|
+
/**
|
|
1426
|
+
* Create Fragments from a reactive array
|
|
1427
|
+
* @param array Reactive array
|
|
1428
|
+
* @param identify Function to identify item
|
|
1429
|
+
* @param fragment Function to create fragment from item
|
|
1430
|
+
* @returns Fragments
|
|
1431
|
+
*/
|
|
1432
|
+
function fragments(array, identify, fragment) {
|
|
1433
|
+
return new Fragments(array, identify, fragment);
|
|
1434
|
+
}
|
|
1435
|
+
/**
|
|
1436
|
+
* Create Fragment from a template
|
|
1437
|
+
* @returns Fragment
|
|
1438
|
+
*/
|
|
1439
|
+
function html(template, ...values) {
|
|
1440
|
+
return new Fragment(template, values);
|
|
1441
|
+
}
|
|
1442
|
+
//#endregion
|
|
1443
|
+
export { array, computed, effect, fragments, html, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
|