vasille 2.2.2 → 2.3.2

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 (68) hide show
  1. package/README.md +34 -28
  2. package/cdn/es2015.js +18 -724
  3. package/cdn/es5.js +687 -957
  4. package/flow-typed/vasille.js +14 -59
  5. package/lib/core/core.js +3 -3
  6. package/lib/index.js +5 -4
  7. package/lib/models/array-model.js +6 -9
  8. package/lib/models/object-model.js +3 -17
  9. package/lib/node/node.js +6 -3
  10. package/lib/views/object-view.js +1 -1
  11. package/lib-node/binding/attribute.js +35 -0
  12. package/lib-node/binding/binding.js +33 -0
  13. package/lib-node/binding/class.js +48 -0
  14. package/lib-node/binding/style.js +27 -0
  15. package/lib-node/core/core.js +243 -0
  16. package/lib-node/core/destroyable.js +49 -0
  17. package/lib-node/core/errors.js +23 -0
  18. package/lib-node/core/ivalue.js +63 -0
  19. package/lib-node/functional/options.js +2 -0
  20. package/lib-node/index.js +54 -0
  21. package/lib-node/models/array-model.js +218 -0
  22. package/lib-node/models/listener.js +134 -0
  23. package/lib-node/models/map-model.js +70 -0
  24. package/lib-node/models/model.js +2 -0
  25. package/lib-node/models/object-model.js +82 -0
  26. package/lib-node/models/set-model.js +66 -0
  27. package/lib-node/node/app.js +54 -0
  28. package/lib-node/node/node.js +885 -0
  29. package/lib-node/node/watch.js +23 -0
  30. package/lib-node/spec/html.js +2 -0
  31. package/lib-node/spec/react.js +2 -0
  32. package/lib-node/spec/svg.js +2 -0
  33. package/lib-node/value/expression.js +90 -0
  34. package/lib-node/value/mirror.js +60 -0
  35. package/lib-node/value/pointer.js +30 -0
  36. package/lib-node/value/reference.js +55 -0
  37. package/lib-node/views/array-view.js +21 -0
  38. package/lib-node/views/base-view.js +43 -0
  39. package/lib-node/views/map-view.js +18 -0
  40. package/lib-node/views/object-view.js +20 -0
  41. package/lib-node/views/repeat-node.js +71 -0
  42. package/lib-node/views/set-view.js +19 -0
  43. package/package.json +21 -17
  44. package/types/core/core.d.ts +4 -4
  45. package/types/functional/options.d.ts +2 -2
  46. package/types/index.d.ts +10 -7
  47. package/types/models/array-model.d.ts +1 -1
  48. package/types/models/object-model.d.ts +1 -1
  49. package/types/node/node.d.ts +5 -4
  50. package/types/node/watch.d.ts +2 -2
  51. package/types/views/repeat-node.d.ts +2 -2
  52. package/lib/core/executor.js +0 -154
  53. package/lib/core/signal.js +0 -50
  54. package/lib/core/slot.js +0 -47
  55. package/lib/functional/components.js +0 -17
  56. package/lib/functional/merge.js +0 -41
  57. package/lib/functional/models.js +0 -26
  58. package/lib/functional/reactivity.js +0 -33
  59. package/lib/functional/stack.js +0 -127
  60. package/lib/node/interceptor.js +0 -83
  61. package/lib/v/index.js +0 -23
  62. package/lib/views/repeater.js +0 -63
  63. package/types/functional/components.d.ts +0 -4
  64. package/types/functional/merge.d.ts +0 -1
  65. package/types/functional/models.d.ts +0 -10
  66. package/types/functional/reactivity.d.ts +0 -11
  67. package/types/functional/stack.d.ts +0 -24
  68. package/types/v/index.d.ts +0 -36
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Reactive = exports.ReactivePrivate = exports.current = void 0;
4
+ const destroyable_js_1 = require("./destroyable.js");
5
+ const errors_1 = require("./errors");
6
+ const expression_1 = require("../value/expression");
7
+ const reference_1 = require("../value/reference");
8
+ const pointer_1 = require("../value/pointer");
9
+ const mirror_1 = require("../value/mirror");
10
+ exports.current = null;
11
+ const currentStack = [];
12
+ function stack(node) {
13
+ currentStack.push(exports.current);
14
+ exports.current = node;
15
+ }
16
+ function unstack() {
17
+ exports.current = currentStack.pop();
18
+ }
19
+ /**
20
+ * Private stuff of a reactive object
21
+ * @class ReactivePrivate
22
+ * @extends Destroyable
23
+ */
24
+ class ReactivePrivate extends destroyable_js_1.Destroyable {
25
+ constructor() {
26
+ super();
27
+ /**
28
+ * A list of user-defined values
29
+ * @type {Set}
30
+ */
31
+ this.watch = new Set;
32
+ /**
33
+ * A list of user-defined bindings
34
+ * @type {Set}
35
+ */
36
+ this.bindings = new Set;
37
+ /**
38
+ * A list of user defined models
39
+ */
40
+ this.models = new Set;
41
+ /**
42
+ * Reactivity switch state
43
+ * @type {boolean}
44
+ */
45
+ this.enabled = true;
46
+ /**
47
+ * The frozen state of object
48
+ * @type {boolean}
49
+ */
50
+ this.frozen = false;
51
+ this.$seal();
52
+ }
53
+ $destroy() {
54
+ this.watch.forEach(value => value.$destroy());
55
+ this.watch.clear();
56
+ this.bindings.forEach(binding => binding.$destroy());
57
+ this.bindings.clear();
58
+ this.models.forEach(model => model.disableReactivity());
59
+ this.models.clear();
60
+ this.freezeExpr && this.freezeExpr.$destroy();
61
+ this.onDestroy && this.onDestroy();
62
+ super.$destroy();
63
+ }
64
+ }
65
+ exports.ReactivePrivate = ReactivePrivate;
66
+ /**
67
+ * A reactive object
68
+ * @class Reactive
69
+ * @extends Destroyable
70
+ */
71
+ class Reactive extends destroyable_js_1.Destroyable {
72
+ constructor(input, $) {
73
+ super();
74
+ this.input = input;
75
+ this.$ = $ || new ReactivePrivate;
76
+ this.$seal();
77
+ }
78
+ /**
79
+ * Get parent node
80
+ */
81
+ get parent() {
82
+ return this.$.parent;
83
+ }
84
+ /**
85
+ * Create a reference
86
+ * @param value {*} value to reference
87
+ */
88
+ ref(value) {
89
+ const $ = this.$;
90
+ const ref = new reference_1.Reference(value);
91
+ $.watch.add(ref);
92
+ return ref;
93
+ }
94
+ /**
95
+ * Create a mirror
96
+ * @param value {IValue} value to mirror
97
+ */
98
+ mirror(value) {
99
+ const mirror = new mirror_1.Mirror(value, false);
100
+ this.$.watch.add(mirror);
101
+ return mirror;
102
+ }
103
+ /**
104
+ * Create a forward-only mirror
105
+ * @param value {IValue} value to mirror
106
+ */
107
+ forward(value) {
108
+ const mirror = new mirror_1.Mirror(value, true);
109
+ this.$.watch.add(mirror);
110
+ return mirror;
111
+ }
112
+ /**
113
+ * Creates a pointer
114
+ * @param value {*} default value to point
115
+ * @param forwardOnly {boolean} forward only sync
116
+ */
117
+ point(value, forwardOnly = false) {
118
+ const $ = this.$;
119
+ const pointer = new pointer_1.Pointer(value, forwardOnly);
120
+ $.watch.add(pointer);
121
+ return pointer;
122
+ }
123
+ /**
124
+ * Register a model
125
+ * @param model
126
+ */
127
+ register(model) {
128
+ this.$.models.add(model);
129
+ return model;
130
+ }
131
+ /**
132
+ * Creates a watcher
133
+ * @param func {function} function to run on any argument change
134
+ * @param values
135
+ */
136
+ watch(func, ...values) {
137
+ const $ = this.$;
138
+ $.watch.add(new expression_1.Expression(func, !this.$.frozen, ...values));
139
+ }
140
+ /**
141
+ * Creates a computed value
142
+ * @param func {function} function to run on any argument change
143
+ * @param values
144
+ * @return {IValue} the created ivalue
145
+ */
146
+ expr(func, ...values) {
147
+ const res = new expression_1.Expression(func, !this.$.frozen, ...values);
148
+ const $ = this.$;
149
+ $.watch.add(res);
150
+ return res;
151
+ }
152
+ /**
153
+ * Enable reactivity of fields
154
+ */
155
+ enable() {
156
+ const $ = this.$;
157
+ if (!$.enabled) {
158
+ $.watch.forEach(watcher => {
159
+ watcher.$enable();
160
+ });
161
+ $.models.forEach(model => {
162
+ model.enableReactivity();
163
+ });
164
+ $.enabled = true;
165
+ }
166
+ }
167
+ /**
168
+ * Disable reactivity of fields
169
+ */
170
+ disable() {
171
+ const $ = this.$;
172
+ if ($.enabled) {
173
+ $.watch.forEach(watcher => {
174
+ watcher.$disable();
175
+ });
176
+ $.models.forEach(model => {
177
+ model.disableReactivity();
178
+ });
179
+ $.enabled = false;
180
+ }
181
+ }
182
+ /**
183
+ * Disable/Enable reactivity of object fields with feedback
184
+ * @param cond {IValue} show condition
185
+ * @param onOff {function} on show feedback
186
+ * @param onOn {function} on hide feedback
187
+ */
188
+ bindAlive(cond, onOff, onOn) {
189
+ const $ = this.$;
190
+ if ($.freezeExpr) {
191
+ throw (0, errors_1.wrongBinding)("this component already have a freeze state");
192
+ }
193
+ if ($.watch.has(cond)) {
194
+ throw (0, errors_1.wrongBinding)("freeze state must be bound to an external component");
195
+ }
196
+ $.freezeExpr = new expression_1.Expression((cond) => {
197
+ $.frozen = !cond;
198
+ if (cond) {
199
+ onOn === null || onOn === void 0 ? void 0 : onOn();
200
+ this.enable();
201
+ }
202
+ else {
203
+ onOff === null || onOff === void 0 ? void 0 : onOff();
204
+ this.disable();
205
+ }
206
+ }, true, cond);
207
+ return this;
208
+ }
209
+ init() {
210
+ this.applyOptions(this.input);
211
+ return this.compose(this.input);
212
+ }
213
+ applyOptions(input) {
214
+ // empty
215
+ }
216
+ applyOptionsNow() {
217
+ this.applyOptions(this.input);
218
+ }
219
+ compose(input) {
220
+ throw (0, errors_1.notOverwritten)();
221
+ }
222
+ composeNow() {
223
+ this.compose(this.input);
224
+ }
225
+ runFunctional(f, ...args) {
226
+ stack(this);
227
+ // yet another ts bug
228
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
229
+ // @ts-ignore
230
+ const result = f(...args);
231
+ unstack();
232
+ return result;
233
+ }
234
+ runOnDestroy(func) {
235
+ this.$.onDestroy = func;
236
+ }
237
+ $destroy() {
238
+ super.$destroy();
239
+ this.$.$destroy();
240
+ this.$ = null;
241
+ }
242
+ }
243
+ exports.Reactive = Reactive;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Destroyable = void 0;
4
+ /**
5
+ * Mark an object which can be destroyed
6
+ * @class Destroyable
7
+ */
8
+ class Destroyable {
9
+ /**
10
+ * Make object fields non configurable
11
+ * @protected
12
+ */
13
+ $seal() {
14
+ const $ = this;
15
+ Object.keys($).forEach(i => {
16
+ // eslint-disable-next-line no-prototype-builtins
17
+ if (this.hasOwnProperty(i)) {
18
+ const config = Object.getOwnPropertyDescriptor($, i);
19
+ if (config.configurable) {
20
+ let descriptor;
21
+ if (config.set || config.get) {
22
+ descriptor = {
23
+ configurable: false,
24
+ get: config.get,
25
+ set: config.set,
26
+ enumerable: config.enumerable
27
+ };
28
+ }
29
+ else {
30
+ descriptor = {
31
+ value: $[i],
32
+ configurable: false,
33
+ writable: config.writable,
34
+ enumerable: config.enumerable
35
+ };
36
+ }
37
+ Object.defineProperty($, i, descriptor);
38
+ }
39
+ }
40
+ });
41
+ }
42
+ /**
43
+ * Garbage collector method
44
+ */
45
+ $destroy() {
46
+ // nothing here
47
+ }
48
+ }
49
+ exports.Destroyable = Destroyable;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wrongBinding = exports.userError = exports.internalError = exports.notOverwritten = void 0;
4
+ const reportIt = "Report it here: https://gitlab.com/vasille-js/vasille-js/-/issues";
5
+ function notOverwritten() {
6
+ console.error("Vasille-SFP: Internal error", "Must be overwritten", reportIt);
7
+ return "not-overwritten";
8
+ }
9
+ exports.notOverwritten = notOverwritten;
10
+ function internalError(msg) {
11
+ console.error("Vasille-SFP: Internal error", msg, reportIt);
12
+ return "internal-error";
13
+ }
14
+ exports.internalError = internalError;
15
+ function userError(msg, err) {
16
+ console.error("Vasille-SFP: User error", msg);
17
+ return err;
18
+ }
19
+ exports.userError = userError;
20
+ function wrongBinding(msg) {
21
+ return userError(msg, "wrong-binding");
22
+ }
23
+ exports.wrongBinding = wrongBinding;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IValue = exports.Switchable = void 0;
4
+ const destroyable_js_1 = require("./destroyable.js");
5
+ const errors_1 = require("./errors");
6
+ class Switchable extends destroyable_js_1.Destroyable {
7
+ /**
8
+ * Enable update handlers triggering
9
+ */
10
+ $enable() {
11
+ throw (0, errors_1.notOverwritten)();
12
+ }
13
+ /**
14
+ * disable update handlers triggering
15
+ */
16
+ $disable() {
17
+ throw (0, errors_1.notOverwritten)();
18
+ }
19
+ }
20
+ exports.Switchable = Switchable;
21
+ /**
22
+ * Interface which describes a value
23
+ * @class IValue
24
+ * @extends Destroyable
25
+ */
26
+ class IValue extends Switchable {
27
+ /**
28
+ * @param isEnabled {boolean} initial is enabled state
29
+ */
30
+ constructor(isEnabled) {
31
+ super();
32
+ this.isEnabled = isEnabled;
33
+ }
34
+ /**
35
+ * Get the encapsulated value
36
+ * @return {*} the encapsulated value
37
+ */
38
+ get $() {
39
+ throw (0, errors_1.notOverwritten)();
40
+ }
41
+ /**
42
+ * Sets the encapsulated value
43
+ * @param value {*} value to encapsulate
44
+ */
45
+ set $(value) {
46
+ throw (0, errors_1.notOverwritten)();
47
+ }
48
+ /**
49
+ * Add a new handler to value change
50
+ * @param handler {function(value : *)} the handler to add
51
+ */
52
+ $on(handler) {
53
+ throw (0, errors_1.notOverwritten)();
54
+ }
55
+ /**
56
+ * Removes a handler of value change
57
+ * @param handler {function(value : *)} the handler to remove
58
+ */
59
+ $off(handler) {
60
+ throw (0, errors_1.notOverwritten)();
61
+ }
62
+ }
63
+ exports.IValue = IValue;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.current = exports.userError = exports.Watch = exports.Reactive = exports.Binding = exports.Expression = exports.Portal = exports.App = exports.AppNode = exports.Extension = exports.Component = exports.Tag = exports.INode = exports.Fragment = exports.SetView = exports.ObjectView = exports.MapView = exports.ArrayView = exports.Listener = exports.BaseView = exports.SetModel = exports.ObjectModel = exports.MapModel = exports.ArrayModel = exports.Pointer = exports.Mirror = exports.Reference = exports.IValue = exports.Destroyable = void 0;
4
+ const destroyable_1 = require("./core/destroyable");
5
+ Object.defineProperty(exports, "Destroyable", { enumerable: true, get: function () { return destroyable_1.Destroyable; } });
6
+ const core_1 = require("./core/core");
7
+ Object.defineProperty(exports, "current", { enumerable: true, get: function () { return core_1.current; } });
8
+ Object.defineProperty(exports, "Reactive", { enumerable: true, get: function () { return core_1.Reactive; } });
9
+ const ivalue_1 = require("./core/ivalue");
10
+ Object.defineProperty(exports, "IValue", { enumerable: true, get: function () { return ivalue_1.IValue; } });
11
+ const array_model_1 = require("./models/array-model");
12
+ Object.defineProperty(exports, "ArrayModel", { enumerable: true, get: function () { return array_model_1.ArrayModel; } });
13
+ const listener_1 = require("./models/listener");
14
+ Object.defineProperty(exports, "Listener", { enumerable: true, get: function () { return listener_1.Listener; } });
15
+ const map_model_1 = require("./models/map-model");
16
+ Object.defineProperty(exports, "MapModel", { enumerable: true, get: function () { return map_model_1.MapModel; } });
17
+ const object_model_1 = require("./models/object-model");
18
+ Object.defineProperty(exports, "ObjectModel", { enumerable: true, get: function () { return object_model_1.ObjectModel; } });
19
+ const set_model_1 = require("./models/set-model");
20
+ Object.defineProperty(exports, "SetModel", { enumerable: true, get: function () { return set_model_1.SetModel; } });
21
+ const app_1 = require("./node/app");
22
+ Object.defineProperty(exports, "App", { enumerable: true, get: function () { return app_1.App; } });
23
+ Object.defineProperty(exports, "AppNode", { enumerable: true, get: function () { return app_1.AppNode; } });
24
+ Object.defineProperty(exports, "Portal", { enumerable: true, get: function () { return app_1.Portal; } });
25
+ const node_1 = require("./node/node");
26
+ Object.defineProperty(exports, "Component", { enumerable: true, get: function () { return node_1.Component; } });
27
+ Object.defineProperty(exports, "Extension", { enumerable: true, get: function () { return node_1.Extension; } });
28
+ Object.defineProperty(exports, "Fragment", { enumerable: true, get: function () { return node_1.Fragment; } });
29
+ Object.defineProperty(exports, "INode", { enumerable: true, get: function () { return node_1.INode; } });
30
+ Object.defineProperty(exports, "Tag", { enumerable: true, get: function () { return node_1.Tag; } });
31
+ const expression_1 = require("./value/expression");
32
+ Object.defineProperty(exports, "Expression", { enumerable: true, get: function () { return expression_1.Expression; } });
33
+ const mirror_1 = require("./value/mirror");
34
+ Object.defineProperty(exports, "Mirror", { enumerable: true, get: function () { return mirror_1.Mirror; } });
35
+ const pointer_1 = require("./value/pointer");
36
+ Object.defineProperty(exports, "Pointer", { enumerable: true, get: function () { return pointer_1.Pointer; } });
37
+ const reference_1 = require("./value/reference");
38
+ Object.defineProperty(exports, "Reference", { enumerable: true, get: function () { return reference_1.Reference; } });
39
+ const array_view_1 = require("./views/array-view");
40
+ Object.defineProperty(exports, "ArrayView", { enumerable: true, get: function () { return array_view_1.ArrayView; } });
41
+ const base_view_1 = require("./views/base-view");
42
+ Object.defineProperty(exports, "BaseView", { enumerable: true, get: function () { return base_view_1.BaseView; } });
43
+ const map_view_1 = require("./views/map-view");
44
+ Object.defineProperty(exports, "MapView", { enumerable: true, get: function () { return map_view_1.MapView; } });
45
+ const object_view_1 = require("./views/object-view");
46
+ Object.defineProperty(exports, "ObjectView", { enumerable: true, get: function () { return object_view_1.ObjectView; } });
47
+ const set_view_1 = require("./views/set-view");
48
+ Object.defineProperty(exports, "SetView", { enumerable: true, get: function () { return set_view_1.SetView; } });
49
+ const binding_1 = require("./binding/binding");
50
+ Object.defineProperty(exports, "Binding", { enumerable: true, get: function () { return binding_1.Binding; } });
51
+ const errors_1 = require("./core/errors");
52
+ Object.defineProperty(exports, "userError", { enumerable: true, get: function () { return errors_1.userError; } });
53
+ const watch_1 = require("./node/watch");
54
+ Object.defineProperty(exports, "Watch", { enumerable: true, get: function () { return watch_1.Watch; } });
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ArrayModel = void 0;
4
+ const listener_1 = require("./listener");
5
+ /**
6
+ * Model based on Array class
7
+ * @extends Array
8
+ * @implements IModel
9
+ */
10
+ class ArrayModel extends Array {
11
+ /**
12
+ * @param data {Array} input data
13
+ */
14
+ constructor(data = []) {
15
+ super();
16
+ Object.defineProperty(this, 'listener', {
17
+ value: new listener_1.Listener,
18
+ writable: false,
19
+ configurable: false
20
+ });
21
+ for (let i = 0; i < data.length; i++) {
22
+ super.push(data[i]);
23
+ }
24
+ }
25
+ /* Array members */
26
+ /**
27
+ * Gets the last item of array
28
+ * @return {*} the last item of array
29
+ */
30
+ get last() {
31
+ return this.length ? this[this.length - 1] : null;
32
+ }
33
+ /**
34
+ * Calls Array.fill and notify about changes
35
+ * @param value {*} value to fill with
36
+ * @param start {?number} begin index
37
+ * @param end {?number} end index
38
+ */
39
+ fill(value, start, end) {
40
+ if (!start) {
41
+ start = 0;
42
+ }
43
+ if (!end) {
44
+ end = this.length;
45
+ }
46
+ for (let i = start; i < end; i++) {
47
+ this.listener.emitRemoved(this[i], this[i]);
48
+ this[i] = value;
49
+ this.listener.emitAdded(value, value);
50
+ }
51
+ return this;
52
+ }
53
+ /**
54
+ * Calls Array.pop and notify about changes
55
+ * @return {*} removed value
56
+ */
57
+ pop() {
58
+ const v = super.pop();
59
+ if (v !== undefined) {
60
+ this.listener.emitRemoved(v, v);
61
+ }
62
+ return v;
63
+ }
64
+ /**
65
+ * Calls Array.push and notify about changes
66
+ * @param items {...*} values to push
67
+ * @return {number} new length of array
68
+ */
69
+ push(...items) {
70
+ items.forEach(item => {
71
+ this.listener.emitAdded(item, item);
72
+ super.push(item);
73
+ });
74
+ return this.length;
75
+ }
76
+ /**
77
+ * Calls Array.shift and notify about changed
78
+ * @return {*} the shifted value
79
+ */
80
+ shift() {
81
+ const v = super.shift();
82
+ if (v !== undefined) {
83
+ this.listener.emitRemoved(v, v);
84
+ }
85
+ return v;
86
+ }
87
+ /**
88
+ * Calls Array.splice and notify about changed
89
+ * @param start {number} start index
90
+ * @param deleteCount {?number} delete count
91
+ * @param items {...*}
92
+ * @return {ArrayModel} a pointer to this
93
+ */
94
+ splice(start, deleteCount, ...items) {
95
+ start = Math.min(start, this.length);
96
+ deleteCount = deleteCount || this.length - start;
97
+ const before = this[start + deleteCount];
98
+ for (let i = 0; i < deleteCount; i++) {
99
+ const index = start + deleteCount - i - 1;
100
+ if (this[index] !== undefined) {
101
+ this.listener.emitRemoved(this[index], this[index]);
102
+ }
103
+ }
104
+ for (let i = 0; i < items.length; i++) {
105
+ this.listener.emitAdded(before, items[i]);
106
+ }
107
+ return new ArrayModel(super.splice(start, deleteCount, ...items));
108
+ }
109
+ /**
110
+ * Calls Array.unshift and notify about changed
111
+ * @param items {...*} values to insert
112
+ * @return {number} the length after prepend
113
+ */
114
+ unshift(...items) {
115
+ for (let i = 0; i < items.length; i++) {
116
+ this.listener.emitAdded(this[i], items[i]);
117
+ }
118
+ return super.unshift(...items);
119
+ }
120
+ /**
121
+ * Inserts a value to the end of array
122
+ * @param v {*} value to insert
123
+ */
124
+ append(v) {
125
+ this.listener.emitAdded(null, v);
126
+ super.push(v);
127
+ return this;
128
+ }
129
+ /**
130
+ * Clears array
131
+ * @return {this} a pointer to this
132
+ */
133
+ clear() {
134
+ this.forEach(v => {
135
+ this.listener.emitRemoved(v, v);
136
+ });
137
+ super.splice(0);
138
+ return this;
139
+ }
140
+ /**
141
+ * Inserts a value to position `index`
142
+ * @param index {number} index to insert value
143
+ * @param v {*} value to insert
144
+ * @return {this} a pointer to this
145
+ */
146
+ insert(index, v) {
147
+ this.listener.emitAdded(this[index], v);
148
+ super.splice(index, 0, v);
149
+ return this;
150
+ }
151
+ /**
152
+ * Inserts a value to the beginning of array
153
+ * @param v {*} value to insert
154
+ * @return {this} a pointer to this
155
+ */
156
+ prepend(v) {
157
+ this.listener.emitAdded(this[0], v);
158
+ super.unshift(v);
159
+ return this;
160
+ }
161
+ /**
162
+ * Removes a value from an index
163
+ * @param index {number} index of value to remove
164
+ * @return {this} a pointer to this
165
+ */
166
+ removeAt(index) {
167
+ if (index > 0 && index < this.length) {
168
+ this.listener.emitRemoved(this[index], this[index]);
169
+ super.splice(index, 1);
170
+ }
171
+ return this;
172
+ }
173
+ /**
174
+ * Removes the first value of array
175
+ * @return {this} a pointer to this
176
+ */
177
+ removeFirst() {
178
+ if (this.length) {
179
+ this.listener.emitRemoved(this[0], this[0]);
180
+ super.shift();
181
+ }
182
+ return this;
183
+ }
184
+ /**
185
+ * Removes the ast value of array
186
+ * @return {this} a pointer to this
187
+ */
188
+ removeLast() {
189
+ const last = this.last;
190
+ if (last != null) {
191
+ this.listener.emitRemoved(this[this.length - 1], last);
192
+ super.pop();
193
+ }
194
+ return this;
195
+ }
196
+ /**
197
+ * Remove the first occurrence of value
198
+ * @param v {*} value to remove
199
+ * @return {this}
200
+ */
201
+ removeOne(v) {
202
+ this.removeAt(this.indexOf(v));
203
+ return this;
204
+ }
205
+ replace(at, with_) {
206
+ this.listener.emitAdded(this[at], with_);
207
+ this.listener.emitRemoved(this[at], this[at]);
208
+ this[at] = with_;
209
+ return this;
210
+ }
211
+ enableReactivity() {
212
+ this.listener.enableReactivity();
213
+ }
214
+ disableReactivity() {
215
+ this.listener.disableReactivity();
216
+ }
217
+ }
218
+ exports.ArrayModel = ArrayModel;