vasille 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
  * [Installation](#installation)
12
12
  * [How to use Vasille](#how-to-use-vasille)
13
13
  * [How SAFE is Vasille](#how-safe-is-vasille)
14
- * [How SIMPLE is Vasille](#how-simple-is-vasille)
14
+ * [How INTUITIVE is Vasille](#how-intuitive-is-vasille)
15
15
  * [How POWERFUL is Vasille](#how-powerful-is-vasille)
16
16
  * [Road Map](#road-map)
17
17
 
@@ -44,6 +44,7 @@ $ npx degit vasille-js/example-javascript my-project
44
44
 
45
45
  ### Full documentation:
46
46
  * [Learn `Vasille` in 5 minutes](https://github.com/vasille-js/vasille-js/blob/v3/doc/V3-API.md)
47
+ * [Vasille Router Documentation](https://github.com/vasille-js/vasille-js/blob/v3/doc/Router-API.md)
47
48
 
48
49
  ### Examples
49
50
  * [TypeScript Example](https://github.com/vasille-js/example-typescript)
@@ -60,7 +61,7 @@ The safe of your application is ensured by
60
61
  * `strong typing` makes your javascript/typescript code safe as C++ code.
61
62
  All entities of `vasille` core library are strongly typed, including:
62
63
  * data fields & properties.
63
- * computed properties (function parameters & result).
64
+ * computed properties (function parameters and result).
64
65
  * methods.
65
66
  * events (defined handlers & event emit).
66
67
  * DOM events & DOM operation (attributing, styling, etc.).
@@ -68,7 +69,7 @@ All entities of `vasille` core library are strongly typed, including:
68
69
  * references to children.
69
70
  * No asynchronous code, when the line of code is executed, the DOM and reactive things are already synced.
70
71
 
71
- ## How SIMPLE is Vasille
72
+ ## How INTUITIVE is Vasille
72
73
 
73
74
  There is the "Hello World":
74
75
  ```typescript jsx
@@ -105,7 +106,7 @@ All of these are supported:
105
106
  * [x] Develop the `Vasille Babel Plugin`.
106
107
  * [x] `100%` Test Coverage fot babel plugin.
107
108
  * [x] Add CSS support (define styles in components).
108
- * [ ] Add router.
109
+ * [x] Add router.
109
110
  * [ ] Add SSR (server side rendering).
110
111
  * [ ] Develop tools extension for debugging.
111
112
 
package/lib/core/core.js CHANGED
@@ -10,11 +10,6 @@ import { OwningPointer, Pointer } from "../value/pointer.js";
10
10
  export class Reactive extends Destroyable {
11
11
  constructor(input) {
12
12
  super();
13
- /**
14
- * A list of user-defined values
15
- * @type {Set}
16
- */
17
- this._watch = new Set();
18
13
  /**
19
14
  * A list of user-defined bindings
20
15
  * @type {Set}
@@ -30,7 +25,7 @@ export class Reactive extends Destroyable {
30
25
  */
31
26
  ref(value, name) {
32
27
  const ref = new Reference(value);
33
- this._watch.add(ref);
28
+ this.bindings.add(ref);
34
29
  if (name) {
35
30
  this.addState("ref", name, ref);
36
31
  }
@@ -43,7 +38,7 @@ export class Reactive extends Destroyable {
43
38
  */
44
39
  forward(value, name) {
45
40
  const mirror = new Pointer(value);
46
- this._watch.add(mirror);
41
+ this.bindings.add(mirror);
47
42
  if (name) {
48
43
  this.addState("forward", name, mirror);
49
44
  }
@@ -56,7 +51,8 @@ export class Reactive extends Destroyable {
56
51
  */
57
52
  own(value, name) {
58
53
  const pointer = new OwningPointer(value);
59
- this._watch.add(pointer);
54
+ this.bindings.add(pointer);
55
+ /* istanbul ignore else */
60
56
  if (name) {
61
57
  this.addState("own", name, pointer);
62
58
  }
@@ -81,7 +77,7 @@ export class Reactive extends Destroyable {
81
77
  * @param values
82
78
  */
83
79
  watch(func, values) {
84
- this._watch.add(new Expression(func, values));
80
+ this.bindings.add(new Expression(func, values));
85
81
  }
86
82
  /**
87
83
  * Creates a computed value
@@ -92,7 +88,7 @@ export class Reactive extends Destroyable {
92
88
  */
93
89
  expr(func, values, name) {
94
90
  const res = new Expression(func, values);
95
- this._watch.add(res);
91
+ this.bindings.add(res);
96
92
  if (name) {
97
93
  this.addState("expr", name, res);
98
94
  }
@@ -110,8 +106,6 @@ export class Reactive extends Destroyable {
110
106
  }
111
107
  destroy() {
112
108
  super.destroy();
113
- this._watch.forEach(value => value.destroy());
114
- this._watch.clear();
115
109
  this.bindings.forEach(binding => binding.destroy());
116
110
  this.bindings.clear();
117
111
  this.onDestroy?.();
package/lib/node/node.js CHANGED
@@ -33,6 +33,7 @@ export class Root extends Reactive {
33
33
  let first;
34
34
  for (const child of this.children) {
35
35
  first = child.findFirstChild();
36
+ /* istanbul ignore else */
36
37
  if (first) {
37
38
  break;
38
39
  }
@@ -322,6 +323,7 @@ export class DebugNode extends Fragment {
322
323
  super(input, runner, ":debug");
323
324
  }
324
325
  destroy() {
326
+ /* istanbul ignore else */
325
327
  if (this.handler) {
326
328
  this.input.text.off(this.handler);
327
329
  }
@@ -27,10 +27,12 @@ export class DynamicalClassBinding extends Binding {
27
27
  super(value);
28
28
  this.current = "";
29
29
  this.init((value) => {
30
+ /* istanbul ignore else */
30
31
  if (this.current != value) {
31
32
  if (this.current.length) {
32
33
  removeClass(node, this.current);
33
34
  }
35
+ /* istanbul ignore else */
34
36
  if (value.length) {
35
37
  addClass(node, value);
36
38
  }
@@ -23,6 +23,7 @@ export class StyleBinding extends Binding {
23
23
  constructor(node, name, value) {
24
24
  super(value);
25
25
  this.init(value => {
26
+ /* istanbul ignore else */
26
27
  if (node.element instanceof HTMLElement) {
27
28
  node.element.style.setProperty(name, stringifyStyleValue(value));
28
29
  }
@@ -65,7 +65,9 @@ export class Tag extends AbstractTag {
65
65
  this.register(new AttributeBinding(this, name, value));
66
66
  }
67
67
  else {
68
+ /* istanbul ignore else */
68
69
  if (typeof value === "boolean") {
70
+ /* istanbul ignore else */
69
71
  if (value) {
70
72
  this.node.setAttribute(name, "");
71
73
  }
@@ -140,6 +142,7 @@ export class Runner {
140
142
  }
141
143
  insertBefore(node, before) {
142
144
  const parent = before.parentElement;
145
+ /* istanbul ignore else */
143
146
  if (parent) {
144
147
  parent.insertBefore(node, before);
145
148
  }
@@ -19,6 +19,7 @@ export class Expression extends IValue {
19
19
  */
20
20
  this.linkedFunc = [];
21
21
  const handler = (i) => {
22
+ /* istanbul ignore else */
22
23
  if (typeof i === "number") {
23
24
  this.valuesCache[i] = this.values[i].$;
24
25
  }
@@ -31,6 +31,7 @@ export class Pointer extends IValue {
31
31
  return this.reference.$;
32
32
  }
33
33
  set $$(v) {
34
+ /* istanbul ignore else */
34
35
  if (this.target !== v) {
35
36
  this.disconnectTarget();
36
37
  }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "vasille",
3
- "description": "The first Developer eXperience orientated front-end framework (core library).",
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.1.0",
6
+ "version": "3.2.0",
7
7
  "exports": {
8
8
  ".": {
9
9
  "types": "./types/index.d.ts",
@@ -8,11 +8,6 @@ import { Pointer } from "../value/pointer.js";
8
8
  * @extends Destroyable
9
9
  */
10
10
  export declare class Reactive<T extends object = object> extends Destroyable {
11
- /**
12
- * A list of user-defined values
13
- * @type {Set}
14
- */
15
- private _watch;
16
11
  /**
17
12
  * A list of user-defined bindings
18
13
  * @type {Set}
@@ -1,147 +0,0 @@
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
- if (!start) {
31
- start = 0;
32
- }
33
- if (!end) {
34
- end = this.length;
35
- }
36
- for (let i = start; i < end; i++) {
37
- this.listener.emitRemoved(this[i], this[i]);
38
- this[i] = value;
39
- this.listener.emitAdded(value, value);
40
- }
41
- this.passive = false;
42
- return this;
43
- }
44
- /**
45
- * Calls Array.pop and notify about changes
46
- * @return {*} removed value
47
- */
48
- pop() {
49
- this.passive = true;
50
- const v = super.pop();
51
- if (v !== undefined) {
52
- this.listener.emitRemoved(v, v);
53
- }
54
- this.passive = false;
55
- return v;
56
- }
57
- /**
58
- * Calls Array.push and notify about changes
59
- * @param items {...*} values to push
60
- * @return {number} new length of array
61
- */
62
- push(...items) {
63
- this.passive = true;
64
- items.forEach(item => {
65
- this.listener.emitAdded(item, item);
66
- super.push(item);
67
- });
68
- this.passive = false;
69
- return this.length;
70
- }
71
- /**
72
- * Calls Array.shift and notify about changed
73
- * @return {*} the shifted value
74
- */
75
- shift() {
76
- this.passive = true;
77
- const v = super.shift();
78
- if (v !== undefined) {
79
- this.listener.emitRemoved(v, v);
80
- }
81
- this.passive = false;
82
- return v;
83
- }
84
- /**
85
- * Calls Array.splice and notify about changed
86
- * @param start {number} start index
87
- * @param deleteCount {?number} delete count
88
- * @param items {...*}
89
- * @return {ArrayModel} a pointer to this
90
- */
91
- splice(start, deleteCount, ...items) {
92
- this.passive = true;
93
- start = Math.min(start, this.length);
94
- deleteCount = typeof deleteCount === "number" ? deleteCount : this.length - start;
95
- const before = this[start + deleteCount];
96
- for (let i = 0; i < deleteCount; i++) {
97
- const index = start + deleteCount - i - 1;
98
- if (this[index] !== undefined) {
99
- this.listener.emitRemoved(this[index], this[index]);
100
- }
101
- }
102
- for (let i = 0; i < items.length; i++) {
103
- this.listener.emitAdded(before, items[i]);
104
- }
105
- this.passive = false;
106
- return new ArrayModel(super.splice(start, deleteCount, ...items));
107
- }
108
- /**
109
- * Calls Array.unshift and notify about changed
110
- * @param items {...*} values to insert
111
- * @return {number} the length after prepend
112
- */
113
- unshift(...items) {
114
- this.passive = true;
115
- for (let i = 0; i < items.length; i++) {
116
- this.listener.emitAdded(this[i], items[i]);
117
- }
118
- const r = super.unshift(...items);
119
- this.passive = false;
120
- return r;
121
- }
122
- replace(at, with_) {
123
- this.passive = true;
124
- this.listener.emitAdded(this[at], with_);
125
- this.listener.emitRemoved(this[at], this[at]);
126
- this[at] = with_;
127
- this.passive = false;
128
- return this;
129
- }
130
- destroy() {
131
- this.splice(0);
132
- }
133
- }
134
- export function proxyArrayModel(arr) {
135
- return new Proxy(arr, {
136
- set(target, p, newValue, receiver) {
137
- if (!arr.passive && typeof p === "string") {
138
- const index = parseInt(p);
139
- if (Number.isFinite(index)) {
140
- arr.replace(index, newValue);
141
- return true;
142
- }
143
- }
144
- return Reflect.set(target, p, newValue, receiver);
145
- },
146
- });
147
- }
@@ -1,66 +0,0 @@
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
- }
@@ -1,59 +0,0 @@
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
- if (tmp) {
37
- this.listener.emitRemoved(key, tmp);
38
- }
39
- return super.delete(key);
40
- }
41
- /**
42
- * Calls Map.set and notify abut changes
43
- * @param key {*} key
44
- * @param value {*} value
45
- * @return {MapModel} a pointer to this
46
- */
47
- set(key, value) {
48
- const tmp = super.get(key);
49
- if (tmp) {
50
- this.listener.emitRemoved(key, tmp);
51
- }
52
- super.set(key, value);
53
- this.listener.emitAdded(key, value);
54
- return this;
55
- }
56
- destroy() {
57
- this.clear();
58
- }
59
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,55 +0,0 @@
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
- if (!super.has(value)) {
27
- this.listener.emitAdded(value, value);
28
- super.add(value);
29
- }
30
- return this;
31
- }
32
- /**
33
- * Calls Set.clear and notify abut changes
34
- */
35
- clear() {
36
- this.forEach(item => {
37
- this.listener.emitRemoved(item, item);
38
- });
39
- super.clear();
40
- }
41
- /**
42
- * Calls Set.delete and notify abut changes
43
- * @param value {*}
44
- * @return {boolean} true if a value was deleted, otherwise false
45
- */
46
- delete(value) {
47
- if (super.has(value)) {
48
- this.listener.emitRemoved(value, value);
49
- }
50
- return super.delete(value);
51
- }
52
- destroy() {
53
- this.clear();
54
- }
55
- }
@@ -1,55 +0,0 @@
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>;
@@ -1,48 +0,0 @@
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
- }
@@ -1,34 +0,0 @@
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
- }
@@ -1,14 +0,0 @@
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
- }
@@ -1,33 +0,0 @@
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
- }