vasille 2.3.5 → 2.3.8

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