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/lib/node.js DELETED
@@ -1,2155 +0,0 @@
1
- //
2
- import { AttributeBinding, attributify } from "./attribute.js";
3
- import { Binding, Expression } from "./bind.js";
4
- import { classify } from "./class.js";
5
- import { Executor, InstantExecutor } from "./executor.js";
6
- import { VasilleNode, VasilleNodePrivate } from "./interfaces/core.js";
7
- import { internalError, notFound, typeError, userError, wrongBinding } from "./interfaces/errors.js";
8
- import { IBind } from "./interfaces/ibind.js";
9
- import { Callable, checkType } from "./interfaces/idefinition.js";
10
- import { IValue } from "./interfaces/ivalue.js";
11
- import { vassilify } from "./models.js";
12
- import { StyleBinding, stylify } from "./style.js";
13
- import { Pointer, Reference } from "./value.js";
14
-
15
-
16
-
17
- /**
18
- * The private part of a text node
19
- */
20
- export class TextNodePrivate extends VasilleNodePrivate {
21
- /**
22
- * Contains the text of node as Reference
23
- * @type {IValue}
24
- */
25
- value;
26
-
27
- /**
28
- * User defined handler to handle text change
29
- * @type {Function}
30
- */
31
- handler;
32
-
33
- constructor () {
34
- super ();
35
-
36
- this.seal();
37
- }
38
-
39
- /**
40
- * Pre-initializes a text node
41
- * @param app {App} the app node
42
- * @param rt {INode} The root node
43
- * @param ts {INode} The this node
44
- * @param before {?VasilleNode} node to paste after
45
- * @param text {String | IValue}
46
- */
47
- preinitText (
48
- app,
49
- rt,
50
- ts,
51
- before,
52
- text
53
- ) {
54
- super.preinit(app, rt, ts, before);
55
-
56
- let value = text instanceof IValue ? text : new Reference(text);
57
- let node = document.createTextNode(value.$);
58
-
59
- this.value = value;
60
- this.handler = function (v) {
61
- node.replaceData(0, -1, v.$);
62
- }.bind(null, value);
63
-
64
- value.on(this.handler);
65
- this.encapsulate(node);
66
-
67
- ts.$$appendChild(node, before);
68
- }
69
-
70
- /**
71
- * Clear node data
72
- */
73
- $destroy () {
74
- //$FlowFixMe
75
- this.value = null;
76
- //$FlowFixMe
77
- this.handler = null;
78
-
79
- super.$destroy();
80
- }
81
- }
82
-
83
- /**
84
- * Represents a text node
85
- */
86
- export class TextNode extends VasilleNode {
87
- /**
88
- * private data
89
- * @type {TextNodePrivate}
90
- */
91
- $ = new TextNodePrivate();
92
-
93
- /**
94
- * Pointer to text node
95
- * @type {Text}
96
- */
97
- node;
98
-
99
- /**
100
- * Constructs a text node
101
- */
102
- constructor () {
103
- super();
104
-
105
- this.seal();
106
- }
107
-
108
- /**
109
- * Pre-initializes a text node
110
- * @param app {App} the app node
111
- * @param rt {INode} The root node
112
- * @param ts {INode} The this node
113
- * @param before {?VasilleNode} node to paste after
114
- * @param text {String | IValue}
115
- */
116
- $$preinitText (app, rt, ts, before, text) {
117
- this.$.preinitText(app, rt, ts, before, text);
118
- this.node = this.$.text;
119
- }
120
-
121
- /**
122
- * Runs garbage collector
123
- */
124
- $destroy () {
125
- this.$.$destroy();
126
- this.$ = null;
127
- //$FlowFixMe
128
- this.node = null;
129
-
130
- super.$destroy();
131
- }
132
- }
133
-
134
-
135
- /**
136
- * The private part of a base node
137
- */
138
- export class BaseNodePrivate extends VasilleNodePrivate {
139
- /**
140
- * The building active state
141
- * @type {boolean}
142
- */
143
- building;
144
-
145
- /**
146
- * Represents style bindings
147
- * @type {Set<Binding>}
148
- */
149
- class = new Set;
150
-
151
- /**
152
- * Represents a list of user-defined bindings
153
- * @type {Set<IValue>}
154
- */
155
- watch = new Set;
156
-
157
- /**
158
- * List of user defined signals
159
- * @type {Map<string, {args : Array<Function>, handlers : Array<Function>}>}
160
- */
161
- signal = new Map;
162
-
163
- /**
164
- * List of references
165
- * @type {Map<String, INode|Set<INode>>}
166
- */
167
- refs = new Map;
168
-
169
- /**
170
- * List of $slots
171
- * @type {Map<String, INode>}
172
- */
173
- slots = new Map;
174
-
175
- /**
176
- * Defined the frozen state of component
177
- * @type {boolean}
178
- */
179
- frozen = false;
180
-
181
- /**
182
- * Defines if node is unmounted
183
- * @type {boolean}
184
- */
185
- unmounted = false;
186
-
187
- /**
188
- * Handle to run on component destroy
189
- * @type {Function}
190
- */
191
- onDestroy;
192
-
193
- /**
194
- * Defines a HTML class for all html nodes
195
- * @type {string}
196
- */
197
- metaClass;
198
-
199
- /**
200
- * Defines a container for CSS rule in creation time
201
- * @type {Array<{scoped : string, unscoped : string, rules : {[p : string] : string}}>}
202
- */
203
- metaStyle;
204
-
205
- /**
206
- * Get the current root (ts on building, rt on filling)
207
- * @type {INode}
208
- */
209
- get rt () {
210
- return !this.building && super.root instanceof INode ? super.root : this.ts;
211
- }
212
-
213
- constructor () {
214
- super ();
215
- this.seal();
216
- }
217
-
218
- /**
219
- * Garbage collection
220
- */
221
- $destroy () {
222
- for (let c of this.class) {
223
- c.$destroy();
224
- }
225
- this.class.clear();
226
- //$FlowFixMe
227
- this.class = null;
228
-
229
- for (let w of this.watch) {
230
- w.$destroy();
231
- }
232
- this.watch.clear();
233
- //$FlowFixMe
234
- this.watch = null;
235
-
236
- this.signal.clear();
237
- //$FlowFixMe
238
- this.signal = null;
239
-
240
- for (let ref of this.refs) {
241
- if (ref instanceof Set) {
242
- ref.clear();
243
- }
244
- }
245
- this.refs.clear();
246
- //$FlowFixMe
247
- this.refs = null;
248
-
249
- this.slots.clear();
250
- //$FlowFixMe
251
- this.slots = null;
252
-
253
- if (this.onDestroy) {
254
- this.onDestroy();
255
- }
256
-
257
- super.$destroy();
258
- }
259
- }
260
-
261
- /**
262
- * Represents an Vasille.js node which can contains children
263
- * @extends VasilleNode
264
- */
265
- export class INode extends VasilleNode {
266
- /**
267
- * The children list
268
- * @type {Array<VasilleNode>}
269
- */
270
- $children = [];
271
-
272
- /**
273
- * Constructs a base node
274
- * @param $ {?BaseNodePrivate}
275
- */
276
- constructor ($) {
277
- super($ || new BaseNodePrivate);
278
-
279
- this.seal();
280
- }
281
-
282
- /**
283
- * Pre-initializes a base node which can contain children
284
- * @param app {App} the app node
285
- * @param rt {INode} The root node
286
- * @param ts {INode} The this node
287
- * @param before {?VasilleNode} node to paste after it
288
- * @param node {HTMLElement | Text | Comment} The encapsulated node
289
- */
290
- $$preinitNode (
291
- app,
292
- rt,
293
- ts,
294
- before,
295
- node
296
- ) {
297
- this.$.preinit(app, rt, ts, before);
298
- this.$.encapsulate(node);
299
-
300
- ts.$$appendChild(node, before);
301
- }
302
-
303
- /**
304
- * Start component building
305
- */
306
- $$startBuilding () {
307
- this.$.slots.set("default", this);
308
- this.$.building = true;
309
- }
310
-
311
- /**
312
- * Stop component building
313
- */
314
- $$stopBuilding () {
315
- this.$.building = false;
316
- this.$mounted();
317
- }
318
-
319
- /**
320
- * Initialize node
321
- */
322
- $init () {
323
- this.$$startBuilding();
324
-
325
- this.$createAttrs();
326
- this.$createStyle();
327
- this.$createSignals();
328
- this.$createWatchers();
329
-
330
- this.$created();
331
- this.$createDom();
332
-
333
- this.$$stopBuilding();
334
- }
335
-
336
- /**
337
- * Assigns value to this property is such exists and is a IValue
338
- * @param ts {Object} pointer to this
339
- * @param prop {string} property name
340
- * @param value {*} value to assign
341
- */
342
- $$unsafeAssign (ts, prop, value) {
343
- let field = ts[prop];
344
-
345
- if (!field || !(
346
- field instanceof IValue
347
- )) {
348
- throw notFound("no such property: " + prop);
349
- }
350
- if (!field.type) {
351
- throw userError(`field ${prop} is private`, "private-field");
352
- }
353
-
354
- if (field instanceof Pointer && field.value instanceof Reference && value instanceof IValue) {
355
- field.$ = value;
356
- }
357
-
358
- if (value instanceof IValue) {
359
- ts[prop] = value;
360
- }
361
- else {
362
- field.$ = value;
363
- }
364
- }
365
-
366
- /** To be overloaded: created event handler */
367
- $created () {
368
- }
369
-
370
- /** To be overloaded: mounted event handler */
371
- $mounted () {
372
- }
373
-
374
- /** To be overloaded: ready event handler */
375
- $ready () {
376
- }
377
-
378
- /** To be overloaded: attributes creation milestone */
379
- $createAttrs () {
380
- }
381
-
382
- /**
383
- * Runs garbage collector
384
- */
385
- $destroy () {
386
- let $ = this.$;
387
-
388
- if ($.root instanceof INode) {
389
- for (let it of $.root.$.refs) {
390
- let ref = it[1];
391
-
392
- if (ref === this) {
393
- $.root.$.refs.delete(it[0]);
394
- }
395
- else if (ref instanceof Set && ref.has(this)) {
396
- ref.delete(this);
397
- }
398
- }
399
- }
400
-
401
- for (let child of this.$children) {
402
- child.$destroy();
403
- }
404
-
405
- $.$destroy();
406
- this.$ = null;
407
- this.$children.splice(0);
408
- //$FlowFixMe
409
- this.$children = null;
410
-
411
- super.$destroy();
412
- }
413
-
414
- /** To be overloaded: $style attributes creation milestone */
415
- $createStyle () {
416
- }
417
-
418
- /** To be overloaded: signals creation milestone */
419
- $createSignals () {
420
- }
421
-
422
- /** To be overloaded: watchers creation milestone */
423
- $createWatchers () {
424
- }
425
-
426
- /** To be overloaded: DOM creation milestone */
427
- $createDom () {
428
- }
429
-
430
- /** To be overloaded: CSS creation milestone */
431
- $createCss () {
432
- }
433
-
434
- /**
435
- * create a private field
436
- * @param value {*}
437
- * @return {IValue<*>}
438
- */
439
- $ref (value) {
440
- let ret = vassilify(value);
441
- this.$.watch.add(ret);
442
- return ret;
443
- }
444
-
445
- /**
446
- * creates a public field
447
- * @param type {Function}
448
- * @param value {*}
449
- * @return {Reference}
450
- */
451
- $prop (type, value = null) {
452
- if (!checkType(value, type) || value instanceof IValue) {
453
- throw typeError("wrong initial public field value");
454
- }
455
-
456
- let ret = vassilify(value);
457
- if (ret instanceof Reference) {
458
- ret.type = type;
459
- this.$.watch.add(ret);
460
- return ret;
461
- }
462
- else {
463
- throw internalError("Something goes wrong :(");
464
- }
465
- }
466
-
467
- /**
468
- * creates a pointer
469
- * @param type {Function}
470
- * @return {Pointer}
471
- */
472
- $pointer (type) {
473
- let ref = new Reference();
474
- let pointer = new Pointer(ref);
475
-
476
- ref.type = type;
477
- this.$.watch.add(ref);
478
- this.$.watch.add(pointer);
479
-
480
- return pointer;
481
- }
482
-
483
- /**
484
- * Gets a attribute value
485
- * @param name {string} Attribute name
486
- * @return {IValue<string>}
487
- */
488
- $attr (name) {
489
- return this.$.attr(name);
490
- }
491
-
492
- /**
493
- * Defines a attribute
494
- * @param name {String} The name of attribute
495
- * @param value {String | IValue | Callable} A $$value or a $$value getter
496
- * @return {INode} A pointer to this
497
- */
498
- $defAttr (name, value) {
499
- if (value instanceof Callable) {
500
- this.$.$attrs[name] = attributify(this.$.rt, this, name, null, value);
501
- }
502
- else {
503
- this.$.$attrs[name] = attributify(this.$.rt, this, name, value);
504
- }
505
- return this;
506
- }
507
-
508
- /**
509
- * Defines a set of attributes
510
- * @param obj {Object<String, String | IValue>} A set attributes
511
- * @return {INode} A pointer to this
512
- */
513
- $defAttrs (obj) {
514
- for (let i in obj) {
515
- this.$.$attrs[i] = attributify(this.$.rt, this, i, obj[i]);
516
- }
517
- return this;
518
- }
519
-
520
- /**
521
- * Creates and binds a multivalued binding to attribute
522
- * @param name {String} The name of attribute
523
- * @param calculator {Function} Binding calculator (must return a value)
524
- * @param values {...IValue} Values to bind
525
- * @return {INode} A pointer to this
526
- */
527
- $bindAttr (
528
- name,
529
- calculator,
530
- ...values
531
- ) {
532
- this.$.$attrs[name] = new AttributeBinding(
533
- this.$.rt,
534
- this,
535
- name,
536
- calculator,
537
- ...values
538
- );
539
- return this;
540
- }
541
-
542
- /**
543
- * Sets a attribute value
544
- * @param name {string} Name of attribute
545
- * @param value {string} Reference of attribute
546
- * @return {INode} A pointer to this
547
- */
548
- $setAttr (
549
- name,
550
- value
551
- ) {
552
- this.$.app.$run.setAttribute(this.$.el, name, value);
553
- return this;
554
- }
555
-
556
- /**
557
- * Sets value of some attributes
558
- * @param data {Object<string, string>} Names and values of attributes
559
- * @return {INode} A pointer to this
560
- */
561
- $setAttrs (
562
- data
563
- ) {
564
- for (let i in data) {
565
- this.$.app.$run.setAttribute(this.$.el, i, data[i]);
566
- }
567
- return this;
568
- }
569
-
570
- /**
571
- * Adds a CSS class
572
- * @param cl {string} Class name
573
- * @return {INode} A pointer to this
574
- */
575
- $addClass (cl) {
576
- this.$.el.classList.add(cl);
577
- return this;
578
- }
579
-
580
- /**
581
- * Adds some CSS classes
582
- * @param cl {...string} Classes names
583
- * @return {INode} A pointer to this
584
- */
585
- $addClasses (...cl) {
586
- this.$.el.classList.add(...cl);
587
- return this;
588
- }
589
-
590
- /**
591
- * Bind a CSS class
592
- * @param cl {?string}
593
- * @param value {string | IValue | null}
594
- * @param func {?Callable}
595
- * @return {INode}
596
- */
597
- $bindClass (
598
- cl,
599
- value = null,
600
- func = null
601
- ) {
602
- this.$.class.add(classify(this.$.rt, this, cl || "", value, func));
603
- return this;
604
- }
605
-
606
- /**
607
- * Gets a style attribute value
608
- * @param name {string} Name of style attribute
609
- * @return {IValue}
610
- */
611
- $style (name) {
612
- return this.$.style(name);
613
- }
614
-
615
- /**
616
- * Defines a style attribute
617
- * @param name {String} The name of style attribute
618
- * @param value {String | IValue | Callable} A value or a value getter
619
- * @return {this} A pointer to this
620
- */
621
- $defStyle (name, value) {
622
- if (value instanceof Callable) {
623
- this.$.$style[name] = stylify(this.$.rt, this, name, null, value);
624
- }
625
- else {
626
- this.$.$style[name] = stylify(this.$.rt, this, name, value);
627
- }
628
- return this;
629
- }
630
-
631
- /**
632
- * Defines a set of style attributes
633
- * @param obj {Object<String, String | IValue>} A set of style attributes
634
- * @return {this} A pointer to this
635
- */
636
- $defStyles (obj) {
637
- for (let i in obj) {
638
- this.$.$style[i] = stylify(this.$.rt, this, i, obj[i]);
639
- }
640
- return this;
641
- }
642
-
643
- /**
644
- * Creates and binds a calculator to a style attribute
645
- * @param name {String} Name of style attribute
646
- * @param calculator {Function} A calculator for style value
647
- * @param values {...IValue} Values to bind
648
- * @return {this} A pointer to this
649
- */
650
- $bindStyle (
651
- name,
652
- calculator,
653
- ...values
654
- ) {
655
- this.$.$style[name] = new StyleBinding(
656
- this.$.rt,
657
- this,
658
- name,
659
- calculator,
660
- ...values
661
- );
662
- return this;
663
- }
664
-
665
- /**
666
- * Sets a style property value
667
- * @param prop {string} Property name
668
- * @param value {string} Property value
669
- * @return {INode}
670
- */
671
- $setStyle (
672
- prop,
673
- value
674
- ) {
675
- this.$.app.$run.setStyle(this.$.el, prop, value);
676
- return this;
677
- }
678
-
679
- /**
680
- * Sets some style property value
681
- * @param data {Object<string, string>} Names and value of properties
682
- * @return {INode}
683
- */
684
- $setStyles (
685
- data
686
- ) {
687
- for (let i in data) {
688
- this.$.app.$run.setStyle(this.$.el, i, data[i]);
689
- }
690
- return this;
691
- }
692
-
693
- /**
694
- * Defines a signal
695
- * @param name {string} Signal name
696
- * @param types {...Function} Arguments types
697
- */
698
- $defSignal (name, ...types) {
699
- this.$.signal.set(name, { args : types, handlers : [] });
700
- }
701
-
702
- /**
703
- * Add a handler for a signal
704
- * @param name {string} Signal name
705
- * @param func {Function} Handler
706
- */
707
- $on (name, func) {
708
- let signal = this.$.signal.get(name);
709
-
710
- if (!signal) {
711
- throw notFound("no such signal: " + name);
712
- }
713
-
714
- signal.handlers.push(func);
715
- }
716
-
717
- /**
718
- * Emit a signal
719
- * @param name {string} Signal name
720
- * @param args {...*} Signal arguments
721
- */
722
- $emit (name, ...args) {
723
- let signal = this.$.signal.get(name);
724
-
725
- if (!signal) {
726
- throw notFound("no such signal: " + name);
727
- }
728
-
729
- let compatible = args.length === signal.args.length;
730
-
731
- if (compatible && this.$.app.$debug) {
732
- for (let i = 0; i < args.length; i++) {
733
- if (!checkType(args[i], signal.args[i])) {
734
- compatible = false;
735
- }
736
- }
737
- }
738
-
739
- if (!compatible) {
740
- throw typeError("incompatible signals arguments");
741
- }
742
-
743
- for (let handler of signal.handlers) {
744
- try {
745
- handler(...args);
746
- }
747
- catch (e) {
748
- console.error(`Vasille.js: Handler throw exception at ${this.constructor.name}::${name}: `, e);
749
- }
750
- }
751
- }
752
-
753
- /**
754
- * Add a listener for an event
755
- * @param name {string} Event name
756
- * @param handler {function (Event)} Event handler
757
- * @param options {Object | boolean} addEventListener options
758
- * @return {this}
759
- */
760
- $listen (name, handler, options) {
761
- this.$.el.addEventListener(name, handler, options || {});
762
- return this;
763
- }
764
-
765
- /**
766
- * @param handler {function (MouseEvent)}
767
- * @param options {Object | boolean}
768
- */
769
- $oncontextmenu (handler, options) {
770
- this.$listen("contextmenu", handler, options);
771
- }
772
-
773
- /**
774
- * @param handler {function (MouseEvent)}
775
- * @param options {Object | boolean}
776
- */
777
- $onmousedown (handler, options) {
778
- this.$listen("mousedown", handler, options);
779
- }
780
-
781
- /**
782
- * @param handler {function (MouseEvent)}
783
- * @param options {Object | boolean}
784
- */
785
- $onmouseenter (handler, options) {
786
- this.$listen("mouseenter", handler, options);
787
- }
788
-
789
- /**
790
- * @param handler {function (MouseEvent)}
791
- * @param options {Object | boolean}
792
- */
793
- $onmouseleave (handler, options) {
794
- this.$listen("mouseleave", handler, options);
795
- }
796
-
797
- /**
798
- * @param handler {function (MouseEvent)}
799
- * @param options {Object | boolean}
800
- */
801
- $onmousemove (handler, options) {
802
- this.$listen("mousemove", handler, options);
803
- }
804
-
805
- /**
806
- * @param handler {function (MouseEvent)}
807
- * @param options {Object | boolean}
808
- */
809
- $onmouseout (handler, options) {
810
- this.$listen("mouseout", handler, options);
811
- }
812
-
813
- /**
814
- * @param handler {function (MouseEvent)}
815
- * @param options {Object | boolean}
816
- */
817
- $onmouseover (handler, options) {
818
- this.$listen("mouseover", handler, options);
819
- }
820
-
821
- /**
822
- * @param handler {function (MouseEvent)}
823
- * @param options {Object | boolean}
824
- */
825
- $onmouseup (handler, options) {
826
- this.$listen("mouseup", handler, options);
827
- }
828
-
829
- /**
830
- * @param handler {function (MouseEvent)}
831
- * @param options {Object | boolean}
832
- */
833
- $onclick (handler, options) {
834
- this.$listen("click", handler, options);
835
- }
836
-
837
- /**
838
- * @param handler {function (MouseEvent)}
839
- * @param options {Object | boolean}
840
- */
841
- $ondblclick (handler, options) {
842
- this.$listen("dblclick", handler, options);
843
- }
844
-
845
- /**
846
- * @param handler {function (FocusEvent)}
847
- * @param options {Object | boolean}
848
- */
849
- $onblur (handler, options) {
850
- this.$listen("blur", handler, options);
851
- }
852
-
853
- /**
854
- * @param handler {function (FocusEvent)}
855
- * @param options {Object | boolean}
856
- */
857
- $onfocus (handler, options) {
858
- this.$listen("focus", handler, options);
859
- }
860
-
861
- /**
862
- * @param handler {function (FocusEvent)}
863
- * @param options {Object | boolean}
864
- */
865
- $onfocusin (handler, options) {
866
- this.$listen("focusin", handler, options);
867
- }
868
-
869
- /**
870
- * @param handler {function (FocusEvent)}
871
- * @param options {Object | boolean}
872
- */
873
- $onfocusout (handler, options) {
874
- this.$listen("focusout", handler, options);
875
- }
876
-
877
- /**
878
- * @param handler {function (KeyboardEvent)}
879
- * @param options {Object | boolean}
880
- */
881
- $onkeydown (handler, options) {
882
- this.$listen("keydown", handler, options);
883
- }
884
-
885
- /**
886
- * @param handler {function (KeyboardEvent)}
887
- * @param options {Object | boolean}
888
- */
889
- $onkeyup (handler, options) {
890
- this.$listen("keyup", handler, options);
891
- }
892
-
893
- /**
894
- * @param handler {function (KeyboardEvent)}
895
- * @param options {Object | boolean}
896
- */
897
- $onkeypress (handler, options) {
898
- this.$listen("keypress", handler, options);
899
- }
900
-
901
- /**
902
- * @param handler {function (TouchEvent)}
903
- * @param options {Object | boolean}
904
- */
905
- $ontouchstart (handler, options) {
906
- this.$listen("touchstart", handler, options);
907
- }
908
-
909
- /**
910
- * @param handler {function (TouchEvent)}
911
- * @param options {Object | boolean}
912
- */
913
- $ontouchmove (handler, options) {
914
- this.$listen("touchmove", handler, options);
915
- }
916
-
917
- /**
918
- * @param handler {function (TouchEvent)}
919
- * @param options {Object | boolean}
920
- */
921
- $ontouchend (handler, options) {
922
- this.$listen("touchend", handler, options);
923
- }
924
-
925
- /**
926
- * @param handler {function (TouchEvent)}
927
- * @param options {Object | boolean}
928
- */
929
- $ontouchcancel (handler, options) {
930
- this.$listen("touchcancel", handler, options);
931
- }
932
-
933
- /**
934
- * @param handler {function (WheelEvent)}
935
- * @param options {Object | boolean}
936
- */
937
- $onwheel (handler, options) {
938
- this.$listen("wheel", handler, options);
939
- }
940
-
941
- /**
942
- * @param handler {function (ProgressEvent)}
943
- * @param options {Object | boolean}
944
- */
945
- $onabort (handler, options) {
946
- this.$listen("abort", handler, options);
947
- }
948
-
949
- /**
950
- * @param handler {function (ProgressEvent)}
951
- * @param options {Object | boolean}
952
- */
953
- $onerror (handler, options) {
954
- this.$listen("error", handler, options);
955
- }
956
-
957
- /**
958
- * @param handler {function (ProgressEvent)}
959
- * @param options {Object | boolean}
960
- */
961
- $onload (handler, options) {
962
- this.$listen("load", handler, options);
963
- }
964
-
965
- /**
966
- * @param handler {function (ProgressEvent)}
967
- * @param options {Object | boolean}
968
- */
969
- $onloadend (handler, options) {
970
- this.$listen("loadend", handler, options);
971
- }
972
-
973
- /**
974
- * @param handler {function (ProgressEvent)}
975
- * @param options {Object | boolean}
976
- */
977
- $onloadstart (handler, options) {
978
- this.$listen("loadstart", handler, options);
979
- }
980
-
981
- /**
982
- * @param handler {function (ProgressEvent)}
983
- * @param options {Object | boolean}
984
- */
985
- $onprogress (handler, options) {
986
- this.$listen("progress", handler, options);
987
- }
988
-
989
- /**
990
- * @param handler {function (ProgressEvent)}
991
- * @param options {Object | boolean}
992
- */
993
- $ontimeout (handler, options) {
994
- this.$listen("timeout", handler, options);
995
- }
996
-
997
- /**
998
- * @param handler {function (DragEvent)}
999
- * @param options {Object | boolean}
1000
- */
1001
- $ondrag (handler, options) {
1002
- this.$listen("drag", handler, options);
1003
- }
1004
-
1005
- /**
1006
- * @param handler {function (DragEvent)}
1007
- * @param options {Object | boolean}
1008
- */
1009
- $ondragend (handler, options) {
1010
- this.$listen("dragend", handler, options);
1011
- }
1012
-
1013
- /**
1014
- * @param handler {function (DragEvent)}
1015
- * @param options {Object | boolean}
1016
- */
1017
- $ondragenter (handler, options) {
1018
- this.$listen("dragenter", handler, options);
1019
- }
1020
-
1021
- /**
1022
- * @param handler {function (DragEvent)}
1023
- * @param options {Object | boolean}
1024
- */
1025
- $ondragexit (handler, options) {
1026
- this.$listen("dragexit", handler, options);
1027
- }
1028
-
1029
- /**
1030
- * @param handler {function (DragEvent)}
1031
- * @param options {Object | boolean}
1032
- */
1033
- $ondragleave (handler, options) {
1034
- this.$listen("dragleave", handler, options);
1035
- }
1036
-
1037
- /**
1038
- * @param handler {function (DragEvent)}
1039
- * @param options {Object | boolean}
1040
- */
1041
- $ondragover (handler, options) {
1042
- this.$listen("dragover", handler, options);
1043
- }
1044
-
1045
- /**
1046
- * @param handler {function (DragEvent)}
1047
- * @param options {Object | boolean}
1048
- */
1049
- $ondragstart (handler, options) {
1050
- this.$listen("dragstart", handler, options);
1051
- }
1052
-
1053
- /**
1054
- * @param handler {function (DragEvent)}
1055
- * @param options {Object | boolean}
1056
- */
1057
- $ondrop (handler, options) {
1058
- this.$listen("drop", handler, options);
1059
- }
1060
-
1061
- /**
1062
- * @param handler {function (PointerEvent)}
1063
- * @param options {Object | boolean}
1064
- */
1065
- $onpointerover (handler, options) {
1066
- this.$listen("pointerover", handler, options);
1067
- }
1068
-
1069
- /**
1070
- * @param handler {function (PointerEvent)}
1071
- * @param options {Object | boolean}
1072
- */
1073
- $onpointerenter (handler, options) {
1074
- this.$listen("pointerenter", handler, options);
1075
- }
1076
-
1077
- /**
1078
- * @param handler {function (PointerEvent)}
1079
- * @param options {Object | boolean}
1080
- */
1081
- $onpointerdown (handler, options) {
1082
- this.$listen("pointerdown", handler, options);
1083
- }
1084
-
1085
- /**
1086
- * @param handler {function (PointerEvent)}
1087
- * @param options {Object | boolean}
1088
- */
1089
- $onpointermove (handler, options) {
1090
- this.$listen("pointermove", handler, options);
1091
- }
1092
-
1093
- /**
1094
- * @param handler {function (PointerEvent)}
1095
- * @param options {Object | boolean}
1096
- */
1097
- $onpointerup (handler, options) {
1098
- this.$listen("pointerup", handler, options);
1099
- }
1100
-
1101
- /**
1102
- * @param handler {function (PointerEvent)}
1103
- * @param options {Object | boolean}
1104
- */
1105
- $onpointercancel (handler, options) {
1106
- this.$listen("pointercancel", handler, options);
1107
- }
1108
-
1109
- /**
1110
- * @param handler {function (PointerEvent)}
1111
- * @param options {Object | boolean}
1112
- */
1113
- $onpointerout (handler, options) {
1114
- this.$listen("pointerout", handler, options);
1115
- }
1116
-
1117
- /**
1118
- * @param handler {function (PointerEvent)}
1119
- * @param options {Object | boolean}
1120
- */
1121
- $onpointerleave (handler, options) {
1122
- this.$listen("pointerleave", handler, options);
1123
- }
1124
-
1125
- /**
1126
- * @param handler {function (PointerEvent)}
1127
- * @param options {Object | boolean}
1128
- */
1129
- $ongotpointercapture (handler, options) {
1130
- this.$listen("gotpointercapture", handler, options);
1131
- }
1132
-
1133
- /**
1134
- * @param handler {function (PointerEvent)}
1135
- * @param options {Object | boolean}
1136
- */
1137
- $onlostpointercapture (handler, options) {
1138
- this.$listen("lostpointercapture", handler, options);
1139
- }
1140
-
1141
- /**
1142
- * @param handler {function (AnimationEvent)}
1143
- * @param options {Object | boolean}
1144
- */
1145
- $onanimationstart (handler, options) {
1146
- this.$listen("animationstart", handler, options);
1147
- }
1148
-
1149
- /**
1150
- * @param handler {function (AnimationEvent)}
1151
- * @param options {Object | boolean}
1152
- */
1153
- $onanimationend (handler, options) {
1154
- this.$listen("animationend", handler, options);
1155
- }
1156
-
1157
- /**
1158
- * @param handler {function (AnimationEvent)}
1159
- * @param options {Object | boolean}
1160
- */
1161
- $onanimationiteraton (handler, options) {
1162
- this.$listen("animationiteration", handler, options);
1163
- }
1164
-
1165
- /**
1166
- * @param handler {function (ClipboardEvent)}
1167
- * @param options {Object | boolean}
1168
- */
1169
- $onclipboardchange (handler, options) {
1170
- this.$listen("clipboardchange", handler, options);
1171
- }
1172
-
1173
- /**
1174
- * @param handler {function (ClipboardEvent)}
1175
- * @param options {Object | boolean}
1176
- */
1177
- $oncut (handler, options) {
1178
- this.$listen("cut", handler, options);
1179
- }
1180
-
1181
- /**
1182
- * @param handler {function (ClipboardEvent)}
1183
- * @param options {Object | boolean}
1184
- */
1185
- $oncopy (handler, options) {
1186
- this.$listen("copy", handler, options);
1187
- }
1188
-
1189
- /**
1190
- * @param handler {function (ClipboardEvent)}
1191
- * @param options {Object | boolean}
1192
- */
1193
- $onpaste (handler, options) {
1194
- this.$listen("paste", handler, options);
1195
- }
1196
-
1197
- /**
1198
- * Defines a watcher
1199
- * @param func {function} Function to run on value change
1200
- * @param vars {...IValue} Values to listen
1201
- */
1202
- $watch (func, ...vars) {
1203
- if (vars.length === 0) {
1204
- throw wrongBinding("a watcher must be bound to a value at last");
1205
- }
1206
-
1207
- this.$.watch.add(new Expression(func, vars, !this.$.frozen));
1208
- }
1209
-
1210
- /**
1211
- * Creates a bind expression
1212
- * @param f {Function} function to alc expression value
1213
- * @param args {...IValue} value sto bind
1214
- * @return {IBind}
1215
- */
1216
- $bind (f, ...args) {
1217
- let res;
1218
-
1219
- if (args.length === 0) {
1220
- throw wrongBinding("no values to bind");
1221
- }
1222
- else {
1223
- res = new Expression(f, args, !this.$.frozen);
1224
- }
1225
-
1226
- this.$.watch.add(res);
1227
- return res;
1228
- }
1229
-
1230
- $runOnDestroy (f) {
1231
- (this.$).onDestroy = f;
1232
- }
1233
-
1234
- /**
1235
- * Register current node as named slot
1236
- * @param name {String} The name of slot
1237
- */
1238
- $makeSlot (name) {
1239
- if (this.$.rt instanceof INode) {
1240
- this.$.rt.$.slots.set(name, this);
1241
- }
1242
- return this;
1243
- }
1244
-
1245
- /**
1246
- * Gets a slot by name
1247
- * @param name {string} Name of slot
1248
- * @return {INode}
1249
- */
1250
- $slot (name) {
1251
- let node = this.$.slots.get(name);
1252
-
1253
- if (node instanceof INode) {
1254
- return node;
1255
- }
1256
-
1257
- throw notFound("no such slot: " + name);
1258
- }
1259
-
1260
- /**
1261
- * Pushes a node to children immediately
1262
- * @param node {VasilleNode} A node to push
1263
- * @private
1264
- */
1265
- $$pushNode (node) {
1266
- let lastChild = null;
1267
-
1268
- if (this.$children.length) {
1269
- lastChild = this.$children[this.$children.length - 1];
1270
- }
1271
-
1272
- if (lastChild) {
1273
- lastChild.$.next = node;
1274
- }
1275
- node.$.prev = lastChild;
1276
- node.$.parent = this;
1277
-
1278
- this.$children.push(node);
1279
- }
1280
-
1281
- /**
1282
- * Find first core node in shadow element if so exists
1283
- * @param node {Extension} Node to iterate
1284
- * @return {?CoreEl}
1285
- */
1286
- $$findFirstChild (node) {
1287
- for (let child of node.$children) {
1288
- if (child.$.unmounted) continue;
1289
-
1290
- if (child instanceof Extension) {
1291
- let first = this.$$findFirstChild(child);
1292
-
1293
- if (first) {
1294
- return first;
1295
- }
1296
- }
1297
- else if (child instanceof Tag || child instanceof TextNode) {
1298
- return child.$.$el;
1299
- }
1300
- }
1301
- }
1302
-
1303
- /**
1304
- * Append a child in correct parent (to be overwritten)
1305
- * @param node {HTMLElement | Text | Comment} A node to push
1306
- * @param before {VasilleNode} node to paste after
1307
- * @private
1308
- */
1309
- $$appendChild (node, before) {
1310
- let $ = this.$;
1311
- before = before || $.next;
1312
-
1313
- while (before && before.$.unmounted) {
1314
- before = before.$.next;
1315
- }
1316
-
1317
- // If we are inserting before a element node
1318
- if (before instanceof Tag) {
1319
- $.app.$run.insertBefore($.el, node, before.$.el);
1320
- return;
1321
- }
1322
-
1323
- // If we are inserting before a shadow node
1324
- if (before instanceof Extension) {
1325
- let beforeNode = this.$$findFirstChild(before);
1326
-
1327
- if (beforeNode) {
1328
- $.app.$run.insertBefore($.el, node, beforeNode);
1329
- return;
1330
- }
1331
- }
1332
-
1333
- // If we are inserting in a shadow node or uninitiated element node
1334
- if (
1335
- (this instanceof Extension && !($.parent instanceof App)) ||
1336
- (this instanceof Tag && (!$.el || $.el === node))) {
1337
- $.parent.$$appendChild(node, $.next);
1338
- return;
1339
- }
1340
-
1341
- // If we have no more variants
1342
- $.app.$run.appendChild($.el, node);
1343
- }
1344
-
1345
- /**
1346
- * Disable/Enable reactivity of component with feedback
1347
- * @param cond {IValue} show condition
1348
- * @param onOff {Function} on show feedback
1349
- * @param onOn {Function} on hide feedback
1350
- */
1351
- $bindFreeze (cond, onOff, onOn) {
1352
- let $ = this.$;
1353
-
1354
- if ($.watch.has(cond)) {
1355
- throw wrongBinding(":show must be bound to an external component");
1356
- }
1357
-
1358
- let expr = null;
1359
-
1360
- expr = new Expression((cond) => {
1361
- $.frozen = !cond;
1362
-
1363
- if (cond) {
1364
- onOn?.();
1365
- for (let watcher of $.watch) {
1366
- if (watcher instanceof IBind) {
1367
- watcher.link();
1368
- }
1369
- }
1370
- }
1371
- else {
1372
- onOff?.();
1373
- for (let watcher of $.watch) {
1374
- if (watcher instanceof IBind && watcher !== expr) {
1375
- watcher.unlink();
1376
- }
1377
- }
1378
- }
1379
- }, [cond]);
1380
-
1381
- $.watch.add(expr);
1382
- return this;
1383
- }
1384
-
1385
- /**
1386
- * A v-show & ngShow alternative
1387
- * @param cond {IValue} show condition
1388
- */
1389
- $bindShow (cond) {
1390
- let $ = this.$;
1391
- let lastDisplay = $.el.style.display;
1392
-
1393
- return this.$bindFreeze(cond, () => {
1394
- lastDisplay = $.el.style.display;
1395
- $.el.style.display = 'none';
1396
- }, () => {
1397
- $.el.style.display = lastDisplay;
1398
- });
1399
- }
1400
-
1401
- /**
1402
- * Mount/Unmount a node
1403
- * @param cond {IValue} show condition
1404
- */
1405
- $bindMount (cond) {
1406
- let $ = this.$;
1407
-
1408
- return this.$bindFreeze(cond, () => {
1409
- $.unmounted = true;
1410
- }, () => {
1411
- $.unmounted = false;
1412
- });
1413
- }
1414
-
1415
- /**
1416
- * Enable/Disable reactivity o component
1417
- * @param cond {IValue} show condition
1418
- */
1419
- $bindAlive (cond) {
1420
- return this.$bindFreeze(cond);
1421
- }
1422
-
1423
- /**
1424
- * Defines a text fragment
1425
- * @param text {String | IValue} A text fragment string
1426
- * @param cb {?function (TextNode)} Callback if previous is slot name
1427
- * @return {INode} A pointer to this
1428
- */
1429
- $defText (
1430
- text,
1431
- cb
1432
- ) {
1433
- let $ = this.$;
1434
- let default_ = $.slots.get("default");
1435
-
1436
- if (default_ && default_ !== this && !$.building) {
1437
- default_.$defText(text, cb);
1438
- return this;
1439
- }
1440
-
1441
- let node = new TextNode();
1442
-
1443
- node.$$preinitText($.app, $.rt, this, null, text);
1444
- this.$$pushNode(node);
1445
-
1446
- if (cb) {
1447
- $.app.$run.callCallback(() => {
1448
- cb(node);
1449
- });
1450
- }
1451
- return this;
1452
- }
1453
-
1454
- /**
1455
- * Defines a tag element
1456
- * @param tagName {String} is the tag name
1457
- * @param cb {function(Tag, *)} Callback if previous is slot name
1458
- * @return {INode} A pointer to this
1459
- */
1460
- $defTag (
1461
- tagName,
1462
- cb
1463
- ) {
1464
- let $ = this.$;
1465
- let default_ = $.slots.get("default");
1466
-
1467
- if (default_ && default_ !== this && !$.building) {
1468
- default_.$defTag(tagName, cb);
1469
- return this;
1470
- }
1471
- let node = new Tag();
1472
-
1473
- node.$.parent = this;
1474
- node.$$preinitElementNode($.app, $.rt, this, null, tagName);
1475
- node.$init();
1476
- this.$$pushNode(node);
1477
-
1478
- $.app.$run.callCallback(() => {
1479
- if (cb) {
1480
- cb(node);
1481
- }
1482
- node.$ready();
1483
- });
1484
- return this;
1485
- }
1486
-
1487
- /**
1488
- * Defines a custom element
1489
- * @param node {*} Custom element constructor
1490
- * @param props {function(INode)} List of properties values
1491
- * @param cb {?function(INode, *)} Callback if previous is slot name
1492
- * @return {INode} A pointer to this
1493
- */
1494
- $defElement (
1495
- node,
1496
- props,
1497
- cb
1498
- ) {
1499
- let $ = this.$;
1500
- let default_ = $.slots.get("default");
1501
-
1502
- if (default_ && default_ !== this && !$.building) {
1503
- default_.$defElement(node, props, cb);
1504
- return this;
1505
- }
1506
-
1507
- if (node instanceof VasilleNode) {
1508
- node.$.parent = this;
1509
- }
1510
-
1511
- if (node instanceof Extension) {
1512
- node.$$preinitShadow($.app, $.rt, this, null);
1513
- }
1514
- else if (node instanceof Tag || node instanceof TextNode) {
1515
- node.$.preinit($.app, $.rt, this, null);
1516
- }
1517
-
1518
- this.$$callPropsCallback(node, props);
1519
-
1520
- if (node instanceof VasilleNode) {
1521
- this.$$pushNode(node);
1522
- }
1523
-
1524
- $.app.$run.callCallback(() => {
1525
- if (cb) {
1526
- cb(node);
1527
- }
1528
-
1529
- if (node instanceof INode) {
1530
- node.$ready();
1531
- }
1532
- });
1533
-
1534
- return this;
1535
- }
1536
-
1537
- /**
1538
- * Calls callback function to create properties
1539
- * @param node {INode}
1540
- * @param props {function(INode)}
1541
- * @return {*}
1542
- */
1543
- $$callPropsCallback (node, props) {
1544
- if (node instanceof INode) {
1545
- let obj = {
1546
- $bind : function (...args) {
1547
- return node.$bind(...args);
1548
- }
1549
- };
1550
-
1551
- for (let i in node) {
1552
- if (node.hasOwnProperty(i)) {
1553
- Object.defineProperty(obj, i, {
1554
- configurable : false,
1555
- enumerable : false,
1556
- set (value) {
1557
- node.$$unsafeAssign(node, i, value);
1558
- },
1559
- get () {
1560
- return (node)[i];
1561
- }
1562
- });
1563
- }
1564
- }
1565
-
1566
- //$FlowFixMe[incompatible-call]
1567
- props(obj);
1568
- node.$init();
1569
- }
1570
- }
1571
-
1572
- /**
1573
- * Defines a repeater node
1574
- * @param nodeT {RepeatNode} A repeat node object
1575
- * @param props {function(INode)} Send data to repeat node
1576
- * @param cb {function(RepeatNodeItem, *)} Call-back to create child nodes
1577
- * @return {INode}
1578
- */
1579
- $defRepeater (
1580
- nodeT,
1581
- props,
1582
- cb
1583
- ) {
1584
- let $ = this.$;
1585
- let default_ = $.slots.get("default");
1586
-
1587
- if (default_ && default_ !== this && !$.building) {
1588
- default_.$defRepeater(nodeT, props, cb);
1589
- return this;
1590
- }
1591
-
1592
- //$FlowFixMe[incompatible-type]
1593
- let node = nodeT;
1594
-
1595
- node.$.parent = this;
1596
- node.$$preinitShadow($.app, this.$.rt, this, null);
1597
- this.$$callPropsCallback(nodeT, props);
1598
- this.$$pushNode(node);
1599
- node.setCallback(cb);
1600
- $.app.$run.callCallback(() => {
1601
- node.$ready();
1602
- });
1603
-
1604
- return this;
1605
- }
1606
-
1607
- /**
1608
- * Defines a if node
1609
- * @param cond {* | IValue<*>} condition
1610
- * @param cb {function(RepeatNodeItem, ?number)} Call-back to create child nodes
1611
- * @return {this}
1612
- */
1613
- $defIf (
1614
- cond,
1615
- cb
1616
- ) {
1617
- return this.$defSwitch({ cond, cb });
1618
- }
1619
-
1620
- /**
1621
- * Defines a if-else node
1622
- * @param ifCond {* | IValue<*>} `if` condition
1623
- * @param ifCb {function(RepeatNodeItem, ?number)} Call-back to create `if` child nodes
1624
- * @param elseCb {function(RepeatNodeItem, ?number)} Call-back to create `else` child nodes
1625
- * @return {this}
1626
- */
1627
- $defIfElse (
1628
- ifCond,
1629
- ifCb,
1630
- elseCb
1631
- ) {
1632
- return this.$defSwitch({ cond : ifCond, cb : ifCb }, { cond : true, cb : elseCb });
1633
- }
1634
-
1635
- /**
1636
- * Defines a switch nodes: Will break after first true condition
1637
- * @param cases {...{ cond : IValue<boolean> | boolean, cb : function(RepeatNodeItem, ?number) }}
1638
- * @return {INode}
1639
- */
1640
- $defSwitch (
1641
- ...cases
1642
- ) {
1643
- let $ = this.$;
1644
- let default_ = $.slots.get("default");
1645
-
1646
- if (default_ && default_ !== this && !$.building) {
1647
- default_.$defSwitch(...cases);
1648
- return this;
1649
- }
1650
-
1651
- let node = new SwitchedNode();
1652
-
1653
- node.$.parent = this;
1654
- node.$$preinitShadow($.app, this.$.rt, this, null);
1655
- node.$init();
1656
- this.$$pushNode(node);
1657
- node.setCases(cases);
1658
- $.app.$run.callCallback(() => {
1659
- node.$ready();
1660
- });
1661
-
1662
- return this;
1663
- }
1664
-
1665
- /**
1666
- * @param cond {IValue<boolean> | boolean}
1667
- * @param cb {(function(RepeatNodeItem, ?number) : void)}
1668
- * @return {{cond : (IValue<boolean>|boolean), cb : (function(RepeatNodeItem, ?number) : void)}}
1669
- */
1670
- $case (cond, cb)
1671
- {
1672
- return {cond, cb};
1673
- }
1674
-
1675
- /**
1676
- * @param cb {(function(RepeatNodeItem, ?number) : void)}
1677
- * @return {{cond : boolean, cb : (function(RepeatNodeItem, ?number) : void)}}
1678
- */
1679
- $default (cb)
1680
- {
1681
- return {cond: true, cb};
1682
- }
1683
-
1684
- /**
1685
- * bind HTML
1686
- * @param value {IValue<string>}
1687
- */
1688
- $bindHTML (value) {
1689
- let $ = this.$;
1690
-
1691
- $.el.innerHTML = value.$;
1692
- this.$watch((v) => {
1693
- $.el.innerHTML = v;
1694
- }, value);
1695
- }
1696
-
1697
- /**
1698
- * collect identifiers of created rules packs
1699
- * @type {Set<string>}
1700
- */
1701
- static cssRules = new Set;
1702
-
1703
- /**
1704
- * @param class_ {string} set class which will be used to scope style
1705
- */
1706
- $setMetaClass (class_) {
1707
- (this.$).metaClass = class_;
1708
- }
1709
-
1710
- /**
1711
- * Scope a selector to current component
1712
- * @param selector {string} selector to scope
1713
- * @return {string}
1714
- */
1715
- $scope (selector) {
1716
- return selector + '.' + (this.$).metaClass;
1717
- }
1718
-
1719
- /**
1720
- * Defines a local CSS rule
1721
- * @param scoped {string} selector to scope
1722
- * @param rules {Object<string, string>} css rules
1723
- */
1724
- $local (scoped, rules) {
1725
- (this.$).metaStyle.push({scoped, rules});
1726
- }
1727
-
1728
- /**
1729
- * Defines a hybrid rule
1730
- * @param scoped {string} selector to scope
1731
- * @param unscoped {string} selector to append unscoped
1732
- * @param rules {Object<string, string>} css rules
1733
- */
1734
- $hybrid (scoped, unscoped, rules) {
1735
- (this.$).metaStyle.push({scoped, unscoped, rules});
1736
- }
1737
-
1738
- /**
1739
- * Make style tag for component
1740
- */
1741
- $$makeStyleTag () {
1742
- let $ = this.$;
1743
-
1744
- if (!$.metaClass || INode.cssRules.has($.metaClass)) {
1745
- return;
1746
- }
1747
-
1748
- $.metaStyle = [];
1749
- this.$createCss();
1750
-
1751
- let content = '';
1752
- let suffix = $.app.$debug ? '\n' : '';
1753
-
1754
- for (let pack of $.metaStyle) {
1755
- content += this.$scope(pack.scoped) + ' ' + (pack.unscoped || '') + '{' + suffix;
1756
-
1757
- for (let i in pack.rules) {
1758
- content += i + ':' + pack.rules[i] + ';' + suffix;
1759
- }
1760
-
1761
- content += '}' + suffix;
1762
- }
1763
-
1764
- let style = document.createElement('style');
1765
- style.classList.add($.metaClass);
1766
- style.innerHTML = content;
1767
- document.head?.appendChild(style);
1768
- INode.cssRules.add($.metaClass);
1769
- }
1770
- }
1771
-
1772
- /**
1773
- * Represents an Vasille.js HTML element node
1774
- */
1775
- export class Tag extends INode {
1776
-
1777
- /**
1778
- * HTML node created by this TagNode
1779
- * @type {HTMLElement}
1780
- */
1781
- $node;
1782
-
1783
- constructor () {
1784
- super ();
1785
- this.seal();
1786
- }
1787
-
1788
- /**
1789
- * Constructs a element node
1790
- * @param app {App} the app node
1791
- * @param rt {INode} The root node
1792
- * @param ts {INode} The this node
1793
- * @param before {VasilleNode} Node to insert before it
1794
- * @param tagName {String} Name of HTML tag
1795
- */
1796
- $$preinitElementNode (
1797
- app,
1798
- rt,
1799
- ts,
1800
- before,
1801
- tagName
1802
- ) {
1803
- this.$node = document.createElement(tagName);
1804
- this.$$preinitNode(app, rt, ts, before, this.$node);
1805
- }
1806
-
1807
- /**
1808
- * Runs GC
1809
- */
1810
- $destroy () {
1811
- super.$destroy();
1812
- this.$node.remove();
1813
- //$FlowFixMe
1814
- this.$node = null;
1815
- }
1816
- }
1817
-
1818
- /**
1819
- * Represents a Vasille.js shadow node
1820
- */
1821
- export class Extension extends INode {
1822
- /**
1823
- * Pre-initialize a shadow node
1824
- * @param app {App} the app node
1825
- * @param rt {INode} The root node
1826
- * @param ts {INode} The this node
1827
- * @param before {VasilleNode} node to paste after it
1828
- */
1829
- $$preinitShadow (
1830
- app,
1831
- rt,
1832
- ts,
1833
- before
1834
- ) {
1835
- this.$.preinit(app, rt, ts, before);
1836
-
1837
- try {
1838
- this.$.encapsulate(ts.$.el);
1839
- }
1840
- catch (e) {
1841
- throw internalError("A extension node can be encapsulated in a tag or extension node only");
1842
- }
1843
- }
1844
-
1845
- constructor ($) {
1846
- super ($);
1847
- this.seal();
1848
- }
1849
-
1850
- /**
1851
- * Runs GC
1852
- */
1853
- $destroy () {
1854
- super.$destroy();
1855
- }
1856
- }
1857
-
1858
- /**
1859
- * Defines a node which cas has just a child (TagNode | Component)
1860
- */
1861
- export class Component extends Extension {
1862
- constructor () {
1863
- super ();
1864
- this.seal();
1865
- }
1866
-
1867
- $mounted () {
1868
- super.$mounted();
1869
-
1870
- if (this.$children.length !== 1) {
1871
- throw userError("UserNode must have a child only", "dom-error");
1872
- }
1873
- let child = this.$children[0];
1874
-
1875
- if (child instanceof Tag || child instanceof Component) {
1876
- let $ = this.$;
1877
-
1878
- $.encapsulate(child.$.el);
1879
- if ($.app.$debug) {
1880
- //$FlowFixMe
1881
- $.el.vasille = $.el.vasille || this;
1882
- }
1883
- }
1884
- else {
1885
- throw userError("UserNode child must be TagNode or UserNode", "dom-error");
1886
- }
1887
- }
1888
- }
1889
-
1890
-
1891
- /**
1892
- * Defines a abstract node, which represents a dynamical part of application
1893
- */
1894
- export class RepeatNodeItem extends Extension {
1895
- /**
1896
- * node identifier
1897
- * @type {*}
1898
- */
1899
- $id;
1900
-
1901
- /**
1902
- * Constructs a repeat node item
1903
- * @param id {*}
1904
- */
1905
- constructor (id) {
1906
- super();
1907
- this.$id = id;
1908
- this.seal();
1909
- }
1910
-
1911
- /**
1912
- * Destroy all children
1913
- */
1914
- $destroy () {
1915
- this.$id = null;
1916
- super.$destroy();
1917
- }
1918
- }
1919
-
1920
- /**
1921
- * Private part of switch node
1922
- */
1923
- export class SwitchedNodePrivate extends BaseNodePrivate {
1924
- /**
1925
- * Index of current true condition
1926
- * @type {number}
1927
- */
1928
- index = -1;
1929
-
1930
- /**
1931
- * The unique child which can be absent
1932
- * @type {Extension}
1933
- */
1934
- node;
1935
-
1936
- /**
1937
- * Array of possible casses
1938
- * @type {Array<{cond : IValue<boolean>, cb : function(RepeatNodeItem, ?number)}>}
1939
- */
1940
- cases;
1941
-
1942
- /**
1943
- * A function which sync index and content, will be bounded to each condition
1944
- * @type {Function}
1945
- */
1946
- sync;
1947
-
1948
- constructor () {
1949
- super ();
1950
- this.seal();
1951
- }
1952
-
1953
- /**
1954
- * Runs GC
1955
- */
1956
- $destroy () {
1957
- //$FlowFixMe
1958
- this.index = null;
1959
- //$FlowFixMe
1960
- this.node = null;
1961
-
1962
- for (let c of this.cases) {
1963
- //$FlowFixMe
1964
- delete c.cond;
1965
- //$FlowFixMe
1966
- delete c.cb;
1967
- }
1968
- this.cases.splice(0);
1969
- //$FlowFixMe
1970
- this.cases = null;
1971
- //$FlowFixMe
1972
- this.sync = null;
1973
-
1974
- super.$destroy();
1975
- }
1976
- }
1977
-
1978
- /**
1979
- * Defines a node witch can switch its children conditionally
1980
- */
1981
- class SwitchedNode extends Extension {
1982
- /**
1983
- * Constructs a switch node and define a sync function
1984
- */
1985
- constructor ($) {
1986
- super($ ?? new SwitchedNodePrivate);
1987
-
1988
- this.$.sync = () => {
1989
- let $ = this.$;
1990
- let i = 0;
1991
-
1992
- for (; i < $.cases.length; i++) {
1993
- if ($.cases[i].cond.$) {
1994
- break;
1995
- }
1996
- }
1997
-
1998
- if (i === $.index) {
1999
- return;
2000
- }
2001
-
2002
- if ($.node) {
2003
- $.node.$destroy();
2004
- this.$children.splice(this.$children.indexOf($.node), 1);
2005
- //$FlowFixMe
2006
- $.node = null;
2007
- }
2008
-
2009
- if (i !== $.cases.length) {
2010
- $.index = i;
2011
- this.createChild(i, $.cases[i].cb);
2012
- }
2013
- else {
2014
- $.index = -1;
2015
- }
2016
- };
2017
-
2018
- this.seal();
2019
- };
2020
-
2021
- /**
2022
- * Set up switch cases
2023
- * @param cases {{ cond : IValue | boolean, cb : function(RepeatNodeItem, ?number) }}
2024
- */
2025
- setCases (cases) {
2026
- let $ = this.$;
2027
- $.cases = [];
2028
-
2029
- for (let case_ of cases) {
2030
- $.cases.push({ cond : vassilify(case_.cond), cb : case_.cb });
2031
- }
2032
- }
2033
-
2034
- /**
2035
- * Creates a child node
2036
- * @param id {*} id of node
2037
- * @param cb {function(RepeatNodeItem, *)} Call-back
2038
- */
2039
- createChild (id, cb) {
2040
- let node = new RepeatNodeItem(id);
2041
-
2042
- node.$.parent = this;
2043
- node.$$preinitShadow(this.$.app, this.$.rt, this);
2044
-
2045
- node.$init();
2046
- cb(node, id);
2047
- node.$ready();
2048
-
2049
- this.$.node = node;
2050
- this.$children.push(node);
2051
- };
2052
-
2053
- /**
2054
- * Prepare shadow node
2055
- * @param app {App} App node
2056
- * @param rt {INode} Root node
2057
- * @param ts {INode} This node
2058
- * @param before {VasilleNode} The next node
2059
- */
2060
- $$preinitShadow (app, rt, ts, before) {
2061
- super.$$preinitShadow(app, rt, ts, before);
2062
- this.$.encapsulate(ts.$.el);
2063
- }
2064
-
2065
-
2066
-
2067
- /**
2068
- * Run then the node is ready
2069
- */
2070
- $ready () {
2071
- let $ = this.$;
2072
-
2073
- super.$ready();
2074
-
2075
- for (let c of $.cases) {
2076
- c.cond.on($.sync);
2077
- }
2078
-
2079
- $.sync();
2080
- }
2081
-
2082
- /**
2083
- * Unbind and clear dynamical nodes
2084
- */
2085
- $destroy () {
2086
- let $ = this.$;
2087
-
2088
- for (let c of $.cases) {
2089
- c.cond.off($.sync);
2090
- }
2091
-
2092
- super.$destroy();
2093
- }
2094
- }
2095
-
2096
- /**
2097
- * Represents a Vasille.js application node
2098
- */
2099
- export class App extends INode {
2100
- /**
2101
- * The debug state of application, if true will output debug data
2102
- * @type {boolean}
2103
- */
2104
- $debug = false;
2105
-
2106
- /**
2107
- * Executor is use to optimize the page creation/update
2108
- * @type {Executor}
2109
- */
2110
- $run;
2111
-
2112
- /**
2113
- * Constructs a app node
2114
- * @param node {HTMLElement} The root of application
2115
- * @param meta {?{debug : boolean}} Application properties
2116
- */
2117
- constructor (node, meta) {
2118
- super();
2119
-
2120
- this.$run = new InstantExecutor();
2121
- this.$.encapsulate(node);
2122
- this.$.preinit(this, this, this, this);
2123
-
2124
- if (meta?.debug instanceof Boolean) {
2125
- this.$debug = meta.debug;
2126
- }
2127
-
2128
- this.seal();
2129
- }
2130
-
2131
- /**
2132
- * @param props {function($ : any) : void}
2133
- */
2134
- $create (props) {
2135
- // $FlowFixMe
2136
- this.$$callPropsCallback(this, props);
2137
- }
2138
-
2139
- $mounted () {
2140
- super.$mounted();
2141
-
2142
- if (this.$debug) {
2143
- //$FlowFixMe
2144
- (this.$).el.vasille = this;
2145
- }
2146
- }
2147
-
2148
- $destroy () {
2149
- //$FlowFixMe
2150
- this.$run = null;
2151
- super.$destroy();
2152
- }
2153
- }
2154
-
2155
- //# sourceMappingURL=node.js.map