vasille 2.3.5 → 2.3.7

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,2483 @@
1
+ (function(){
2
+ // ./lib/core/destroyable.js
3
+ /**
4
+ * Mark an object which can be destroyed
5
+ * @class Destroyable
6
+ */
7
+ class Destroyable {
8
+ /**
9
+ * Make object fields non configurable
10
+ * @protected
11
+ */
12
+ $seal() {
13
+ const $ = this;
14
+ Object.keys($).forEach(i => {
15
+ // eslint-disable-next-line no-prototype-builtins
16
+ if (this.hasOwnProperty(i)) {
17
+ const config = Object.getOwnPropertyDescriptor($, i);
18
+ if (config.configurable) {
19
+ let descriptor;
20
+ if (config.set || config.get) {
21
+ descriptor = {
22
+ configurable: false,
23
+ get: config.get,
24
+ set: config.set,
25
+ enumerable: config.enumerable
26
+ };
27
+ }
28
+ else {
29
+ descriptor = {
30
+ value: $[i],
31
+ configurable: false,
32
+ writable: config.writable,
33
+ enumerable: config.enumerable
34
+ };
35
+ }
36
+ Object.defineProperty($, i, descriptor);
37
+ }
38
+ }
39
+ });
40
+ }
41
+ /**
42
+ * Garbage collector method
43
+ */
44
+ $destroy() {
45
+ // nothing here
46
+ }
47
+ }
48
+
49
+ window.Destroyable = Destroyable;
50
+
51
+ // ./lib/core/errors.js
52
+ const reportIt = "Report it here: https://gitlab.com/vasille-js/vasille-js/-/issues";
53
+ function notOverwritten() {
54
+ console.error("Vasille-SFP: Internal error", "Must be overwritten", reportIt);
55
+ return "not-overwritten";
56
+ }
57
+ function internalError(msg) {
58
+ console.error("Vasille-SFP: Internal error", msg, reportIt);
59
+ return "internal-error";
60
+ }
61
+ function userError(msg, err) {
62
+ console.error("Vasille-SFP: User error", msg);
63
+ return err;
64
+ }
65
+ function wrongBinding(msg) {
66
+ return userError(msg, "wrong-binding");
67
+ }
68
+
69
+ window.notOverwritten = notOverwritten;
70
+ window.internalError = internalError;
71
+ window.userError = userError;
72
+ window.wrongBinding = wrongBinding;
73
+
74
+ // ./lib/core/ivalue.js
75
+ class Switchable extends Destroyable {
76
+ /**
77
+ * Enable update handlers triggering
78
+ */
79
+ $enable() {
80
+ throw notOverwritten();
81
+ }
82
+ /**
83
+ * disable update handlers triggering
84
+ */
85
+ $disable() {
86
+ throw notOverwritten();
87
+ }
88
+ }
89
+ /**
90
+ * Interface which describes a value
91
+ * @class IValue
92
+ * @extends Destroyable
93
+ */
94
+ class IValue extends Switchable {
95
+ /**
96
+ * @param isEnabled {boolean} initial is enabled state
97
+ */
98
+ constructor(isEnabled) {
99
+ super();
100
+ this.isEnabled = isEnabled;
101
+ }
102
+ /**
103
+ * Get the encapsulated value
104
+ * @return {*} the encapsulated value
105
+ */
106
+ get $() {
107
+ throw notOverwritten();
108
+ }
109
+ /**
110
+ * Sets the encapsulated value
111
+ * @param value {*} value to encapsulate
112
+ */
113
+ set $(value) {
114
+ throw notOverwritten();
115
+ }
116
+ /**
117
+ * Add a new handler to value change
118
+ * @param handler {function(value : *)} the handler to add
119
+ */
120
+ $on(handler) {
121
+ throw notOverwritten();
122
+ }
123
+ /**
124
+ * Removes a handler of value change
125
+ * @param handler {function(value : *)} the handler to remove
126
+ */
127
+ $off(handler) {
128
+ throw notOverwritten();
129
+ }
130
+ }
131
+
132
+ window.Switchable = Switchable;
133
+ window.IValue = IValue;
134
+
135
+ // ./lib/core/core.js
136
+
137
+ const currentStack = [];
138
+ function stack(node) {
139
+ currentStack.push(current);
140
+ current = node;
141
+ }
142
+ function unstack() {
143
+ current = currentStack.pop();
144
+ }
145
+ /**
146
+ * Private stuff of a reactive object
147
+ * @class ReactivePrivate
148
+ * @extends Destroyable
149
+ */
150
+ class ReactivePrivate extends Destroyable {
151
+ constructor() {
152
+ super();
153
+ /**
154
+ * A list of user-defined values
155
+ * @type {Set}
156
+ */
157
+ this.watch = new Set;
158
+ /**
159
+ * A list of user-defined bindings
160
+ * @type {Set}
161
+ */
162
+ this.bindings = new Set;
163
+ /**
164
+ * A list of user defined models
165
+ */
166
+ this.models = new Set;
167
+ /**
168
+ * Reactivity switch state
169
+ * @type {boolean}
170
+ */
171
+ this.enabled = true;
172
+ /**
173
+ * The frozen state of object
174
+ * @type {boolean}
175
+ */
176
+ this.frozen = false;
177
+ this.$seal();
178
+ }
179
+ $destroy() {
180
+ this.watch.forEach(value => value.$destroy());
181
+ this.watch.clear();
182
+ this.bindings.forEach(binding => binding.$destroy());
183
+ this.bindings.clear();
184
+ this.models.forEach(model => model.disableReactivity());
185
+ this.models.clear();
186
+ this.freezeExpr && this.freezeExpr.$destroy();
187
+ this.onDestroy && this.onDestroy();
188
+ super.$destroy();
189
+ }
190
+ }
191
+ /**
192
+ * A reactive object
193
+ * @class Reactive
194
+ * @extends Destroyable
195
+ */
196
+ class Reactive extends Destroyable {
197
+ constructor(input, $) {
198
+ super();
199
+ this.input = input;
200
+ this.$ = $ || new ReactivePrivate;
201
+ this.$seal();
202
+ }
203
+ /**
204
+ * Get parent node
205
+ */
206
+ get parent() {
207
+ return this.$.parent;
208
+ }
209
+ /**
210
+ * Create a reference
211
+ * @param value {*} value to reference
212
+ */
213
+ ref(value) {
214
+ const $ = this.$;
215
+ const ref = new Reference(value);
216
+ $.watch.add(ref);
217
+ return ref;
218
+ }
219
+ /**
220
+ * Create a mirror
221
+ * @param value {IValue} value to mirror
222
+ */
223
+ mirror(value) {
224
+ const mirror = new Mirror(value, false);
225
+ this.$.watch.add(mirror);
226
+ return mirror;
227
+ }
228
+ /**
229
+ * Create a forward-only mirror
230
+ * @param value {IValue} value to mirror
231
+ */
232
+ forward(value) {
233
+ const mirror = new Mirror(value, true);
234
+ this.$.watch.add(mirror);
235
+ return mirror;
236
+ }
237
+ /**
238
+ * Creates a pointer
239
+ * @param value {*} default value to point
240
+ * @param forwardOnly {boolean} forward only sync
241
+ */
242
+ point(value, forwardOnly = false) {
243
+ const $ = this.$;
244
+ const pointer = new Pointer(value, forwardOnly);
245
+ $.watch.add(pointer);
246
+ return pointer;
247
+ }
248
+ /**
249
+ * Register a model
250
+ * @param model
251
+ */
252
+ register(model) {
253
+ this.$.models.add(model);
254
+ return model;
255
+ }
256
+ /**
257
+ * Creates a watcher
258
+ * @param func {function} function to run on any argument change
259
+ * @param values
260
+ */
261
+ watch(func, ...values) {
262
+ const $ = this.$;
263
+ $.watch.add(new Expression(func, !this.$.frozen, ...values));
264
+ }
265
+ /**
266
+ * Creates a computed value
267
+ * @param func {function} function to run on any argument change
268
+ * @param values
269
+ * @return {IValue} the created ivalue
270
+ */
271
+ expr(func, ...values) {
272
+ const res = new Expression(func, !this.$.frozen, ...values);
273
+ const $ = this.$;
274
+ $.watch.add(res);
275
+ return res;
276
+ }
277
+ /**
278
+ * Enable reactivity of fields
279
+ */
280
+ enable() {
281
+ const $ = this.$;
282
+ if (!$.enabled) {
283
+ $.watch.forEach(watcher => {
284
+ watcher.$enable();
285
+ });
286
+ $.models.forEach(model => {
287
+ model.enableReactivity();
288
+ });
289
+ $.enabled = true;
290
+ }
291
+ }
292
+ /**
293
+ * Disable reactivity of fields
294
+ */
295
+ disable() {
296
+ const $ = this.$;
297
+ if ($.enabled) {
298
+ $.watch.forEach(watcher => {
299
+ watcher.$disable();
300
+ });
301
+ $.models.forEach(model => {
302
+ model.disableReactivity();
303
+ });
304
+ $.enabled = false;
305
+ }
306
+ }
307
+ /**
308
+ * Disable/Enable reactivity of object fields with feedback
309
+ * @param cond {IValue} show condition
310
+ * @param onOff {function} on show feedback
311
+ * @param onOn {function} on hide feedback
312
+ */
313
+ bindAlive(cond, onOff, onOn) {
314
+ const $ = this.$;
315
+ if ($.freezeExpr) {
316
+ throw wrongBinding("this component already have a freeze state");
317
+ }
318
+ if ($.watch.has(cond)) {
319
+ throw wrongBinding("freeze state must be bound to an external component");
320
+ }
321
+ $.freezeExpr = new Expression((cond) => {
322
+ $.frozen = !cond;
323
+ if (cond) {
324
+ onOn === null || onOn === void 0 ? void 0 : onOn();
325
+ this.enable();
326
+ }
327
+ else {
328
+ onOff === null || onOff === void 0 ? void 0 : onOff();
329
+ this.disable();
330
+ }
331
+ }, true, cond);
332
+ return this;
333
+ }
334
+ init() {
335
+ this.applyOptions(this.input);
336
+ return this.compose(this.input);
337
+ }
338
+ applyOptions(input) {
339
+ // empty
340
+ }
341
+ applyOptionsNow() {
342
+ this.applyOptions(this.input);
343
+ }
344
+ compose(input) {
345
+ throw notOverwritten();
346
+ }
347
+ composeNow() {
348
+ return this.compose(this.input);
349
+ }
350
+ runFunctional(f, ...args) {
351
+ stack(this);
352
+ // yet another ts bug
353
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
354
+ // @ts-ignore
355
+ const result = f(...args);
356
+ unstack();
357
+ return result;
358
+ }
359
+ runOnDestroy(func) {
360
+ this.$.onDestroy = func;
361
+ }
362
+ $destroy() {
363
+ super.$destroy();
364
+ this.$.$destroy();
365
+ this.$ = null;
366
+ }
367
+ }
368
+
369
+ window.stack = stack;
370
+ window.unstack = unstack;
371
+ window.ReactivePrivate = ReactivePrivate;
372
+ window.Reactive = Reactive;
373
+
374
+ // ./lib/value/reference.js
375
+ /**
376
+ * Declares a notifiable value
377
+ * @class Reference
378
+ * @extends IValue
379
+ */
380
+ class Reference extends IValue {
381
+ /**
382
+ * @param value {any} the initial value
383
+ */
384
+ constructor(value) {
385
+ super(true);
386
+ this.$value = value;
387
+ this.$onchange = new Set;
388
+ this.$seal();
389
+ }
390
+ get $() {
391
+ return this.$value;
392
+ }
393
+ set $(value) {
394
+ if (this.$value !== value) {
395
+ this.$value = value;
396
+ if (this.isEnabled) {
397
+ this.$onchange.forEach(handler => {
398
+ handler(value);
399
+ });
400
+ }
401
+ }
402
+ }
403
+ $enable() {
404
+ if (!this.isEnabled) {
405
+ this.$onchange.forEach(handler => {
406
+ handler(this.$value);
407
+ });
408
+ this.isEnabled = true;
409
+ }
410
+ }
411
+ $disable() {
412
+ this.isEnabled = false;
413
+ }
414
+ $on(handler) {
415
+ this.$onchange.add(handler);
416
+ }
417
+ $off(handler) {
418
+ this.$onchange.delete(handler);
419
+ }
420
+ $destroy() {
421
+ super.$destroy();
422
+ this.$onchange.clear();
423
+ }
424
+ }
425
+
426
+ window.Reference = Reference;
427
+
428
+ // ./lib/value/expression.js
429
+ /**
430
+ * Bind some values to one expression
431
+ * @class Expression
432
+ * @extends IValue
433
+ */
434
+ class Expression extends IValue {
435
+ /**
436
+ * Creates a function bounded to N values
437
+ * @param func {Function} the function to bound
438
+ * @param values
439
+ * @param link {Boolean} links immediately if true
440
+ */
441
+ constructor(func, link, ...values) {
442
+ super(false);
443
+ /**
444
+ * Expression will link different handler for each value of list
445
+ */
446
+ this.linkedFunc = [];
447
+ const handler = (i) => {
448
+ if (i != null) {
449
+ this.valuesCache[i] = this.values[i].$;
450
+ }
451
+ this.sync.$ = func.apply(this, this.valuesCache);
452
+ };
453
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
454
+ // @ts-ignore
455
+ this.valuesCache = values.map(item => item.$);
456
+ this.sync = new Reference(func.apply(this, this.valuesCache));
457
+ let i = 0;
458
+ values.forEach(() => {
459
+ this.linkedFunc.push(handler.bind(this, Number(i++)));
460
+ });
461
+ this.values = values;
462
+ this.func = handler;
463
+ if (link) {
464
+ this.$enable();
465
+ }
466
+ else {
467
+ handler();
468
+ }
469
+ this.$seal();
470
+ }
471
+ get $() {
472
+ return this.sync.$;
473
+ }
474
+ set $(value) {
475
+ this.sync.$ = value;
476
+ }
477
+ $on(handler) {
478
+ this.sync.$on(handler);
479
+ return this;
480
+ }
481
+ $off(handler) {
482
+ this.sync.$off(handler);
483
+ return this;
484
+ }
485
+ $enable() {
486
+ if (!this.isEnabled) {
487
+ for (let i = 0; i < this.values.length; i++) {
488
+ this.values[i].$on(this.linkedFunc[i]);
489
+ this.valuesCache[i] = this.values[i].$;
490
+ }
491
+ this.func();
492
+ this.isEnabled = true;
493
+ }
494
+ return this;
495
+ }
496
+ $disable() {
497
+ if (this.isEnabled) {
498
+ for (let i = 0; i < this.values.length; i++) {
499
+ this.values[i].$off(this.linkedFunc[i]);
500
+ }
501
+ this.isEnabled = false;
502
+ }
503
+ return this;
504
+ }
505
+ $destroy() {
506
+ this.$disable();
507
+ this.values.splice(0);
508
+ this.valuesCache.splice(0);
509
+ this.linkedFunc.splice(0);
510
+ super.$destroy();
511
+ }
512
+ }
513
+
514
+ window.Expression = Expression;
515
+
516
+ // ./lib/value/mirror.js
517
+ /**
518
+ * Declares a notifiable bind to a value
519
+ * @class Mirror
520
+ * @extends IValue
521
+ * @version 2
522
+ */
523
+ class Mirror extends Reference {
524
+ /**
525
+ * Constructs a notifiable bind to a value
526
+ * @param value {IValue} is initial value
527
+ * @param forwardOnly {boolean} ensure forward only synchronization
528
+ */
529
+ constructor(value, forwardOnly = false) {
530
+ super(value.$);
531
+ this.$handler = (v) => {
532
+ this.$ = v;
533
+ };
534
+ this.$pointedValue = value;
535
+ this.$forwardOnly = forwardOnly;
536
+ value.$on(this.$handler);
537
+ this.$seal();
538
+ }
539
+ get $() {
540
+ // this is a ts bug
541
+ // eslint-disable-next-line
542
+ // @ts-ignore
543
+ return super.$;
544
+ }
545
+ set $(v) {
546
+ if (!this.$forwardOnly) {
547
+ this.$pointedValue.$ = v;
548
+ }
549
+ // this is a ts bug
550
+ // eslint-disable-next-line
551
+ // @ts-ignore
552
+ super.$ = v;
553
+ }
554
+ $enable() {
555
+ if (!this.isEnabled) {
556
+ this.isEnabled = true;
557
+ this.$pointedValue.$on(this.$handler);
558
+ this.$ = this.$pointedValue.$;
559
+ }
560
+ }
561
+ $disable() {
562
+ if (this.isEnabled) {
563
+ this.$pointedValue.$off(this.$handler);
564
+ this.isEnabled = false;
565
+ }
566
+ }
567
+ $destroy() {
568
+ this.$disable();
569
+ super.$destroy();
570
+ }
571
+ }
572
+
573
+ window.Mirror = Mirror;
574
+
575
+ // ./lib/value/pointer.js
576
+ /**
577
+ * r/w pointer to a value
578
+ * @class Pointer
579
+ * @extends Mirror
580
+ */
581
+ class Pointer extends Mirror {
582
+ /**
583
+ * @param value {IValue} value to point
584
+ * @param forwardOnly {boolean} forward only data flow
585
+ */
586
+ constructor(value, forwardOnly = false) {
587
+ super(value, forwardOnly);
588
+ }
589
+ /**
590
+ * Point a new ivalue
591
+ * @param value {IValue} value to point
592
+ */
593
+ set $$(value) {
594
+ if (this.$pointedValue !== value) {
595
+ this.$disable();
596
+ this.$pointedValue = value;
597
+ this.$enable();
598
+ }
599
+ }
600
+ }
601
+
602
+ window.Pointer = Pointer;
603
+
604
+ // ./lib/models/listener.js
605
+ /**
606
+ * Represent a listener for a model
607
+ * @class Listener
608
+ */
609
+ class Listener {
610
+ constructor() {
611
+ Object.defineProperties(this, {
612
+ onAdded: {
613
+ value: new Set,
614
+ writable: false,
615
+ configurable: false
616
+ },
617
+ onRemoved: {
618
+ value: new Set,
619
+ writable: false,
620
+ configurable: false
621
+ },
622
+ frozen: {
623
+ value: false,
624
+ writable: true,
625
+ configurable: false
626
+ },
627
+ queue: {
628
+ value: [],
629
+ writable: false,
630
+ configurable: false
631
+ }
632
+ });
633
+ }
634
+ /**
635
+ * Exclude the repeated operation in queue
636
+ * @private
637
+ */
638
+ excludeRepeat(index) {
639
+ this.queue.forEach((item, i) => {
640
+ if (item.index === index) {
641
+ this.queue.splice(i, 1);
642
+ return true;
643
+ }
644
+ });
645
+ return false;
646
+ }
647
+ /**
648
+ * Emits added event to listeners
649
+ * @param index {*} index of value
650
+ * @param value {*} value of added item
651
+ */
652
+ emitAdded(index, value) {
653
+ if (this.frozen) {
654
+ if (!this.excludeRepeat(index)) {
655
+ this.queue.push({ sign: true, index, value });
656
+ }
657
+ }
658
+ else {
659
+ this.onAdded.forEach(handler => {
660
+ handler(index, value);
661
+ });
662
+ }
663
+ }
664
+ /**
665
+ * Emits removed event to listeners
666
+ * @param index {*} index of removed value
667
+ * @param value {*} value of removed item
668
+ */
669
+ emitRemoved(index, value) {
670
+ if (this.frozen) {
671
+ if (!this.excludeRepeat(index)) {
672
+ this.queue.push({ sign: false, index, value });
673
+ }
674
+ }
675
+ else {
676
+ this.onRemoved.forEach(handler => {
677
+ handler(index, value);
678
+ });
679
+ }
680
+ }
681
+ /**
682
+ * Adds a handler to added event
683
+ * @param handler {function} function to run on event emitting
684
+ */
685
+ onAdd(handler) {
686
+ this.onAdded.add(handler);
687
+ }
688
+ /**
689
+ * Adds a handler to removed event
690
+ * @param handler {function} function to run on event emitting
691
+ */
692
+ onRemove(handler) {
693
+ this.onRemoved.add(handler);
694
+ }
695
+ /**
696
+ * Removes an handler from added event
697
+ * @param handler {function} handler to remove
698
+ */
699
+ offAdd(handler) {
700
+ this.onAdded.delete(handler);
701
+ }
702
+ /**
703
+ * Removes an handler form removed event
704
+ * @param handler {function} handler to remove
705
+ */
706
+ offRemove(handler) {
707
+ this.onRemoved.delete(handler);
708
+ }
709
+ /**
710
+ * Run all queued operation and enable reactivity
711
+ */
712
+ enableReactivity() {
713
+ this.queue.forEach(item => {
714
+ if (item.sign) {
715
+ this.onAdded.forEach(handler => {
716
+ handler(item.index, item.value);
717
+ });
718
+ }
719
+ else {
720
+ this.onRemoved.forEach(handler => {
721
+ handler(item.index, item.value);
722
+ });
723
+ }
724
+ });
725
+ this.queue.splice(0);
726
+ this.frozen = false;
727
+ }
728
+ /**
729
+ * Disable the reactivity and enable the queue
730
+ */
731
+ disableReactivity() {
732
+ this.frozen = true;
733
+ }
734
+ }
735
+
736
+ window.Listener = Listener;
737
+
738
+ // ./lib/models/model.js
739
+
740
+
741
+
742
+ // ./lib/models/array-model.js
743
+ /**
744
+ * Model based on Array class
745
+ * @extends Array
746
+ * @implements IModel
747
+ */
748
+ class ArrayModel extends Array {
749
+ /**
750
+ * @param data {Array} input data
751
+ */
752
+ constructor(data = []) {
753
+ super();
754
+ Object.defineProperty(this, 'listener', {
755
+ value: new Listener,
756
+ writable: false,
757
+ configurable: false
758
+ });
759
+ for (let i = 0; i < data.length; i++) {
760
+ super.push(data[i]);
761
+ }
762
+ }
763
+ /* Array members */
764
+ /**
765
+ * Gets the last item of array
766
+ * @return {*} the last item of array
767
+ */
768
+ get last() {
769
+ return this.length ? this[this.length - 1] : null;
770
+ }
771
+ /**
772
+ * Calls Array.fill and notify about changes
773
+ * @param value {*} value to fill with
774
+ * @param start {?number} begin index
775
+ * @param end {?number} end index
776
+ */
777
+ fill(value, start, end) {
778
+ if (!start) {
779
+ start = 0;
780
+ }
781
+ if (!end) {
782
+ end = this.length;
783
+ }
784
+ for (let i = start; i < end; i++) {
785
+ this.listener.emitRemoved(this[i], this[i]);
786
+ this[i] = value;
787
+ this.listener.emitAdded(value, value);
788
+ }
789
+ return this;
790
+ }
791
+ /**
792
+ * Calls Array.pop and notify about changes
793
+ * @return {*} removed value
794
+ */
795
+ pop() {
796
+ const v = super.pop();
797
+ if (v !== undefined) {
798
+ this.listener.emitRemoved(v, v);
799
+ }
800
+ return v;
801
+ }
802
+ /**
803
+ * Calls Array.push and notify about changes
804
+ * @param items {...*} values to push
805
+ * @return {number} new length of array
806
+ */
807
+ push(...items) {
808
+ items.forEach(item => {
809
+ this.listener.emitAdded(item, item);
810
+ super.push(item);
811
+ });
812
+ return this.length;
813
+ }
814
+ /**
815
+ * Calls Array.shift and notify about changed
816
+ * @return {*} the shifted value
817
+ */
818
+ shift() {
819
+ const v = super.shift();
820
+ if (v !== undefined) {
821
+ this.listener.emitRemoved(v, v);
822
+ }
823
+ return v;
824
+ }
825
+ /**
826
+ * Calls Array.splice and notify about changed
827
+ * @param start {number} start index
828
+ * @param deleteCount {?number} delete count
829
+ * @param items {...*}
830
+ * @return {ArrayModel} a pointer to this
831
+ */
832
+ splice(start, deleteCount, ...items) {
833
+ start = Math.min(start, this.length);
834
+ deleteCount = deleteCount || this.length - start;
835
+ const before = this[start + deleteCount];
836
+ for (let i = 0; i < deleteCount; i++) {
837
+ const index = start + deleteCount - i - 1;
838
+ if (this[index] !== undefined) {
839
+ this.listener.emitRemoved(this[index], this[index]);
840
+ }
841
+ }
842
+ for (let i = 0; i < items.length; i++) {
843
+ this.listener.emitAdded(before, items[i]);
844
+ }
845
+ return new ArrayModel(super.splice(start, deleteCount, ...items));
846
+ }
847
+ /**
848
+ * Calls Array.unshift and notify about changed
849
+ * @param items {...*} values to insert
850
+ * @return {number} the length after prepend
851
+ */
852
+ unshift(...items) {
853
+ for (let i = 0; i < items.length; i++) {
854
+ this.listener.emitAdded(this[i], items[i]);
855
+ }
856
+ return super.unshift(...items);
857
+ }
858
+ /**
859
+ * Inserts a value to the end of array
860
+ * @param v {*} value to insert
861
+ */
862
+ append(v) {
863
+ this.listener.emitAdded(null, v);
864
+ super.push(v);
865
+ return this;
866
+ }
867
+ /**
868
+ * Clears array
869
+ * @return {this} a pointer to this
870
+ */
871
+ clear() {
872
+ this.forEach(v => {
873
+ this.listener.emitRemoved(v, v);
874
+ });
875
+ super.splice(0);
876
+ return this;
877
+ }
878
+ /**
879
+ * Inserts a value to position `index`
880
+ * @param index {number} index to insert value
881
+ * @param v {*} value to insert
882
+ * @return {this} a pointer to this
883
+ */
884
+ insert(index, v) {
885
+ this.listener.emitAdded(this[index], v);
886
+ super.splice(index, 0, v);
887
+ return this;
888
+ }
889
+ /**
890
+ * Inserts a value to the beginning of array
891
+ * @param v {*} value to insert
892
+ * @return {this} a pointer to this
893
+ */
894
+ prepend(v) {
895
+ this.listener.emitAdded(this[0], v);
896
+ super.unshift(v);
897
+ return this;
898
+ }
899
+ /**
900
+ * Removes a value from an index
901
+ * @param index {number} index of value to remove
902
+ * @return {this} a pointer to this
903
+ */
904
+ removeAt(index) {
905
+ if (index > 0 && index < this.length) {
906
+ this.listener.emitRemoved(this[index], this[index]);
907
+ super.splice(index, 1);
908
+ }
909
+ return this;
910
+ }
911
+ /**
912
+ * Removes the first value of array
913
+ * @return {this} a pointer to this
914
+ */
915
+ removeFirst() {
916
+ if (this.length) {
917
+ this.listener.emitRemoved(this[0], this[0]);
918
+ super.shift();
919
+ }
920
+ return this;
921
+ }
922
+ /**
923
+ * Removes the ast value of array
924
+ * @return {this} a pointer to this
925
+ */
926
+ removeLast() {
927
+ const last = this.last;
928
+ if (last != null) {
929
+ this.listener.emitRemoved(this[this.length - 1], last);
930
+ super.pop();
931
+ }
932
+ return this;
933
+ }
934
+ /**
935
+ * Remove the first occurrence of value
936
+ * @param v {*} value to remove
937
+ * @return {this}
938
+ */
939
+ removeOne(v) {
940
+ this.removeAt(this.indexOf(v));
941
+ return this;
942
+ }
943
+ replace(at, with_) {
944
+ this.listener.emitAdded(this[at], with_);
945
+ this.listener.emitRemoved(this[at], this[at]);
946
+ this[at] = with_;
947
+ return this;
948
+ }
949
+ enableReactivity() {
950
+ this.listener.enableReactivity();
951
+ }
952
+ disableReactivity() {
953
+ this.listener.disableReactivity();
954
+ }
955
+ }
956
+
957
+ window.ArrayModel = ArrayModel;
958
+
959
+ // ./lib/models/map-model.js
960
+ /**
961
+ * A Map based memory
962
+ * @class MapModel
963
+ * @extends Map
964
+ * @implements IModel
965
+ */
966
+ class MapModel extends Map {
967
+ /**
968
+ * Constructs a map model
969
+ * @param map {[*, *][]} input data
970
+ */
971
+ constructor(map = []) {
972
+ super();
973
+ Object.defineProperty(this, 'listener', {
974
+ value: new Listener,
975
+ writable: false,
976
+ configurable: false
977
+ });
978
+ map.forEach(([key, value]) => {
979
+ super.set(key, value);
980
+ });
981
+ }
982
+ /**
983
+ * Calls Map.clear and notify abut changes
984
+ */
985
+ clear() {
986
+ this.forEach((value, key) => {
987
+ this.listener.emitRemoved(key, value);
988
+ });
989
+ super.clear();
990
+ }
991
+ /**
992
+ * Calls Map.delete and notify abut changes
993
+ * @param key {*} key
994
+ * @return {boolean} true if removed something, otherwise false
995
+ */
996
+ delete(key) {
997
+ const tmp = super.get(key);
998
+ if (tmp) {
999
+ this.listener.emitRemoved(key, tmp);
1000
+ }
1001
+ return super.delete(key);
1002
+ }
1003
+ /**
1004
+ * Calls Map.set and notify abut changes
1005
+ * @param key {*} key
1006
+ * @param value {*} value
1007
+ * @return {MapModel} a pointer to this
1008
+ */
1009
+ set(key, value) {
1010
+ const tmp = super.get(key);
1011
+ if (tmp) {
1012
+ this.listener.emitRemoved(key, tmp);
1013
+ }
1014
+ super.set(key, value);
1015
+ this.listener.emitAdded(key, value);
1016
+ return this;
1017
+ }
1018
+ enableReactivity() {
1019
+ this.listener.enableReactivity();
1020
+ }
1021
+ disableReactivity() {
1022
+ this.listener.disableReactivity();
1023
+ }
1024
+ }
1025
+
1026
+ window.MapModel = MapModel;
1027
+
1028
+ // ./lib/models/object-model.js
1029
+ /**
1030
+ * Object based model
1031
+ * @extends Object
1032
+ */
1033
+ class ObjectModel extends Object {
1034
+ /**
1035
+ * Constructs a object model
1036
+ * @param obj {Object} input data
1037
+ */
1038
+ constructor(obj = {}) {
1039
+ super();
1040
+ this.container = Object.create(null);
1041
+ Object.defineProperty(this, 'listener', {
1042
+ value: new Listener,
1043
+ writable: false,
1044
+ configurable: false
1045
+ });
1046
+ for (const i in obj) {
1047
+ Object.defineProperty(this.container, i, {
1048
+ value: obj[i],
1049
+ configurable: true,
1050
+ writable: true,
1051
+ enumerable: true
1052
+ });
1053
+ this.listener.emitAdded(i, obj[i]);
1054
+ }
1055
+ }
1056
+ /**
1057
+ * Gets a value of a field
1058
+ * @param key {string}
1059
+ * @return {*}
1060
+ */
1061
+ get(key) {
1062
+ return this.container[key];
1063
+ }
1064
+ /**
1065
+ * Sets an object property value
1066
+ * @param key {string} property name
1067
+ * @param v {*} property value
1068
+ * @return {ObjectModel} a pointer to this
1069
+ */
1070
+ set(key, v) {
1071
+ if (Reflect.has(this.container, key)) {
1072
+ this.listener.emitRemoved(key, this.container[key]);
1073
+ this.container[key] = v;
1074
+ }
1075
+ else {
1076
+ Object.defineProperty(this.container, key, {
1077
+ value: v,
1078
+ configurable: true,
1079
+ writable: true,
1080
+ enumerable: true
1081
+ });
1082
+ }
1083
+ this.listener.emitAdded(key, this.container[key]);
1084
+ return this;
1085
+ }
1086
+ get values() {
1087
+ return this.container;
1088
+ }
1089
+ /**
1090
+ * Deletes an object property
1091
+ * @param key {string} property name
1092
+ */
1093
+ delete(key) {
1094
+ if (this.container[key]) {
1095
+ this.listener.emitRemoved(key, this.container[key]);
1096
+ delete this.container[key];
1097
+ }
1098
+ }
1099
+ enableReactivity() {
1100
+ this.listener.enableReactivity();
1101
+ }
1102
+ disableReactivity() {
1103
+ this.listener.disableReactivity();
1104
+ }
1105
+ }
1106
+
1107
+ window.ObjectModel = ObjectModel;
1108
+
1109
+ // ./lib/models/set-model.js
1110
+ /**
1111
+ * A Set based model
1112
+ * @class SetModel
1113
+ * @extends Set
1114
+ * @implements IModel
1115
+ */
1116
+ class SetModel extends Set {
1117
+ /**
1118
+ * Constructs a set model based on a set
1119
+ * @param set {Set} input data
1120
+ */
1121
+ constructor(set = []) {
1122
+ super();
1123
+ Object.defineProperty(this, 'listener', {
1124
+ value: new Listener,
1125
+ writable: false,
1126
+ configurable: false
1127
+ });
1128
+ set.forEach(item => {
1129
+ super.add(item);
1130
+ });
1131
+ }
1132
+ /**
1133
+ * Calls Set.add and notify abut changes
1134
+ * @param value {*} value
1135
+ * @return {this} a pointer to this
1136
+ */
1137
+ add(value) {
1138
+ if (!super.has(value)) {
1139
+ this.listener.emitAdded(value, value);
1140
+ super.add(value);
1141
+ }
1142
+ return this;
1143
+ }
1144
+ /**
1145
+ * Calls Set.clear and notify abut changes
1146
+ */
1147
+ clear() {
1148
+ this.forEach(item => {
1149
+ this.listener.emitRemoved(item, item);
1150
+ });
1151
+ super.clear();
1152
+ }
1153
+ /**
1154
+ * Calls Set.delete and notify abut changes
1155
+ * @param value {*}
1156
+ * @return {boolean} true if a value was deleted, otherwise false
1157
+ */
1158
+ delete(value) {
1159
+ if (super.has(value)) {
1160
+ this.listener.emitRemoved(value, value);
1161
+ }
1162
+ return super.delete(value);
1163
+ }
1164
+ enableReactivity() {
1165
+ this.listener.enableReactivity();
1166
+ }
1167
+ disableReactivity() {
1168
+ this.listener.disableReactivity();
1169
+ }
1170
+ }
1171
+
1172
+ window.SetModel = SetModel;
1173
+
1174
+ // ./lib/spec/html.js
1175
+
1176
+
1177
+
1178
+ // ./lib/spec/svg.js
1179
+
1180
+
1181
+
1182
+ // ./lib/spec/react.js
1183
+
1184
+
1185
+
1186
+ // ./lib/binding/binding.js
1187
+ /**
1188
+ * Describe a common binding logic
1189
+ * @class Binding
1190
+ * @extends Destroyable
1191
+ */
1192
+ class Binding extends Destroyable {
1193
+ /**
1194
+ * Constructs a common binding logic
1195
+ * @param value {IValue} the value to bind
1196
+ */
1197
+ constructor(value) {
1198
+ super();
1199
+ this.binding = value;
1200
+ this.$seal();
1201
+ }
1202
+ init(bounded) {
1203
+ this.func = bounded;
1204
+ this.binding.$on(this.func);
1205
+ this.func(this.binding.$);
1206
+ }
1207
+ /**
1208
+ * Just clear bindings
1209
+ */
1210
+ $destroy() {
1211
+ this.binding.$off(this.func);
1212
+ super.$destroy();
1213
+ }
1214
+ }
1215
+
1216
+ window.Binding = Binding;
1217
+
1218
+ // ./lib/binding/attribute.js
1219
+ /**
1220
+ * Represents an Attribute binding description
1221
+ * @class AttributeBinding
1222
+ * @extends Binding
1223
+ */
1224
+ class AttributeBinding extends Binding {
1225
+ /**
1226
+ * Constructs an attribute binding description
1227
+ * @param node {INode} the vasille node
1228
+ * @param name {String} the name of attribute
1229
+ * @param value {IValue} value to bind
1230
+ */
1231
+ constructor(node, name, value) {
1232
+ super(value);
1233
+ this.init((value) => {
1234
+ if (value) {
1235
+ if (typeof value === 'boolean') {
1236
+ node.node.setAttribute(name, "");
1237
+ }
1238
+ else {
1239
+ node.node.setAttribute(name, `${value}`);
1240
+ }
1241
+ }
1242
+ else {
1243
+ node.node.removeAttribute(name);
1244
+ }
1245
+ });
1246
+ this.$seal();
1247
+ }
1248
+ }
1249
+
1250
+ window.AttributeBinding = AttributeBinding;
1251
+
1252
+ // ./lib/binding/class.js
1253
+ function addClass(node, cl) {
1254
+ node.node.classList.add(cl);
1255
+ }
1256
+ function removeClass(node, cl) {
1257
+ node.node.classList.remove(cl);
1258
+ }
1259
+ class StaticClassBinding extends Binding {
1260
+ constructor(node, name, value) {
1261
+ super(value);
1262
+ this.current = false;
1263
+ this.init((value) => {
1264
+ if (value !== this.current) {
1265
+ if (value) {
1266
+ addClass(node, name);
1267
+ }
1268
+ else {
1269
+ removeClass(node, name);
1270
+ }
1271
+ this.current = value;
1272
+ }
1273
+ });
1274
+ this.$seal();
1275
+ }
1276
+ }
1277
+ class DynamicalClassBinding extends Binding {
1278
+ constructor(node, value) {
1279
+ super(value);
1280
+ this.current = "";
1281
+ this.init((value) => {
1282
+ if (this.current != value) {
1283
+ if (this.current.length) {
1284
+ removeClass(node, this.current);
1285
+ }
1286
+ if (value.length) {
1287
+ addClass(node, value);
1288
+ }
1289
+ this.current = value;
1290
+ }
1291
+ });
1292
+ this.$seal();
1293
+ }
1294
+ }
1295
+
1296
+ window.StaticClassBinding = StaticClassBinding;
1297
+ window.DynamicalClassBinding = DynamicalClassBinding;
1298
+
1299
+ // ./lib/binding/style.js
1300
+ /**
1301
+ * Describes a style attribute binding
1302
+ * @class StyleBinding
1303
+ * @extends Binding
1304
+ */
1305
+ class StyleBinding extends Binding {
1306
+ /**
1307
+ * Constructs a style binding attribute
1308
+ * @param node {INode} the vasille node
1309
+ * @param name {string} the name of style property
1310
+ * @param value {IValue} the value to bind
1311
+ */
1312
+ constructor(node, name, value) {
1313
+ super(value);
1314
+ this.init((value) => {
1315
+ if (node.node instanceof HTMLElement) {
1316
+ node.node.style.setProperty(name, value);
1317
+ }
1318
+ });
1319
+ this.$seal();
1320
+ }
1321
+ }
1322
+
1323
+ window.StyleBinding = StyleBinding;
1324
+
1325
+ // ./lib/node/node.js
1326
+ /**
1327
+ * Represents a Vasille.js node
1328
+ * @class FragmentPrivate
1329
+ * @extends ReactivePrivate
1330
+ */
1331
+ class FragmentPrivate extends ReactivePrivate {
1332
+ constructor() {
1333
+ super();
1334
+ this.$seal();
1335
+ }
1336
+ /**
1337
+ * Pre-initializes the base of a fragment
1338
+ * @param app {App} the app node
1339
+ * @param parent {Fragment} the parent node
1340
+ */
1341
+ preinit(app, parent) {
1342
+ this.app = app;
1343
+ this.parent = parent;
1344
+ }
1345
+ /**
1346
+ * Unlinks all bindings
1347
+ */
1348
+ $destroy() {
1349
+ this.next = null;
1350
+ this.prev = null;
1351
+ super.$destroy();
1352
+ }
1353
+ }
1354
+ /**
1355
+ * This class is symbolic
1356
+ * @extends Reactive
1357
+ */
1358
+ class Fragment extends Reactive {
1359
+ /**
1360
+ * Constructs a Vasille Node
1361
+ * @param input
1362
+ * @param $ {FragmentPrivate}
1363
+ */
1364
+ constructor(input, $) {
1365
+ super(input, $ || new FragmentPrivate);
1366
+ /**
1367
+ * The children list
1368
+ * @type Array
1369
+ */
1370
+ this.children = new Set;
1371
+ this.lastChild = null;
1372
+ }
1373
+ /**
1374
+ * Gets the app of node
1375
+ */
1376
+ get app() {
1377
+ return this.$.app;
1378
+ }
1379
+ /**
1380
+ * Prepare to init fragment
1381
+ * @param app {AppNode} app of node
1382
+ * @param parent {Fragment} parent of node
1383
+ * @param data {*} additional data
1384
+ */
1385
+ preinit(app, parent, data) {
1386
+ const $ = this.$;
1387
+ $.preinit(app, parent);
1388
+ }
1389
+ init() {
1390
+ const ret = super.init();
1391
+ this.ready();
1392
+ return ret;
1393
+ }
1394
+ compose(input) {
1395
+ input.slot && input.slot(this);
1396
+ return {};
1397
+ }
1398
+ /** To be overloaded: ready event handler */
1399
+ ready() {
1400
+ // empty
1401
+ }
1402
+ /**
1403
+ * Pushes a node to children immediately
1404
+ * @param node {Fragment} A node to push
1405
+ * @protected
1406
+ */
1407
+ pushNode(node) {
1408
+ if (this.lastChild) {
1409
+ this.lastChild.$.next = node;
1410
+ }
1411
+ node.$.prev = this.lastChild;
1412
+ this.lastChild = node;
1413
+ this.children.add(node);
1414
+ }
1415
+ /**
1416
+ * Find first node in element if so exists
1417
+ * @return {?Element}
1418
+ * @protected
1419
+ */
1420
+ findFirstChild() {
1421
+ let first;
1422
+ this.children.forEach(child => {
1423
+ first = first || child.findFirstChild();
1424
+ });
1425
+ return first;
1426
+ }
1427
+ /**
1428
+ * Append a node to end of element
1429
+ * @param node {Node} node to insert
1430
+ */
1431
+ appendNode(node) {
1432
+ const $ = this.$;
1433
+ if ($.next) {
1434
+ $.next.insertAdjacent(node);
1435
+ }
1436
+ else {
1437
+ $.parent.appendNode(node);
1438
+ }
1439
+ }
1440
+ /**
1441
+ * Insert a node as a sibling of this
1442
+ * @param node {Node} node to insert
1443
+ */
1444
+ insertAdjacent(node) {
1445
+ const child = this.findFirstChild();
1446
+ const $ = this.$;
1447
+ if (child) {
1448
+ child.parentElement.insertBefore(node, child);
1449
+ }
1450
+ else if ($.next) {
1451
+ $.next.insertAdjacent(node);
1452
+ }
1453
+ else {
1454
+ $.parent.appendNode(node);
1455
+ }
1456
+ }
1457
+ /**
1458
+ * Defines a text fragment
1459
+ * @param text {String | IValue} A text fragment string
1460
+ * @param cb {function (TextNode)} Callback if previous is slot name
1461
+ */
1462
+ text(text, cb) {
1463
+ const $ = this.$;
1464
+ const node = new TextNode();
1465
+ node.preinit($.app, this, text);
1466
+ this.pushNode(node);
1467
+ cb && cb(node);
1468
+ }
1469
+ debug(text) {
1470
+ if (this.$.app.debugUi) {
1471
+ const node = new DebugNode();
1472
+ node.preinit(this.$.app, this, text);
1473
+ this.pushNode(node);
1474
+ }
1475
+ }
1476
+ /**
1477
+ * Defines a tag element
1478
+ * @param tagName {String} the tag name
1479
+ * @param input
1480
+ * @param cb {function(Tag, *)} callback
1481
+ */
1482
+ tag(tagName, input, cb
1483
+ // @ts-ignore
1484
+ ) {
1485
+ const $ = this.$;
1486
+ const node = new Tag(input);
1487
+ input.slot = cb || input.slot;
1488
+ node.preinit($.app, this, tagName);
1489
+ node.init();
1490
+ this.pushNode(node);
1491
+ node.ready();
1492
+ // @ts-ignore
1493
+ return node.node;
1494
+ }
1495
+ /**
1496
+ * Defines a custom element
1497
+ * @param node {Fragment} vasille element to insert
1498
+ * @param callback {function($ : *)}
1499
+ */
1500
+ create(node, callback) {
1501
+ const $ = this.$;
1502
+ node.$.parent = this;
1503
+ node.preinit($.app, this);
1504
+ node.input.slot = callback || node.input.slot;
1505
+ this.pushNode(node);
1506
+ return node.init();
1507
+ }
1508
+ /**
1509
+ * Defines an if node
1510
+ * @param cond {IValue} condition
1511
+ * @param cb {function(Fragment)} callback to run on true
1512
+ * @return {this}
1513
+ */
1514
+ if(cond, cb) {
1515
+ const node = new SwitchedNode();
1516
+ node.preinit(this.$.app, this);
1517
+ node.init();
1518
+ this.pushNode(node);
1519
+ node.addCase(this.case(cond, cb));
1520
+ node.ready();
1521
+ }
1522
+ else(cb) {
1523
+ if (this.lastChild instanceof SwitchedNode) {
1524
+ this.lastChild.addCase(this.default(cb));
1525
+ }
1526
+ else {
1527
+ throw userError('wrong `else` function use', 'logic-error');
1528
+ }
1529
+ }
1530
+ elif(cond, cb) {
1531
+ if (this.lastChild instanceof SwitchedNode) {
1532
+ this.lastChild.addCase(this.case(cond, cb));
1533
+ }
1534
+ else {
1535
+ throw userError('wrong `elif` function use', 'logic-error');
1536
+ }
1537
+ }
1538
+ /**
1539
+ * Create a case for switch
1540
+ * @param cond {IValue<boolean>}
1541
+ * @param cb {function(Fragment) : void}
1542
+ * @return {{cond : IValue, cb : (function(Fragment) : void)}}
1543
+ */
1544
+ case(cond, cb) {
1545
+ return { cond, cb };
1546
+ }
1547
+ /**
1548
+ * @param cb {(function(Fragment) : void)}
1549
+ * @return {{cond : IValue, cb : (function(Fragment) : void)}}
1550
+ */
1551
+ default(cb) {
1552
+ return { cond: trueIValue, cb };
1553
+ }
1554
+ insertBefore(node) {
1555
+ const $ = this.$;
1556
+ node.$.prev = $.prev;
1557
+ node.$.next = this;
1558
+ if ($.prev) {
1559
+ $.prev.$.next = node;
1560
+ }
1561
+ $.prev = node;
1562
+ }
1563
+ insertAfter(node) {
1564
+ const $ = this.$;
1565
+ node.$.prev = this;
1566
+ node.$.next = $.next;
1567
+ $.next = node;
1568
+ }
1569
+ remove() {
1570
+ const $ = this.$;
1571
+ if ($.next) {
1572
+ $.next.$.prev = $.prev;
1573
+ }
1574
+ if ($.prev) {
1575
+ $.prev.$.next = $.next;
1576
+ }
1577
+ }
1578
+ $destroy() {
1579
+ this.children.forEach(child => child.$destroy());
1580
+ this.children.clear();
1581
+ this.lastChild = null;
1582
+ if (this.$.parent.lastChild === this) {
1583
+ this.$.parent.lastChild = this.$.prev;
1584
+ }
1585
+ super.$destroy();
1586
+ }
1587
+ }
1588
+ const trueIValue = new Reference(true);
1589
+ /**
1590
+ * The private part of a text node
1591
+ * @class TextNodePrivate
1592
+ * @extends FragmentPrivate
1593
+ */
1594
+ class TextNodePrivate extends FragmentPrivate {
1595
+ constructor() {
1596
+ super();
1597
+ this.$seal();
1598
+ }
1599
+ /**
1600
+ * Pre-initializes a text node
1601
+ * @param app {AppNode} the app node
1602
+ * @param parent
1603
+ * @param text {IValue}
1604
+ */
1605
+ preinitText(app, parent, text) {
1606
+ super.preinit(app, parent);
1607
+ this.node = document.createTextNode(text instanceof IValue ? text.$ : text);
1608
+ if (text instanceof IValue) {
1609
+ this.bindings.add(new Expression((v) => {
1610
+ this.node.replaceData(0, -1, v);
1611
+ }, true, text));
1612
+ }
1613
+ }
1614
+ /**
1615
+ * Clear node data
1616
+ */
1617
+ $destroy() {
1618
+ super.$destroy();
1619
+ }
1620
+ }
1621
+ /**
1622
+ * Represents a text node
1623
+ * @class TextNode
1624
+ * @extends Fragment
1625
+ */
1626
+ class TextNode extends Fragment {
1627
+ constructor($ = new TextNodePrivate()) {
1628
+ super({}, $);
1629
+ this.$seal();
1630
+ }
1631
+ preinit(app, parent, text) {
1632
+ const $ = this.$;
1633
+ if (!text) {
1634
+ throw internalError('wrong TextNode::$preninit call');
1635
+ }
1636
+ $.preinitText(app, parent, text);
1637
+ $.parent.appendNode($.node);
1638
+ }
1639
+ findFirstChild() {
1640
+ return this.$.node;
1641
+ }
1642
+ $destroy() {
1643
+ this.$.node.remove();
1644
+ this.$.$destroy();
1645
+ super.$destroy();
1646
+ }
1647
+ }
1648
+ /**
1649
+ * The private part of a base node
1650
+ * @class INodePrivate
1651
+ * @extends FragmentPrivate
1652
+ */
1653
+ class INodePrivate extends FragmentPrivate {
1654
+ constructor() {
1655
+ super();
1656
+ /**
1657
+ * Defines if node is unmounted
1658
+ * @type {boolean}
1659
+ */
1660
+ this.unmounted = false;
1661
+ this.$seal();
1662
+ }
1663
+ $destroy() {
1664
+ super.$destroy();
1665
+ }
1666
+ }
1667
+ /**
1668
+ * Vasille node which can manipulate an element node
1669
+ * @class INode
1670
+ * @extends Fragment
1671
+ */
1672
+ class INode extends Fragment {
1673
+ /**
1674
+ * Constructs a base node
1675
+ * @param input
1676
+ * @param $ {?INodePrivate}
1677
+ */
1678
+ constructor(input, $) {
1679
+ super(input, $ || new INodePrivate);
1680
+ this.$seal();
1681
+ }
1682
+ /**
1683
+ * Get the bound node
1684
+ */
1685
+ get node() {
1686
+ return this.$.node;
1687
+ }
1688
+ /**
1689
+ * Bind attribute value
1690
+ * @param name {String} name of attribute
1691
+ * @param value {IValue} value
1692
+ */
1693
+ attr(name, value) {
1694
+ const $ = this.$;
1695
+ const attr = new AttributeBinding(this, name, value);
1696
+ $.bindings.add(attr);
1697
+ }
1698
+ /**
1699
+ * Set attribute value
1700
+ * @param name {string} name of attribute
1701
+ * @param value {string} value
1702
+ */
1703
+ setAttr(name, value) {
1704
+ if (typeof value === 'boolean') {
1705
+ if (value) {
1706
+ this.$.node.setAttribute(name, "");
1707
+ }
1708
+ }
1709
+ else {
1710
+ this.$.node.setAttribute(name, `${value}`);
1711
+ }
1712
+ return this;
1713
+ }
1714
+ /**
1715
+ * Adds a CSS class
1716
+ * @param cl {string} Class name
1717
+ */
1718
+ addClass(cl) {
1719
+ this.$.node.classList.add(cl);
1720
+ return this;
1721
+ }
1722
+ /**
1723
+ * Adds some CSS classes
1724
+ * @param cls {...string} classes names
1725
+ */
1726
+ removeClasse(cl) {
1727
+ this.$.node.classList.remove(cl);
1728
+ return this;
1729
+ }
1730
+ /**
1731
+ * Bind a CSS class
1732
+ * @param className {IValue}
1733
+ */
1734
+ bindClass(className) {
1735
+ const $ = this.$;
1736
+ $.bindings.add(new DynamicalClassBinding(this, className));
1737
+ return this;
1738
+ }
1739
+ /**
1740
+ * Bind a floating class name
1741
+ * @param cond {IValue} condition
1742
+ * @param className {string} class name
1743
+ */
1744
+ floatingClass(cond, className) {
1745
+ this.$.bindings.add(new StaticClassBinding(this, className, cond));
1746
+ return this;
1747
+ }
1748
+ /**
1749
+ * Defines a style attribute
1750
+ * @param name {String} name of style attribute
1751
+ * @param value {IValue} value
1752
+ */
1753
+ style(name, value) {
1754
+ const $ = this.$;
1755
+ if ($.node instanceof HTMLElement) {
1756
+ $.bindings.add(new StyleBinding(this, name, value));
1757
+ }
1758
+ else {
1759
+ throw userError('style can be applied to HTML elements only', 'non-html-element');
1760
+ }
1761
+ return this;
1762
+ }
1763
+ /**
1764
+ * Sets a style property value
1765
+ * @param prop {string} Property name
1766
+ * @param value {string} Property value
1767
+ */
1768
+ setStyle(prop, value) {
1769
+ if (this.$.node instanceof HTMLElement) {
1770
+ this.$.node.style.setProperty(prop, value);
1771
+ }
1772
+ else {
1773
+ throw userError("Style can be set for HTML elements only", "non-html-element");
1774
+ }
1775
+ return this;
1776
+ }
1777
+ /**
1778
+ * Add a listener for an event
1779
+ * @param name {string} Event name
1780
+ * @param handler {function (Event)} Event handler
1781
+ * @param options {Object | boolean} addEventListener options
1782
+ */
1783
+ listen(name, handler, options) {
1784
+ this.$.node.addEventListener(name, handler, options);
1785
+ return this;
1786
+ }
1787
+ insertAdjacent(node) {
1788
+ this.$.node.parentNode.insertBefore(node, this.$.node);
1789
+ }
1790
+ /**
1791
+ * A v-show & ngShow alternative
1792
+ * @param cond {IValue} show condition
1793
+ */
1794
+ bindShow(cond) {
1795
+ const $ = this.$;
1796
+ const node = $.node;
1797
+ if (node instanceof HTMLElement) {
1798
+ let lastDisplay = node.style.display;
1799
+ const htmlNode = node;
1800
+ return this.bindAlive(cond, () => {
1801
+ lastDisplay = htmlNode.style.display;
1802
+ htmlNode.style.display = 'none';
1803
+ }, () => {
1804
+ htmlNode.style.display = lastDisplay;
1805
+ });
1806
+ }
1807
+ else {
1808
+ throw userError('the element must be a html element', 'bind-show');
1809
+ }
1810
+ }
1811
+ /**
1812
+ * bind HTML
1813
+ * @param value {IValue}
1814
+ */
1815
+ bindDomApi(name, value) {
1816
+ const $ = this.$;
1817
+ const node = $.node;
1818
+ if (node instanceof HTMLElement) {
1819
+ node[name] = value.$;
1820
+ this.watch((v) => {
1821
+ node[name] = v;
1822
+ }, value);
1823
+ }
1824
+ else {
1825
+ throw userError("HTML can be bound for HTML nodes only", "dom-error");
1826
+ }
1827
+ }
1828
+ applyOptions(options) {
1829
+ options["v:attr"] && Object.keys(options["v:attr"]).forEach(name => {
1830
+ const value = options["v:attr"][name];
1831
+ if (value instanceof IValue) {
1832
+ this.attr(name, value);
1833
+ }
1834
+ else {
1835
+ this.setAttr(name, value);
1836
+ }
1837
+ });
1838
+ if (options.class) {
1839
+ const handleClass = (name, value) => {
1840
+ if (value instanceof IValue) {
1841
+ this.floatingClass(value, name);
1842
+ }
1843
+ else if (value && name !== '$') {
1844
+ this.addClass(name);
1845
+ }
1846
+ else {
1847
+ this.removeClasse(name);
1848
+ }
1849
+ };
1850
+ if (Array.isArray(options.class)) {
1851
+ options.class.forEach(item => {
1852
+ if (item instanceof IValue) {
1853
+ this.bindClass(item);
1854
+ }
1855
+ else if (typeof item == "string") {
1856
+ this.addClass(item);
1857
+ }
1858
+ else {
1859
+ Reflect.ownKeys(item).forEach((name) => {
1860
+ handleClass(name, item[name]);
1861
+ });
1862
+ }
1863
+ });
1864
+ }
1865
+ else {
1866
+ options.class.$.forEach(item => {
1867
+ this.bindClass(item);
1868
+ });
1869
+ Reflect.ownKeys(options.class).forEach((name) => {
1870
+ handleClass(name, options.class[name]);
1871
+ });
1872
+ }
1873
+ }
1874
+ options.style && Object.keys(options.style).forEach(name => {
1875
+ const value = options.style[name];
1876
+ if (value instanceof IValue) {
1877
+ this.style(name, value);
1878
+ }
1879
+ else if (typeof value === "string") {
1880
+ this.setStyle(name, value);
1881
+ }
1882
+ else {
1883
+ if (value[0] instanceof IValue) {
1884
+ this.style(name, this.expr((v) => v + value[1], value[0]));
1885
+ }
1886
+ else {
1887
+ this.setStyle(name, value[0] + value[1]);
1888
+ }
1889
+ }
1890
+ });
1891
+ options["v:events"] && Object.keys(options["v:events"]).forEach(name => {
1892
+ this.listen(name, options["v:events"][name]);
1893
+ });
1894
+ if (options["v:bind"]) {
1895
+ const inode = this.node;
1896
+ Reflect.ownKeys(options["v:bind"]).forEach((k) => {
1897
+ const value = options["v:bind"][k];
1898
+ if (k === 'value' && (inode instanceof HTMLInputElement || inode instanceof HTMLTextAreaElement)) {
1899
+ inode.oninput = () => value.$ = inode.value;
1900
+ }
1901
+ else if (k === 'checked' && inode instanceof HTMLInputElement) {
1902
+ inode.oninput = () => value.$ = inode.checked;
1903
+ }
1904
+ else if (k === 'volume' && inode instanceof HTMLMediaElement) {
1905
+ inode.onvolumechange = () => value.$ = inode.volume;
1906
+ }
1907
+ this.bindDomApi(k, value);
1908
+ });
1909
+ }
1910
+ options["v:set"] && Object.keys(options["v:set"]).forEach(key => {
1911
+ this.node[key] = options["v:set"][key];
1912
+ });
1913
+ }
1914
+ }
1915
+ /**
1916
+ * Represents an Vasille.js HTML element node
1917
+ * @class Tag
1918
+ * @extends INode
1919
+ */
1920
+ class Tag extends INode {
1921
+ constructor(input) {
1922
+ super(input);
1923
+ this.$seal();
1924
+ }
1925
+ preinit(app, parent, tagName) {
1926
+ if (!tagName || typeof tagName !== "string") {
1927
+ throw internalError('wrong Tag::$preinit call');
1928
+ }
1929
+ const node = document.createElement(tagName);
1930
+ const $ = this.$;
1931
+ $.preinit(app, parent);
1932
+ $.node = node;
1933
+ $.parent.appendNode(node);
1934
+ }
1935
+ compose(input) {
1936
+ input.slot && input.slot(this);
1937
+ return {};
1938
+ }
1939
+ findFirstChild() {
1940
+ return this.$.unmounted ? null : this.$.node;
1941
+ }
1942
+ insertAdjacent(node) {
1943
+ if (this.$.unmounted) {
1944
+ if (this.$.next) {
1945
+ this.$.next.insertAdjacent(node);
1946
+ }
1947
+ else {
1948
+ this.$.parent.appendNode(node);
1949
+ }
1950
+ }
1951
+ else {
1952
+ super.insertAdjacent(node);
1953
+ }
1954
+ }
1955
+ appendNode(node) {
1956
+ this.$.node.appendChild(node);
1957
+ }
1958
+ /**
1959
+ * Mount/Unmount a node
1960
+ * @param cond {IValue} show condition
1961
+ */
1962
+ bindMount(cond) {
1963
+ const $ = this.$;
1964
+ this.bindAlive(cond, () => {
1965
+ $.node.remove();
1966
+ $.unmounted = true;
1967
+ }, () => {
1968
+ if ($.unmounted) {
1969
+ this.insertAdjacent($.node);
1970
+ $.unmounted = false;
1971
+ }
1972
+ });
1973
+ }
1974
+ /**
1975
+ * Runs GC
1976
+ */
1977
+ $destroy() {
1978
+ this.node.remove();
1979
+ super.$destroy();
1980
+ }
1981
+ }
1982
+ /**
1983
+ * Represents a vasille extension node
1984
+ * @class Extension
1985
+ * @extends INode
1986
+ */
1987
+ class Extension extends INode {
1988
+ preinit(app, parent) {
1989
+ const $ = this.$;
1990
+ let it = parent;
1991
+ while (it && !(it instanceof INode)) {
1992
+ it = it.parent;
1993
+ }
1994
+ if (it && it instanceof INode) {
1995
+ $.node = it.node;
1996
+ }
1997
+ $.preinit(app, parent);
1998
+ if (!it) {
1999
+ throw userError("A extension node can be encapsulated only in a tag/extension/component", "virtual-dom");
2000
+ }
2001
+ }
2002
+ extend(options) {
2003
+ this.applyOptions(options);
2004
+ }
2005
+ $destroy() {
2006
+ super.$destroy();
2007
+ }
2008
+ }
2009
+ /**
2010
+ * Node which cas has just a child
2011
+ * @class Component
2012
+ * @extends Extension
2013
+ */
2014
+ class Component extends Extension {
2015
+ init() {
2016
+ const ret = super.composeNow();
2017
+ this.ready();
2018
+ super.applyOptionsNow();
2019
+ return ret;
2020
+ }
2021
+ ready() {
2022
+ super.ready();
2023
+ if (this.children.size !== 1) {
2024
+ throw userError("Component must have a child only", "dom-error");
2025
+ }
2026
+ const child = this.lastChild;
2027
+ if (child instanceof Tag || child instanceof Component) {
2028
+ const $ = this.$;
2029
+ $.node = child.node;
2030
+ }
2031
+ else {
2032
+ throw userError("Component child must be Tag or Component", "dom-error");
2033
+ }
2034
+ }
2035
+ preinit(app, parent) {
2036
+ this.$.preinit(app, parent);
2037
+ }
2038
+ }
2039
+ /**
2040
+ * Private part of switch node
2041
+ * @class SwitchedNodePrivate
2042
+ * @extends INodePrivate
2043
+ */
2044
+ class SwitchedNodePrivate extends FragmentPrivate {
2045
+ constructor() {
2046
+ super();
2047
+ /**
2048
+ * Array of possible cases
2049
+ * @type {Array<{cond : IValue<boolean>, cb : function(Fragment)}>}
2050
+ */
2051
+ this.cases = [];
2052
+ this.$seal();
2053
+ }
2054
+ /**
2055
+ * Runs GC
2056
+ */
2057
+ $destroy() {
2058
+ this.cases.forEach(c => {
2059
+ delete c.cond;
2060
+ delete c.cb;
2061
+ });
2062
+ this.cases.splice(0);
2063
+ super.$destroy();
2064
+ }
2065
+ }
2066
+ /**
2067
+ * Defines a node witch can switch its children conditionally
2068
+ */
2069
+ class SwitchedNode extends Fragment {
2070
+ /**
2071
+ * Constructs a switch node and define a sync function
2072
+ */
2073
+ constructor() {
2074
+ super({}, new SwitchedNodePrivate);
2075
+ this.$.sync = () => {
2076
+ const $ = this.$;
2077
+ let i = 0;
2078
+ for (; i < $.cases.length; i++) {
2079
+ if ($.cases[i].cond.$) {
2080
+ break;
2081
+ }
2082
+ }
2083
+ if (i === $.index) {
2084
+ return;
2085
+ }
2086
+ if (this.lastChild) {
2087
+ this.lastChild.$destroy();
2088
+ this.children.clear();
2089
+ this.lastChild = null;
2090
+ }
2091
+ if (i !== $.cases.length) {
2092
+ $.index = i;
2093
+ this.createChild($.cases[i].cb);
2094
+ }
2095
+ else {
2096
+ $.index = -1;
2097
+ }
2098
+ };
2099
+ this.$seal();
2100
+ }
2101
+ addCase(case_) {
2102
+ this.$.cases.push(case_);
2103
+ case_.cond.$on(this.$.sync);
2104
+ this.$.sync();
2105
+ }
2106
+ /**
2107
+ * Creates a child node
2108
+ * @param cb {function(Fragment)} Call-back
2109
+ */
2110
+ createChild(cb) {
2111
+ const node = new Fragment({});
2112
+ node.preinit(this.$.app, this);
2113
+ node.init();
2114
+ this.lastChild = node;
2115
+ this.children.add(node);
2116
+ cb(node);
2117
+ }
2118
+ ready() {
2119
+ const $ = this.$;
2120
+ $.cases.forEach(c => {
2121
+ c.cond.$on($.sync);
2122
+ });
2123
+ $.sync();
2124
+ }
2125
+ $destroy() {
2126
+ const $ = this.$;
2127
+ $.cases.forEach(c => {
2128
+ c.cond.$off($.sync);
2129
+ });
2130
+ super.$destroy();
2131
+ }
2132
+ }
2133
+ /**
2134
+ * The private part of a text node
2135
+ */
2136
+ class DebugPrivate extends FragmentPrivate {
2137
+ constructor() {
2138
+ super();
2139
+ this.$seal();
2140
+ }
2141
+ /**
2142
+ * Pre-initializes a text node
2143
+ * @param app {App} the app node
2144
+ * @param parent {Fragment} parent node
2145
+ * @param text {String | IValue}
2146
+ */
2147
+ preinitComment(app, parent, text) {
2148
+ super.preinit(app, parent);
2149
+ this.node = document.createComment(text.$);
2150
+ this.bindings.add(new Expression((v) => {
2151
+ this.node.replaceData(0, -1, v);
2152
+ }, true, text));
2153
+ this.parent.appendNode(this.node);
2154
+ }
2155
+ /**
2156
+ * Clear node data
2157
+ */
2158
+ $destroy() {
2159
+ this.node.remove();
2160
+ super.$destroy();
2161
+ }
2162
+ }
2163
+ /**
2164
+ * Represents a debug node
2165
+ * @class DebugNode
2166
+ * @extends Fragment
2167
+ */
2168
+ class DebugNode extends Fragment {
2169
+ constructor() {
2170
+ super({});
2171
+ /**
2172
+ * private data
2173
+ * @type {DebugNode}
2174
+ */
2175
+ this.$ = new DebugPrivate();
2176
+ this.$seal();
2177
+ }
2178
+ preinit(app, parent, text) {
2179
+ const $ = this.$;
2180
+ if (!text) {
2181
+ throw internalError('wrong DebugNode::$preninit call');
2182
+ }
2183
+ $.preinitComment(app, parent, text);
2184
+ }
2185
+ /**
2186
+ * Runs garbage collector
2187
+ */
2188
+ $destroy() {
2189
+ this.$.$destroy();
2190
+ super.$destroy();
2191
+ }
2192
+ }
2193
+
2194
+ window.FragmentPrivate = FragmentPrivate;
2195
+ window.Fragment = Fragment;
2196
+ window.TextNodePrivate = TextNodePrivate;
2197
+ window.TextNode = TextNode;
2198
+ window.INodePrivate = INodePrivate;
2199
+ window.INode = INode;
2200
+ window.Tag = Tag;
2201
+ window.Extension = Extension;
2202
+ window.Component = Component;
2203
+ window.SwitchedNodePrivate = SwitchedNodePrivate;
2204
+ window.SwitchedNode = SwitchedNode;
2205
+ window.DebugPrivate = DebugPrivate;
2206
+ window.DebugNode = DebugNode;
2207
+
2208
+ // ./lib/node/watch.js
2209
+ /**
2210
+ * Watch Node
2211
+ * @class Watch
2212
+ * @extends Fragment
2213
+ */
2214
+ class Watch extends Fragment {
2215
+ compose(input) {
2216
+ this.watch((value) => {
2217
+ this.children.forEach(child => {
2218
+ child.$destroy();
2219
+ });
2220
+ this.children.clear();
2221
+ this.lastChild = null;
2222
+ input.slot && input.slot(this, value);
2223
+ }, input.model);
2224
+ input.slot(this, input.model.$);
2225
+ return {};
2226
+ }
2227
+ }
2228
+
2229
+ window.Watch = Watch;
2230
+
2231
+ // ./lib/views/repeat-node.js
2232
+ /**
2233
+ * Private part of repeat node
2234
+ * @class RepeatNodePrivate
2235
+ * @extends INodePrivate
2236
+ */
2237
+ class RepeatNodePrivate extends INodePrivate {
2238
+ constructor() {
2239
+ super();
2240
+ /**
2241
+ * Children node hash
2242
+ * @type {Map}
2243
+ */
2244
+ this.nodes = new Map();
2245
+ this.$seal();
2246
+ }
2247
+ $destroy() {
2248
+ this.nodes.clear();
2249
+ super.$destroy();
2250
+ }
2251
+ }
2252
+ /**
2253
+ * Repeat node repeats its children
2254
+ * @class RepeatNode
2255
+ * @extends Fragment
2256
+ */
2257
+ class RepeatNode extends Fragment {
2258
+ constructor(input, $) {
2259
+ super(input, $);
2260
+ /**
2261
+ * If false will use timeout executor, otherwise the app executor
2262
+ */
2263
+ this.freezeUi = true;
2264
+ }
2265
+ createChild(opts, id, item, before) {
2266
+ const node = new Fragment({});
2267
+ this.destroyChild(id, item);
2268
+ if (before) {
2269
+ this.children.add(node);
2270
+ before.insertBefore(node);
2271
+ }
2272
+ else {
2273
+ const lastChild = this.lastChild;
2274
+ if (lastChild) {
2275
+ lastChild.insertAfter(node);
2276
+ }
2277
+ this.children.add(node);
2278
+ }
2279
+ this.lastChild = node;
2280
+ node.preinit(this.$.app, this);
2281
+ node.init();
2282
+ opts.slot && opts.slot(node, item, id);
2283
+ node.ready();
2284
+ this.$.nodes.set(id, node);
2285
+ }
2286
+ destroyChild(id, item) {
2287
+ const $ = this.$;
2288
+ const child = $.nodes.get(id);
2289
+ if (child) {
2290
+ child.remove();
2291
+ child.$destroy();
2292
+ this.$.nodes.delete(id);
2293
+ this.children.delete(child);
2294
+ }
2295
+ }
2296
+ }
2297
+
2298
+ window.RepeatNodePrivate = RepeatNodePrivate;
2299
+ window.RepeatNode = RepeatNode;
2300
+
2301
+ // ./lib/views/base-view.js
2302
+ /**
2303
+ * Private part of BaseView
2304
+ * @class BaseViewPrivate
2305
+ * @extends RepeatNodePrivate
2306
+ */
2307
+ class BaseViewPrivate extends RepeatNodePrivate {
2308
+ constructor() {
2309
+ super();
2310
+ this.$seal();
2311
+ }
2312
+ }
2313
+ /**
2314
+ * Base class of default views
2315
+ * @class BaseView
2316
+ * @extends RepeatNode
2317
+ * @implements IModel
2318
+ */
2319
+ class BaseView extends RepeatNode {
2320
+ constructor(input, $) {
2321
+ super(input, $ || new BaseViewPrivate);
2322
+ }
2323
+ compose(input) {
2324
+ const $ = this.$;
2325
+ $.addHandler = (id, item) => {
2326
+ this.createChild(input, id, item);
2327
+ };
2328
+ $.removeHandler = (id, item) => {
2329
+ this.destroyChild(id, item);
2330
+ };
2331
+ input.model.listener.onAdd($.addHandler);
2332
+ input.model.listener.onRemove($.removeHandler);
2333
+ this.runOnDestroy(() => {
2334
+ input.model.listener.offAdd($.addHandler);
2335
+ input.model.listener.offRemove($.removeHandler);
2336
+ });
2337
+ return {};
2338
+ }
2339
+ }
2340
+
2341
+ window.BaseViewPrivate = BaseViewPrivate;
2342
+ window.BaseView = BaseView;
2343
+
2344
+ // ./lib/views/array-view.js
2345
+ /**
2346
+ * Represents a view of an array model
2347
+ * @class ArrayView
2348
+ * @extends BaseView
2349
+ */
2350
+ class ArrayView extends BaseView {
2351
+ createChild(input, id, item, before) {
2352
+ super.createChild(input, item, item, before || this.$.nodes.get(id));
2353
+ }
2354
+ compose(input) {
2355
+ super.compose(input);
2356
+ input.model.forEach(item => {
2357
+ this.createChild(input, item, item);
2358
+ });
2359
+ return {};
2360
+ }
2361
+ }
2362
+
2363
+ window.ArrayView = ArrayView;
2364
+
2365
+ // ./lib/views/map-view.js
2366
+ /**
2367
+ * Create a children pack for each map value
2368
+ * @class MapView
2369
+ * @extends BaseView
2370
+ */
2371
+ class MapView extends BaseView {
2372
+ compose(input) {
2373
+ super.compose(input);
2374
+ input.model.forEach((value, key) => {
2375
+ this.createChild(input, key, value);
2376
+ });
2377
+ return {};
2378
+ }
2379
+ }
2380
+
2381
+ window.MapView = MapView;
2382
+
2383
+ // ./lib/views/object-view.js
2384
+ /**
2385
+ * Create a children pack for each object field
2386
+ * @class ObjectView
2387
+ * @extends BaseView
2388
+ */
2389
+ class ObjectView extends BaseView {
2390
+ compose(input) {
2391
+ super.compose(input);
2392
+ const obj = input.model.values;
2393
+ for (const key in obj) {
2394
+ this.createChild(input, key, obj[key]);
2395
+ }
2396
+ super.ready();
2397
+ return {};
2398
+ }
2399
+ }
2400
+
2401
+ window.ObjectView = ObjectView;
2402
+
2403
+ // ./lib/views/set-view.js
2404
+ /**
2405
+ * Create a children pack for each set value
2406
+ * @class SetView
2407
+ * @extends BaseView
2408
+ */
2409
+ class SetView extends BaseView {
2410
+ compose(input) {
2411
+ super.compose(input);
2412
+ const set = input.model;
2413
+ set.forEach(item => {
2414
+ this.createChild(input, item, item);
2415
+ });
2416
+ return {};
2417
+ }
2418
+ }
2419
+
2420
+ window.SetView = SetView;
2421
+
2422
+ // ./lib/index.js
2423
+
2424
+
2425
+
2426
+ // ./lib/node/app.js
2427
+ /**
2428
+ * Application Node
2429
+ * @class AppNode
2430
+ * @extends INode
2431
+ */
2432
+ class AppNode extends INode {
2433
+ /**
2434
+ * @param input
2435
+ */
2436
+ constructor(input) {
2437
+ super(input);
2438
+ this.debugUi = input.debugUi || false;
2439
+ this.$seal();
2440
+ }
2441
+ }
2442
+ /**
2443
+ * Represents a Vasille.js application
2444
+ * @class App
2445
+ * @extends AppNode
2446
+ */
2447
+ class App extends AppNode {
2448
+ /**
2449
+ * Constructs an app node
2450
+ * @param node {Element} The root of application
2451
+ * @param input
2452
+ */
2453
+ constructor(node, input) {
2454
+ super(input);
2455
+ this.$.node = node;
2456
+ this.preinit(this, this);
2457
+ this.init();
2458
+ this.$seal();
2459
+ }
2460
+ appendNode(node) {
2461
+ this.$.node.appendChild(node);
2462
+ }
2463
+ }
2464
+ class Portal extends AppNode {
2465
+ constructor(input) {
2466
+ super(input);
2467
+ this.$.node = input.node;
2468
+ this.$seal();
2469
+ }
2470
+ appendNode(node) {
2471
+ this.$.node.appendChild(node);
2472
+ }
2473
+ }
2474
+
2475
+ window.AppNode = AppNode;
2476
+ window.App = App;
2477
+ window.Portal = Portal;
2478
+
2479
+ // ./lib/functional/options.js
2480
+
2481
+
2482
+
2483
+ })();