vasille 3.2.0 → 3.2.1

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.
@@ -0,0 +1,152 @@
1
+ import { Listener } from "./listener.js";
2
+ /**
3
+ * Model based on Array class
4
+ * @extends Array
5
+ * @implements IModel
6
+ */
7
+ export class ArrayModel extends Array {
8
+ /**
9
+ * @param data {Array} input data
10
+ */
11
+ constructor(data) {
12
+ super();
13
+ this.passive = false;
14
+ this.listener = new Listener();
15
+ if (data instanceof Array) {
16
+ for (let i = 0; i < data.length; i++) {
17
+ super.push(data[i]);
18
+ }
19
+ }
20
+ }
21
+ /* Array members */
22
+ /**
23
+ * Calls Array.fill and notify about changes
24
+ * @param value {*} value to fill with
25
+ * @param start {?number} begin index
26
+ * @param end {?number} end index
27
+ */
28
+ fill(value, start, end) {
29
+ this.passive = true;
30
+ /* istanbul ignore else */
31
+ if (!start) {
32
+ start = 0;
33
+ }
34
+ /* istanbul ignore else */
35
+ if (!end) {
36
+ end = this.length;
37
+ }
38
+ for (let i = start; i < end; i++) {
39
+ this.listener.emitRemoved(this[i], this[i]);
40
+ this[i] = value;
41
+ this.listener.emitAdded(value, value);
42
+ }
43
+ this.passive = false;
44
+ return this;
45
+ }
46
+ /**
47
+ * Calls Array.pop and notify about changes
48
+ * @return {*} removed value
49
+ */
50
+ pop() {
51
+ this.passive = true;
52
+ const v = super.pop();
53
+ /* istanbul ignore else */
54
+ if (v !== undefined) {
55
+ this.listener.emitRemoved(v, v);
56
+ }
57
+ this.passive = false;
58
+ return v;
59
+ }
60
+ /**
61
+ * Calls Array.push and notify about changes
62
+ * @param items {...*} values to push
63
+ * @return {number} new length of array
64
+ */
65
+ push(...items) {
66
+ this.passive = true;
67
+ items.forEach(item => {
68
+ this.listener.emitAdded(item, item);
69
+ super.push(item);
70
+ });
71
+ this.passive = false;
72
+ return this.length;
73
+ }
74
+ /**
75
+ * Calls Array.shift and notify about changed
76
+ * @return {*} the shifted value
77
+ */
78
+ shift() {
79
+ this.passive = true;
80
+ const v = super.shift();
81
+ /* istanbul ignore else */
82
+ if (v !== undefined) {
83
+ this.listener.emitRemoved(v, v);
84
+ }
85
+ this.passive = false;
86
+ return v;
87
+ }
88
+ /**
89
+ * Calls Array.splice and notify about changed
90
+ * @param start {number} start index
91
+ * @param deleteCount {?number} delete count
92
+ * @param items {...*}
93
+ * @return {ArrayModel} a pointer to this
94
+ */
95
+ splice(start, deleteCount, ...items) {
96
+ this.passive = true;
97
+ start = Math.min(start, this.length);
98
+ deleteCount = typeof deleteCount === "number" ? deleteCount : this.length - start;
99
+ const before = this[start + deleteCount];
100
+ for (let i = 0; i < deleteCount; i++) {
101
+ const index = start + deleteCount - i - 1;
102
+ /* istanbul ignore else */
103
+ if (this[index] !== undefined) {
104
+ this.listener.emitRemoved(this[index], this[index]);
105
+ }
106
+ }
107
+ for (let i = 0; i < items.length; i++) {
108
+ this.listener.emitAdded(before, items[i]);
109
+ }
110
+ this.passive = false;
111
+ return new ArrayModel(super.splice(start, deleteCount, ...items));
112
+ }
113
+ /**
114
+ * Calls Array.unshift and notify about changed
115
+ * @param items {...*} values to insert
116
+ * @return {number} the length after prepend
117
+ */
118
+ unshift(...items) {
119
+ this.passive = true;
120
+ for (let i = 0; i < items.length; i++) {
121
+ this.listener.emitAdded(this[i], items[i]);
122
+ }
123
+ const r = super.unshift(...items);
124
+ this.passive = false;
125
+ return r;
126
+ }
127
+ replace(at, with_) {
128
+ this.passive = true;
129
+ this.listener.emitAdded(this[at], with_);
130
+ this.listener.emitRemoved(this[at], this[at]);
131
+ this[at] = with_;
132
+ this.passive = false;
133
+ return this;
134
+ }
135
+ destroy() {
136
+ this.splice(0);
137
+ }
138
+ }
139
+ export function proxyArrayModel(arr) {
140
+ return new Proxy(arr, {
141
+ set(target, p, newValue, receiver) {
142
+ if (!arr.passive && typeof p === "string") {
143
+ const index = parseInt(p);
144
+ if (Number.isFinite(index)) {
145
+ arr.replace(index, newValue);
146
+ return true;
147
+ }
148
+ }
149
+ return Reflect.set(target, p, newValue, receiver);
150
+ },
151
+ });
152
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Represent a listener for a model
3
+ * @class Listener
4
+ */
5
+ export class Listener {
6
+ constructor() {
7
+ /**
8
+ * Functions to run on adding new items
9
+ * @type Set
10
+ */
11
+ this.onAdded = new Set();
12
+ /**
13
+ * Functions to run on item removing
14
+ * @type Set
15
+ */
16
+ this.onRemoved = new Set();
17
+ }
18
+ /**
19
+ * Emits added event to listeners
20
+ * @param index {*} index of value
21
+ * @param value {*} value of added item
22
+ */
23
+ emitAdded(index, value) {
24
+ this.onAdded.forEach(handler => {
25
+ handler(index, value);
26
+ });
27
+ }
28
+ /**
29
+ * Emits removed event to listeners
30
+ * @param index {*} index of removed value
31
+ * @param value {*} value of removed item
32
+ */
33
+ emitRemoved(index, value) {
34
+ this.onRemoved.forEach(handler => {
35
+ handler(index, value);
36
+ });
37
+ }
38
+ /**
39
+ * Adds a handler to added event
40
+ * @param handler {function} function to run on event emitting
41
+ */
42
+ onAdd(handler) {
43
+ this.onAdded.add(handler);
44
+ }
45
+ /**
46
+ * Adds a handler to removed event
47
+ * @param handler {function} function to run on event emitting
48
+ */
49
+ onRemove(handler) {
50
+ this.onRemoved.add(handler);
51
+ }
52
+ /**
53
+ * Removes an handler from added event
54
+ * @param handler {function} handler to remove
55
+ */
56
+ offAdd(handler) {
57
+ this.onAdded.delete(handler);
58
+ }
59
+ /**
60
+ * Removes an handler form removed event
61
+ * @param handler {function} handler to remove
62
+ */
63
+ offRemove(handler) {
64
+ this.onRemoved.delete(handler);
65
+ }
66
+ }
@@ -0,0 +1,60 @@
1
+ import { Listener } from "./listener.js";
2
+ /**
3
+ * A Map based memory
4
+ * @class MapModel
5
+ * @extends Map
6
+ * @implements IModel
7
+ */
8
+ export class MapModel extends Map {
9
+ /**
10
+ * Constructs a map model
11
+ * @param map {[*, *][]} input data
12
+ */
13
+ constructor(map) {
14
+ super();
15
+ this.listener = new Listener();
16
+ map?.forEach(([key, value]) => {
17
+ super.set(key, value);
18
+ });
19
+ }
20
+ /**
21
+ * Calls Map.clear and notify about changes
22
+ */
23
+ clear() {
24
+ this.forEach((value, key) => {
25
+ this.listener.emitRemoved(key, value);
26
+ });
27
+ super.clear();
28
+ }
29
+ /**
30
+ * Calls Map.delete and notify abut changes
31
+ * @param key {*} key
32
+ * @return {boolean} true if removed something, otherwise false
33
+ */
34
+ delete(key) {
35
+ const tmp = super.get(key);
36
+ /* istanbul ignore else */
37
+ if (tmp) {
38
+ this.listener.emitRemoved(key, tmp);
39
+ }
40
+ return super.delete(key);
41
+ }
42
+ /**
43
+ * Calls Map.set and notify abut changes
44
+ * @param key {*} key
45
+ * @param value {*} value
46
+ * @return {MapModel} a pointer to this
47
+ */
48
+ set(key, value) {
49
+ const tmp = super.get(key);
50
+ if (tmp) {
51
+ this.listener.emitRemoved(key, tmp);
52
+ }
53
+ super.set(key, value);
54
+ this.listener.emitAdded(key, value);
55
+ return this;
56
+ }
57
+ destroy() {
58
+ this.clear();
59
+ }
60
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,56 @@
1
+ import { Listener } from "./listener.js";
2
+ /**
3
+ * A Set based model
4
+ * @class SetModel
5
+ * @extends Set
6
+ * @implements IModel
7
+ */
8
+ export class SetModel extends Set {
9
+ /**
10
+ * Constructs a set model based on a set
11
+ * @param set {Set} input data
12
+ */
13
+ constructor(set) {
14
+ super();
15
+ this.listener = new Listener();
16
+ set?.forEach(item => {
17
+ super.add(item);
18
+ });
19
+ }
20
+ /**
21
+ * Calls Set.add and notify abut changes
22
+ * @param value {*} value
23
+ * @return {this} a pointer to this
24
+ */
25
+ add(value) {
26
+ /* istanbul ignore else */
27
+ if (!super.has(value)) {
28
+ this.listener.emitAdded(value, value);
29
+ super.add(value);
30
+ }
31
+ return this;
32
+ }
33
+ /**
34
+ * Calls Set.clear and notify abut changes
35
+ */
36
+ clear() {
37
+ this.forEach(item => {
38
+ this.listener.emitRemoved(item, item);
39
+ });
40
+ super.clear();
41
+ }
42
+ /**
43
+ * Calls Set.delete and notify abut changes
44
+ * @param value {*}
45
+ * @return {boolean} true if a value was deleted, otherwise false
46
+ */
47
+ delete(value) {
48
+ if (super.has(value)) {
49
+ this.listener.emitRemoved(value, value);
50
+ }
51
+ return super.delete(value);
52
+ }
53
+ destroy() {
54
+ this.clear();
55
+ }
56
+ }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "The first Developer eXperience Orientated front-end framework (core library).",
4
4
  "main": "lib/index.js",
5
5
  "types": "types/index.d.ts",
6
- "version": "3.2.0",
6
+ "version": "3.2.1",
7
7
  "exports": {
8
8
  ".": {
9
9
  "types": "./types/index.d.ts",
@@ -0,0 +1,55 @@
1
+ import { Listener } from "./listener.js";
2
+ import { ListenableModel } from "./model.js";
3
+ /**
4
+ * Model based on Array class
5
+ * @extends Array
6
+ * @implements IModel
7
+ */
8
+ export declare class ArrayModel<T> extends Array<T> implements ListenableModel<T, T> {
9
+ listener: Listener<T, T>;
10
+ passive: boolean;
11
+ /**
12
+ * @param data {Array} input data
13
+ */
14
+ constructor(data?: Array<T> | number);
15
+ /**
16
+ * Calls Array.fill and notify about changes
17
+ * @param value {*} value to fill with
18
+ * @param start {?number} begin index
19
+ * @param end {?number} end index
20
+ */
21
+ fill(value: T, start?: number, end?: number): this;
22
+ /**
23
+ * Calls Array.pop and notify about changes
24
+ * @return {*} removed value
25
+ */
26
+ pop(): T | undefined;
27
+ /**
28
+ * Calls Array.push and notify about changes
29
+ * @param items {...*} values to push
30
+ * @return {number} new length of array
31
+ */
32
+ push(...items: Array<T>): number;
33
+ /**
34
+ * Calls Array.shift and notify about changed
35
+ * @return {*} the shifted value
36
+ */
37
+ shift(): T | undefined;
38
+ /**
39
+ * Calls Array.splice and notify about changed
40
+ * @param start {number} start index
41
+ * @param deleteCount {?number} delete count
42
+ * @param items {...*}
43
+ * @return {ArrayModel} a pointer to this
44
+ */
45
+ splice(start: number, deleteCount?: number, ...items: Array<T>): ArrayModel<T>;
46
+ /**
47
+ * Calls Array.unshift and notify about changed
48
+ * @param items {...*} values to insert
49
+ * @return {number} the length after prepend
50
+ */
51
+ unshift(...items: Array<T>): number;
52
+ replace(at: number, with_: T): this;
53
+ destroy(): void;
54
+ }
55
+ export declare function proxyArrayModel<T>(arr: ArrayModel<T>): ArrayModel<T>;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Represent a listener for a model
3
+ * @class Listener
4
+ */
5
+ export declare class Listener<ValueT, IndexT = string | number> {
6
+ /**
7
+ * Functions to run on adding new items
8
+ * @type Set
9
+ */
10
+ private readonly onAdded;
11
+ /**
12
+ * Functions to run on item removing
13
+ * @type Set
14
+ */
15
+ private readonly onRemoved;
16
+ /**
17
+ * Emits added event to listeners
18
+ * @param index {*} index of value
19
+ * @param value {*} value of added item
20
+ */
21
+ emitAdded(index: IndexT, value: ValueT): void;
22
+ /**
23
+ * Emits removed event to listeners
24
+ * @param index {*} index of removed value
25
+ * @param value {*} value of removed item
26
+ */
27
+ emitRemoved(index: IndexT, value: ValueT): void;
28
+ /**
29
+ * Adds a handler to added event
30
+ * @param handler {function} function to run on event emitting
31
+ */
32
+ onAdd(handler: (index: IndexT, value: ValueT) => void): void;
33
+ /**
34
+ * Adds a handler to removed event
35
+ * @param handler {function} function to run on event emitting
36
+ */
37
+ onRemove(handler: (index: IndexT, value: ValueT) => void): void;
38
+ /**
39
+ * Removes an handler from added event
40
+ * @param handler {function} handler to remove
41
+ */
42
+ offAdd(handler: (index: IndexT, value: ValueT) => void): void;
43
+ /**
44
+ * Removes an handler form removed event
45
+ * @param handler {function} handler to remove
46
+ */
47
+ offRemove(handler: (index: IndexT, value: ValueT) => void): void;
48
+ }
@@ -0,0 +1,34 @@
1
+ import { Listener } from "./listener.js";
2
+ import { ListenableModel } from "./model.js";
3
+ /**
4
+ * A Map based memory
5
+ * @class MapModel
6
+ * @extends Map
7
+ * @implements IModel
8
+ */
9
+ export declare class MapModel<K, T> extends Map<K, T> implements ListenableModel<K, T> {
10
+ listener: Listener<T, K>;
11
+ /**
12
+ * Constructs a map model
13
+ * @param map {[*, *][]} input data
14
+ */
15
+ constructor(map?: [K, T][]);
16
+ /**
17
+ * Calls Map.clear and notify about changes
18
+ */
19
+ clear(): void;
20
+ /**
21
+ * Calls Map.delete and notify abut changes
22
+ * @param key {*} key
23
+ * @return {boolean} true if removed something, otherwise false
24
+ */
25
+ delete(key: K): boolean;
26
+ /**
27
+ * Calls Map.set and notify abut changes
28
+ * @param key {*} key
29
+ * @param value {*} value
30
+ * @return {MapModel} a pointer to this
31
+ */
32
+ set(key: K, value: T): this;
33
+ destroy(): void;
34
+ }
@@ -0,0 +1,14 @@
1
+ import { IDestroyable } from "../core/destroyable.js";
2
+ import { Listener } from "./listener.js";
3
+ /**
4
+ * @interface IModel
5
+ */
6
+ export interface IModel extends IDestroyable {
7
+ }
8
+ export interface ListenableModel<K, T> extends IModel {
9
+ /**
10
+ * The listener of model
11
+ * @type Listener
12
+ */
13
+ listener: Listener<T, K>;
14
+ }
@@ -0,0 +1,33 @@
1
+ import { Listener } from "./listener.js";
2
+ import { ListenableModel } from "./model.js";
3
+ /**
4
+ * A Set based model
5
+ * @class SetModel
6
+ * @extends Set
7
+ * @implements IModel
8
+ */
9
+ export declare class SetModel<T> extends Set<T> implements ListenableModel<T, T> {
10
+ listener: Listener<T, T>;
11
+ /**
12
+ * Constructs a set model based on a set
13
+ * @param set {Set} input data
14
+ */
15
+ constructor(set?: T[]);
16
+ /**
17
+ * Calls Set.add and notify abut changes
18
+ * @param value {*} value
19
+ * @return {this} a pointer to this
20
+ */
21
+ add(value: T): this;
22
+ /**
23
+ * Calls Set.clear and notify abut changes
24
+ */
25
+ clear(): void;
26
+ /**
27
+ * Calls Set.delete and notify abut changes
28
+ * @param value {*}
29
+ * @return {boolean} true if a value was deleted, otherwise false
30
+ */
31
+ delete(value: T): boolean;
32
+ destroy(): void;
33
+ }