vasille 2.0.0 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cdn/es2015.js ADDED
@@ -0,0 +1,3234 @@
1
+ (function(){
2
+ // ./lib/models/model.js
3
+
4
+
5
+
6
+ // ./lib/models/listener.js
7
+ /**
8
+ * Represent a listener for a model
9
+ * @class Listener
10
+ */
11
+ class Listener {
12
+ constructor() {
13
+ Object.defineProperties(this, {
14
+ onAdded: {
15
+ value: new Set,
16
+ writable: false,
17
+ configurable: false
18
+ },
19
+ onRemoved: {
20
+ value: new Set,
21
+ writable: false,
22
+ configurable: false
23
+ },
24
+ frozen: {
25
+ value: false,
26
+ writable: true,
27
+ configurable: false
28
+ },
29
+ queue: {
30
+ value: [],
31
+ writable: false,
32
+ configurable: false
33
+ }
34
+ });
35
+ }
36
+ /**
37
+ * Exclude the repeated operation in queue
38
+ * @private
39
+ */
40
+ excludeRepeat(index) {
41
+ this.queue.forEach((item, i) => {
42
+ if (item.index === index) {
43
+ this.queue.splice(i, 1);
44
+ return true;
45
+ }
46
+ });
47
+ return false;
48
+ }
49
+ /**
50
+ * Emits added event to listeners
51
+ * @param index {*} index of value
52
+ * @param value {*} value of added item
53
+ */
54
+ emitAdded(index, value) {
55
+ if (this.frozen) {
56
+ if (!this.excludeRepeat(index)) {
57
+ this.queue.push({ sign: true, index, value });
58
+ }
59
+ }
60
+ else {
61
+ this.onAdded.forEach(handler => {
62
+ handler(index, value);
63
+ });
64
+ }
65
+ }
66
+ /**
67
+ * Emits removed event to listeners
68
+ * @param index {*} index of removed value
69
+ * @param value {*} value of removed item
70
+ */
71
+ emitRemoved(index, value) {
72
+ if (this.frozen) {
73
+ if (!this.excludeRepeat(index)) {
74
+ this.queue.push({ sign: false, index, value });
75
+ }
76
+ }
77
+ else {
78
+ this.onRemoved.forEach(handler => {
79
+ handler(index, value);
80
+ });
81
+ }
82
+ }
83
+ /**
84
+ * Adds a handler to added event
85
+ * @param handler {function} function to run on event emitting
86
+ */
87
+ onAdd(handler) {
88
+ this.onAdded.add(handler);
89
+ }
90
+ /**
91
+ * Adds a handler to removed event
92
+ * @param handler {function} function to run on event emitting
93
+ */
94
+ onRemove(handler) {
95
+ this.onRemoved.add(handler);
96
+ }
97
+ /**
98
+ * Removes an handler from added event
99
+ * @param handler {function} handler to remove
100
+ */
101
+ offAdd(handler) {
102
+ this.onAdded.delete(handler);
103
+ }
104
+ /**
105
+ * Removes an handler form removed event
106
+ * @param handler {function} handler to remove
107
+ */
108
+ offRemove(handler) {
109
+ this.onRemoved.delete(handler);
110
+ }
111
+ /**
112
+ * Run all queued operation and enable reactivity
113
+ */
114
+ enableReactivity() {
115
+ this.queue.forEach(item => {
116
+ if (item.sign) {
117
+ this.onAdded.forEach(handler => {
118
+ handler(item.index, item.value);
119
+ });
120
+ }
121
+ else {
122
+ this.onRemoved.forEach(handler => {
123
+ handler(item.index, item.value);
124
+ });
125
+ }
126
+ });
127
+ this.queue.splice(0);
128
+ this.frozen = false;
129
+ }
130
+ /**
131
+ * Disable the reactivity and enable the queue
132
+ */
133
+ disableReactivity() {
134
+ this.frozen = true;
135
+ }
136
+ }
137
+
138
+ window.Listener = Listener;
139
+
140
+ // ./lib/models/object-model.js
141
+ /**
142
+ * Object based model
143
+ * @extends Object
144
+ */
145
+ class ObjectModel extends Object {
146
+ /**
147
+ * Constructs a object model
148
+ * @param obj {Object} input data
149
+ */
150
+ constructor(obj = {}) {
151
+ super();
152
+ Object.defineProperty(this, 'listener', {
153
+ value: new Listener,
154
+ writable: false,
155
+ configurable: false
156
+ });
157
+ for (const i in obj) {
158
+ Object.defineProperty(this, i, {
159
+ value: obj[i],
160
+ configurable: true,
161
+ writable: true,
162
+ enumerable: true
163
+ });
164
+ this.listener.emitAdded(i, obj[i]);
165
+ }
166
+ }
167
+ /**
168
+ * Gets a value of a field
169
+ * @param key {string}
170
+ * @return {*}
171
+ */
172
+ get(key) {
173
+ const ts = this;
174
+ return ts[key];
175
+ }
176
+ /**
177
+ * Sets an object property value
178
+ * @param key {string} property name
179
+ * @param v {*} property value
180
+ * @return {ObjectModel} a pointer to this
181
+ */
182
+ set(key, v) {
183
+ const ts = this;
184
+ // eslint-disable-next-line no-prototype-builtins
185
+ if (ts.hasOwnProperty(key)) {
186
+ this.listener.emitRemoved(key, ts[key]);
187
+ ts[key] = v;
188
+ }
189
+ else {
190
+ Object.defineProperty(ts, key, {
191
+ value: v,
192
+ configurable: true,
193
+ writable: true,
194
+ enumerable: true
195
+ });
196
+ }
197
+ this.listener.emitAdded(key, ts[key]);
198
+ return this;
199
+ }
200
+ /**
201
+ * Deletes an object property
202
+ * @param key {string} property name
203
+ */
204
+ delete(key) {
205
+ const ts = this;
206
+ if (ts[key]) {
207
+ this.listener.emitRemoved(key, ts[key]);
208
+ delete ts[key];
209
+ }
210
+ }
211
+ enableReactivity() {
212
+ this.listener.enableReactivity();
213
+ }
214
+ disableReactivity() {
215
+ this.listener.disableReactivity();
216
+ }
217
+ }
218
+
219
+ window.ObjectModel = ObjectModel;
220
+
221
+ // ./lib/models/set-model.js
222
+ /**
223
+ * A Set based model
224
+ * @class SetModel
225
+ * @extends Set
226
+ * @implements IModel
227
+ */
228
+ class SetModel extends Set {
229
+ /**
230
+ * Constructs a set model based on a set
231
+ * @param set {Set} input data
232
+ */
233
+ constructor(set = []) {
234
+ super();
235
+ Object.defineProperty(this, 'listener', {
236
+ value: new Listener,
237
+ writable: false,
238
+ configurable: false
239
+ });
240
+ set.forEach(item => {
241
+ super.add(item);
242
+ });
243
+ }
244
+ /**
245
+ * Calls Set.add and notify abut changes
246
+ * @param value {*} value
247
+ * @return {this} a pointer to this
248
+ */
249
+ add(value) {
250
+ if (!super.has(value)) {
251
+ this.listener.emitAdded(value, value);
252
+ super.add(value);
253
+ }
254
+ return this;
255
+ }
256
+ /**
257
+ * Calls Set.clear and notify abut changes
258
+ */
259
+ clear() {
260
+ this.forEach(item => {
261
+ this.listener.emitRemoved(item, item);
262
+ });
263
+ super.clear();
264
+ }
265
+ /**
266
+ * Calls Set.delete and notify abut changes
267
+ * @param value {*}
268
+ * @return {boolean} true if a value was deleted, otherwise false
269
+ */
270
+ delete(value) {
271
+ if (super.has(value)) {
272
+ this.listener.emitRemoved(value, value);
273
+ }
274
+ return super.delete(value);
275
+ }
276
+ enableReactivity() {
277
+ this.listener.enableReactivity();
278
+ }
279
+ disableReactivity() {
280
+ this.listener.disableReactivity();
281
+ }
282
+ }
283
+
284
+ window.SetModel = SetModel;
285
+
286
+ // ./lib/models/map-model.js
287
+ /**
288
+ * A Map based memory
289
+ * @class MapModel
290
+ * @extends Map
291
+ * @implements IModel
292
+ */
293
+ class MapModel extends Map {
294
+ /**
295
+ * Constructs a map model
296
+ * @param map {[*, *][]} input data
297
+ */
298
+ constructor(map = []) {
299
+ super();
300
+ Object.defineProperty(this, 'listener', {
301
+ value: new Listener,
302
+ writable: false,
303
+ configurable: false
304
+ });
305
+ map.forEach(([key, value]) => {
306
+ super.set(key, value);
307
+ });
308
+ }
309
+ /**
310
+ * Calls Map.clear and notify abut changes
311
+ */
312
+ clear() {
313
+ this.forEach((value, key) => {
314
+ this.listener.emitRemoved(key, value);
315
+ });
316
+ super.clear();
317
+ }
318
+ /**
319
+ * Calls Map.delete and notify abut changes
320
+ * @param key {*} key
321
+ * @return {boolean} true if removed something, otherwise false
322
+ */
323
+ delete(key) {
324
+ const tmp = super.get(key);
325
+ if (tmp) {
326
+ this.listener.emitRemoved(key, tmp);
327
+ }
328
+ return super.delete(key);
329
+ }
330
+ /**
331
+ * Calls Map.set and notify abut changes
332
+ * @param key {*} key
333
+ * @param value {*} value
334
+ * @return {MapModel} a pointer to this
335
+ */
336
+ set(key, value) {
337
+ const tmp = super.get(key);
338
+ if (tmp) {
339
+ this.listener.emitRemoved(key, tmp);
340
+ }
341
+ super.set(key, value);
342
+ this.listener.emitAdded(key, value);
343
+ return this;
344
+ }
345
+ enableReactivity() {
346
+ this.listener.enableReactivity();
347
+ }
348
+ disableReactivity() {
349
+ this.listener.disableReactivity();
350
+ }
351
+ }
352
+
353
+ window.MapModel = MapModel;
354
+
355
+ // ./lib/models/array-model.js
356
+ /**
357
+ * Model based on Array class
358
+ * @extends Array
359
+ * @implements IModel
360
+ */
361
+ class ArrayModel extends Array {
362
+ /**
363
+ * @param data {Array} input data
364
+ */
365
+ constructor(data = []) {
366
+ super();
367
+ Object.defineProperty(this, 'listener', {
368
+ value: new Listener,
369
+ writable: false,
370
+ configurable: false
371
+ });
372
+ for (let i = 0; i < data.length; i++) {
373
+ super.push(data[i]);
374
+ }
375
+ }
376
+ /* Array members */
377
+ /**
378
+ * Gets the last item of array
379
+ * @return {*} the last item of array
380
+ */
381
+ get last() {
382
+ return this.length ? this[this.length - 1] : null;
383
+ }
384
+ /**
385
+ * Calls Array.fill and notify about changes
386
+ * @param value {*} value to fill with
387
+ * @param start {?number} begin index
388
+ * @param end {?number} end index
389
+ */
390
+ fill(value, start, end) {
391
+ if (!start) {
392
+ start = 0;
393
+ }
394
+ if (!end) {
395
+ end = this.length;
396
+ }
397
+ for (let i = start; i < end; i++) {
398
+ this.listener.emitRemoved(this[i], this[i]);
399
+ this[i] = value;
400
+ this.listener.emitAdded(value, value);
401
+ }
402
+ return this;
403
+ }
404
+ /**
405
+ * Calls Array.pop and notify about changes
406
+ * @return {*} removed value
407
+ */
408
+ pop() {
409
+ const v = super.pop();
410
+ if (v !== undefined) {
411
+ this.listener.emitRemoved(v, v);
412
+ }
413
+ return v;
414
+ }
415
+ /**
416
+ * Calls Array.push and notify about changes
417
+ * @param items {...*} values to push
418
+ * @return {number} new length of array
419
+ */
420
+ push(...items) {
421
+ items.forEach(item => {
422
+ this.listener.emitAdded(item, item);
423
+ super.push(item);
424
+ });
425
+ return this.length;
426
+ }
427
+ /**
428
+ * Calls Array.shift and notify about changed
429
+ * @return {*} the shifted value
430
+ */
431
+ shift() {
432
+ const v = super.shift();
433
+ if (v !== undefined) {
434
+ this.listener.emitRemoved(v, v);
435
+ }
436
+ return v;
437
+ }
438
+ /**
439
+ * Calls Array.splice and notify about changed
440
+ * @param start {number} start index
441
+ * @param deleteCount {?number} delete count
442
+ * @param items {...*}
443
+ * @return {ArrayModel} a pointer to this
444
+ */
445
+ splice(start, deleteCount, ...items) {
446
+ start = Math.min(start, this.length);
447
+ deleteCount = deleteCount || this.length - start;
448
+ const before = this[start + deleteCount];
449
+ for (let i = 0; i < deleteCount; i++) {
450
+ const index = start + deleteCount - i - 1;
451
+ if (this[index] !== undefined) {
452
+ this.listener.emitRemoved(this[index], this[index]);
453
+ }
454
+ }
455
+ for (let i = 0; i < items.length; i++) {
456
+ this.listener.emitAdded(before, items[i]);
457
+ }
458
+ return new ArrayModel(super.splice(start, deleteCount, ...items));
459
+ }
460
+ /**
461
+ * Calls Array.unshift and notify about changed
462
+ * @param items {...*} values to insert
463
+ * @return {number} the length after prepend
464
+ */
465
+ unshift(...items) {
466
+ for (let i = 0; i < items.length; i++) {
467
+ this.listener.emitAdded(this[i], items[i]);
468
+ }
469
+ return super.unshift(...items);
470
+ }
471
+ /**
472
+ * Inserts a value to the end of array
473
+ * @param v {*} value to insert
474
+ */
475
+ append(v) {
476
+ this.listener.emitAdded(null, v);
477
+ super.push(v);
478
+ return this;
479
+ }
480
+ /**
481
+ * Clears array
482
+ * @return {this} a pointer to this
483
+ */
484
+ clear() {
485
+ this.forEach(v => {
486
+ this.listener.emitRemoved(v, v);
487
+ });
488
+ super.splice(0);
489
+ return this;
490
+ }
491
+ /**
492
+ * Inserts a value to position `index`
493
+ * @param index {number} index to insert value
494
+ * @param v {*} value to insert
495
+ * @return {this} a pointer to this
496
+ */
497
+ insert(index, v) {
498
+ this.listener.emitAdded(this[index], v);
499
+ super.splice(index, 0, v);
500
+ return this;
501
+ }
502
+ /**
503
+ * Inserts a value to the beginning of array
504
+ * @param v {*} value to insert
505
+ * @return {this} a pointer to this
506
+ */
507
+ prepend(v) {
508
+ this.listener.emitAdded(this[0], v);
509
+ super.unshift(v);
510
+ return this;
511
+ }
512
+ /**
513
+ * Removes a value from an index
514
+ * @param index {number} index of value to remove
515
+ * @return {this} a pointer to this
516
+ */
517
+ removeAt(index) {
518
+ if (index > 0 && index < this.length) {
519
+ this.listener.emitRemoved(this[index], this[index]);
520
+ super.splice(index, 1);
521
+ }
522
+ return this;
523
+ }
524
+ /**
525
+ * Removes the first value of array
526
+ * @return {this} a pointer to this
527
+ */
528
+ removeFirst() {
529
+ if (this.length) {
530
+ this.listener.emitRemoved(this[0], this[0]);
531
+ super.shift();
532
+ }
533
+ return this;
534
+ }
535
+ /**
536
+ * Removes the ast value of array
537
+ * @return {this} a pointer to this
538
+ */
539
+ removeLast() {
540
+ const last = this.last;
541
+ if (last != null) {
542
+ this.listener.emitRemoved(this[this.length - 1], last);
543
+ super.pop();
544
+ }
545
+ return this;
546
+ }
547
+ /**
548
+ * Remove the first occurrence of value
549
+ * @param v {*} value to remove
550
+ * @return {this}
551
+ */
552
+ removeOne(v) {
553
+ this.removeAt(this.indexOf(v));
554
+ return this;
555
+ }
556
+ enableReactivity() {
557
+ this.listener.enableReactivity();
558
+ }
559
+ disableReactivity() {
560
+ this.listener.disableReactivity();
561
+ }
562
+ }
563
+
564
+ window.ArrayModel = ArrayModel;
565
+
566
+ // ./lib/core/signal.js
567
+ /**
568
+ * Signal is an event generator
569
+ * @class Signal
570
+ */
571
+ class Signal {
572
+ constructor() {
573
+ /**
574
+ * Handler of event
575
+ * @type {Set}
576
+ * @private
577
+ */
578
+ this.handlers = new Set;
579
+ }
580
+ /**
581
+ * Emit event
582
+ * @param a1 {*} argument
583
+ * @param a2 {*} argument
584
+ * @param a3 {*} argument
585
+ * @param a4 {*} argument
586
+ * @param a5 {*} argument
587
+ * @param a6 {*} argument
588
+ * @param a7 {*} argument
589
+ * @param a8 {*} argument
590
+ * @param a9 {*} argument
591
+ */
592
+ emit(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
593
+ this.handlers.forEach(handler => {
594
+ try {
595
+ handler(a1, a2, a3, a4, a5, a6, a7, a8, a9);
596
+ }
597
+ catch (e) {
598
+ console.error(`Vasille.js: Handler throw exception: `, e);
599
+ }
600
+ });
601
+ }
602
+ /**
603
+ * Subscribe to event
604
+ * @param func {function} handler
605
+ */
606
+ subscribe(func) {
607
+ this.handlers.add(func);
608
+ }
609
+ /**
610
+ * Unsubscribe from event
611
+ * @param func {function} handler
612
+ */
613
+ unsubscribe(func) {
614
+ this.handlers.delete(func);
615
+ }
616
+ }
617
+
618
+ window.Signal = Signal;
619
+
620
+ // ./lib/core/slot.js
621
+ /**
622
+ * Component slot
623
+ * @class Slot
624
+ */
625
+ class Slot {
626
+ /**
627
+ * Sets the runner
628
+ * @param func {function} the function to run
629
+ */
630
+ insert(func) {
631
+ this.runner = func;
632
+ }
633
+ /**
634
+ * @param a0 {Fragment} node to paste content
635
+ * @param a1 {*} 1st argument
636
+ * @param a2 {*} 2nd argument
637
+ * @param a3 {*} 3rd argument
638
+ * @param a4 {*} 4th argument
639
+ * @param a5 {*} 5th argument
640
+ * @param a6 {*} 6th argument
641
+ * @param a7 {*} 7th argument
642
+ * @param a8 {*} 8th argument
643
+ * @param a9 {*} 9th argument
644
+ */
645
+ release(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
646
+ if (this.runner) {
647
+ this.runner(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
648
+ }
649
+ }
650
+ /**
651
+ * Predefine a handler for a slot
652
+ * @param func {function(node : Fragment)} Function to run if no handler specified
653
+ * @param a0 {Fragment} node to paste content
654
+ * @param a1 {*} 1st argument
655
+ * @param a2 {*} 2nd argument
656
+ * @param a3 {*} 3rd argument
657
+ * @param a4 {*} 4th argument
658
+ * @param a5 {*} 5th argument
659
+ * @param a6 {*} 6th argument
660
+ * @param a7 {*} 7th argument
661
+ * @param a8 {*} 8th argument
662
+ * @param a9 {*} 9th argument
663
+ */
664
+ predefine(func, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
665
+ (this.runner || func)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
666
+ }
667
+ }
668
+
669
+ window.Slot = Slot;
670
+
671
+ // ./lib/core/errors.js
672
+ const reportIt = "Report it here: https://gitlab.com/vasille-js/vasille-js/-/issues";
673
+ function notOverwritten() {
674
+ console.error("Vasille-SFP: Internal error", "Must be overwritten", reportIt);
675
+ return "not-overwritten";
676
+ }
677
+ function internalError(msg) {
678
+ console.error("Vasille-SFP: Internal error", msg, reportIt);
679
+ return "internal-error";
680
+ }
681
+ function userError(msg, err) {
682
+ console.error("Vasille-SFP: User error", msg);
683
+ return err;
684
+ }
685
+ function wrongBinding(msg) {
686
+ return userError(msg, "wrong-binding");
687
+ }
688
+
689
+ window.notOverwritten = notOverwritten;
690
+ window.internalError = internalError;
691
+ window.userError = userError;
692
+ window.wrongBinding = wrongBinding;
693
+
694
+ // ./lib/core/executor.js
695
+ /**
696
+ * Represents an executor unit interface
697
+ * @class Executor
698
+ */
699
+ class Executor {
700
+ /**
701
+ * Adds a CSS class
702
+ * @param el {Element} element to manipulate
703
+ * @param cl {string} class to be added
704
+ */
705
+ addClass(el, cl) {
706
+ throw notOverwritten();
707
+ }
708
+ /**
709
+ * Removes a CSS class
710
+ * @param el {Element} element to manipulate
711
+ * @param cl {string} class to be removed
712
+ */
713
+ removeClass(el, cl) {
714
+ throw notOverwritten();
715
+ }
716
+ /**
717
+ * Sets a tag attribute
718
+ * @param el {Element} element to manipulate
719
+ * @param name {string} name of attribute
720
+ * @param value {string} value of attribute
721
+ */
722
+ setAttribute(el, name, value) {
723
+ throw notOverwritten();
724
+ }
725
+ /**
726
+ * Removes a tag attribute
727
+ * @param el {Element} element to manipulate
728
+ * @param name {string} name of attribute
729
+ */
730
+ removeAttribute(el, name) {
731
+ throw notOverwritten();
732
+ }
733
+ /**
734
+ * Sets a style attribute
735
+ * @param el {HTMLElement} element to manipulate
736
+ * @param prop {string} property name
737
+ * @param value {string} property value
738
+ */
739
+ setStyle(el, prop, value) {
740
+ throw notOverwritten();
741
+ }
742
+ /**
743
+ * Inserts a child before target
744
+ * @param target {Element} target element
745
+ * @param child {Node} element to insert before
746
+ */
747
+ insertBefore(target, child) {
748
+ throw notOverwritten();
749
+ }
750
+ /**
751
+ * Appends a child to element
752
+ * @param el {Element} element
753
+ * @param child {Node} child to be inserted
754
+ */
755
+ appendChild(el, child) {
756
+ throw notOverwritten();
757
+ }
758
+ /**
759
+ * Calls a call-back function
760
+ * @param cb {function} call-back function
761
+ */
762
+ callCallback(cb) {
763
+ throw notOverwritten();
764
+ }
765
+ }
766
+ /**
767
+ * Executor which execute any commands immediately
768
+ * @class InstantExecutor
769
+ * @extends Executor
770
+ */
771
+ class InstantExecutor extends Executor {
772
+ addClass(el, cl) {
773
+ el.classList.add(cl);
774
+ }
775
+ removeClass(el, cl) {
776
+ el.classList.remove(cl);
777
+ }
778
+ setAttribute(el, name, value) {
779
+ el.setAttribute(name, value);
780
+ }
781
+ removeAttribute(el, name) {
782
+ el.removeAttribute(name);
783
+ }
784
+ setStyle(el, prop, value) {
785
+ el.style.setProperty(prop, value);
786
+ }
787
+ insertBefore(target, child) {
788
+ const parent = target.parentNode;
789
+ if (!parent) {
790
+ throw internalError('element don\'t have a parent node');
791
+ }
792
+ parent.insertBefore(child, target);
793
+ }
794
+ appendChild(el, child) {
795
+ el.appendChild(child);
796
+ }
797
+ callCallback(cb) {
798
+ cb();
799
+ }
800
+ }
801
+ /**
802
+ * Executor which execute any commands over timeout
803
+ * @class TimeoutExecutor
804
+ * @extends InstantExecutor
805
+ */
806
+ class TimeoutExecutor extends InstantExecutor {
807
+ addClass(el, cl) {
808
+ setTimeout(() => {
809
+ super.addClass(el, cl);
810
+ }, 0);
811
+ }
812
+ removeClass(el, cl) {
813
+ setTimeout(() => {
814
+ super.removeClass(el, cl);
815
+ }, 0);
816
+ }
817
+ setAttribute(el, name, value) {
818
+ setTimeout(() => {
819
+ super.setAttribute(el, name, value);
820
+ }, 0);
821
+ }
822
+ removeAttribute(el, name) {
823
+ setTimeout(() => {
824
+ super.removeAttribute(el, name);
825
+ }, 0);
826
+ }
827
+ setStyle(el, prop, value) {
828
+ setTimeout(() => {
829
+ super.setStyle(el, prop, value);
830
+ }, 0);
831
+ }
832
+ insertBefore(target, child) {
833
+ setTimeout(() => {
834
+ super.insertBefore(target, child);
835
+ }, 0);
836
+ }
837
+ appendChild(el, child) {
838
+ setTimeout(() => {
839
+ super.appendChild(el, child);
840
+ }, 0);
841
+ }
842
+ callCallback(cb) {
843
+ setTimeout(cb, 0);
844
+ }
845
+ }
846
+ const instantExecutor = new InstantExecutor();
847
+ const timeoutExecutor = new TimeoutExecutor();
848
+
849
+ window.Executor = Executor;
850
+ window.InstantExecutor = InstantExecutor;
851
+ window.TimeoutExecutor = TimeoutExecutor;
852
+ window.instantExecutor = instantExecutor;
853
+ window.timeoutExecutor = timeoutExecutor;
854
+
855
+ // ./lib/core/destroyable.js
856
+ /**
857
+ * Mark an object which can be destroyed
858
+ * @class Destroyable
859
+ */
860
+ class Destroyable {
861
+ /**
862
+ * Make object fields non configurable
863
+ * @protected
864
+ */
865
+ $seal() {
866
+ const $ = this;
867
+ Object.keys($).forEach(i => {
868
+ // eslint-disable-next-line no-prototype-builtins
869
+ if (this.hasOwnProperty(i)) {
870
+ const config = Object.getOwnPropertyDescriptor($, i);
871
+ if (config.configurable) {
872
+ let descriptor;
873
+ if (config.set || config.get) {
874
+ descriptor = {
875
+ configurable: false,
876
+ get: config.get,
877
+ set: config.set,
878
+ enumerable: config.enumerable
879
+ };
880
+ }
881
+ else {
882
+ descriptor = {
883
+ value: $[i],
884
+ configurable: false,
885
+ writable: config.writable,
886
+ enumerable: config.enumerable
887
+ };
888
+ }
889
+ Object.defineProperty($, i, descriptor);
890
+ }
891
+ }
892
+ });
893
+ }
894
+ /**
895
+ * Garbage collector method
896
+ */
897
+ $destroy() {
898
+ // nothing here
899
+ }
900
+ }
901
+
902
+ window.Destroyable = Destroyable;
903
+
904
+ // ./lib/core/ivalue.js
905
+ /**
906
+ * Interface which describes a value
907
+ * @class IValue
908
+ * @extends Destroyable
909
+ */
910
+ class IValue extends Destroyable {
911
+ /**
912
+ * @param isEnabled {boolean} initial is enabled state
913
+ */
914
+ constructor(isEnabled) {
915
+ super();
916
+ this.isEnabled = isEnabled;
917
+ }
918
+ /**
919
+ * Get the encapsulated value
920
+ * @return {*} the encapsulated value
921
+ */
922
+ get $() {
923
+ throw notOverwritten();
924
+ }
925
+ /**
926
+ * Sets the encapsulated value
927
+ * @param value {*} value to encapsulate
928
+ */
929
+ set $(value) {
930
+ throw notOverwritten();
931
+ }
932
+ /**
933
+ * Add a new handler to value change
934
+ * @param handler {function(value : *)} the handler to add
935
+ */
936
+ on(handler) {
937
+ throw notOverwritten();
938
+ }
939
+ /**
940
+ * Removes a handler of value change
941
+ * @param handler {function(value : *)} the handler to remove
942
+ */
943
+ off(handler) {
944
+ throw notOverwritten();
945
+ }
946
+ /**
947
+ * Enable update handlers triggering
948
+ */
949
+ enable() {
950
+ throw notOverwritten();
951
+ }
952
+ /**
953
+ * disable update handlers triggering
954
+ */
955
+ disable() {
956
+ throw notOverwritten();
957
+ }
958
+ }
959
+
960
+ window.IValue = IValue;
961
+
962
+ // ./lib/index.js
963
+
964
+
965
+
966
+ // ./lib/value/expression.js
967
+ /**
968
+ * Bind some values to one expression
969
+ * @class Expression
970
+ * @extends IValue
971
+ */
972
+ class Expression extends IValue {
973
+ constructor(func, link, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
974
+ super(false);
975
+ /**
976
+ * Expression will link different handler for each value of list
977
+ */
978
+ this.linkedFunc = [];
979
+ const values = [v1, v2, v3, v4, v5, v6, v7, v8, v9].filter(v => v instanceof IValue);
980
+ const handler = (i) => {
981
+ if (i != null) {
982
+ this.valuesCache[i] = this.values[i].$;
983
+ }
984
+ this.sync.$ = func.apply(this, this.valuesCache);
985
+ };
986
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
987
+ // @ts-ignore
988
+ this.valuesCache = values.map(iValue => iValue.$);
989
+ this.sync = new Reference(func.apply(this, this.valuesCache));
990
+ let i = 0;
991
+ values.forEach(() => {
992
+ this.linkedFunc.push(handler.bind(this, Number(i++)));
993
+ });
994
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
995
+ // @ts-ignore
996
+ this.values = values;
997
+ this.func = handler;
998
+ if (link) {
999
+ this.enable();
1000
+ }
1001
+ else {
1002
+ handler();
1003
+ }
1004
+ this.$seal();
1005
+ }
1006
+ get $() {
1007
+ return this.sync.$;
1008
+ }
1009
+ set $(value) {
1010
+ this.sync.$ = value;
1011
+ }
1012
+ on(handler) {
1013
+ this.sync.on(handler);
1014
+ return this;
1015
+ }
1016
+ off(handler) {
1017
+ this.sync.off(handler);
1018
+ return this;
1019
+ }
1020
+ enable() {
1021
+ if (!this.isEnabled) {
1022
+ for (let i = 0; i < this.values.length; i++) {
1023
+ this.values[i].on(this.linkedFunc[i]);
1024
+ this.valuesCache[i] = this.values[i].$;
1025
+ }
1026
+ this.func();
1027
+ this.isEnabled = true;
1028
+ }
1029
+ return this;
1030
+ }
1031
+ disable() {
1032
+ if (this.isEnabled) {
1033
+ for (let i = 0; i < this.values.length; i++) {
1034
+ this.values[i].off(this.linkedFunc[i]);
1035
+ }
1036
+ this.isEnabled = false;
1037
+ }
1038
+ return this;
1039
+ }
1040
+ $destroy() {
1041
+ this.disable();
1042
+ this.values.splice(0);
1043
+ this.valuesCache.splice(0);
1044
+ this.linkedFunc.splice(0);
1045
+ super.$destroy();
1046
+ }
1047
+ }
1048
+
1049
+ window.Expression = Expression;
1050
+
1051
+ // ./lib/value/reference.js
1052
+ /**
1053
+ * Declares a notifiable value
1054
+ * @class Reference
1055
+ * @extends IValue
1056
+ */
1057
+ class Reference extends IValue {
1058
+ /**
1059
+ * @param value {any} the initial value
1060
+ */
1061
+ constructor(value) {
1062
+ super(true);
1063
+ this.value = value;
1064
+ this.onchange = new Set;
1065
+ this.$seal();
1066
+ }
1067
+ get $() {
1068
+ return this.value;
1069
+ }
1070
+ set $(value) {
1071
+ if (this.value !== value) {
1072
+ this.value = value;
1073
+ if (this.isEnabled) {
1074
+ this.onchange.forEach(handler => {
1075
+ handler(value);
1076
+ });
1077
+ }
1078
+ }
1079
+ }
1080
+ enable() {
1081
+ if (!this.isEnabled) {
1082
+ this.onchange.forEach(handler => {
1083
+ handler(this.value);
1084
+ });
1085
+ this.isEnabled = true;
1086
+ }
1087
+ return this;
1088
+ }
1089
+ disable() {
1090
+ this.isEnabled = false;
1091
+ return this;
1092
+ }
1093
+ on(handler) {
1094
+ this.onchange.add(handler);
1095
+ return this;
1096
+ }
1097
+ off(handler) {
1098
+ this.onchange.delete(handler);
1099
+ return this;
1100
+ }
1101
+ $destroy() {
1102
+ super.$destroy();
1103
+ this.onchange.clear();
1104
+ }
1105
+ }
1106
+
1107
+ window.Reference = Reference;
1108
+
1109
+ // ./lib/value/mirror.js
1110
+ /**
1111
+ * Declares a notifiable bind to a value
1112
+ * @class Mirror
1113
+ * @extends IValue
1114
+ * @version 2
1115
+ */
1116
+ class Mirror extends Reference {
1117
+ /**
1118
+ * Constructs a notifiable bind to a value
1119
+ * @param value {IValue} is initial value
1120
+ * @param forwardOnly {boolean} ensure forward only synchronization
1121
+ */
1122
+ constructor(value, forwardOnly = false) {
1123
+ super(value.$);
1124
+ this.handler = (v) => {
1125
+ this.$ = v;
1126
+ };
1127
+ this.pointedValue = value;
1128
+ this.forwardOnly = forwardOnly;
1129
+ value.on(this.handler);
1130
+ this.$seal();
1131
+ }
1132
+ get $() {
1133
+ // this is a ts bug
1134
+ // eslint-disable-next-line
1135
+ // @ts-ignore
1136
+ return super.$;
1137
+ }
1138
+ set $(v) {
1139
+ // this is a ts bug
1140
+ // eslint-disable-next-line
1141
+ // @ts-ignore
1142
+ super.$ = v;
1143
+ if (!this.forwardOnly) {
1144
+ this.pointedValue.$ = v;
1145
+ }
1146
+ }
1147
+ enable() {
1148
+ if (!this.isEnabled) {
1149
+ this.isEnabled = true;
1150
+ this.pointedValue.on(this.handler);
1151
+ this.$ = this.pointedValue.$;
1152
+ }
1153
+ return this;
1154
+ }
1155
+ disable() {
1156
+ if (this.isEnabled) {
1157
+ this.pointedValue.off(this.handler);
1158
+ this.isEnabled = false;
1159
+ }
1160
+ return this;
1161
+ }
1162
+ $destroy() {
1163
+ this.disable();
1164
+ super.$destroy();
1165
+ }
1166
+ }
1167
+
1168
+ window.Mirror = Mirror;
1169
+
1170
+ // ./lib/value/pointer.js
1171
+ /**
1172
+ * r/w pointer to a value
1173
+ * @class Pointer
1174
+ * @extends Mirror
1175
+ */
1176
+ class Pointer extends Mirror {
1177
+ /**
1178
+ * @param value {IValue} value to point
1179
+ * @param forwardOnly {boolean} forward only data flow
1180
+ */
1181
+ constructor(value, forwardOnly = false) {
1182
+ super(value, forwardOnly);
1183
+ }
1184
+ /**
1185
+ * Point a new ivalue
1186
+ * @param value {IValue} value to point
1187
+ */
1188
+ point(value) {
1189
+ if (this.pointedValue !== value) {
1190
+ this.disable();
1191
+ this.pointedValue = value;
1192
+ this.enable();
1193
+ }
1194
+ }
1195
+ }
1196
+
1197
+ window.Pointer = Pointer;
1198
+
1199
+ // ./lib/binding/binding.js
1200
+ /**
1201
+ * Describe a common binding logic
1202
+ * @class Binding
1203
+ * @extends Destroyable
1204
+ */
1205
+ class Binding extends Destroyable {
1206
+ /**
1207
+ * Constructs a common binding logic
1208
+ * @param node {INode} the vasille node
1209
+ * @param name {String} the name of property/attribute/class
1210
+ * @param value {IValue} the value to bind
1211
+ */
1212
+ constructor(node, name, value) {
1213
+ super();
1214
+ this.updateFunc = this.bound(name).bind(null, node);
1215
+ this.binding = value;
1216
+ this.binding.on(this.updateFunc);
1217
+ this.updateFunc(this.binding.$);
1218
+ this.$seal();
1219
+ }
1220
+ /**
1221
+ * Is a virtual function to get the specific bind function
1222
+ * @param name {String} the name of attribute/property
1223
+ * @returns {Function} a function to update attribute/property value
1224
+ * @throws Always throws and must be overloaded in child class
1225
+ */
1226
+ bound(name) {
1227
+ throw notOverwritten();
1228
+ }
1229
+ /**
1230
+ * Just clear bindings
1231
+ */
1232
+ $destroy() {
1233
+ this.binding.off(this.updateFunc);
1234
+ super.$destroy();
1235
+ }
1236
+ }
1237
+
1238
+ window.Binding = Binding;
1239
+
1240
+ // ./lib/core/core.js
1241
+ /**
1242
+ * Private stuff of a reactive object
1243
+ * @class ReactivePrivate
1244
+ * @extends Destroyable
1245
+ */
1246
+ class ReactivePrivate extends Destroyable {
1247
+ constructor() {
1248
+ super();
1249
+ /**
1250
+ * A list of user-defined values
1251
+ * @type {Set}
1252
+ */
1253
+ this.watch = new Set;
1254
+ /**
1255
+ * A list of user-defined bindings
1256
+ * @type {Set}
1257
+ */
1258
+ this.bindings = new Set;
1259
+ /**
1260
+ * A list of user defined models
1261
+ */
1262
+ this.models = new Set;
1263
+ /**
1264
+ * Reactivity switch state
1265
+ * @type {boolean}
1266
+ */
1267
+ this.enabled = true;
1268
+ /**
1269
+ * The frozen state of object
1270
+ * @type {boolean}
1271
+ */
1272
+ this.frozen = false;
1273
+ this.$seal();
1274
+ }
1275
+ $destroy() {
1276
+ var _a;
1277
+ this.watch.forEach(value => value.$destroy());
1278
+ this.watch.clear();
1279
+ this.bindings.forEach(binding => binding.$destroy());
1280
+ this.bindings.clear();
1281
+ (_a = this.freezeExpr) === null || _a === void 0 ? void 0 : _a.$destroy();
1282
+ super.$destroy();
1283
+ }
1284
+ }
1285
+ /**
1286
+ * A reactive object
1287
+ * @class Reactive
1288
+ * @extends Destroyable
1289
+ */
1290
+ class Reactive extends Destroyable {
1291
+ constructor($) {
1292
+ super();
1293
+ this.$ = $ || new ReactivePrivate;
1294
+ }
1295
+ /**
1296
+ * Create a reference
1297
+ * @param value {*} value to reference
1298
+ */
1299
+ $ref(value) {
1300
+ const $ = this.$;
1301
+ const ref = new Reference(value);
1302
+ $.watch.add(ref);
1303
+ return ref;
1304
+ }
1305
+ /**
1306
+ * Create a mirror
1307
+ * @param value {IValue} value to mirror
1308
+ */
1309
+ $mirror(value) {
1310
+ const mirror = new Mirror(value, false);
1311
+ this.$.watch.add(mirror);
1312
+ return mirror;
1313
+ }
1314
+ /**
1315
+ * Create a forward-only mirror
1316
+ * @param value {IValue} value to mirror
1317
+ */
1318
+ $forward(value) {
1319
+ const mirror = new Mirror(value, true);
1320
+ this.$.watch.add(mirror);
1321
+ return mirror;
1322
+ }
1323
+ /**
1324
+ * Creates a pointer
1325
+ * @param value {*} default value to point
1326
+ * @param forwardOnly {boolean} forward only sync
1327
+ */
1328
+ $point(value, forwardOnly = false) {
1329
+ const $ = this.$;
1330
+ const ref = value instanceof IValue ? value : new Reference(value);
1331
+ const pointer = new Pointer(ref, forwardOnly);
1332
+ // when value is an ivalue will be equal to ref
1333
+ if (value !== ref) {
1334
+ $.watch.add(ref);
1335
+ }
1336
+ $.watch.add(pointer);
1337
+ return pointer;
1338
+ }
1339
+ /**
1340
+ * Register a model
1341
+ * @param model
1342
+ */
1343
+ $register(model) {
1344
+ this.$.models.add(model);
1345
+ return model;
1346
+ }
1347
+ $watch(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
1348
+ const $ = this.$;
1349
+ $.watch.add(new Expression(func, !this.$.frozen, v1, v2, v3, v4, v5, v6, v7, v8, v9));
1350
+ }
1351
+ $bind(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
1352
+ const res = new Expression(func, !this.$.frozen, v1, v2, v3, v4, v5, v6, v7, v8, v9);
1353
+ const $ = this.$;
1354
+ $.watch.add(res);
1355
+ return res;
1356
+ }
1357
+ /**
1358
+ * Enable reactivity of fields
1359
+ */
1360
+ $enable() {
1361
+ const $ = this.$;
1362
+ if (!$.enabled) {
1363
+ $.watch.forEach(watcher => {
1364
+ watcher.enable();
1365
+ });
1366
+ $.models.forEach(model => {
1367
+ model.enableReactivity();
1368
+ });
1369
+ $.enabled = true;
1370
+ }
1371
+ }
1372
+ /**
1373
+ * Disable reactivity of fields
1374
+ */
1375
+ $disable() {
1376
+ const $ = this.$;
1377
+ if ($.enabled) {
1378
+ $.watch.forEach(watcher => {
1379
+ watcher.disable();
1380
+ });
1381
+ $.models.forEach(model => {
1382
+ model.disableReactivity();
1383
+ });
1384
+ $.enabled = false;
1385
+ }
1386
+ }
1387
+ /**
1388
+ * Disable/Enable reactivity of object fields with feedback
1389
+ * @param cond {IValue} show condition
1390
+ * @param onOff {function} on show feedback
1391
+ * @param onOn {function} on hide feedback
1392
+ */
1393
+ $bindAlive(cond, onOff, onOn) {
1394
+ const $ = this.$;
1395
+ if ($.freezeExpr) {
1396
+ throw wrongBinding("this component already have a freeze state");
1397
+ }
1398
+ if ($.watch.has(cond)) {
1399
+ throw wrongBinding("freeze state must be bound to an external component");
1400
+ }
1401
+ $.freezeExpr = new Expression((cond) => {
1402
+ $.frozen = !cond;
1403
+ if (cond) {
1404
+ onOn === null || onOn === void 0 ? void 0 : onOn();
1405
+ this.$enable();
1406
+ }
1407
+ else {
1408
+ onOff === null || onOff === void 0 ? void 0 : onOff();
1409
+ this.$disable();
1410
+ }
1411
+ }, true, cond);
1412
+ return this;
1413
+ }
1414
+ $destroy() {
1415
+ super.$destroy();
1416
+ this.$.$destroy();
1417
+ this.$ = null;
1418
+ }
1419
+ }
1420
+
1421
+ window.ReactivePrivate = ReactivePrivate;
1422
+ window.Reactive = Reactive;
1423
+
1424
+ // ./lib/node/node.js
1425
+ /**
1426
+ * Represents a Vasille.js node
1427
+ * @class FragmentPrivate
1428
+ * @extends ReactivePrivate
1429
+ */
1430
+ class FragmentPrivate extends ReactivePrivate {
1431
+ constructor() {
1432
+ super();
1433
+ this.$seal();
1434
+ }
1435
+ /**
1436
+ * Pre-initializes the base of a fragment
1437
+ * @param app {App} the app node
1438
+ * @param parent {Fragment} the parent node
1439
+ */
1440
+ preinit(app, parent) {
1441
+ this.app = app;
1442
+ this.parent = parent;
1443
+ }
1444
+ /**
1445
+ * Unlinks all bindings
1446
+ */
1447
+ $destroy() {
1448
+ this.next = null;
1449
+ this.prev = null;
1450
+ super.$destroy();
1451
+ }
1452
+ }
1453
+ /**
1454
+ * This class is symbolic
1455
+ * @extends Reactive
1456
+ */
1457
+ class Fragment extends Reactive {
1458
+ /**
1459
+ * Constructs a Vasille Node
1460
+ * @param $ {FragmentPrivate}
1461
+ */
1462
+ constructor($) {
1463
+ super();
1464
+ /**
1465
+ * The children list
1466
+ * @type Array
1467
+ */
1468
+ this.$children = [];
1469
+ this.$ = $ || new FragmentPrivate;
1470
+ }
1471
+ /**
1472
+ * Gets the app of node
1473
+ */
1474
+ get app() {
1475
+ return this.$.app;
1476
+ }
1477
+ /**
1478
+ * Prepare to init fragment
1479
+ * @param app {AppNode} app of node
1480
+ * @param parent {Fragment} parent of node
1481
+ * @param data {*} additional data
1482
+ */
1483
+ $preinit(app, parent, data) {
1484
+ const $ = this.$;
1485
+ $.preinit(app, parent);
1486
+ }
1487
+ /**
1488
+ * Initialize node
1489
+ */
1490
+ $init() {
1491
+ this.$createSignals();
1492
+ this.$createWatchers();
1493
+ this.$created();
1494
+ this.$compose();
1495
+ this.$mounted();
1496
+ return this;
1497
+ }
1498
+ /** To be overloaded: created event handler */
1499
+ $created() {
1500
+ // empty
1501
+ }
1502
+ /** To be overloaded: mounted event handler */
1503
+ $mounted() {
1504
+ // empty
1505
+ }
1506
+ /** To be overloaded: ready event handler */
1507
+ $ready() {
1508
+ // empty
1509
+ }
1510
+ /** To be overloaded: signals creation milestone */
1511
+ $createSignals() {
1512
+ // empty
1513
+ }
1514
+ /** To be overloaded: watchers creation milestone */
1515
+ $createWatchers() {
1516
+ // empty
1517
+ }
1518
+ /** To be overloaded: DOM creation milestone */
1519
+ $compose() {
1520
+ // empty
1521
+ }
1522
+ /**
1523
+ * Pushes a node to children immediately
1524
+ * @param node {Fragment} A node to push
1525
+ * @protected
1526
+ */
1527
+ $$pushNode(node) {
1528
+ let lastChild = null;
1529
+ if (this.$children.length) {
1530
+ lastChild = this.$children[this.$children.length - 1];
1531
+ }
1532
+ if (lastChild) {
1533
+ lastChild.$.next = node;
1534
+ }
1535
+ node.$.prev = lastChild;
1536
+ node.$.parent = this;
1537
+ this.$children.push(node);
1538
+ }
1539
+ /**
1540
+ * Find first node in element if so exists
1541
+ * @return {?Element}
1542
+ * @protected
1543
+ */
1544
+ $$findFirstChild() {
1545
+ let first;
1546
+ this.$children.forEach(child => {
1547
+ first = first || child.$$findFirstChild();
1548
+ });
1549
+ return first;
1550
+ }
1551
+ /**
1552
+ * Append a node to end of element
1553
+ * @param node {Node} node to insert
1554
+ */
1555
+ $$appendNode(node) {
1556
+ const $ = this.$;
1557
+ if ($.next) {
1558
+ $.next.$$insertAdjacent(node);
1559
+ }
1560
+ else {
1561
+ $.parent.$$appendNode(node);
1562
+ }
1563
+ }
1564
+ /**
1565
+ * Insert a node as a sibling of this
1566
+ * @param node {Node} node to insert
1567
+ */
1568
+ $$insertAdjacent(node) {
1569
+ const child = this.$$findFirstChild();
1570
+ const $ = this.$;
1571
+ if (child) {
1572
+ $.app.$run.insertBefore(child, node);
1573
+ }
1574
+ else if ($.next) {
1575
+ $.next.$$insertAdjacent(node);
1576
+ }
1577
+ else {
1578
+ $.parent.$$appendNode(node);
1579
+ }
1580
+ }
1581
+ /**
1582
+ * Defines a text fragment
1583
+ * @param text {String | IValue} A text fragment string
1584
+ * @param cb {function (TextNode)} Callback if previous is slot name
1585
+ */
1586
+ $text(text, cb) {
1587
+ const $ = this.$;
1588
+ const node = new TextNode();
1589
+ const textValue = text instanceof IValue ? text : this.$ref(text);
1590
+ node.$preinit($.app, this, textValue);
1591
+ this.$$pushNode(node);
1592
+ if (cb) {
1593
+ $.app.$run.callCallback(() => {
1594
+ cb(node);
1595
+ });
1596
+ }
1597
+ return this;
1598
+ }
1599
+ $debug(text) {
1600
+ if (this.$.app.$debugUi) {
1601
+ const node = new DebugNode();
1602
+ node.$preinit(this.$.app, this, text);
1603
+ this.$$pushNode(node);
1604
+ }
1605
+ return this;
1606
+ }
1607
+ $tag(tagName, cb) {
1608
+ const $ = this.$;
1609
+ const node = new Tag();
1610
+ node.$preinit($.app, this, tagName);
1611
+ node.$init();
1612
+ this.$$pushNode(node);
1613
+ $.app.$run.callCallback(() => {
1614
+ if (cb) {
1615
+ cb(node, node.node);
1616
+ }
1617
+ node.$ready();
1618
+ });
1619
+ return this;
1620
+ }
1621
+ /**
1622
+ * Defines a custom element
1623
+ * @param node {Fragment} vasille element to insert
1624
+ * @param callback {function($ : *)}
1625
+ * @param callback1 {function($ : *)}
1626
+ */
1627
+ $create(node, callback, callback1) {
1628
+ const $ = this.$;
1629
+ node.$.parent = this;
1630
+ node.$preinit($.app, this);
1631
+ if (callback) {
1632
+ callback(node);
1633
+ }
1634
+ if (callback1) {
1635
+ callback1(node);
1636
+ }
1637
+ this.$$pushNode(node);
1638
+ node.$init().$ready();
1639
+ return this;
1640
+ }
1641
+ /**
1642
+ * Defines an if node
1643
+ * @param cond {IValue} condition
1644
+ * @param cb {function(Fragment)} callback to run on true
1645
+ * @return {this}
1646
+ */
1647
+ $if(cond, cb) {
1648
+ return this.$switch({ cond, cb });
1649
+ }
1650
+ /**
1651
+ * Defines a if-else node
1652
+ * @param ifCond {IValue} `if` condition
1653
+ * @param ifCb {function(Fragment)} Call-back to create `if` child nodes
1654
+ * @param elseCb {function(Fragment)} Call-back to create `else` child nodes
1655
+ */
1656
+ $if_else(ifCond, ifCb, elseCb) {
1657
+ return this.$switch({ cond: ifCond, cb: ifCb }, { cond: trueIValue, cb: elseCb });
1658
+ }
1659
+ /**
1660
+ * Defines a switch nodes: Will break after first true condition
1661
+ * @param cases {...{ cond : IValue, cb : function(Fragment) }} cases
1662
+ * @return {INode}
1663
+ */
1664
+ $switch(...cases) {
1665
+ const $ = this.$;
1666
+ const node = new SwitchedNode();
1667
+ node.$preinit($.app, this);
1668
+ node.$init();
1669
+ this.$$pushNode(node);
1670
+ node.setCases(cases);
1671
+ node.$ready();
1672
+ return this;
1673
+ }
1674
+ /**
1675
+ * Create a case for switch
1676
+ * @param cond {IValue<boolean>}
1677
+ * @param cb {function(Fragment) : void}
1678
+ * @return {{cond : IValue, cb : (function(Fragment) : void)}}
1679
+ */
1680
+ $case(cond, cb) {
1681
+ return { cond, cb };
1682
+ }
1683
+ /**
1684
+ * @param cb {(function(Fragment) : void)}
1685
+ * @return {{cond : IValue, cb : (function(Fragment) : void)}}
1686
+ */
1687
+ $default(cb) {
1688
+ return { cond: trueIValue, cb };
1689
+ }
1690
+ $destroy() {
1691
+ for (const child of this.$children) {
1692
+ child.$destroy();
1693
+ }
1694
+ this.$children.splice(0);
1695
+ super.$destroy();
1696
+ }
1697
+ }
1698
+ const trueIValue = new Reference(true);
1699
+ /**
1700
+ * The private part of a text node
1701
+ * @class TextNodePrivate
1702
+ * @extends FragmentPrivate
1703
+ */
1704
+ class TextNodePrivate extends FragmentPrivate {
1705
+ constructor() {
1706
+ super();
1707
+ this.$seal();
1708
+ }
1709
+ /**
1710
+ * Pre-initializes a text node
1711
+ * @param app {AppNode} the app node
1712
+ * @param text {IValue}
1713
+ */
1714
+ preinitText(app, parent, text) {
1715
+ super.preinit(app, parent);
1716
+ this.node = document.createTextNode(text.$);
1717
+ this.bindings.add(new Expression((v) => {
1718
+ this.node.replaceData(0, -1, v);
1719
+ }, true, text));
1720
+ this.parent.$$appendNode(this.node);
1721
+ }
1722
+ /**
1723
+ * Clear node data
1724
+ */
1725
+ $destroy() {
1726
+ super.$destroy();
1727
+ }
1728
+ }
1729
+ /**
1730
+ * Represents a text node
1731
+ * @class TextNode
1732
+ * @extends Fragment
1733
+ */
1734
+ class TextNode extends Fragment {
1735
+ constructor() {
1736
+ super();
1737
+ this.$ = new TextNodePrivate();
1738
+ this.$seal();
1739
+ }
1740
+ $preinit(app, parent, text) {
1741
+ const $ = this.$;
1742
+ if (!text) {
1743
+ throw internalError('wrong TextNode::$preninit call');
1744
+ }
1745
+ $.preinitText(app, parent, text);
1746
+ }
1747
+ $$findFirstChild() {
1748
+ return this.$.node;
1749
+ }
1750
+ $destroy() {
1751
+ this.$.node.remove();
1752
+ this.$.$destroy();
1753
+ super.$destroy();
1754
+ }
1755
+ }
1756
+ /**
1757
+ * The private part of a base node
1758
+ * @class INodePrivate
1759
+ * @extends FragmentPrivate
1760
+ */
1761
+ class INodePrivate extends FragmentPrivate {
1762
+ constructor() {
1763
+ super();
1764
+ /**
1765
+ * Defines if node is unmounted
1766
+ * @type {boolean}
1767
+ */
1768
+ this.unmounted = false;
1769
+ this.$seal();
1770
+ }
1771
+ $destroy() {
1772
+ super.$destroy();
1773
+ }
1774
+ }
1775
+ /**
1776
+ * Vasille node which can manipulate an element node
1777
+ * @class INode
1778
+ * @extends Fragment
1779
+ */
1780
+ class INode extends Fragment {
1781
+ /**
1782
+ * Constructs a base node
1783
+ * @param $ {?INodePrivate}
1784
+ */
1785
+ constructor($) {
1786
+ super($ || new INodePrivate);
1787
+ this.$seal();
1788
+ }
1789
+ /**
1790
+ * Get the bound node
1791
+ */
1792
+ get node() {
1793
+ return this.$.node;
1794
+ }
1795
+ /**
1796
+ * Initialize node
1797
+ */
1798
+ $init() {
1799
+ this.$createSignals();
1800
+ this.$createWatchers();
1801
+ this.$createAttrs();
1802
+ this.$createStyle();
1803
+ this.$created();
1804
+ this.$compose();
1805
+ this.$mounted();
1806
+ return this;
1807
+ }
1808
+ /** To be overloaded: attributes creation milestone */
1809
+ $createAttrs() {
1810
+ // empty
1811
+ }
1812
+ /** To be overloaded: $style attributes creation milestone */
1813
+ $createStyle() {
1814
+ // empty
1815
+ }
1816
+ /**
1817
+ * Bind attribute value
1818
+ * @param name {String} name of attribute
1819
+ * @param value {IValue} value
1820
+ */
1821
+ $attr(name, value) {
1822
+ const $ = this.$;
1823
+ const attr = new AttributeBinding(this, name, value);
1824
+ $.bindings.add(attr);
1825
+ return this;
1826
+ }
1827
+ $bindAttr(name, calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
1828
+ const $ = this.$;
1829
+ const expr = this.$bind(calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9);
1830
+ $.bindings.add(new AttributeBinding(this, name, expr));
1831
+ return this;
1832
+ }
1833
+ /**
1834
+ * Set attribute value
1835
+ * @param name {string} name of attribute
1836
+ * @param value {string} value
1837
+ */
1838
+ $setAttr(name, value) {
1839
+ this.$.app.$run.setAttribute(this.$.node, name, value);
1840
+ return this;
1841
+ }
1842
+ /**
1843
+ * Adds a CSS class
1844
+ * @param cl {string} Class name
1845
+ */
1846
+ $addClass(cl) {
1847
+ this.$.app.$run.addClass(this.$.node, cl);
1848
+ return this;
1849
+ }
1850
+ /**
1851
+ * Adds some CSS classes
1852
+ * @param cls {...string} classes names
1853
+ */
1854
+ $addClasses(...cls) {
1855
+ cls.forEach(cl => {
1856
+ this.$.app.$run.addClass(this.$.node, cl);
1857
+ });
1858
+ return this;
1859
+ }
1860
+ /**
1861
+ * Bind a CSS class
1862
+ * @param className {IValue}
1863
+ */
1864
+ $bindClass(className) {
1865
+ const $ = this.$;
1866
+ $.bindings.add(new ClassBinding(this, "", className));
1867
+ return this;
1868
+ }
1869
+ /**
1870
+ * Bind a floating class name
1871
+ * @param cond {IValue} condition
1872
+ * @param className {string} class name
1873
+ */
1874
+ $floatingClass(cond, className) {
1875
+ this.$.bindings.add(new ClassBinding(this, className, cond));
1876
+ return this;
1877
+ }
1878
+ /**
1879
+ * Defines a style attribute
1880
+ * @param name {String} name of style attribute
1881
+ * @param value {IValue} value
1882
+ */
1883
+ $style(name, value) {
1884
+ const $ = this.$;
1885
+ if ($.node instanceof HTMLElement) {
1886
+ $.bindings.add(new StyleBinding(this, name, value));
1887
+ }
1888
+ else {
1889
+ throw userError('style can be applied to HTML elements only', 'non-html-element');
1890
+ }
1891
+ return this;
1892
+ }
1893
+ $bindStyle(name, calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
1894
+ const $ = this.$;
1895
+ const expr = this.$bind(calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9);
1896
+ if ($.node instanceof HTMLElement) {
1897
+ $.bindings.add(new StyleBinding(this, name, expr));
1898
+ }
1899
+ else {
1900
+ throw userError('style can be applied to HTML elements only', 'non-html-element');
1901
+ }
1902
+ return this;
1903
+ }
1904
+ /**
1905
+ * Sets a style property value
1906
+ * @param prop {string} Property name
1907
+ * @param value {string} Property value
1908
+ */
1909
+ $setStyle(prop, value) {
1910
+ if (this.$.node instanceof HTMLElement) {
1911
+ this.$.app.$run.setStyle(this.$.node, prop, value);
1912
+ }
1913
+ else {
1914
+ throw userError("Style can be setted for HTML elements only", "non-html-element");
1915
+ }
1916
+ return this;
1917
+ }
1918
+ /**
1919
+ * Add a listener for an event
1920
+ * @param name {string} Event name
1921
+ * @param handler {function (Event)} Event handler
1922
+ * @param options {Object | boolean} addEventListener options
1923
+ */
1924
+ $listen(name, handler, options) {
1925
+ this.$.node.addEventListener(name, handler, options);
1926
+ return this;
1927
+ }
1928
+ /**
1929
+ * @param handler {function (MouseEvent)}
1930
+ * @param options {Object | boolean}
1931
+ */
1932
+ $oncontextmenu(handler, options) {
1933
+ return this.$listen("contextmenu", handler, options);
1934
+ }
1935
+ /**
1936
+ * @param handler {function (MouseEvent)}
1937
+ * @param options {Object | boolean}
1938
+ */
1939
+ $onmousedown(handler, options) {
1940
+ return this.$listen("mousedown", handler, options);
1941
+ }
1942
+ /**
1943
+ * @param handler {function (MouseEvent)}
1944
+ * @param options {Object | boolean}
1945
+ */
1946
+ $onmouseenter(handler, options) {
1947
+ return this.$listen("mouseenter", handler, options);
1948
+ }
1949
+ /**
1950
+ * @param handler {function (MouseEvent)}
1951
+ * @param options {Object | boolean}
1952
+ */
1953
+ $onmouseleave(handler, options) {
1954
+ return this.$listen("mouseleave", handler, options);
1955
+ }
1956
+ /**
1957
+ * @param handler {function (MouseEvent)}
1958
+ * @param options {Object | boolean}
1959
+ */
1960
+ $onmousemove(handler, options) {
1961
+ return this.$listen("mousemove", handler, options);
1962
+ }
1963
+ /**
1964
+ * @param handler {function (MouseEvent)}
1965
+ * @param options {Object | boolean}
1966
+ */
1967
+ $onmouseout(handler, options) {
1968
+ return this.$listen("mouseout", handler, options);
1969
+ }
1970
+ /**
1971
+ * @param handler {function (MouseEvent)}
1972
+ * @param options {Object | boolean}
1973
+ */
1974
+ $onmouseover(handler, options) {
1975
+ return this.$listen("mouseover", handler, options);
1976
+ }
1977
+ /**
1978
+ * @param handler {function (MouseEvent)}
1979
+ * @param options {Object | boolean}
1980
+ */
1981
+ $onmouseup(handler, options) {
1982
+ return this.$listen("mouseup", handler, options);
1983
+ }
1984
+ /**
1985
+ * @param handler {function (MouseEvent)}
1986
+ * @param options {Object | boolean}
1987
+ */
1988
+ $onclick(handler, options) {
1989
+ return this.$listen("click", handler, options);
1990
+ }
1991
+ /**
1992
+ * @param handler {function (MouseEvent)}
1993
+ * @param options {Object | boolean}
1994
+ */
1995
+ $ondblclick(handler, options) {
1996
+ return this.$listen("dblclick", handler, options);
1997
+ }
1998
+ /**
1999
+ * @param handler {function (FocusEvent)}
2000
+ * @param options {Object | boolean}
2001
+ */
2002
+ $onblur(handler, options) {
2003
+ return this.$listen("blur", handler, options);
2004
+ }
2005
+ /**
2006
+ * @param handler {function (FocusEvent)}
2007
+ * @param options {Object | boolean}
2008
+ */
2009
+ $onfocus(handler, options) {
2010
+ return this.$listen("focus", handler, options);
2011
+ }
2012
+ /**
2013
+ * @param handler {function (FocusEvent)}
2014
+ * @param options {Object | boolean}
2015
+ */
2016
+ $onfocusin(handler, options) {
2017
+ return this.$listen("focusin", handler, options);
2018
+ }
2019
+ /**
2020
+ * @param handler {function (FocusEvent)}
2021
+ * @param options {Object | boolean}
2022
+ */
2023
+ $onfocusout(handler, options) {
2024
+ return this.$listen("focusout", handler, options);
2025
+ }
2026
+ /**
2027
+ * @param handler {function (KeyboardEvent)}
2028
+ * @param options {Object | boolean}
2029
+ */
2030
+ $onkeydown(handler, options) {
2031
+ return this.$listen("keydown", handler, options);
2032
+ }
2033
+ /**
2034
+ * @param handler {function (KeyboardEvent)}
2035
+ * @param options {Object | boolean}
2036
+ */
2037
+ $onkeyup(handler, options) {
2038
+ return this.$listen("keyup", handler, options);
2039
+ }
2040
+ /**
2041
+ * @param handler {function (KeyboardEvent)}
2042
+ * @param options {Object | boolean}
2043
+ */
2044
+ $onkeypress(handler, options) {
2045
+ return this.$listen("keypress", handler, options);
2046
+ }
2047
+ /**
2048
+ * @param handler {function (TouchEvent)}
2049
+ * @param options {Object | boolean}
2050
+ */
2051
+ $ontouchstart(handler, options) {
2052
+ return this.$listen("touchstart", handler, options);
2053
+ }
2054
+ /**
2055
+ * @param handler {function (TouchEvent)}
2056
+ * @param options {Object | boolean}
2057
+ */
2058
+ $ontouchmove(handler, options) {
2059
+ return this.$listen("touchmove", handler, options);
2060
+ }
2061
+ /**
2062
+ * @param handler {function (TouchEvent)}
2063
+ * @param options {Object | boolean}
2064
+ */
2065
+ $ontouchend(handler, options) {
2066
+ return this.$listen("touchend", handler, options);
2067
+ }
2068
+ /**
2069
+ * @param handler {function (TouchEvent)}
2070
+ * @param options {Object | boolean}
2071
+ */
2072
+ $ontouchcancel(handler, options) {
2073
+ return this.$listen("touchcancel", handler, options);
2074
+ }
2075
+ /**
2076
+ * @param handler {function (WheelEvent)}
2077
+ * @param options {Object | boolean}
2078
+ */
2079
+ $onwheel(handler, options) {
2080
+ return this.$listen("wheel", handler, options);
2081
+ }
2082
+ /**
2083
+ * @param handler {function (ProgressEvent)}
2084
+ * @param options {Object | boolean}
2085
+ */
2086
+ $onabort(handler, options) {
2087
+ return this.$listen("abort", handler, options);
2088
+ }
2089
+ /**
2090
+ * @param handler {function (ProgressEvent)}
2091
+ * @param options {Object | boolean}
2092
+ */
2093
+ $onerror(handler, options) {
2094
+ return this.$listen("error", handler, options);
2095
+ }
2096
+ /**
2097
+ * @param handler {function (ProgressEvent)}
2098
+ * @param options {Object | boolean}
2099
+ */
2100
+ $onload(handler, options) {
2101
+ return this.$listen("load", handler, options);
2102
+ }
2103
+ /**
2104
+ * @param handler {function (ProgressEvent)}
2105
+ * @param options {Object | boolean}
2106
+ */
2107
+ $onloadend(handler, options) {
2108
+ return this.$listen("loadend", handler, options);
2109
+ }
2110
+ /**
2111
+ * @param handler {function (ProgressEvent)}
2112
+ * @param options {Object | boolean}
2113
+ */
2114
+ $onloadstart(handler, options) {
2115
+ return this.$listen("loadstart", handler, options);
2116
+ }
2117
+ /**
2118
+ * @param handler {function (ProgressEvent)}
2119
+ * @param options {Object | boolean}
2120
+ */
2121
+ $onprogress(handler, options) {
2122
+ return this.$listen("progress", handler, options);
2123
+ }
2124
+ /**
2125
+ * @param handler {function (ProgressEvent)}
2126
+ * @param options {Object | boolean}
2127
+ */
2128
+ $ontimeout(handler, options) {
2129
+ return this.$listen("timeout", handler, options);
2130
+ }
2131
+ /**
2132
+ * @param handler {function (DragEvent)}
2133
+ * @param options {Object | boolean}
2134
+ */
2135
+ $ondrag(handler, options) {
2136
+ return this.$listen("drag", handler, options);
2137
+ }
2138
+ /**
2139
+ * @param handler {function (DragEvent)}
2140
+ * @param options {Object | boolean}
2141
+ */
2142
+ $ondragend(handler, options) {
2143
+ return this.$listen("dragend", handler, options);
2144
+ }
2145
+ /**
2146
+ * @param handler {function (DragEvent)}
2147
+ * @param options {Object | boolean}
2148
+ */
2149
+ $ondragenter(handler, options) {
2150
+ return this.$listen("dragenter", handler, options);
2151
+ }
2152
+ /**
2153
+ * @param handler {function (DragEvent)}
2154
+ * @param options {Object | boolean}
2155
+ */
2156
+ $ondragexit(handler, options) {
2157
+ return this.$listen("dragexit", handler, options);
2158
+ }
2159
+ /**
2160
+ * @param handler {function (DragEvent)}
2161
+ * @param options {Object | boolean}
2162
+ */
2163
+ $ondragleave(handler, options) {
2164
+ return this.$listen("dragleave", handler, options);
2165
+ }
2166
+ /**
2167
+ * @param handler {function (DragEvent)}
2168
+ * @param options {Object | boolean}
2169
+ */
2170
+ $ondragover(handler, options) {
2171
+ return this.$listen("dragover", handler, options);
2172
+ }
2173
+ /**
2174
+ * @param handler {function (DragEvent)}
2175
+ * @param options {Object | boolean}
2176
+ */
2177
+ $ondragstart(handler, options) {
2178
+ return this.$listen("dragstart", handler, options);
2179
+ }
2180
+ /**
2181
+ * @param handler {function (DragEvent)}
2182
+ * @param options {Object | boolean}
2183
+ */
2184
+ $ondrop(handler, options) {
2185
+ return this.$listen("drop", handler, options);
2186
+ }
2187
+ /**
2188
+ * @param handler {function (PointerEvent)}
2189
+ * @param options {Object | boolean}
2190
+ */
2191
+ $onpointerover(handler, options) {
2192
+ return this.$listen("pointerover", handler, options);
2193
+ }
2194
+ /**
2195
+ * @param handler {function (PointerEvent)}
2196
+ * @param options {Object | boolean}
2197
+ */
2198
+ $onpointerenter(handler, options) {
2199
+ return this.$listen("pointerenter", handler, options);
2200
+ }
2201
+ /**
2202
+ * @param handler {function (PointerEvent)}
2203
+ * @param options {Object | boolean}
2204
+ */
2205
+ $onpointerdown(handler, options) {
2206
+ return this.$listen("pointerdown", handler, options);
2207
+ }
2208
+ /**
2209
+ * @param handler {function (PointerEvent)}
2210
+ * @param options {Object | boolean}
2211
+ */
2212
+ $onpointermove(handler, options) {
2213
+ return this.$listen("pointermove", handler, options);
2214
+ }
2215
+ /**
2216
+ * @param handler {function (PointerEvent)}
2217
+ * @param options {Object | boolean}
2218
+ */
2219
+ $onpointerup(handler, options) {
2220
+ return this.$listen("pointerup", handler, options);
2221
+ }
2222
+ /**
2223
+ * @param handler {function (PointerEvent)}
2224
+ * @param options {Object | boolean}
2225
+ */
2226
+ $onpointercancel(handler, options) {
2227
+ return this.$listen("pointercancel", handler, options);
2228
+ }
2229
+ /**
2230
+ * @param handler {function (PointerEvent)}
2231
+ * @param options {Object | boolean}
2232
+ */
2233
+ $onpointerout(handler, options) {
2234
+ return this.$listen("pointerout", handler, options);
2235
+ }
2236
+ /**
2237
+ * @param handler {function (PointerEvent)}
2238
+ * @param options {Object | boolean}
2239
+ */
2240
+ $onpointerleave(handler, options) {
2241
+ return this.$listen("pointerleave", handler, options);
2242
+ }
2243
+ /**
2244
+ * @param handler {function (PointerEvent)}
2245
+ * @param options {Object | boolean}
2246
+ */
2247
+ $ongotpointercapture(handler, options) {
2248
+ return this.$listen("gotpointercapture", handler, options);
2249
+ }
2250
+ /**
2251
+ * @param handler {function (PointerEvent)}
2252
+ * @param options {Object | boolean}
2253
+ */
2254
+ $onlostpointercapture(handler, options) {
2255
+ return this.$listen("lostpointercapture", handler, options);
2256
+ }
2257
+ /**
2258
+ * @param handler {function (AnimationEvent)}
2259
+ * @param options {Object | boolean}
2260
+ */
2261
+ $onanimationstart(handler, options) {
2262
+ return this.$listen("animationstart", handler, options);
2263
+ }
2264
+ /**
2265
+ * @param handler {function (AnimationEvent)}
2266
+ * @param options {Object | boolean}
2267
+ */
2268
+ $onanimationend(handler, options) {
2269
+ return this.$listen("animationend", handler, options);
2270
+ }
2271
+ /**
2272
+ * @param handler {function (AnimationEvent)}
2273
+ * @param options {Object | boolean}
2274
+ */
2275
+ $onanimationiteraton(handler, options) {
2276
+ return this.$listen("animationiteration", handler, options);
2277
+ }
2278
+ /**
2279
+ * @param handler {function (ClipboardEvent)}
2280
+ * @param options {Object | boolean}
2281
+ */
2282
+ $onclipboardchange(handler, options) {
2283
+ return this.$listen("clipboardchange", handler, options);
2284
+ }
2285
+ /**
2286
+ * @param handler {function (ClipboardEvent)}
2287
+ * @param options {Object | boolean}
2288
+ */
2289
+ $oncut(handler, options) {
2290
+ return this.$listen("cut", handler, options);
2291
+ }
2292
+ /**
2293
+ * @param handler {function (ClipboardEvent)}
2294
+ * @param options {Object | boolean}
2295
+ */
2296
+ $oncopy(handler, options) {
2297
+ return this.$listen("copy", handler, options);
2298
+ }
2299
+ /**
2300
+ * @param handler {function (ClipboardEvent)}
2301
+ * @param options {Object | boolean}
2302
+ */
2303
+ $onpaste(handler, options) {
2304
+ return this.$listen("paste", handler, options);
2305
+ }
2306
+ $$insertAdjacent(node) {
2307
+ const $ = this.$;
2308
+ $.app.$run.insertBefore($.node, node);
2309
+ }
2310
+ /**
2311
+ * A v-show & ngShow alternative
2312
+ * @param cond {IValue} show condition
2313
+ */
2314
+ $bindShow(cond) {
2315
+ const $ = this.$;
2316
+ const node = $.node;
2317
+ if (node instanceof HTMLElement) {
2318
+ let lastDisplay = node.style.display;
2319
+ const htmlNode = node;
2320
+ return this.$bindAlive(cond, () => {
2321
+ lastDisplay = htmlNode.style.display;
2322
+ htmlNode.style.display = 'none';
2323
+ }, () => {
2324
+ htmlNode.style.display = lastDisplay;
2325
+ });
2326
+ }
2327
+ else {
2328
+ throw userError('the element must be a html element', 'bind-show');
2329
+ }
2330
+ }
2331
+ /**
2332
+ * bind HTML
2333
+ * @param value {IValue}
2334
+ */
2335
+ $html(value) {
2336
+ const $ = this.$;
2337
+ const node = $.node;
2338
+ if (node instanceof HTMLElement) {
2339
+ node.innerHTML = value.$;
2340
+ this.$watch((v) => {
2341
+ node.innerHTML = v;
2342
+ }, value);
2343
+ }
2344
+ else {
2345
+ throw userError("HTML can be bound for HTML nodes only", "dom-error");
2346
+ }
2347
+ }
2348
+ }
2349
+ /**
2350
+ * Represents an Vasille.js HTML element node
2351
+ * @class Tag
2352
+ * @extends INode
2353
+ */
2354
+ class Tag extends INode {
2355
+ constructor() {
2356
+ super();
2357
+ this.$seal();
2358
+ }
2359
+ $preinit(app, parent, tagName) {
2360
+ if (!tagName || typeof tagName !== "string") {
2361
+ throw internalError('wrong Tag::$preinit call');
2362
+ }
2363
+ const node = document.createElement(tagName);
2364
+ const $ = this.$;
2365
+ $.preinit(app, parent);
2366
+ $.node = node;
2367
+ $.parent.$$appendNode(node);
2368
+ }
2369
+ $$findFirstChild() {
2370
+ return this.$.unmounted ? null : this.$.node;
2371
+ }
2372
+ $$insertAdjacent(node) {
2373
+ if (this.$.unmounted) {
2374
+ if (this.$.next) {
2375
+ this.$.next.$$insertAdjacent(node);
2376
+ }
2377
+ else {
2378
+ this.$.parent.$$appendNode(node);
2379
+ }
2380
+ }
2381
+ else {
2382
+ super.$$insertAdjacent(node);
2383
+ }
2384
+ }
2385
+ $$appendNode(node) {
2386
+ const $ = this.$;
2387
+ $.app.$run.appendChild($.node, node);
2388
+ }
2389
+ /**
2390
+ * Mount/Unmount a node
2391
+ * @param cond {IValue} show condition
2392
+ */
2393
+ $bindMount(cond) {
2394
+ const $ = this.$;
2395
+ return this.$bindAlive(cond, () => {
2396
+ $.node.remove();
2397
+ $.unmounted = true;
2398
+ }, () => {
2399
+ if (!$.unmounted)
2400
+ return;
2401
+ if ($.next) {
2402
+ $.next.$$insertAdjacent($.node);
2403
+ }
2404
+ else {
2405
+ $.parent.$$appendNode($.node);
2406
+ }
2407
+ $.unmounted = false;
2408
+ });
2409
+ }
2410
+ /**
2411
+ * Runs GC
2412
+ */
2413
+ $destroy() {
2414
+ this.node.remove();
2415
+ super.$destroy();
2416
+ }
2417
+ }
2418
+ /**
2419
+ * Represents a vasille extension node
2420
+ * @class Extension
2421
+ * @extends INode
2422
+ */
2423
+ class Extension extends INode {
2424
+ $preinit(app, parent) {
2425
+ if (parent instanceof INode) {
2426
+ const $ = this.$;
2427
+ $.preinit(app, parent);
2428
+ $.node = parent.node;
2429
+ }
2430
+ else {
2431
+ throw userError("A extension node can be encapsulated only in a tag/extension/component", "virtual-dom");
2432
+ }
2433
+ }
2434
+ constructor($) {
2435
+ super($);
2436
+ this.$seal();
2437
+ }
2438
+ $destroy() {
2439
+ super.$destroy();
2440
+ }
2441
+ }
2442
+ /**
2443
+ * Node which cas has just a child
2444
+ * @class Component
2445
+ * @extends Extension
2446
+ */
2447
+ class Component extends Extension {
2448
+ constructor() {
2449
+ super();
2450
+ this.$seal();
2451
+ }
2452
+ $mounted() {
2453
+ super.$mounted();
2454
+ if (this.$children.length !== 1) {
2455
+ throw userError("Component must have a child only", "dom-error");
2456
+ }
2457
+ const child = this.$children[0];
2458
+ if (child instanceof Tag || child instanceof Component) {
2459
+ const $ = this.$;
2460
+ $.node = child.node;
2461
+ }
2462
+ else {
2463
+ throw userError("Component child must be Tag or Component", "dom-error");
2464
+ }
2465
+ }
2466
+ $preinit(app, parent) {
2467
+ this.$.preinit(app, parent);
2468
+ }
2469
+ }
2470
+ /**
2471
+ * Private part of switch node
2472
+ * @class SwitchedNodePrivate
2473
+ * @extends INodePrivate
2474
+ */
2475
+ class SwitchedNodePrivate extends INodePrivate {
2476
+ constructor() {
2477
+ super();
2478
+ this.$seal();
2479
+ }
2480
+ /**
2481
+ * Runs GC
2482
+ */
2483
+ $destroy() {
2484
+ this.cases.forEach(c => {
2485
+ delete c.cond;
2486
+ delete c.cb;
2487
+ });
2488
+ this.cases.splice(0);
2489
+ super.$destroy();
2490
+ }
2491
+ }
2492
+ /**
2493
+ * Defines a node witch can switch its children conditionally
2494
+ */
2495
+ class SwitchedNode extends Fragment {
2496
+ /**
2497
+ * Constructs a switch node and define a sync function
2498
+ */
2499
+ constructor() {
2500
+ super(new SwitchedNodePrivate);
2501
+ this.$.sync = () => {
2502
+ const $ = this.$;
2503
+ let i = 0;
2504
+ for (; i < $.cases.length; i++) {
2505
+ if ($.cases[i].cond.$) {
2506
+ break;
2507
+ }
2508
+ }
2509
+ if (i === $.index) {
2510
+ return;
2511
+ }
2512
+ if ($.fragment) {
2513
+ $.fragment.$destroy();
2514
+ this.$children.splice(0);
2515
+ $.fragment = null;
2516
+ }
2517
+ if (i !== $.cases.length) {
2518
+ $.index = i;
2519
+ this.createChild($.cases[i].cb);
2520
+ }
2521
+ else {
2522
+ $.index = -1;
2523
+ }
2524
+ };
2525
+ this.$seal();
2526
+ }
2527
+ /**
2528
+ * Set up switch cases
2529
+ * @param cases {{ cond : IValue, cb : function(Fragment) }}
2530
+ */
2531
+ setCases(cases) {
2532
+ const $ = this.$;
2533
+ $.cases = [...cases];
2534
+ }
2535
+ /**
2536
+ * Creates a child node
2537
+ * @param cb {function(Fragment)} Call-back
2538
+ */
2539
+ createChild(cb) {
2540
+ const node = new Fragment();
2541
+ node.$preinit(this.$.app, this);
2542
+ node.$init();
2543
+ node.$ready();
2544
+ this.$.fragment = node;
2545
+ this.$children.push(node);
2546
+ cb(node);
2547
+ }
2548
+ $ready() {
2549
+ const $ = this.$;
2550
+ super.$ready();
2551
+ $.cases.forEach(c => {
2552
+ c.cond.on($.sync);
2553
+ });
2554
+ $.sync();
2555
+ }
2556
+ $destroy() {
2557
+ const $ = this.$;
2558
+ $.cases.forEach(c => {
2559
+ c.cond.off($.sync);
2560
+ });
2561
+ super.$destroy();
2562
+ }
2563
+ }
2564
+ /**
2565
+ * The private part of a text node
2566
+ */
2567
+ class DebugPrivate extends FragmentPrivate {
2568
+ constructor() {
2569
+ super();
2570
+ this.$seal();
2571
+ }
2572
+ /**
2573
+ * Pre-initializes a text node
2574
+ * @param app {App} the app node
2575
+ * @param parent {Fragment} parent node
2576
+ * @param text {String | IValue}
2577
+ */
2578
+ preinitComment(app, parent, text) {
2579
+ super.preinit(app, parent);
2580
+ this.node = document.createComment(text.$);
2581
+ this.bindings.add(new Expression((v) => {
2582
+ this.node.replaceData(0, -1, v);
2583
+ }, true, text));
2584
+ this.parent.$$appendNode(this.node);
2585
+ }
2586
+ /**
2587
+ * Clear node data
2588
+ */
2589
+ $destroy() {
2590
+ this.node.remove();
2591
+ super.$destroy();
2592
+ }
2593
+ }
2594
+ /**
2595
+ * Represents a debug node
2596
+ * @class DebugNode
2597
+ * @extends Fragment
2598
+ */
2599
+ class DebugNode extends Fragment {
2600
+ constructor() {
2601
+ super();
2602
+ /**
2603
+ * private data
2604
+ * @type {DebugNode}
2605
+ */
2606
+ this.$ = new DebugPrivate();
2607
+ this.$seal();
2608
+ }
2609
+ $preinit(app, parent, text) {
2610
+ const $ = this.$;
2611
+ if (!text) {
2612
+ throw internalError('wrong DebugNode::$preninit call');
2613
+ }
2614
+ $.preinitComment(app, parent, text);
2615
+ }
2616
+ /**
2617
+ * Runs garbage collector
2618
+ */
2619
+ $destroy() {
2620
+ this.$.$destroy();
2621
+ super.$destroy();
2622
+ }
2623
+ }
2624
+
2625
+ window.FragmentPrivate = FragmentPrivate;
2626
+ window.Fragment = Fragment;
2627
+ window.TextNodePrivate = TextNodePrivate;
2628
+ window.TextNode = TextNode;
2629
+ window.INodePrivate = INodePrivate;
2630
+ window.INode = INode;
2631
+ window.Tag = Tag;
2632
+ window.Extension = Extension;
2633
+ window.Component = Component;
2634
+ window.SwitchedNodePrivate = SwitchedNodePrivate;
2635
+ window.DebugPrivate = DebugPrivate;
2636
+ window.DebugNode = DebugNode;
2637
+
2638
+ // ./lib/node/app.js
2639
+ /**
2640
+ * Application Node
2641
+ * @class AppNode
2642
+ * @extends INode
2643
+ */
2644
+ class AppNode extends INode {
2645
+ /**
2646
+ * @param options {Object} Application options
2647
+ */
2648
+ constructor(options) {
2649
+ super();
2650
+ this.$run = (options === null || options === void 0 ? void 0 : options.executor) || ((options === null || options === void 0 ? void 0 : options.freezeUi) === false ? timeoutExecutor : instantExecutor);
2651
+ this.$debugUi = (options === null || options === void 0 ? void 0 : options.debugUi) || false;
2652
+ }
2653
+ }
2654
+ /**
2655
+ * Represents a Vasille.js application
2656
+ * @class App
2657
+ * @extends AppNode
2658
+ */
2659
+ class App extends AppNode {
2660
+ /**
2661
+ * Constructs an app node
2662
+ * @param node {Element} The root of application
2663
+ * @param options {Object} Application options
2664
+ */
2665
+ constructor(node, options) {
2666
+ super(options);
2667
+ this.$.node = node;
2668
+ this.$preinit(this, this);
2669
+ this.$seal();
2670
+ }
2671
+ $$appendNode(node) {
2672
+ const $ = this.$;
2673
+ $.app.$run.appendChild($.node, node);
2674
+ }
2675
+ }
2676
+
2677
+ window.AppNode = AppNode;
2678
+ window.App = App;
2679
+
2680
+ // ./lib/node/interceptor.js
2681
+ /**
2682
+ * Interceptor is designed to connect signals & methods of children elements
2683
+ * @class Interceptor
2684
+ * @extends Destroyable
2685
+ */
2686
+ class Interceptor extends Destroyable {
2687
+ constructor() {
2688
+ super(...arguments);
2689
+ /**
2690
+ * Set of signals
2691
+ * @type Set
2692
+ */
2693
+ this.signals = new Set;
2694
+ /**
2695
+ * Set of handlers
2696
+ * @type Set
2697
+ */
2698
+ this.handlers = new Set;
2699
+ }
2700
+ /**
2701
+ * Connect a signal or a handler
2702
+ * @param thing {Signal | function}
2703
+ */
2704
+ connect(thing) {
2705
+ // interceptor will connect signals and handlers together
2706
+ if (thing instanceof Signal) {
2707
+ this.handlers.forEach(handler => {
2708
+ thing.subscribe(handler);
2709
+ });
2710
+ this.signals.add(thing);
2711
+ }
2712
+ else {
2713
+ this.signals.forEach(signal => {
2714
+ signal.subscribe(thing);
2715
+ });
2716
+ this.handlers.add(thing);
2717
+ }
2718
+ }
2719
+ /**
2720
+ * Disconnect a handler from signals
2721
+ * @param handler {function}
2722
+ */
2723
+ disconnect(handler) {
2724
+ this.signals.forEach(signal => {
2725
+ signal.unsubscribe(handler);
2726
+ });
2727
+ }
2728
+ $destroy() {
2729
+ super.$destroy();
2730
+ this.signals.forEach(signal => {
2731
+ this.handlers.forEach(handler => {
2732
+ signal.unsubscribe(handler);
2733
+ });
2734
+ });
2735
+ }
2736
+ }
2737
+ /**
2738
+ * Interceptor node to implement directly to vasille DOM
2739
+ * @class InterceptorNode
2740
+ * @extends Extension
2741
+ */
2742
+ class InterceptorNode extends Fragment {
2743
+ constructor() {
2744
+ super(...arguments);
2745
+ /**
2746
+ * Internal interceptor
2747
+ * @type Interceptor
2748
+ */
2749
+ this.interceptor = new Interceptor;
2750
+ /**
2751
+ * The default slot of node
2752
+ * @type Slot
2753
+ */
2754
+ this.slot = new Slot;
2755
+ }
2756
+ $compose() {
2757
+ this.slot.release(this, this.interceptor);
2758
+ }
2759
+ }
2760
+
2761
+ window.Interceptor = Interceptor;
2762
+ window.InterceptorNode = InterceptorNode;
2763
+
2764
+ // ./lib/binding/attribute.js
2765
+ /**
2766
+ * Represents an Attribute binding description
2767
+ * @class AttributeBinding
2768
+ * @extends Binding
2769
+ */
2770
+ class AttributeBinding extends Binding {
2771
+ /**
2772
+ * Constructs an attribute binding description
2773
+ * @param node {INode} the vasille node
2774
+ * @param name {String} the name of attribute
2775
+ * @param value {IValue} value to bind
2776
+ */
2777
+ constructor(node, name, value) {
2778
+ super(node, name, value);
2779
+ }
2780
+ /**
2781
+ * Generates a function which updates the attribute value
2782
+ * @param name {String} The name of attribute
2783
+ * @returns {Function} a function which will update attribute value
2784
+ */
2785
+ bound(name) {
2786
+ return function (node, value) {
2787
+ if (value) {
2788
+ node.app.$run.setAttribute(node.node, name, value);
2789
+ }
2790
+ else {
2791
+ node.app.$run.removeAttribute(node.node, name);
2792
+ }
2793
+ };
2794
+ }
2795
+ }
2796
+
2797
+ window.AttributeBinding = AttributeBinding;
2798
+
2799
+ // ./lib/binding/style.js
2800
+ /**
2801
+ * Describes a style attribute binding
2802
+ * @class StyleBinding
2803
+ * @extends Binding
2804
+ */
2805
+ class StyleBinding extends Binding {
2806
+ /**
2807
+ * Constructs a style binding attribute
2808
+ * @param node {INode} the vasille node
2809
+ * @param name {string} the name of style property
2810
+ * @param value {IValue} the value to bind
2811
+ */
2812
+ constructor(node, name, value) {
2813
+ super(node, name, value);
2814
+ }
2815
+ /**
2816
+ * Generates a function to update style property value
2817
+ * @param name {string}
2818
+ * @returns {Function} a function to update style property
2819
+ */
2820
+ bound(name) {
2821
+ return function (node, value) {
2822
+ if (node.node instanceof HTMLElement) {
2823
+ node.app.$run.setStyle(node.node, name, value);
2824
+ }
2825
+ };
2826
+ }
2827
+ }
2828
+
2829
+ window.StyleBinding = StyleBinding;
2830
+
2831
+ // ./lib/binding/class.js
2832
+ /**
2833
+ * Represents a HTML class binding description
2834
+ * @class ClassBinding
2835
+ * @extends Binding
2836
+ */
2837
+ class ClassBinding extends Binding {
2838
+ /**
2839
+ * Constructs an HTML class binding description
2840
+ * @param node {INode} the vasille node
2841
+ * @param name {String} the name of class
2842
+ * @param value {IValue} the value to bind
2843
+ */
2844
+ constructor(node, name, value) {
2845
+ super(node, name, value);
2846
+ this.$seal();
2847
+ }
2848
+ /**
2849
+ * Generates a function which updates the html class value
2850
+ * @param name {String} The name of attribute
2851
+ * @returns {Function} a function which will update attribute value
2852
+ */
2853
+ bound(name) {
2854
+ let current = null;
2855
+ function addClass(node, cl) {
2856
+ node.app.$run.addClass(node.node, cl);
2857
+ }
2858
+ function removeClass(node, cl) {
2859
+ node.app.$run.removeClass(node.node, cl);
2860
+ }
2861
+ return (node, value) => {
2862
+ if (value !== current) {
2863
+ if (typeof current === "string" && current !== "") {
2864
+ removeClass(node, current);
2865
+ }
2866
+ if (typeof value === "boolean") {
2867
+ if (value) {
2868
+ addClass(node, name);
2869
+ }
2870
+ else {
2871
+ removeClass(node, name);
2872
+ }
2873
+ }
2874
+ else if (typeof value === "string" && value !== "") {
2875
+ addClass(node, value);
2876
+ }
2877
+ current = value;
2878
+ }
2879
+ };
2880
+ }
2881
+ }
2882
+
2883
+ window.ClassBinding = ClassBinding;
2884
+
2885
+ // ./lib/views/repeat-node.js
2886
+ /**
2887
+ * Private part of repeat node
2888
+ * @class RepeatNodePrivate
2889
+ * @extends INodePrivate
2890
+ */
2891
+ class RepeatNodePrivate extends INodePrivate {
2892
+ constructor() {
2893
+ super();
2894
+ /**
2895
+ * Children node hash
2896
+ * @type {Map}
2897
+ */
2898
+ this.nodes = new Map();
2899
+ this.$seal();
2900
+ }
2901
+ $destroy() {
2902
+ this.nodes.clear();
2903
+ super.$destroy();
2904
+ }
2905
+ }
2906
+ /**
2907
+ * Repeat node repeats its children
2908
+ * @class RepeatNode
2909
+ * @extends Fragment
2910
+ */
2911
+ class RepeatNode extends Fragment {
2912
+ constructor($) {
2913
+ super($ || new RepeatNodePrivate);
2914
+ /**
2915
+ * If false will use timeout executor, otherwise the app executor
2916
+ */
2917
+ this.freezeUi = true;
2918
+ this.slot = new Slot;
2919
+ }
2920
+ createChild(id, item, before) {
2921
+ // TODO: Refactor: remove @ts-ignore
2922
+ const node = new Fragment();
2923
+ // eslint-disable-next-line
2924
+ // @ts-ignore
2925
+ const $ = node.$;
2926
+ this.destroyChild(id, item);
2927
+ if (before) {
2928
+ $.next = before;
2929
+ // eslint-disable-next-line
2930
+ // @ts-ignore
2931
+ $.prev = before.$.prev;
2932
+ // eslint-disable-next-line
2933
+ // @ts-ignore
2934
+ before.$.prev = node;
2935
+ if ($.prev) {
2936
+ // eslint-disable-next-line
2937
+ // @ts-ignore
2938
+ $.prev.$.next = node;
2939
+ }
2940
+ this.$children.splice(this.$children.indexOf(before), 0, node);
2941
+ }
2942
+ else {
2943
+ const lastChild = this.$children[this.$children.length - 1];
2944
+ if (lastChild) {
2945
+ // eslint-disable-next-line
2946
+ // @ts-ignore
2947
+ lastChild.$.next = node;
2948
+ }
2949
+ $.prev = lastChild;
2950
+ this.$children.push(node);
2951
+ }
2952
+ node.$preinit(this.$.app, this);
2953
+ node.$init();
2954
+ const callback = () => {
2955
+ this.slot.release(node, item, id);
2956
+ node.$ready();
2957
+ };
2958
+ if (this.freezeUi) {
2959
+ this.$.app.$run.callCallback(callback);
2960
+ }
2961
+ else {
2962
+ timeoutExecutor.callCallback(callback);
2963
+ }
2964
+ this.$.nodes.set(id, node);
2965
+ }
2966
+ destroyChild(id, item) {
2967
+ const $ = this.$;
2968
+ const child = $.nodes.get(id);
2969
+ if (child) {
2970
+ // eslint-disable-next-line
2971
+ // @ts-ignore
2972
+ const $ = child.$;
2973
+ if ($.prev) {
2974
+ // eslint-disable-next-line
2975
+ // @ts-ignore
2976
+ $.prev.$.next = $.next;
2977
+ }
2978
+ if ($.next) {
2979
+ // eslint-disable-next-line
2980
+ // @ts-ignore
2981
+ $.next.$.prev = $.prev;
2982
+ }
2983
+ child.$destroy();
2984
+ this.$.nodes.delete(id);
2985
+ this.$children.splice(this.$children.indexOf(child), 1);
2986
+ }
2987
+ }
2988
+ }
2989
+
2990
+ window.RepeatNodePrivate = RepeatNodePrivate;
2991
+ window.RepeatNode = RepeatNode;
2992
+
2993
+ // ./lib/views/repeater.js
2994
+ /**
2995
+ * Private part of repeater
2996
+ * @class RepeaterPrivate
2997
+ * @extends RepeatNodePrivate
2998
+ */
2999
+ class RepeaterPrivate extends RepeatNodePrivate {
3000
+ constructor() {
3001
+ super();
3002
+ /**
3003
+ * Current count of child nodes
3004
+ */
3005
+ this.currentCount = 0;
3006
+ this.$seal();
3007
+ }
3008
+ }
3009
+ /**
3010
+ * The simplest repeat node interpretation, repeat children pack a several times
3011
+ * @class Repeater
3012
+ * @extends RepeatNode
3013
+ */
3014
+ class Repeater extends RepeatNode {
3015
+ constructor($) {
3016
+ super($ || new RepeaterPrivate);
3017
+ /**
3018
+ * The count of children
3019
+ */
3020
+ this.count = new Reference(0);
3021
+ this.$seal();
3022
+ }
3023
+ /**
3024
+ * Changes the children count
3025
+ */
3026
+ changeCount(number) {
3027
+ const $ = this.$;
3028
+ if (number > $.currentCount) {
3029
+ for (let i = $.currentCount; i < number; i++) {
3030
+ this.createChild(i, i);
3031
+ }
3032
+ }
3033
+ else {
3034
+ for (let i = $.currentCount - 1; i >= number; i--) {
3035
+ this.destroyChild(i, i);
3036
+ }
3037
+ }
3038
+ $.currentCount = number;
3039
+ }
3040
+ $created() {
3041
+ const $ = this.$;
3042
+ super.$created();
3043
+ $.updateHandler = this.changeCount.bind(this);
3044
+ this.count.on($.updateHandler);
3045
+ }
3046
+ $ready() {
3047
+ this.changeCount(this.count.$);
3048
+ }
3049
+ $destroy() {
3050
+ const $ = this.$;
3051
+ super.$destroy();
3052
+ this.count.off($.updateHandler);
3053
+ }
3054
+ }
3055
+
3056
+ window.RepeaterPrivate = RepeaterPrivate;
3057
+ window.Repeater = Repeater;
3058
+
3059
+ // ./lib/views/base-view.js
3060
+ /**
3061
+ * Private part of BaseView
3062
+ * @class BaseViewPrivate
3063
+ * @extends RepeatNodePrivate
3064
+ */
3065
+ class BaseViewPrivate extends RepeatNodePrivate {
3066
+ constructor() {
3067
+ super();
3068
+ this.$seal();
3069
+ }
3070
+ }
3071
+ /**
3072
+ * Base class of default views
3073
+ * @class BaseView
3074
+ * @extends RepeatNode
3075
+ * @implements IModel
3076
+ */
3077
+ class BaseView extends RepeatNode {
3078
+ constructor($1) {
3079
+ super($1 || new BaseViewPrivate);
3080
+ const $ = this.$;
3081
+ $.addHandler = (id, item) => {
3082
+ this.createChild(id, item);
3083
+ };
3084
+ $.removeHandler = (id, item) => {
3085
+ this.destroyChild(id, item);
3086
+ };
3087
+ this.$seal();
3088
+ }
3089
+ /**
3090
+ * Handle ready event
3091
+ */
3092
+ $ready() {
3093
+ const $ = this.$;
3094
+ this.model.listener.onAdd($.addHandler);
3095
+ this.model.listener.onRemove($.removeHandler);
3096
+ super.$ready();
3097
+ }
3098
+ /**
3099
+ * Handles destroy event
3100
+ */
3101
+ $destroy() {
3102
+ const $ = this.$;
3103
+ this.model.listener.offAdd($.addHandler);
3104
+ this.model.listener.offRemove($.removeHandler);
3105
+ super.$destroy();
3106
+ }
3107
+ }
3108
+
3109
+ window.BaseViewPrivate = BaseViewPrivate;
3110
+ window.BaseView = BaseView;
3111
+
3112
+ // ./lib/views/array-view.js
3113
+ /**
3114
+ * Represents a view of an array model
3115
+ * @class ArrayView
3116
+ * @extends BaseView
3117
+ */
3118
+ class ArrayView extends BaseView {
3119
+ constructor(model) {
3120
+ super();
3121
+ this.model = model;
3122
+ }
3123
+ createChild(id, item, before) {
3124
+ super.createChild(item, item, before || this.$.nodes.get(id));
3125
+ }
3126
+ $ready() {
3127
+ this.model.forEach(item => {
3128
+ this.createChild(item, item);
3129
+ });
3130
+ super.$ready();
3131
+ }
3132
+ }
3133
+
3134
+ window.ArrayView = ArrayView;
3135
+
3136
+ // ./lib/node/watch.js
3137
+ /**
3138
+ * Watch Node
3139
+ * @class Watch
3140
+ * @extends Fragment
3141
+ */
3142
+ class Watch extends Fragment {
3143
+ constructor() {
3144
+ super();
3145
+ this.slot = new Slot;
3146
+ this.model = this.$ref(null);
3147
+ this.$seal();
3148
+ }
3149
+ $createWatchers() {
3150
+ this.$watch((value) => {
3151
+ this.$children.forEach(child => {
3152
+ child.$destroy();
3153
+ });
3154
+ this.$children.splice(0);
3155
+ this.slot.release(this, value);
3156
+ }, this.model);
3157
+ }
3158
+ $compose() {
3159
+ this.slot.release(this, this.model.$);
3160
+ }
3161
+ }
3162
+
3163
+ window.Watch = Watch;
3164
+
3165
+ // ./lib/views/object-view.js
3166
+ /**
3167
+ * Create a children pack for each object field
3168
+ * @class ObjectView
3169
+ * @extends BaseView
3170
+ */
3171
+ class ObjectView extends BaseView {
3172
+ constructor(model) {
3173
+ super();
3174
+ this.model = model;
3175
+ }
3176
+ $ready() {
3177
+ const obj = this.model;
3178
+ for (const key in obj) {
3179
+ this.createChild(key, obj[key]);
3180
+ }
3181
+ super.$ready();
3182
+ }
3183
+ }
3184
+
3185
+ window.ObjectView = ObjectView;
3186
+
3187
+ // ./lib/views/map-view.js
3188
+ /**
3189
+ * Create a children pack for each map value
3190
+ * @class MapView
3191
+ * @extends BaseView
3192
+ */
3193
+ class MapView extends BaseView {
3194
+ constructor(model) {
3195
+ super();
3196
+ this.model = model;
3197
+ }
3198
+ $ready() {
3199
+ const map = this.model;
3200
+ map.forEach((value, key) => {
3201
+ this.createChild(key, value);
3202
+ });
3203
+ super.$ready();
3204
+ }
3205
+ }
3206
+
3207
+ window.MapView = MapView;
3208
+
3209
+ // ./lib/views/set-view.js
3210
+ /**
3211
+ * Create a children pack for each set value
3212
+ * @class SetView
3213
+ * @extends BaseView
3214
+ */
3215
+ class SetView extends BaseView {
3216
+ constructor(model) {
3217
+ super();
3218
+ this.model = model;
3219
+ }
3220
+ $ready() {
3221
+ const $ = this.$;
3222
+ const set = this.model;
3223
+ set.forEach(item => {
3224
+ $.app.$run.callCallback(() => {
3225
+ this.createChild(item, item);
3226
+ });
3227
+ });
3228
+ super.$ready();
3229
+ }
3230
+ }
3231
+
3232
+ window.SetView = SetView;
3233
+
3234
+ })();