@oscarpalmer/abydon 0.17.0 → 0.19.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 +277 -90
- package/dist/constants.d.mts +18 -1
- package/dist/constants.mjs +22 -5
- package/dist/fragments.mjs +4 -4
- package/dist/helpers/dom.d.mts +2 -1
- package/dist/helpers/dom.mjs +4 -1
- package/dist/helpers/index.d.mts +2 -1
- package/dist/helpers/index.mjs +3 -6
- package/dist/node/attribute/index.mjs +6 -1
- package/dist/node/attribute/value.mjs +3 -3
- package/dist/node/event.mjs +3 -3
- package/dist/node/value.mjs +2 -1
- package/package.json +3 -4
- package/src/constants.ts +38 -4
- package/src/fragment.ts +2 -2
- package/src/fragments.ts +10 -4
- package/src/helpers/dom.ts +10 -0
- package/src/helpers/index.ts +13 -10
- package/src/node/attribute/index.ts +11 -1
- package/src/node/attribute/value.ts +11 -6
- package/src/node/event.ts +9 -4
- package/src/node/value.ts +3 -2
package/dist/abydon.full.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region node_modules/@oscarpalmer/mora/dist/constants.
|
|
1
|
+
//#region node_modules/@oscarpalmer/mora/dist/constants.mjs
|
|
2
2
|
const ACTIVE = {};
|
|
3
3
|
const BATCH = {
|
|
4
4
|
depth: 0,
|
|
@@ -31,7 +31,7 @@ const NAME_ALL = new Set([
|
|
|
31
31
|
NAME_STORE
|
|
32
32
|
]);
|
|
33
33
|
//#endregion
|
|
34
|
-
//#region node_modules/@oscarpalmer/mora/dist/effect.
|
|
34
|
+
//#region node_modules/@oscarpalmer/mora/dist/effect.mjs
|
|
35
35
|
var Effect = class {
|
|
36
36
|
constructor(callback) {
|
|
37
37
|
Object.defineProperty(this, NAME_MORA, { value: NAME_EFFECT });
|
|
@@ -39,40 +39,70 @@ var Effect = class {
|
|
|
39
39
|
runEffect(this);
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
|
-
function runEffect(effect
|
|
42
|
+
function runEffect(effect) {
|
|
43
43
|
const previousEffect = ACTIVE.effect;
|
|
44
|
-
ACTIVE.effect = effect
|
|
44
|
+
ACTIVE.effect = effect;
|
|
45
45
|
try {
|
|
46
|
-
effect
|
|
46
|
+
effect.state.callback();
|
|
47
47
|
} finally {
|
|
48
48
|
ACTIVE.effect = previousEffect;
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Create an effect
|
|
53
|
+
* @param callback Callback for handling signal effects
|
|
54
|
+
* @returns Effect
|
|
55
|
+
*/
|
|
51
56
|
function effect(callback) {
|
|
52
57
|
return typeof callback === "function" ? new Effect(callback) : void 0;
|
|
53
58
|
}
|
|
54
59
|
//#endregion
|
|
55
|
-
//#region node_modules/@oscarpalmer/mora/dist/helpers/is.
|
|
60
|
+
//#region node_modules/@oscarpalmer/mora/dist/helpers/is.mjs
|
|
61
|
+
/**
|
|
62
|
+
* Is the value a reactive array?
|
|
63
|
+
* @param value Value to check
|
|
64
|
+
* @returns True if value is a {@link ReactiveArray}
|
|
65
|
+
*/
|
|
56
66
|
function isArray(value) {
|
|
57
67
|
return isMora(value, NAME_ARRAY);
|
|
58
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Is the value a computed signal?
|
|
71
|
+
* @param value Value to check
|
|
72
|
+
* @returns True if value is a {@link Computed}
|
|
73
|
+
*/
|
|
59
74
|
function isComputed(value) {
|
|
60
75
|
return isMora(value, NAME_COMPUTED);
|
|
61
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Is the value an effect?
|
|
79
|
+
* @param value Value to check
|
|
80
|
+
* @returns True if value is an {@link Effect}
|
|
81
|
+
*/
|
|
62
82
|
function isEffect(value) {
|
|
63
83
|
return isMora(value, NAME_EFFECT);
|
|
64
84
|
}
|
|
65
85
|
function isMora(value, name) {
|
|
66
86
|
return typeof value === "object" && value != null && "$mora" in value && (typeof name === "string" ? value["$mora"] === name : name.has(value["$mora"]));
|
|
67
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Is the value reactive?
|
|
90
|
+
* @param value Value to check
|
|
91
|
+
* @returns True if value is a {@link Reactive}
|
|
92
|
+
*/
|
|
68
93
|
function isReactive(value) {
|
|
69
94
|
return isMora(value, NAME_ALL);
|
|
70
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Is the value a signal?
|
|
98
|
+
* @param value Value to check
|
|
99
|
+
* @returns True if value is a {@link Signal}
|
|
100
|
+
*/
|
|
71
101
|
function isSignal(value) {
|
|
72
102
|
return isMora(value, NAME_SIGNAL);
|
|
73
103
|
}
|
|
74
104
|
//#endregion
|
|
75
|
-
//#region node_modules/@oscarpalmer/mora/dist/batch.
|
|
105
|
+
//#region node_modules/@oscarpalmer/mora/dist/batch.mjs
|
|
76
106
|
function flushHandlers() {
|
|
77
107
|
while (BATCH.depth === 0 && BATCH.handlers.size > 0) {
|
|
78
108
|
const handlers = [...BATCH.handlers];
|
|
@@ -81,15 +111,23 @@ function flushHandlers() {
|
|
|
81
111
|
else handler.callback(handler.state.value);
|
|
82
112
|
}
|
|
83
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Start batching effects
|
|
116
|
+
*
|
|
117
|
+
* _(Use {@link stopBatch} to flush and run batched effects)_
|
|
118
|
+
*/
|
|
84
119
|
function startBatch() {
|
|
85
120
|
BATCH.depth += 1;
|
|
86
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Stop batching effects and flush _(run)_ them
|
|
124
|
+
*/
|
|
87
125
|
function stopBatch() {
|
|
88
126
|
if (BATCH.depth > 0) BATCH.depth -= 1;
|
|
89
127
|
flushHandlers();
|
|
90
128
|
}
|
|
91
129
|
//#endregion
|
|
92
|
-
//#region node_modules/@oscarpalmer/mora/dist/subscription.
|
|
130
|
+
//#region node_modules/@oscarpalmer/mora/dist/subscription.mjs
|
|
93
131
|
var Subscription = class {
|
|
94
132
|
callback;
|
|
95
133
|
state;
|
|
@@ -116,7 +154,7 @@ function unsubscribe(state, callback) {
|
|
|
116
154
|
state.subscriptions.delete(callback);
|
|
117
155
|
}
|
|
118
156
|
//#endregion
|
|
119
|
-
//#region node_modules/@oscarpalmer/mora/dist/value/reactive.
|
|
157
|
+
//#region node_modules/@oscarpalmer/mora/dist/value/reactive.mjs
|
|
120
158
|
var Reactive = class {
|
|
121
159
|
state = {
|
|
122
160
|
computeds: /* @__PURE__ */ new Set(),
|
|
@@ -130,24 +168,45 @@ var Reactive = class {
|
|
|
130
168
|
if (typeof options === "object" && typeof options.equal === "function") this.state.equal = options.equal;
|
|
131
169
|
Object.defineProperty(this, NAME_MORA, { value: name });
|
|
132
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Get the value _(without reactivity)_
|
|
173
|
+
* @return Current value
|
|
174
|
+
*/
|
|
133
175
|
peek() {
|
|
134
176
|
return this.state.value;
|
|
135
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Subscribe to changes
|
|
180
|
+
* @param callback Callback for changes
|
|
181
|
+
* @return Unsubscribe callback
|
|
182
|
+
*/
|
|
136
183
|
subscribe(callback) {
|
|
137
184
|
return subscribe(this.state, callback);
|
|
138
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* JSON representation of the value
|
|
188
|
+
* @return JSON value
|
|
189
|
+
*/
|
|
139
190
|
toJSON() {
|
|
140
191
|
return this.get();
|
|
141
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* String representation of the value
|
|
195
|
+
* @return Value as string
|
|
196
|
+
*/
|
|
142
197
|
toString() {
|
|
143
198
|
return String(this.get());
|
|
144
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Unsubscribe from changes
|
|
202
|
+
* @param callback Callback to unsubscribe
|
|
203
|
+
*/
|
|
145
204
|
unsubscribe(callback) {
|
|
146
205
|
unsubscribe(this.state, callback);
|
|
147
206
|
}
|
|
148
207
|
};
|
|
149
208
|
//#endregion
|
|
150
|
-
//#region node_modules/@oscarpalmer/mora/dist/value/computed.
|
|
209
|
+
//#region node_modules/@oscarpalmer/mora/dist/value/computed.mjs
|
|
151
210
|
var Computed = class extends Reactive {
|
|
152
211
|
effect = {
|
|
153
212
|
dirty: true,
|
|
@@ -163,13 +222,16 @@ var Computed = class extends Reactive {
|
|
|
163
222
|
ACTIVE.computed = previousComputed;
|
|
164
223
|
if (!this.state.equal(this.state.value, value)) {
|
|
165
224
|
this.state.value = value;
|
|
166
|
-
for (const computed
|
|
167
|
-
for (const effect
|
|
225
|
+
for (const computed of this.state.computeds) computed.effect.dirty = true;
|
|
226
|
+
for (const effect of this.state.effects) BATCH.handlers.add(effect);
|
|
168
227
|
for (const [, subscription] of this.state.subscriptions) subscription.callback(value);
|
|
169
228
|
}
|
|
170
229
|
this.effect.dirty = false;
|
|
171
230
|
});
|
|
172
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* @inheritdoc
|
|
234
|
+
*/
|
|
173
235
|
get() {
|
|
174
236
|
if (ACTIVE.computed != null && this !== ACTIVE.computed) this.state.computeds.add(ACTIVE.computed);
|
|
175
237
|
if (ACTIVE.effect != null && ACTIVE.effect !== this.effect.instance) this.state.effects.add(ACTIVE.effect);
|
|
@@ -177,11 +239,17 @@ var Computed = class extends Reactive {
|
|
|
177
239
|
return this.state.value;
|
|
178
240
|
}
|
|
179
241
|
};
|
|
242
|
+
/**
|
|
243
|
+
* Create a computed value
|
|
244
|
+
* @param callback Callback to compute the value
|
|
245
|
+
* @param options Reactivity options
|
|
246
|
+
* @returns Computed value
|
|
247
|
+
*/
|
|
180
248
|
function computed(callback, options) {
|
|
181
249
|
return new Computed(callback, options);
|
|
182
250
|
}
|
|
183
251
|
//#endregion
|
|
184
|
-
//#region node_modules/@oscarpalmer/mora/dist/helpers/value.
|
|
252
|
+
//#region node_modules/@oscarpalmer/mora/dist/helpers/value.mjs
|
|
185
253
|
function emitValue(state) {
|
|
186
254
|
for (const computed of state.computeds) computed.effect.dirty = true;
|
|
187
255
|
for (const effect of state.effects) BATCH.handlers.add(effect);
|
|
@@ -207,29 +275,46 @@ function getValue$1(state) {
|
|
|
207
275
|
return state.value;
|
|
208
276
|
}
|
|
209
277
|
//#endregion
|
|
210
|
-
//#region node_modules/@oscarpalmer/mora/dist/value/signal.
|
|
278
|
+
//#region node_modules/@oscarpalmer/mora/dist/value/signal.mjs
|
|
211
279
|
var Signal = class extends Reactive {
|
|
212
280
|
constructor(value, options) {
|
|
213
281
|
super(NAME_SIGNAL, value, options);
|
|
214
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* @inheritdoc
|
|
285
|
+
*/
|
|
215
286
|
get() {
|
|
216
287
|
return getValue$1(this.state);
|
|
217
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Set the value
|
|
291
|
+
* @param value New value
|
|
292
|
+
*/
|
|
218
293
|
set(value) {
|
|
219
294
|
if (!this.state.equal(this.state.value, value)) {
|
|
220
295
|
this.state.value = value;
|
|
221
296
|
emitValue(this.state);
|
|
222
297
|
}
|
|
223
298
|
}
|
|
299
|
+
/**
|
|
300
|
+
* Update the value _(based on the current value)_
|
|
301
|
+
* @param callback Callback to update the value
|
|
302
|
+
*/
|
|
224
303
|
update(callback) {
|
|
225
304
|
this.set(callback(this.state.value));
|
|
226
305
|
}
|
|
227
306
|
};
|
|
307
|
+
/**
|
|
308
|
+
* Create a reactive value
|
|
309
|
+
* @param value Initial value
|
|
310
|
+
* @param options Reactivity options
|
|
311
|
+
* @returns Reactive value
|
|
312
|
+
*/
|
|
228
313
|
function signal(value, options) {
|
|
229
314
|
return new Signal(value, options);
|
|
230
315
|
}
|
|
231
316
|
//#endregion
|
|
232
|
-
//#region node_modules/@oscarpalmer/mora/dist/helpers/proxy.
|
|
317
|
+
//#region node_modules/@oscarpalmer/mora/dist/helpers/proxy.mjs
|
|
233
318
|
function emityProxyValues(state, mapped) {
|
|
234
319
|
const values = [...mapped.values()];
|
|
235
320
|
const { length } = values;
|
|
@@ -274,23 +359,29 @@ function setValueInProxy(parameters) {
|
|
|
274
359
|
return true;
|
|
275
360
|
}
|
|
276
361
|
//#endregion
|
|
277
|
-
//#region node_modules/@oscarpalmer/mora/dist/value/array.
|
|
362
|
+
//#region node_modules/@oscarpalmer/mora/dist/value/array.mjs
|
|
278
363
|
var ReactiveArray = class extends Reactive {
|
|
279
364
|
#indiced = /* @__PURE__ */ new Map();
|
|
280
365
|
#size = signal(0);
|
|
366
|
+
/**
|
|
367
|
+
* The length of the array
|
|
368
|
+
*/
|
|
281
369
|
get length() {
|
|
282
370
|
return this.#size.get();
|
|
283
371
|
}
|
|
372
|
+
/**
|
|
373
|
+
* Set the length of the array
|
|
374
|
+
*/
|
|
284
375
|
set length(value) {
|
|
285
376
|
if (typeof value === "number" && value >= 0 && value !== this.state.value.length) this.get().length = value;
|
|
286
377
|
}
|
|
287
378
|
constructor(value, options) {
|
|
288
379
|
super(NAME_ARRAY, new Proxy(value, {
|
|
289
380
|
get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, this.state, this.#size) : Reflect.get(target, property),
|
|
290
|
-
set: (target, property, value
|
|
381
|
+
set: (target, property, value) => setValueInProxy({
|
|
291
382
|
property,
|
|
292
383
|
target,
|
|
293
|
-
value
|
|
384
|
+
value,
|
|
294
385
|
isArray: true,
|
|
295
386
|
state: this.state,
|
|
296
387
|
length: this.#size
|
|
@@ -298,9 +389,17 @@ var ReactiveArray = class extends Reactive {
|
|
|
298
389
|
}), options);
|
|
299
390
|
this.#size.set(value.length);
|
|
300
391
|
}
|
|
392
|
+
/**
|
|
393
|
+
* Clear the array
|
|
394
|
+
*/
|
|
301
395
|
clear() {
|
|
302
396
|
this.length = 0;
|
|
303
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* Create a computed, filtered array
|
|
400
|
+
* @param callback Callback to evaluate each item
|
|
401
|
+
* @return Computed array of filtered items
|
|
402
|
+
*/
|
|
304
403
|
filter(callback) {
|
|
305
404
|
return computed(() => this.get().filter(callback));
|
|
306
405
|
}
|
|
@@ -308,9 +407,20 @@ var ReactiveArray = class extends Reactive {
|
|
|
308
407
|
if (typeof first === "number") return getReactiveValueInProxy(this, this.#indiced, first, true).get();
|
|
309
408
|
return first === "length" ? this.length : getValue$1(this.state);
|
|
310
409
|
}
|
|
410
|
+
/**
|
|
411
|
+
* Create a computed, mapped array
|
|
412
|
+
* @param callback Callback to transform each item
|
|
413
|
+
* @return Computed array of mapped items
|
|
414
|
+
*/
|
|
311
415
|
map(callback) {
|
|
312
416
|
return computed(() => this.get().map(callback));
|
|
313
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* Notify dependents of changes
|
|
420
|
+
*
|
|
421
|
+
* _This bypasses equality checks and will immediately notify dependents.
|
|
422
|
+
* Use this only if you're modifying nested data that would be ignored by equality checks._
|
|
423
|
+
*/
|
|
314
424
|
notify() {
|
|
315
425
|
emityProxyValues(this.state, this.#indiced);
|
|
316
426
|
}
|
|
@@ -318,9 +428,18 @@ var ReactiveArray = class extends Reactive {
|
|
|
318
428
|
if (value === "length") return this.#size.peek();
|
|
319
429
|
return typeof value === "number" ? this.state.value.at(value) : [...this.state.value];
|
|
320
430
|
}
|
|
431
|
+
/**
|
|
432
|
+
* Remove and return the last item of the array
|
|
433
|
+
* @returns Removed item, or `undefined` if the array is empty
|
|
434
|
+
*/
|
|
321
435
|
pop() {
|
|
322
436
|
return this.state.value.pop();
|
|
323
437
|
}
|
|
438
|
+
/**
|
|
439
|
+
* Add items to the end of the array
|
|
440
|
+
* @param items Items to add
|
|
441
|
+
* @returns New array length
|
|
442
|
+
*/
|
|
324
443
|
push(...items) {
|
|
325
444
|
return this.state.value.push(...items);
|
|
326
445
|
}
|
|
@@ -329,9 +448,20 @@ var ReactiveArray = class extends Reactive {
|
|
|
329
448
|
else if (first === "length") this.length = second;
|
|
330
449
|
else if (typeof first === "number" && !Number.isNaN(first)) setAtIndex(this.state.value, first, second);
|
|
331
450
|
}
|
|
451
|
+
/**
|
|
452
|
+
* Remove and return the first item of the array
|
|
453
|
+
* @returns Removed item, or `undefined` if the array is empty
|
|
454
|
+
*/
|
|
332
455
|
shift() {
|
|
333
456
|
return this.state.value.shift();
|
|
334
457
|
}
|
|
458
|
+
/**
|
|
459
|
+
* Remove and return items from the array _(and optionally add new items)_
|
|
460
|
+
* @param from Index to start removing items from
|
|
461
|
+
* @param to Index to stop removing items at _(defaults to the end of the array)_
|
|
462
|
+
* @param items Optional items to add
|
|
463
|
+
* @returns Removed items
|
|
464
|
+
*/
|
|
335
465
|
splice(from, to, ...items) {
|
|
336
466
|
return this.state.value.splice(from, to ?? this.state.value.length, ...items);
|
|
337
467
|
}
|
|
@@ -339,54 +469,105 @@ var ReactiveArray = class extends Reactive {
|
|
|
339
469
|
if (typeof first === "number" && typeof second === "function") return getReactiveValueInProxy(this, this.#indiced, first, true).subscribe(second);
|
|
340
470
|
return typeof first === "function" ? subscribe(this.state, first) : noop$1;
|
|
341
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* Add items to the beginning of the array
|
|
474
|
+
* @param items Items to add
|
|
475
|
+
* @returns New array length
|
|
476
|
+
*/
|
|
342
477
|
unshift(...items) {
|
|
343
478
|
return this.state.value.unshift(...items);
|
|
344
479
|
}
|
|
480
|
+
/**
|
|
481
|
+
* Update the value _(based on the current value)_
|
|
482
|
+
* @param callback Callback to update the value
|
|
483
|
+
*/
|
|
345
484
|
update(callback) {
|
|
346
485
|
const updated = callback(this.state.value);
|
|
347
486
|
if (updated == null || Array.isArray(updated)) this.set(updated);
|
|
348
487
|
}
|
|
349
488
|
};
|
|
489
|
+
/**
|
|
490
|
+
* Create a reactive array
|
|
491
|
+
* @param value Initial array of items
|
|
492
|
+
* @param options Reactivity options
|
|
493
|
+
* @returns Reactive array
|
|
494
|
+
*/
|
|
350
495
|
function array(value, options) {
|
|
351
496
|
return new ReactiveArray(Array.isArray(value) ? value : [], options);
|
|
352
497
|
}
|
|
353
|
-
function updateArray(type, array
|
|
498
|
+
function updateArray(type, array, state, length) {
|
|
354
499
|
const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
|
|
355
|
-
const previousArray = affectsLength ? [] : [...array
|
|
356
|
-
const previousLength = array
|
|
500
|
+
const previousArray = affectsLength ? [] : [...array];
|
|
501
|
+
const previousLength = array.length;
|
|
357
502
|
return (...args) => {
|
|
358
|
-
const result = array
|
|
359
|
-
if (affectsLength ? array
|
|
503
|
+
const result = array[type](...args);
|
|
504
|
+
if (affectsLength ? array.length !== previousLength : !equalArrays(state, previousArray, array)) {
|
|
360
505
|
emitValue(state);
|
|
361
|
-
length.set(array
|
|
506
|
+
length.set(array.length);
|
|
362
507
|
}
|
|
363
508
|
return result;
|
|
364
509
|
};
|
|
365
510
|
}
|
|
366
|
-
function setAtIndex(array
|
|
367
|
-
const actual = index < 0 ? array
|
|
368
|
-
if (actual > -1) array
|
|
511
|
+
function setAtIndex(array, index, value) {
|
|
512
|
+
const actual = index < 0 ? array.length + index : index;
|
|
513
|
+
if (actual > -1) array[actual] = value;
|
|
369
514
|
}
|
|
370
515
|
//#endregion
|
|
371
|
-
//#region node_modules/@oscarpalmer/
|
|
516
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
|
|
517
|
+
/**
|
|
518
|
+
* Is the value a key?
|
|
519
|
+
* @param value Value to check
|
|
520
|
+
* @returns `true` if the value is a `Key` _(`number` or `string`)_, otherwise `false`
|
|
521
|
+
*/
|
|
372
522
|
function isKey(value) {
|
|
373
523
|
return typeof value === "number" || typeof value === "string";
|
|
374
524
|
}
|
|
375
|
-
|
|
525
|
+
/**
|
|
526
|
+
* Is the value a plain object?
|
|
527
|
+
* @param value Value to check
|
|
528
|
+
* @returns `true` if the value is a plain object, otherwise `false`
|
|
529
|
+
*/
|
|
530
|
+
function isPlainObject(value) {
|
|
376
531
|
if (value === null || typeof value !== "object") return false;
|
|
377
532
|
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
378
533
|
const prototype = Object.getPrototypeOf(value);
|
|
379
534
|
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
380
535
|
}
|
|
381
536
|
//#endregion
|
|
382
|
-
//#region node_modules/@oscarpalmer/
|
|
537
|
+
//#region node_modules/@oscarpalmer/atoms/dist/internal/string.mjs
|
|
538
|
+
/**
|
|
539
|
+
* Get the string value from any value
|
|
540
|
+
* @param value Original value
|
|
541
|
+
* @returns String representation of the value
|
|
542
|
+
*/
|
|
543
|
+
function getString(value) {
|
|
544
|
+
if (typeof value === "string") return value;
|
|
545
|
+
if (value == null) return "";
|
|
546
|
+
if (typeof value === "function") return getString(value());
|
|
547
|
+
if (typeof value !== "object") return String(value);
|
|
548
|
+
const asString = String(value.valueOf?.() ?? value);
|
|
549
|
+
return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
|
|
550
|
+
}
|
|
551
|
+
//#endregion
|
|
552
|
+
//#region node_modules/@oscarpalmer/atoms/dist/is.mjs
|
|
553
|
+
/**
|
|
554
|
+
* Is the value `undefined`, `null`, or a whitespace-only string?
|
|
555
|
+
* @param value Value to check
|
|
556
|
+
* @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
|
|
557
|
+
*/
|
|
558
|
+
function isNullableOrWhitespace(value) {
|
|
559
|
+
return value == null || EXPRESSION_WHITESPACE$1.test(getString(value));
|
|
560
|
+
}
|
|
561
|
+
const EXPRESSION_WHITESPACE$1 = /^\s*$/;
|
|
562
|
+
//#endregion
|
|
563
|
+
//#region node_modules/@oscarpalmer/mora/dist/value/store.mjs
|
|
383
564
|
var Store = class extends Reactive {
|
|
384
565
|
#keyed = /* @__PURE__ */ new Map();
|
|
385
566
|
constructor(value, options) {
|
|
386
|
-
super(NAME_STORE, new Proxy(value, { set: (target, property, value
|
|
567
|
+
super(NAME_STORE, new Proxy(value, { set: (target, property, value) => setValueInProxy({
|
|
387
568
|
target,
|
|
388
569
|
property,
|
|
389
|
-
value
|
|
570
|
+
value,
|
|
390
571
|
isArray: false,
|
|
391
572
|
state: this.state
|
|
392
573
|
}) }), options);
|
|
@@ -394,6 +575,12 @@ var Store = class extends Reactive {
|
|
|
394
575
|
get(key) {
|
|
395
576
|
return isKey(key) ? getReactiveValueInProxy(this, this.#keyed, key, false).get() : getValue$1(this.state);
|
|
396
577
|
}
|
|
578
|
+
/**
|
|
579
|
+
* Notify dependents of changes
|
|
580
|
+
*
|
|
581
|
+
* _This bypasses equality checks and will immediately notify dependents.
|
|
582
|
+
* Use this only if you're modifying nested data that would be ignored by equality checks._
|
|
583
|
+
*/
|
|
397
584
|
notify() {
|
|
398
585
|
emityProxyValues(this.state, this.#keyed);
|
|
399
586
|
}
|
|
@@ -402,59 +589,30 @@ var Store = class extends Reactive {
|
|
|
402
589
|
}
|
|
403
590
|
set(first, second) {
|
|
404
591
|
if (isKey(first)) this.state.value[first] = second;
|
|
405
|
-
else if (first == null || isPlainObject
|
|
592
|
+
else if (first == null || isPlainObject(first)) setProxyValue(this.state.value, first ?? {});
|
|
406
593
|
}
|
|
407
594
|
subscribe(first, second) {
|
|
408
595
|
if (isKey(first) && typeof second === "function") return getReactiveValueInProxy(this, this.#keyed, first, false).subscribe(second);
|
|
409
596
|
return typeof first === "function" ? subscribe(this.state, first) : noop$1;
|
|
410
597
|
}
|
|
598
|
+
/**
|
|
599
|
+
* Update the value _(based on the current value)_
|
|
600
|
+
* @param callback Callback to update the value
|
|
601
|
+
*/
|
|
411
602
|
update(callback) {
|
|
412
603
|
const updated = callback({ ...this.state.value });
|
|
413
|
-
if (updated == null || isPlainObject
|
|
604
|
+
if (updated == null || isPlainObject(updated)) setProxyValue(this.state.value, updated ?? {});
|
|
414
605
|
}
|
|
415
606
|
};
|
|
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
607
|
/**
|
|
450
|
-
*
|
|
451
|
-
* @param value
|
|
452
|
-
* @
|
|
608
|
+
* Create a reactive store
|
|
609
|
+
* @param value Initial object value
|
|
610
|
+
* @param options Reactivity options
|
|
611
|
+
* @returns Reactive store
|
|
453
612
|
*/
|
|
454
|
-
function
|
|
455
|
-
return value
|
|
613
|
+
function store(value, options) {
|
|
614
|
+
return new Store(isPlainObject(value) ? value : {}, options);
|
|
456
615
|
}
|
|
457
|
-
const EXPRESSION_WHITESPACE$1 = /^\s*$/;
|
|
458
616
|
//#endregion
|
|
459
617
|
//#region node_modules/@oscarpalmer/toretto/dist/internal/is.mjs
|
|
460
618
|
/**
|
|
@@ -760,15 +918,24 @@ let parser;
|
|
|
760
918
|
let templates = {};
|
|
761
919
|
//#endregion
|
|
762
920
|
//#region src/constants.ts
|
|
921
|
+
const ARRAY_COMPARISON_ADDED = "added";
|
|
922
|
+
const ARRAY_COMPARISON_DISSIMILAR = "dissimilar";
|
|
923
|
+
const ARRAY_COMPARISON_REMOVED = "removed";
|
|
924
|
+
const ERROR_FRAGMENT = "Fragment function must return a Fragment instance";
|
|
925
|
+
const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<id>'";
|
|
926
|
+
const ERROR_IDENTIFIER_TYPE = "Identifier cannot be null or undefined";
|
|
927
|
+
const EVENT_CHANGE = "change";
|
|
928
|
+
const EVENT_INPUT = "input";
|
|
929
|
+
const EVENT_SUBMIT = "submit";
|
|
763
930
|
const EVENT_DEFAULTS = {
|
|
764
931
|
A: "click",
|
|
765
932
|
BUTTON: "click",
|
|
766
933
|
DETAILS: "toggle",
|
|
767
|
-
FORM:
|
|
768
|
-
SELECT:
|
|
769
|
-
TEXTAREA:
|
|
934
|
+
FORM: EVENT_SUBMIT,
|
|
935
|
+
SELECT: EVENT_CHANGE,
|
|
936
|
+
TEXTAREA: EVENT_INPUT
|
|
770
937
|
};
|
|
771
|
-
const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(
|
|
938
|
+
const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?[\w-]+)="<!--abydon.(\d+)-->"/g;
|
|
772
939
|
const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX = /^_/;
|
|
773
940
|
const EXPRESSION_ABYDON_CONTENT = /^@?abydon\.(\d+)@?$/;
|
|
774
941
|
const EXPRESSION_ATTRIBUTE_CLASS = /^class\./;
|
|
@@ -783,14 +950,31 @@ const EXPRESSION_EVENT_PREFIX = /^@/;
|
|
|
783
950
|
const EXPRESSION_PERIOD = /\./;
|
|
784
951
|
const NAME_FRAGMENT = "$fragment";
|
|
785
952
|
const NAME_FRAGMENTS = "$fragments";
|
|
953
|
+
const PROPERTY_CHECKED = "checked";
|
|
954
|
+
const PROPERTY_VALUE = "value";
|
|
955
|
+
//#endregion
|
|
956
|
+
//#region node_modules/@oscarpalmer/atoms/dist/string/index.mjs
|
|
957
|
+
/**
|
|
958
|
+
* Parse a JSON string into its proper value _(or `undefined` if it fails)_
|
|
959
|
+
* @param value JSON string to parse
|
|
960
|
+
* @param reviver Reviver function to transform the parsed values
|
|
961
|
+
* @returns Parsed value or `undefined` if parsing fails
|
|
962
|
+
*/
|
|
963
|
+
function parse$1(value, reviver) {
|
|
964
|
+
try {
|
|
965
|
+
return JSON.parse(value, reviver);
|
|
966
|
+
} catch {
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
786
970
|
//#endregion
|
|
787
971
|
//#region src/helpers/index.ts
|
|
788
972
|
function compareArrays(first, second) {
|
|
789
973
|
const firstIsLarger = first.length > second.length;
|
|
790
974
|
const from = firstIsLarger ? first : second;
|
|
791
975
|
const to = firstIsLarger ? second : first;
|
|
792
|
-
if (!from.filter((key) => to.includes(key)).every((key, index) => to[index] === key)) return
|
|
793
|
-
return firstIsLarger ?
|
|
976
|
+
if (!from.filter((key) => to.includes(key)).every((key, index) => to[index] === key)) return ARRAY_COMPARISON_DISSIMILAR;
|
|
977
|
+
return firstIsLarger ? ARRAY_COMPARISON_REMOVED : ARRAY_COMPARISON_ADDED;
|
|
794
978
|
}
|
|
795
979
|
function isFragment(value) {
|
|
796
980
|
return isNamed(value, NAME_FRAGMENT);
|
|
@@ -801,9 +985,6 @@ function isFragments(value) {
|
|
|
801
985
|
function isNamed(value, name) {
|
|
802
986
|
return typeof value === "object" && value != null && name in value && value[name] === true;
|
|
803
987
|
}
|
|
804
|
-
const COMPARISON_ADDED = "added";
|
|
805
|
-
const COMPARISON_DISSIMILAR = "dissimilar";
|
|
806
|
-
const COMPARISON_REMOVED = "removed";
|
|
807
988
|
//#endregion
|
|
808
989
|
//#region src/fragments.ts
|
|
809
990
|
var Fragments = class {
|
|
@@ -839,13 +1020,13 @@ function handleItems(state, items) {
|
|
|
839
1020
|
for (let index = 0; index < length; index += 1) {
|
|
840
1021
|
const item = items[index];
|
|
841
1022
|
const identifier = state.identify(item);
|
|
842
|
-
if (identifier == null) throw new
|
|
1023
|
+
if (identifier == null) throw new TypeError(ERROR_IDENTIFIER_TYPE);
|
|
843
1024
|
const key = getString(identifier);
|
|
844
|
-
if (keys.has(key)) throw new Error(
|
|
1025
|
+
if (keys.has(key)) throw new Error(ERROR_IDENTIFIER_DUPLICATE.replace("<>", key));
|
|
845
1026
|
let instance = state.instances[key];
|
|
846
1027
|
if (instance == null) {
|
|
847
1028
|
instance = state.fragment(item);
|
|
848
|
-
if (!isFragment(instance)) throw new Error(
|
|
1029
|
+
if (!isFragment(instance)) throw new Error(ERROR_FRAGMENT);
|
|
849
1030
|
}
|
|
850
1031
|
instance.identify(key);
|
|
851
1032
|
state.instances[key] = instance;
|
|
@@ -886,6 +1067,9 @@ function createNodes(value) {
|
|
|
886
1067
|
if (isChildNode(value)) return [value];
|
|
887
1068
|
return [new Text(getString(value))];
|
|
888
1069
|
}
|
|
1070
|
+
function isInputElement(node) {
|
|
1071
|
+
return node instanceof HTMLInputElement || node instanceof HTMLSelectElement || node instanceof HTMLTextAreaElement;
|
|
1072
|
+
}
|
|
889
1073
|
function removeNodes(nodes) {
|
|
890
1074
|
const { length } = nodes;
|
|
891
1075
|
for (let index = 0; index < length; index += 1) nodes[index].remove();
|
|
@@ -1023,8 +1207,8 @@ function getOptions(options) {
|
|
|
1023
1207
|
function getType(element, type) {
|
|
1024
1208
|
if (type !== "on") return type;
|
|
1025
1209
|
if (element instanceof HTMLInputElement) {
|
|
1026
|
-
if (EXPRESSION_EVENT_CHANGE_TYPES.test(element.type)) return
|
|
1027
|
-
return element.type === "submit" ?
|
|
1210
|
+
if (EXPRESSION_EVENT_CHANGE_TYPES.test(element.type)) return EVENT_CHANGE;
|
|
1211
|
+
return element.type === "submit" ? EVENT_SUBMIT : EVENT_INPUT;
|
|
1028
1212
|
}
|
|
1029
1213
|
return EVENT_DEFAULTS[element.tagName] ?? type;
|
|
1030
1214
|
}
|
|
@@ -1083,7 +1267,7 @@ function setValue(data, element, name, value) {
|
|
|
1083
1267
|
else callback(element, name, value);
|
|
1084
1268
|
}
|
|
1085
1269
|
function updateChecked(element, name, value) {
|
|
1086
|
-
updateElement(
|
|
1270
|
+
updateElement(EVENT_CHANGE, PROPERTY_CHECKED, element, name, value, value === true);
|
|
1087
1271
|
}
|
|
1088
1272
|
function updateElement(event, property, element, name, value, next) {
|
|
1089
1273
|
if (!(property in element) || element[property] === next) return;
|
|
@@ -1096,7 +1280,7 @@ function updateProperty(element, name, value) {
|
|
|
1096
1280
|
setAttribute$1(element, name, value === true);
|
|
1097
1281
|
}
|
|
1098
1282
|
function updateValue(element, name, value) {
|
|
1099
|
-
updateElement(element instanceof HTMLSelectElement ?
|
|
1283
|
+
updateElement(element instanceof HTMLSelectElement ? EVENT_CHANGE : EVENT_INPUT, PROPERTY_VALUE, element, name, value, String(value));
|
|
1100
1284
|
}
|
|
1101
1285
|
//#endregion
|
|
1102
1286
|
//#region src/node/attribute/index.ts
|
|
@@ -1128,6 +1312,9 @@ function mapAttributes(data, element) {
|
|
|
1128
1312
|
function mapValue$1(data, element, name, value) {
|
|
1129
1313
|
if (typeof value === "function") setComputedAttribute(data, element, name, value);
|
|
1130
1314
|
else setAttribute(data, element, name, value);
|
|
1315
|
+
if (name === "value" && isInputElement(element) && isSignal(value)) mapEvent(element, "@on", () => {
|
|
1316
|
+
value.set(parse$1(element.value) ?? element.value);
|
|
1317
|
+
});
|
|
1131
1318
|
}
|
|
1132
1319
|
function setComputedAttribute(data, element, name, callback) {
|
|
1133
1320
|
const value = computed(callback);
|
|
@@ -1157,7 +1344,7 @@ function handleArray(identifiers, items, nodes) {
|
|
|
1157
1344
|
if (comparison !== "removed") addToArray(identifiers, {
|
|
1158
1345
|
...items,
|
|
1159
1346
|
next
|
|
1160
|
-
}, nodes, comparison ===
|
|
1347
|
+
}, nodes, comparison === ARRAY_COMPARISON_ADDED);
|
|
1161
1348
|
const toRemove = items.fragments?.filter((fragment) => !identifiers.next.has(fragment.identifier)) ?? [];
|
|
1162
1349
|
const { length } = toRemove;
|
|
1163
1350
|
for (let index = 0; index < length; index += 1) toRemove[index].remove();
|
package/dist/constants.d.mts
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
//#region src/constants.d.ts
|
|
2
|
+
declare const ARRAY_COMPARISON_ADDED = "added";
|
|
3
|
+
declare const ARRAY_COMPARISON_DISSIMILAR = "dissimilar";
|
|
4
|
+
declare const ARRAY_COMPARISON_REMOVED = "removed";
|
|
2
5
|
declare const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
6
|
+
declare const ATTRIBUTE_NAME_DELIMITER = ".";
|
|
7
|
+
declare const ERROR_FRAGMENT = "Fragment function must return a Fragment instance";
|
|
8
|
+
declare const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<id>'";
|
|
9
|
+
declare const ERROR_IDENTIFIER_TYPE = "Identifier cannot be null or undefined";
|
|
10
|
+
declare const EVENT_CHANGE = "change";
|
|
11
|
+
declare const EVENT_INPUT = "input";
|
|
12
|
+
declare const EVENT_SUBMIT = "submit";
|
|
3
13
|
declare const EVENT_DEFAULTS: Record<string, string>;
|
|
14
|
+
declare const EVENT_ON_PREFIXED = "@on";
|
|
15
|
+
declare const EVENT_ON_VALUE = "on";
|
|
16
|
+
declare const EVENT_OPTIONS_DELIMITER = ":";
|
|
4
17
|
declare const EXPRESSION_ABYDON_ATTRIBUTE_FULL: RegExp;
|
|
5
18
|
declare const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX: RegExp;
|
|
6
19
|
declare const EXPRESSION_ABYDON_CONTENT: RegExp;
|
|
@@ -16,5 +29,9 @@ declare const EXPRESSION_EVENT_PREFIX: RegExp;
|
|
|
16
29
|
declare const EXPRESSION_PERIOD: RegExp;
|
|
17
30
|
declare const NAME_FRAGMENT = "$fragment";
|
|
18
31
|
declare const NAME_FRAGMENTS = "$fragments";
|
|
32
|
+
declare const PROPERTY_CHECKED = "checked";
|
|
33
|
+
declare const PROPERTY_IDENTIFIER = "identifier";
|
|
34
|
+
declare const PROPERTY_VALUE = "value";
|
|
35
|
+
declare const TEMPLATE_ITEM = "<>";
|
|
19
36
|
//#endregion
|
|
20
|
-
export { ATTRIBUTE_CLASS_PREFIX_LENGTH, EVENT_DEFAULTS, EXPRESSION_ABYDON_ATTRIBUTE_FULL, EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX, EXPRESSION_EVENT_CHANGE_TYPES, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD, NAME_FRAGMENT, NAME_FRAGMENTS };
|
|
37
|
+
export { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, ATTRIBUTE_CLASS_PREFIX_LENGTH, ATTRIBUTE_NAME_DELIMITER, ERROR_FRAGMENT, ERROR_IDENTIFIER_DUPLICATE, ERROR_IDENTIFIER_TYPE, EVENT_CHANGE, EVENT_DEFAULTS, EVENT_INPUT, EVENT_ON_PREFIXED, EVENT_ON_VALUE, EVENT_OPTIONS_DELIMITER, EVENT_SUBMIT, EXPRESSION_ABYDON_ATTRIBUTE_FULL, EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX, EXPRESSION_EVENT_CHANGE_TYPES, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD, NAME_FRAGMENT, NAME_FRAGMENTS, PROPERTY_CHECKED, PROPERTY_IDENTIFIER, PROPERTY_VALUE, TEMPLATE_ITEM };
|
package/dist/constants.mjs
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
//#region src/constants.ts
|
|
2
|
+
const ARRAY_COMPARISON_ADDED = "added";
|
|
3
|
+
const ARRAY_COMPARISON_DISSIMILAR = "dissimilar";
|
|
4
|
+
const ARRAY_COMPARISON_REMOVED = "removed";
|
|
2
5
|
const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
6
|
+
const ATTRIBUTE_NAME_DELIMITER = ".";
|
|
7
|
+
const ERROR_FRAGMENT = "Fragment function must return a Fragment instance";
|
|
8
|
+
const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<id>'";
|
|
9
|
+
const ERROR_IDENTIFIER_TYPE = "Identifier cannot be null or undefined";
|
|
10
|
+
const EVENT_CHANGE = "change";
|
|
11
|
+
const EVENT_INPUT = "input";
|
|
12
|
+
const EVENT_SUBMIT = "submit";
|
|
3
13
|
const EVENT_DEFAULTS = {
|
|
4
14
|
A: "click",
|
|
5
15
|
BUTTON: "click",
|
|
6
16
|
DETAILS: "toggle",
|
|
7
|
-
FORM:
|
|
8
|
-
SELECT:
|
|
9
|
-
TEXTAREA:
|
|
17
|
+
FORM: EVENT_SUBMIT,
|
|
18
|
+
SELECT: EVENT_CHANGE,
|
|
19
|
+
TEXTAREA: EVENT_INPUT
|
|
10
20
|
};
|
|
11
|
-
const
|
|
21
|
+
const EVENT_ON_PREFIXED = "@on";
|
|
22
|
+
const EVENT_ON_VALUE = "on";
|
|
23
|
+
const EVENT_OPTIONS_DELIMITER = ":";
|
|
24
|
+
const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?[\w-]+)="<!--abydon.(\d+)-->"/g;
|
|
12
25
|
const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX = /^_/;
|
|
13
26
|
const EXPRESSION_ABYDON_CONTENT = /^@?abydon\.(\d+)@?$/;
|
|
14
27
|
const EXPRESSION_ATTRIBUTE_CLASS = /^class\./;
|
|
@@ -23,5 +36,9 @@ const EXPRESSION_EVENT_PREFIX = /^@/;
|
|
|
23
36
|
const EXPRESSION_PERIOD = /\./;
|
|
24
37
|
const NAME_FRAGMENT = "$fragment";
|
|
25
38
|
const NAME_FRAGMENTS = "$fragments";
|
|
39
|
+
const PROPERTY_CHECKED = "checked";
|
|
40
|
+
const PROPERTY_IDENTIFIER = "identifier";
|
|
41
|
+
const PROPERTY_VALUE = "value";
|
|
42
|
+
const TEMPLATE_ITEM = "<>";
|
|
26
43
|
//#endregion
|
|
27
|
-
export { ATTRIBUTE_CLASS_PREFIX_LENGTH, EVENT_DEFAULTS, EXPRESSION_ABYDON_ATTRIBUTE_FULL, EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX, EXPRESSION_EVENT_CHANGE_TYPES, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD, NAME_FRAGMENT, NAME_FRAGMENTS };
|
|
44
|
+
export { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, ATTRIBUTE_CLASS_PREFIX_LENGTH, ATTRIBUTE_NAME_DELIMITER, ERROR_FRAGMENT, ERROR_IDENTIFIER_DUPLICATE, ERROR_IDENTIFIER_TYPE, EVENT_CHANGE, EVENT_DEFAULTS, EVENT_INPUT, EVENT_ON_PREFIXED, EVENT_ON_VALUE, EVENT_OPTIONS_DELIMITER, EVENT_SUBMIT, EXPRESSION_ABYDON_ATTRIBUTE_FULL, EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX, EXPRESSION_EVENT_CHANGE_TYPES, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD, NAME_FRAGMENT, NAME_FRAGMENTS, PROPERTY_CHECKED, PROPERTY_IDENTIFIER, PROPERTY_VALUE, TEMPLATE_ITEM };
|
package/dist/fragments.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NAME_FRAGMENTS } from "./constants.mjs";
|
|
1
|
+
import { ERROR_FRAGMENT, ERROR_IDENTIFIER_DUPLICATE, ERROR_IDENTIFIER_TYPE, NAME_FRAGMENTS } from "./constants.mjs";
|
|
2
2
|
import { isFragment, isFragments } from "./helpers/index.mjs";
|
|
3
3
|
import { getString } from "@oscarpalmer/atoms/string";
|
|
4
4
|
import { array } from "@oscarpalmer/mora";
|
|
@@ -36,13 +36,13 @@ function handleItems(state, items) {
|
|
|
36
36
|
for (let index = 0; index < length; index += 1) {
|
|
37
37
|
const item = items[index];
|
|
38
38
|
const identifier = state.identify(item);
|
|
39
|
-
if (identifier == null) throw new
|
|
39
|
+
if (identifier == null) throw new TypeError(ERROR_IDENTIFIER_TYPE);
|
|
40
40
|
const key = getString(identifier);
|
|
41
|
-
if (keys.has(key)) throw new Error(
|
|
41
|
+
if (keys.has(key)) throw new Error(ERROR_IDENTIFIER_DUPLICATE.replace("<>", key));
|
|
42
42
|
let instance = state.instances[key];
|
|
43
43
|
if (instance == null) {
|
|
44
44
|
instance = state.fragment(item);
|
|
45
|
-
if (!isFragment(instance)) throw new Error(
|
|
45
|
+
if (!isFragment(instance)) throw new Error(ERROR_FRAGMENT);
|
|
46
46
|
}
|
|
47
47
|
instance.identify(key);
|
|
48
48
|
state.instances[key] = instance;
|
package/dist/helpers/dom.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//#region src/helpers/dom.d.ts
|
|
2
2
|
declare function createNodes(value: unknown): ChildNode[];
|
|
3
|
+
declare function isInputElement(node: Node): node is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
|
3
4
|
declare function removeNodes(nodes: ChildNode[]): void;
|
|
4
5
|
declare function replaceNodes(from: ChildNode[], to: ChildNode[]): void;
|
|
5
6
|
//#endregion
|
|
6
|
-
export { createNodes, removeNodes, replaceNodes };
|
|
7
|
+
export { createNodes, isInputElement, removeNodes, replaceNodes };
|
package/dist/helpers/dom.mjs
CHANGED
|
@@ -7,6 +7,9 @@ function createNodes(value) {
|
|
|
7
7
|
if (isChildNode(value)) return [value];
|
|
8
8
|
return [new Text(getString(value))];
|
|
9
9
|
}
|
|
10
|
+
function isInputElement(node) {
|
|
11
|
+
return node instanceof HTMLInputElement || node instanceof HTMLSelectElement || node instanceof HTMLTextAreaElement;
|
|
12
|
+
}
|
|
10
13
|
function removeNodes(nodes) {
|
|
11
14
|
const { length } = nodes;
|
|
12
15
|
for (let index = 0; index < length; index += 1) nodes[index].remove();
|
|
@@ -17,4 +20,4 @@ function replaceNodes(from, to) {
|
|
|
17
20
|
for (let index = 1; index < length; index += 1) from[index].remove();
|
|
18
21
|
}
|
|
19
22
|
//#endregion
|
|
20
|
-
export { createNodes, removeNodes, replaceNodes };
|
|
23
|
+
export { createNodes, isInputElement, removeNodes, replaceNodes };
|
package/dist/helpers/index.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED } from "../constants.mjs";
|
|
1
2
|
import { t as Fragment } from "../fragment-9qTBAvtR.mjs";
|
|
2
3
|
import { Fragments } from "../fragments.mjs";
|
|
3
4
|
|
|
4
5
|
//#region src/helpers/index.d.ts
|
|
5
|
-
declare function compareArrays(first: unknown[], second: unknown[]):
|
|
6
|
+
declare function compareArrays(first: unknown[], second: unknown[]): typeof ARRAY_COMPARISON_ADDED | typeof ARRAY_COMPARISON_DISSIMILAR | typeof ARRAY_COMPARISON_REMOVED;
|
|
6
7
|
declare function isFragment(value: unknown): value is Fragment;
|
|
7
8
|
declare function isFragments(value: unknown): value is Fragments;
|
|
8
9
|
//#endregion
|
package/dist/helpers/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { NAME_FRAGMENT, NAME_FRAGMENTS } from "../constants.mjs";
|
|
1
|
+
import { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, NAME_FRAGMENT, NAME_FRAGMENTS } from "../constants.mjs";
|
|
2
2
|
//#region src/helpers/index.ts
|
|
3
3
|
function compareArrays(first, second) {
|
|
4
4
|
const firstIsLarger = first.length > second.length;
|
|
5
5
|
const from = firstIsLarger ? first : second;
|
|
6
6
|
const to = firstIsLarger ? second : first;
|
|
7
|
-
if (!from.filter((key) => to.includes(key)).every((key, index) => to[index] === key)) return
|
|
8
|
-
return firstIsLarger ?
|
|
7
|
+
if (!from.filter((key) => to.includes(key)).every((key, index) => to[index] === key)) return ARRAY_COMPARISON_DISSIMILAR;
|
|
8
|
+
return firstIsLarger ? ARRAY_COMPARISON_REMOVED : ARRAY_COMPARISON_ADDED;
|
|
9
9
|
}
|
|
10
10
|
function isFragment(value) {
|
|
11
11
|
return isNamed(value, NAME_FRAGMENT);
|
|
@@ -16,8 +16,5 @@ function isFragments(value) {
|
|
|
16
16
|
function isNamed(value, name) {
|
|
17
17
|
return typeof value === "object" && value != null && name in value && value[name] === true;
|
|
18
18
|
}
|
|
19
|
-
const COMPARISON_ADDED = "added";
|
|
20
|
-
const COMPARISON_DISSIMILAR = "dissimilar";
|
|
21
|
-
const COMPARISON_REMOVED = "removed";
|
|
22
19
|
//#endregion
|
|
23
20
|
export { compareArrays, isFragment, isFragments };
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD } from "../../constants.mjs";
|
|
2
|
+
import { isInputElement } from "../../helpers/dom.mjs";
|
|
2
3
|
import { mapEvent } from "../event.mjs";
|
|
3
4
|
import { setAttribute } from "./value.mjs";
|
|
4
|
-
import {
|
|
5
|
+
import { parse } from "@oscarpalmer/atoms/string";
|
|
6
|
+
import { computed, isReactive, isSignal } from "@oscarpalmer/mora";
|
|
5
7
|
//#region src/node/attribute/index.ts
|
|
6
8
|
function getValue(data, original) {
|
|
7
9
|
const matches = EXPRESSION_ABYDON_CONTENT.exec(original ?? "");
|
|
@@ -31,6 +33,9 @@ function mapAttributes(data, element) {
|
|
|
31
33
|
function mapValue(data, element, name, value) {
|
|
32
34
|
if (typeof value === "function") setComputedAttribute(data, element, name, value);
|
|
33
35
|
else setAttribute(data, element, name, value);
|
|
36
|
+
if (name === "value" && isInputElement(element) && isSignal(value)) mapEvent(element, "@on", () => {
|
|
37
|
+
value.set(parse(element.value) ?? element.value);
|
|
38
|
+
});
|
|
34
39
|
}
|
|
35
40
|
function setComputedAttribute(data, element, name, callback) {
|
|
36
41
|
const value = computed(callback);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX } from "../../constants.mjs";
|
|
1
|
+
import { EVENT_CHANGE, EVENT_INPUT, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX, PROPERTY_CHECKED, PROPERTY_VALUE } from "../../constants.mjs";
|
|
2
2
|
import { isReactive } from "@oscarpalmer/mora";
|
|
3
3
|
import { isBooleanAttribute, setAttribute as setAttribute$1 } from "@oscarpalmer/toretto/attribute";
|
|
4
4
|
//#region src/node/attribute/value.ts
|
|
@@ -46,7 +46,7 @@ function setValue(data, element, name, value) {
|
|
|
46
46
|
else callback(element, name, value);
|
|
47
47
|
}
|
|
48
48
|
function updateChecked(element, name, value) {
|
|
49
|
-
updateElement(
|
|
49
|
+
updateElement(EVENT_CHANGE, PROPERTY_CHECKED, element, name, value, value === true);
|
|
50
50
|
}
|
|
51
51
|
function updateElement(event, property, element, name, value, next) {
|
|
52
52
|
if (!(property in element) || element[property] === next) return;
|
|
@@ -59,7 +59,7 @@ function updateProperty(element, name, value) {
|
|
|
59
59
|
setAttribute$1(element, name, value === true);
|
|
60
60
|
}
|
|
61
61
|
function updateValue(element, name, value) {
|
|
62
|
-
updateElement(element instanceof HTMLSelectElement ?
|
|
62
|
+
updateElement(element instanceof HTMLSelectElement ? EVENT_CHANGE : EVENT_INPUT, PROPERTY_VALUE, element, name, value, String(value));
|
|
63
63
|
}
|
|
64
64
|
//#endregion
|
|
65
65
|
export { setAttribute };
|
package/dist/node/event.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EVENT_DEFAULTS, EXPRESSION_EVENT_CHANGE_TYPES, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE } from "../constants.mjs";
|
|
1
|
+
import { EVENT_CHANGE, EVENT_DEFAULTS, EVENT_INPUT, EVENT_SUBMIT, EXPRESSION_EVENT_CHANGE_TYPES, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE } from "../constants.mjs";
|
|
2
2
|
import { on } from "@oscarpalmer/toretto/event";
|
|
3
3
|
//#region src/node/event.ts
|
|
4
4
|
function getOptions(options) {
|
|
@@ -12,8 +12,8 @@ function getOptions(options) {
|
|
|
12
12
|
function getType(element, type) {
|
|
13
13
|
if (type !== "on") return type;
|
|
14
14
|
if (element instanceof HTMLInputElement) {
|
|
15
|
-
if (EXPRESSION_EVENT_CHANGE_TYPES.test(element.type)) return
|
|
16
|
-
return element.type === "submit" ?
|
|
15
|
+
if (EXPRESSION_EVENT_CHANGE_TYPES.test(element.type)) return EVENT_CHANGE;
|
|
16
|
+
return element.type === "submit" ? EVENT_SUBMIT : EVENT_INPUT;
|
|
17
17
|
}
|
|
18
18
|
return EVENT_DEFAULTS[element.tagName] ?? type;
|
|
19
19
|
}
|
package/dist/node/value.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ARRAY_COMPARISON_ADDED } from "../constants.mjs";
|
|
1
2
|
import { compareArrays, isFragment } from "../helpers/index.mjs";
|
|
2
3
|
import { createNodes, replaceNodes } from "../helpers/dom.mjs";
|
|
3
4
|
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
@@ -25,7 +26,7 @@ function handleArray(identifiers, items, nodes) {
|
|
|
25
26
|
if (comparison !== "removed") addToArray(identifiers, {
|
|
26
27
|
...items,
|
|
27
28
|
next
|
|
28
|
-
}, nodes, comparison ===
|
|
29
|
+
}, nodes, comparison === ARRAY_COMPARISON_ADDED);
|
|
29
30
|
const toRemove = items.fragments?.filter((fragment) => !identifiers.next.has(fragment.identifier)) ?? [];
|
|
30
31
|
const { length } = toRemove;
|
|
31
32
|
for (let index = 0; index < length; index += 1) toRemove[index].remove();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/abydon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"components",
|
|
6
6
|
"dom",
|
|
@@ -39,12 +39,11 @@
|
|
|
39
39
|
"tsdown:build": "npx tsdown -c ./tsdown.config.ts",
|
|
40
40
|
"tsdown:watch": "npx tsdown -c ./tsdown.config.ts --watch",
|
|
41
41
|
"test": "npx vp test run --coverage",
|
|
42
|
-
"test:leak": "npx vp test run --detect-async-leaks --coverage"
|
|
43
|
-
"watch": "npx vite build --watch"
|
|
42
|
+
"test:leak": "npx vp test run --detect-async-leaks --coverage"
|
|
44
43
|
},
|
|
45
44
|
"dependencies": {
|
|
46
45
|
"@oscarpalmer/atoms": "^0.165",
|
|
47
|
-
"@oscarpalmer/mora": "^0.
|
|
46
|
+
"@oscarpalmer/mora": "^0.27",
|
|
48
47
|
"@oscarpalmer/toretto": "^0.41"
|
|
49
48
|
},
|
|
50
49
|
"devDependencies": {
|
package/src/constants.ts
CHANGED
|
@@ -1,15 +1,41 @@
|
|
|
1
|
+
export const ARRAY_COMPARISON_ADDED = 'added';
|
|
2
|
+
|
|
3
|
+
export const ARRAY_COMPARISON_DISSIMILAR = 'dissimilar';
|
|
4
|
+
|
|
5
|
+
export const ARRAY_COMPARISON_REMOVED = 'removed';
|
|
6
|
+
|
|
1
7
|
export const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
2
8
|
|
|
9
|
+
export const ATTRIBUTE_NAME_DELIMITER = '.';
|
|
10
|
+
|
|
11
|
+
export const ERROR_FRAGMENT = 'Fragment function must return a Fragment instance';
|
|
12
|
+
|
|
13
|
+
export const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<id>'";
|
|
14
|
+
|
|
15
|
+
export const ERROR_IDENTIFIER_TYPE = 'Identifier cannot be null or undefined';
|
|
16
|
+
|
|
17
|
+
export const EVENT_CHANGE = 'change';
|
|
18
|
+
|
|
19
|
+
export const EVENT_INPUT = 'input';
|
|
20
|
+
|
|
21
|
+
export const EVENT_SUBMIT = 'submit';
|
|
22
|
+
|
|
3
23
|
export const EVENT_DEFAULTS: Record<string, string> = {
|
|
4
24
|
A: 'click',
|
|
5
25
|
BUTTON: 'click',
|
|
6
26
|
DETAILS: 'toggle',
|
|
7
|
-
FORM:
|
|
8
|
-
SELECT:
|
|
9
|
-
TEXTAREA:
|
|
27
|
+
FORM: EVENT_SUBMIT,
|
|
28
|
+
SELECT: EVENT_CHANGE,
|
|
29
|
+
TEXTAREA: EVENT_INPUT,
|
|
10
30
|
};
|
|
11
31
|
|
|
12
|
-
export const
|
|
32
|
+
export const EVENT_ON_PREFIXED = '@on';
|
|
33
|
+
|
|
34
|
+
export const EVENT_ON_VALUE = 'on';
|
|
35
|
+
|
|
36
|
+
export const EVENT_OPTIONS_DELIMITER = ':';
|
|
37
|
+
|
|
38
|
+
export const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?[\w-]+)="<!--abydon.(\d+)-->"/g;
|
|
13
39
|
|
|
14
40
|
export const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX = /^_/;
|
|
15
41
|
|
|
@@ -38,3 +64,11 @@ export const EXPRESSION_PERIOD = /\./;
|
|
|
38
64
|
export const NAME_FRAGMENT = '$fragment';
|
|
39
65
|
|
|
40
66
|
export const NAME_FRAGMENTS = '$fragments';
|
|
67
|
+
|
|
68
|
+
export const PROPERTY_CHECKED = 'checked';
|
|
69
|
+
|
|
70
|
+
export const PROPERTY_IDENTIFIER = 'identifier';
|
|
71
|
+
|
|
72
|
+
export const PROPERTY_VALUE = 'value';
|
|
73
|
+
|
|
74
|
+
export const TEMPLATE_ITEM = '<>';
|
package/src/fragment.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
2
|
import {html} from '@oscarpalmer/toretto/html';
|
|
3
|
-
import {NAME_FRAGMENT} from './constants';
|
|
3
|
+
import {NAME_FRAGMENT, PROPERTY_IDENTIFIER} from './constants';
|
|
4
4
|
import {handleFragments} from './fragments';
|
|
5
5
|
import {isFragments} from './helpers';
|
|
6
6
|
import {removeNodes} from './helpers/dom';
|
|
@@ -56,7 +56,7 @@ export class Fragment {
|
|
|
56
56
|
configure(configuration: FragmentConfiguration): Fragment {
|
|
57
57
|
const actual = isPlainObject(configuration) ? configuration : {};
|
|
58
58
|
|
|
59
|
-
if (
|
|
59
|
+
if (PROPERTY_IDENTIFIER in actual) {
|
|
60
60
|
this.#configuration.identifier = actual.identifier;
|
|
61
61
|
}
|
|
62
62
|
|
package/src/fragments.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import {getString} from '@oscarpalmer/atoms/string';
|
|
2
2
|
import {array, type ReactiveArray} from '@oscarpalmer/mora';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ERROR_FRAGMENT,
|
|
5
|
+
ERROR_IDENTIFIER_DUPLICATE,
|
|
6
|
+
ERROR_IDENTIFIER_TYPE,
|
|
7
|
+
NAME_FRAGMENTS,
|
|
8
|
+
TEMPLATE_ITEM,
|
|
9
|
+
} from './constants';
|
|
4
10
|
import type {Fragment} from './fragment';
|
|
5
11
|
import {isFragment, isFragments} from './helpers';
|
|
6
12
|
import type {FragmentsState} from './models';
|
|
@@ -58,13 +64,13 @@ function handleItems(state: FragmentsState, items: unknown[]): void {
|
|
|
58
64
|
const identifier = state.identify(item);
|
|
59
65
|
|
|
60
66
|
if (identifier == null) {
|
|
61
|
-
throw new
|
|
67
|
+
throw new TypeError(ERROR_IDENTIFIER_TYPE);
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
const key = getString(identifier);
|
|
65
71
|
|
|
66
72
|
if (keys.has(key)) {
|
|
67
|
-
throw new Error(
|
|
73
|
+
throw new Error(ERROR_IDENTIFIER_DUPLICATE.replace(TEMPLATE_ITEM, key));
|
|
68
74
|
}
|
|
69
75
|
|
|
70
76
|
let instance = state.instances[key];
|
|
@@ -73,7 +79,7 @@ function handleItems(state: FragmentsState, items: unknown[]): void {
|
|
|
73
79
|
instance = state.fragment(item);
|
|
74
80
|
|
|
75
81
|
if (!isFragment(instance)) {
|
|
76
|
-
throw new Error(
|
|
82
|
+
throw new Error(ERROR_FRAGMENT);
|
|
77
83
|
}
|
|
78
84
|
}
|
|
79
85
|
|
package/src/helpers/dom.ts
CHANGED
|
@@ -14,6 +14,16 @@ export function createNodes(value: unknown): ChildNode[] {
|
|
|
14
14
|
return [new Text(getString(value))];
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
export function isInputElement(
|
|
18
|
+
node: Node,
|
|
19
|
+
): node is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement {
|
|
20
|
+
return (
|
|
21
|
+
node instanceof HTMLInputElement ||
|
|
22
|
+
node instanceof HTMLSelectElement ||
|
|
23
|
+
node instanceof HTMLTextAreaElement
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
17
27
|
export function removeNodes(nodes: ChildNode[]): void {
|
|
18
28
|
const {length} = nodes;
|
|
19
29
|
|
package/src/helpers/index.ts
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ARRAY_COMPARISON_ADDED,
|
|
4
|
+
ARRAY_COMPARISON_DISSIMILAR,
|
|
5
|
+
ARRAY_COMPARISON_REMOVED,
|
|
6
|
+
NAME_FRAGMENT,
|
|
7
|
+
NAME_FRAGMENTS,
|
|
8
|
+
} from '../constants';
|
|
3
9
|
import type {Fragment} from '../fragment';
|
|
4
10
|
import type {Fragments} from '../fragments';
|
|
5
11
|
|
|
6
12
|
export function compareArrays(
|
|
7
13
|
first: unknown[],
|
|
8
14
|
second: unknown[],
|
|
9
|
-
):
|
|
15
|
+
):
|
|
16
|
+
| typeof ARRAY_COMPARISON_ADDED
|
|
17
|
+
| typeof ARRAY_COMPARISON_DISSIMILAR
|
|
18
|
+
| typeof ARRAY_COMPARISON_REMOVED {
|
|
10
19
|
const firstIsLarger = first.length > second.length;
|
|
11
20
|
const from = firstIsLarger ? first : second;
|
|
12
21
|
const to = firstIsLarger ? second : first;
|
|
13
22
|
|
|
14
23
|
if (!from.filter(key => to.includes(key)).every((key, index) => to[index] === key)) {
|
|
15
|
-
return
|
|
24
|
+
return ARRAY_COMPARISON_DISSIMILAR;
|
|
16
25
|
}
|
|
17
26
|
|
|
18
|
-
return firstIsLarger ?
|
|
27
|
+
return firstIsLarger ? ARRAY_COMPARISON_REMOVED : ARRAY_COMPARISON_ADDED;
|
|
19
28
|
}
|
|
20
29
|
|
|
21
30
|
export function isFragment(value: unknown): value is Fragment {
|
|
@@ -34,9 +43,3 @@ function isNamed(value: unknown, name: string): boolean {
|
|
|
34
43
|
(value as PlainObject)[name] === true
|
|
35
44
|
);
|
|
36
45
|
}
|
|
37
|
-
|
|
38
|
-
const COMPARISON_ADDED = 'added';
|
|
39
|
-
|
|
40
|
-
const COMPARISON_DISSIMILAR = 'dissimilar';
|
|
41
|
-
|
|
42
|
-
const COMPARISON_REMOVED = 'removed';
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import {
|
|
2
|
+
import {parse} from '@oscarpalmer/atoms/string';
|
|
3
|
+
import {computed, isReactive, isSignal} from '@oscarpalmer/mora';
|
|
3
4
|
import {
|
|
5
|
+
EVENT_ON_PREFIXED,
|
|
4
6
|
EXPRESSION_ABYDON_ATTRIBUTE_PREFIX,
|
|
5
7
|
EXPRESSION_ABYDON_CONTENT,
|
|
6
8
|
EXPRESSION_EVENT_PREFIX,
|
|
7
9
|
EXPRESSION_PERIOD,
|
|
10
|
+
PROPERTY_VALUE,
|
|
8
11
|
} from '../../constants';
|
|
12
|
+
import {isInputElement} from '../../helpers/dom';
|
|
9
13
|
import type {FragmentData} from '../../models';
|
|
10
14
|
import {mapEvent} from '../event';
|
|
11
15
|
import {setAttribute} from './value';
|
|
@@ -58,6 +62,12 @@ function mapValue(
|
|
|
58
62
|
} else {
|
|
59
63
|
setAttribute(data, element, name, value);
|
|
60
64
|
}
|
|
65
|
+
|
|
66
|
+
if (name === PROPERTY_VALUE && isInputElement(element) && isSignal(value)) {
|
|
67
|
+
mapEvent(element, EVENT_ON_PREFIXED, () => {
|
|
68
|
+
value.set(parse(element.value) ?? element.value);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
61
71
|
}
|
|
62
72
|
|
|
63
73
|
function setComputedAttribute(
|
|
@@ -6,18 +6,23 @@ import {
|
|
|
6
6
|
} from '@oscarpalmer/toretto/attribute';
|
|
7
7
|
import {
|
|
8
8
|
ATTRIBUTE_CLASS_PREFIX_LENGTH,
|
|
9
|
+
ATTRIBUTE_NAME_DELIMITER,
|
|
10
|
+
EVENT_CHANGE,
|
|
11
|
+
EVENT_INPUT,
|
|
9
12
|
EXPRESSION_ATTRIBUTE_CLASS,
|
|
10
13
|
EXPRESSION_ATTRIBUTE_STYLE_FULL,
|
|
11
14
|
EXPRESSION_ATTRIBUTE_STYLE_PREFIX,
|
|
15
|
+
PROPERTY_CHECKED,
|
|
16
|
+
PROPERTY_VALUE,
|
|
12
17
|
} from '../../constants';
|
|
13
18
|
import type {FragmentData} from '../../models';
|
|
14
19
|
|
|
15
20
|
function getCallback(element: HTMLElement | SVGElement, name: string) {
|
|
16
21
|
if (isBooleanAttribute(name) && name in element) {
|
|
17
|
-
return name ===
|
|
22
|
+
return name === PROPERTY_CHECKED ? updateChecked : updateProperty;
|
|
18
23
|
}
|
|
19
24
|
|
|
20
|
-
return name ===
|
|
25
|
+
return name === PROPERTY_VALUE ? updateValue : setTorettoAttribute;
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
export function setAttribute(
|
|
@@ -55,7 +60,7 @@ function setClasses(
|
|
|
55
60
|
}
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
const classes = name.slice(ATTRIBUTE_CLASS_PREFIX_LENGTH).split(
|
|
63
|
+
const classes = name.slice(ATTRIBUTE_CLASS_PREFIX_LENGTH).split(ATTRIBUTE_NAME_DELIMITER);
|
|
59
64
|
|
|
60
65
|
if (isReactive(value)) {
|
|
61
66
|
data.mora.subscribers.add(value.subscribe(update));
|
|
@@ -111,7 +116,7 @@ function setValue(
|
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
function updateChecked(element: HTMLElement | SVGElement, name: string, value: unknown): void {
|
|
114
|
-
updateElement(
|
|
119
|
+
updateElement(EVENT_CHANGE, PROPERTY_CHECKED, element, name, value, value === true);
|
|
115
120
|
}
|
|
116
121
|
|
|
117
122
|
function updateElement(
|
|
@@ -143,8 +148,8 @@ function updateProperty(element: HTMLElement | SVGElement, name: string, value:
|
|
|
143
148
|
|
|
144
149
|
function updateValue(element: HTMLElement | SVGElement, name: string, value: unknown): void {
|
|
145
150
|
updateElement(
|
|
146
|
-
element instanceof HTMLSelectElement ?
|
|
147
|
-
|
|
151
|
+
element instanceof HTMLSelectElement ? EVENT_CHANGE : EVENT_INPUT,
|
|
152
|
+
PROPERTY_VALUE,
|
|
148
153
|
element,
|
|
149
154
|
name,
|
|
150
155
|
value,
|
package/src/node/event.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import {on} from '@oscarpalmer/toretto/event';
|
|
2
2
|
import {
|
|
3
|
+
EVENT_CHANGE,
|
|
3
4
|
EVENT_DEFAULTS,
|
|
5
|
+
EVENT_INPUT,
|
|
6
|
+
EVENT_ON_VALUE,
|
|
7
|
+
EVENT_OPTIONS_DELIMITER,
|
|
8
|
+
EVENT_SUBMIT,
|
|
4
9
|
EXPRESSION_EVENT_CHANGE_TYPES,
|
|
5
10
|
EXPRESSION_EVENT_NAME,
|
|
6
11
|
EXPRESSION_EVENT_OPTIONS_ACTIVE,
|
|
@@ -9,7 +14,7 @@ import {
|
|
|
9
14
|
} from '../constants';
|
|
10
15
|
|
|
11
16
|
function getOptions(options: string): AddEventListenerOptions {
|
|
12
|
-
const parts = options.split(
|
|
17
|
+
const parts = options.split(EVENT_OPTIONS_DELIMITER);
|
|
13
18
|
|
|
14
19
|
return {
|
|
15
20
|
capture: parts.some(part => EXPRESSION_EVENT_OPTIONS_CAPTURE.test(part)),
|
|
@@ -19,16 +24,16 @@ function getOptions(options: string): AddEventListenerOptions {
|
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
function getType(element: HTMLElement | SVGElement, type: string): string {
|
|
22
|
-
if (type !==
|
|
27
|
+
if (type !== EVENT_ON_VALUE) {
|
|
23
28
|
return type;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
if (element instanceof HTMLInputElement) {
|
|
27
32
|
if (EXPRESSION_EVENT_CHANGE_TYPES.test(element.type)) {
|
|
28
|
-
return
|
|
33
|
+
return EVENT_CHANGE;
|
|
29
34
|
}
|
|
30
35
|
|
|
31
|
-
return element.type ===
|
|
36
|
+
return element.type === EVENT_SUBMIT ? EVENT_SUBMIT : EVENT_INPUT;
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
return EVENT_DEFAULTS[element.tagName] ?? type;
|
package/src/node/value.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {isNullableOrWhitespace} from '@oscarpalmer/atoms/is';
|
|
|
2
2
|
import {getString} from '@oscarpalmer/atoms/string';
|
|
3
3
|
import type {Reactive} from '@oscarpalmer/mora';
|
|
4
4
|
import {isChildNode} from '@oscarpalmer/toretto/is';
|
|
5
|
+
import {ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_REMOVED} from '../constants';
|
|
5
6
|
import type {Fragment} from '../fragment';
|
|
6
7
|
import {compareArrays, isFragment} from '../helpers';
|
|
7
8
|
import {createNodes, replaceNodes} from '../helpers/dom';
|
|
@@ -71,8 +72,8 @@ function handleArray(
|
|
|
71
72
|
|
|
72
73
|
const comparison = compareArrays(items.fragments ?? [], items.templates);
|
|
73
74
|
|
|
74
|
-
if (comparison !==
|
|
75
|
-
addToArray(identifiers, {...items, next}, nodes, comparison ===
|
|
75
|
+
if (comparison !== ARRAY_COMPARISON_REMOVED) {
|
|
76
|
+
addToArray(identifiers, {...items, next}, nodes, comparison === ARRAY_COMPARISON_ADDED);
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
const toRemove =
|