vasille 1.2.9 → 2.0.3

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