wallace 0.13.0 → 0.14.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.
- package/lib/component.js +4 -3
- package/lib/detacher.js +8 -9
- package/lib/index.js +1 -0
- package/lib/offsetter.js +2 -2
- package/lib/repeaters/keyed.js +34 -29
- package/lib/repeaters/sequential.js +19 -17
- package/lib/toDateString.js +1 -0
- package/lib/types.d.ts +25 -27
- package/lib/watch.js +8 -4
- package/package.json +3 -3
package/lib/component.js
CHANGED
|
@@ -35,7 +35,8 @@ const ComponentPrototype = {
|
|
|
35
35
|
const watches = this._w,
|
|
36
36
|
props = this.props,
|
|
37
37
|
previous = this._p,
|
|
38
|
-
elements = this._e
|
|
38
|
+
elements = this._e,
|
|
39
|
+
stash = this._s;
|
|
39
40
|
/*
|
|
40
41
|
Watches is an array of objects with keys:
|
|
41
42
|
e: the element index (number)
|
|
@@ -61,7 +62,7 @@ const ComponentPrototype = {
|
|
|
61
62
|
shouldBeVisible = displayToggle.r ? lookupTrue : !lookupTrue;
|
|
62
63
|
detacher = displayToggle.d;
|
|
63
64
|
if (detacher) {
|
|
64
|
-
detacher.apply(element, shouldBeVisible, elements,
|
|
65
|
+
detacher.apply(element, shouldBeVisible, elements, stash);
|
|
65
66
|
} else {
|
|
66
67
|
element.hidden = !shouldBeVisible;
|
|
67
68
|
}
|
|
@@ -74,7 +75,7 @@ const ComponentPrototype = {
|
|
|
74
75
|
callbacks = watch.c;
|
|
75
76
|
for (let key in callbacks) {
|
|
76
77
|
if (key === NO_LOOKUP) {
|
|
77
|
-
callbacks[key](element, props, this);
|
|
78
|
+
callbacks[key](element, props, this, stash);
|
|
78
79
|
} else {
|
|
79
80
|
const oldValue = prev[key],
|
|
80
81
|
newValue = this._q[key](props, this);
|
package/lib/detacher.js
CHANGED
|
@@ -9,18 +9,17 @@ export function Detacher(i, e, s) {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
Detacher.prototype.apply = function (element, shouldBeVisible, elements, stash) {
|
|
12
|
-
let adjustedIndex;
|
|
13
12
|
const index = this.i,
|
|
14
13
|
parent = elements[this.e],
|
|
15
|
-
|
|
16
|
-
let
|
|
17
|
-
if (shouldBeVisible &&
|
|
18
|
-
adjustedIndex = countOffset(
|
|
14
|
+
offsetTracker = stash[this.s];
|
|
15
|
+
let ownOffset = offsetTracker.get(index) || 0;
|
|
16
|
+
if (shouldBeVisible && ownOffset === -1) {
|
|
17
|
+
const adjustedIndex = countOffset(offsetTracker, index);
|
|
19
18
|
parent.insertBefore(element, parent.childNodes[adjustedIndex]);
|
|
20
|
-
|
|
21
|
-
} else if (!shouldBeVisible &&
|
|
19
|
+
ownOffset = 0;
|
|
20
|
+
} else if (!shouldBeVisible && ownOffset === 0) {
|
|
22
21
|
parent.removeChild(element);
|
|
23
|
-
|
|
22
|
+
ownOffset = -1;
|
|
24
23
|
}
|
|
25
|
-
|
|
24
|
+
offsetTracker.set(index, ownOffset);
|
|
26
25
|
};
|
package/lib/index.js
CHANGED
|
@@ -10,5 +10,6 @@ export { KeyedRepeater } from "./repeaters/keyed";
|
|
|
10
10
|
export { SequentialRepeater } from "./repeaters/sequential";
|
|
11
11
|
export { Router, route } from "./router";
|
|
12
12
|
export { getStub } from "./stubs";
|
|
13
|
+
export { toDateString } from "./toDateString";
|
|
13
14
|
export { findElement, onEvent } from "./utils";
|
|
14
15
|
export { watch, protect } from "./watch";
|
package/lib/offsetter.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export function countOffset(
|
|
1
|
+
export function countOffset(offsetTracker, index) {
|
|
2
2
|
let offset = 0;
|
|
3
|
-
for (let [key, value] of
|
|
3
|
+
for (let [key, value] of offsetTracker.entries()) {
|
|
4
4
|
if (key >= index) break;
|
|
5
5
|
offset += value;
|
|
6
6
|
}
|
package/lib/repeaters/keyed.js
CHANGED
|
@@ -7,17 +7,16 @@ import { countOffset } from "../offsetter";
|
|
|
7
7
|
* if allowRepeaterSiblings is false the last two parameters are removed.
|
|
8
8
|
*/
|
|
9
9
|
export function KeyedRepeater(componentDefinition, key, adjustmentTracker, initialIndex) {
|
|
10
|
-
this.
|
|
11
|
-
|
|
12
|
-
this.at = adjustmentTracker;
|
|
13
|
-
this.ii = initialIndex;
|
|
14
|
-
}
|
|
15
|
-
this.keys = []; // array of keys as last set.
|
|
16
|
-
this.pool = {}; // pool of component instances.
|
|
10
|
+
this.d = componentDefinition;
|
|
11
|
+
this.k = []; // array of keys as last set.
|
|
17
12
|
if (typeof key === "function") {
|
|
18
|
-
this.
|
|
13
|
+
this.f = key;
|
|
19
14
|
} else {
|
|
20
|
-
this.
|
|
15
|
+
this.n = key;
|
|
16
|
+
}
|
|
17
|
+
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
18
|
+
this.a = adjustmentTracker;
|
|
19
|
+
this.i = initialIndex;
|
|
21
20
|
}
|
|
22
21
|
}
|
|
23
22
|
|
|
@@ -25,29 +24,30 @@ export function KeyedRepeater(componentDefinition, key, adjustmentTracker, initi
|
|
|
25
24
|
* Updates the element's childNodes to match the items.
|
|
26
25
|
* Performance is important.
|
|
27
26
|
*
|
|
28
|
-
* @param {DOMElement}
|
|
27
|
+
* @param {DOMElement} parent - The DOM element to patch.
|
|
29
28
|
* @param {Array} items - Array of items which will be passed as props.
|
|
29
|
+
* @param {Map} pool - pool of component instances.
|
|
30
30
|
* @param {any} ctrl - The parent item's controller.
|
|
31
31
|
*/
|
|
32
|
-
KeyedRepeater.prototype.patch = function (
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
childNodes =
|
|
32
|
+
KeyedRepeater.prototype.patch = function (parent, items, pool, ctrl) {
|
|
33
|
+
const componentDefinition = this.d,
|
|
34
|
+
keyName = this.n,
|
|
35
|
+
keyFn = this.f,
|
|
36
|
+
useKeyName = keyName !== undefined,
|
|
37
|
+
childNodes = parent.childNodes,
|
|
38
38
|
itemsLength = items.length,
|
|
39
|
-
previousKeys = this.
|
|
39
|
+
previousKeys = this.k,
|
|
40
40
|
previousKeysLength = previousKeys.length,
|
|
41
41
|
newKeys = [],
|
|
42
42
|
previousKeysSet = new Set(previousKeys),
|
|
43
|
-
adjustmentTracker = this.at,
|
|
44
|
-
initialIndex = this.ii,
|
|
45
43
|
frag = document.createDocumentFragment();
|
|
46
44
|
|
|
47
45
|
let item,
|
|
48
46
|
el,
|
|
49
47
|
itemKey,
|
|
50
48
|
component,
|
|
49
|
+
initialIndex,
|
|
50
|
+
offsetTracker,
|
|
51
51
|
endAnchor = null,
|
|
52
52
|
adjustment = 0,
|
|
53
53
|
anchor = null,
|
|
@@ -58,8 +58,10 @@ KeyedRepeater.prototype.patch = function (e, items, ctrl) {
|
|
|
58
58
|
i = itemsLength - 1;
|
|
59
59
|
|
|
60
60
|
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
offsetTracker = this.a;
|
|
62
|
+
initialIndex = this.i;
|
|
63
|
+
if (offsetTracker) {
|
|
64
|
+
adjustment = countOffset(offsetTracker, initialIndex);
|
|
63
65
|
endAnchor = childNodes[previousKeysLength + adjustment] || null;
|
|
64
66
|
anchor = endAnchor;
|
|
65
67
|
untouched = false;
|
|
@@ -69,8 +71,11 @@ KeyedRepeater.prototype.patch = function (e, items, ctrl) {
|
|
|
69
71
|
// Working backwards saves us having to track moves.
|
|
70
72
|
while (i >= 0) {
|
|
71
73
|
item = items[i];
|
|
72
|
-
itemKey =
|
|
73
|
-
component = pool
|
|
74
|
+
itemKey = useKeyName ? item[keyName] : keyFn(item);
|
|
75
|
+
if (!(component = pool.get(itemKey))) {
|
|
76
|
+
component = new componentDefinition();
|
|
77
|
+
pool.set(itemKey, component);
|
|
78
|
+
}
|
|
74
79
|
component.render(item, ctrl);
|
|
75
80
|
el = component.el;
|
|
76
81
|
if (untouched && !previousKeysSet.has(itemKey)) {
|
|
@@ -80,7 +85,7 @@ KeyedRepeater.prototype.patch = function (e, items, ctrl) {
|
|
|
80
85
|
offset++;
|
|
81
86
|
} else {
|
|
82
87
|
if (itemKey !== previousKeys[i + offset]) {
|
|
83
|
-
|
|
88
|
+
parent.insertBefore(el, anchor);
|
|
84
89
|
untouched = false;
|
|
85
90
|
}
|
|
86
91
|
anchor = el;
|
|
@@ -91,20 +96,20 @@ KeyedRepeater.prototype.patch = function (e, items, ctrl) {
|
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
if (append) {
|
|
94
|
-
|
|
99
|
+
parent.insertBefore(frag, endAnchor);
|
|
95
100
|
}
|
|
96
101
|
|
|
97
102
|
let toStrip = previousKeysSet.size;
|
|
98
103
|
while (toStrip > 0) {
|
|
99
|
-
|
|
104
|
+
parent.removeChild(childNodes[adjustment]);
|
|
100
105
|
toStrip--;
|
|
101
106
|
}
|
|
102
107
|
|
|
103
|
-
this.
|
|
108
|
+
this.k = newKeys.reverse();
|
|
104
109
|
|
|
105
110
|
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
106
|
-
if (
|
|
107
|
-
|
|
111
|
+
if (offsetTracker) {
|
|
112
|
+
offsetTracker.set(initialIndex, itemsLength - 1);
|
|
108
113
|
}
|
|
109
114
|
}
|
|
110
115
|
};
|
|
@@ -7,13 +7,12 @@ import { countOffset } from "../offsetter";
|
|
|
7
7
|
* if allowRepeaterSiblings is false the last two parameters are removed.
|
|
8
8
|
*/
|
|
9
9
|
export function SequentialRepeater(componentDefinition, adjustmentTracker, initialIndex) {
|
|
10
|
-
this.
|
|
10
|
+
this.d = componentDefinition;
|
|
11
|
+
this.c = 0; // Child count
|
|
11
12
|
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
12
|
-
this.
|
|
13
|
-
this.
|
|
13
|
+
this.a = adjustmentTracker;
|
|
14
|
+
this.i = initialIndex;
|
|
14
15
|
}
|
|
15
|
-
this.pool = []; // pool of component instances
|
|
16
|
-
this.cc = 0; // Child count
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
/**
|
|
@@ -22,27 +21,30 @@ export function SequentialRepeater(componentDefinition, adjustmentTracker, initi
|
|
|
22
21
|
*
|
|
23
22
|
* @param {DOMElement} parent - The DOM element to patch.
|
|
24
23
|
* @param {Array} items - Array of items which will be passed as props.
|
|
24
|
+
* @param {Array} pool - pool of component instances.
|
|
25
25
|
* @param {any} ctrl - The parent item's controller.
|
|
26
26
|
*/
|
|
27
|
-
SequentialRepeater.prototype.patch = function (parent, items, ctrl) {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
childNodes = parent.childNodes,
|
|
27
|
+
SequentialRepeater.prototype.patch = function (parent, items, pool, ctrl) {
|
|
28
|
+
const componentDefinition = this.d,
|
|
29
|
+
previousChildCount = this.c,
|
|
31
30
|
itemsLength = items.length,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
adjustmentTracker = this.at;
|
|
31
|
+
childNodes = parent.childNodes;
|
|
32
|
+
|
|
35
33
|
let i = 0,
|
|
36
34
|
offset = 0,
|
|
37
35
|
component,
|
|
38
36
|
nextElement,
|
|
37
|
+
initialIndex,
|
|
38
|
+
offsetTracker,
|
|
39
39
|
endOfRange = previousChildCount,
|
|
40
40
|
poolCount = pool.length;
|
|
41
41
|
|
|
42
42
|
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
43
|
-
|
|
43
|
+
initialIndex = this.i;
|
|
44
|
+
offsetTracker = this.a;
|
|
45
|
+
if (offsetTracker) {
|
|
44
46
|
// The repeat element has siblings
|
|
45
|
-
offset = countOffset(
|
|
47
|
+
offset = countOffset(offsetTracker, initialIndex);
|
|
46
48
|
endOfRange += offset;
|
|
47
49
|
nextElement = childNodes[endOfRange] || null;
|
|
48
50
|
}
|
|
@@ -61,7 +63,7 @@ SequentialRepeater.prototype.patch = function (parent, items, ctrl) {
|
|
|
61
63
|
}
|
|
62
64
|
i++;
|
|
63
65
|
}
|
|
64
|
-
this.
|
|
66
|
+
this.c = itemsLength;
|
|
65
67
|
|
|
66
68
|
let removeAtIndex = offset + previousChildCount - 1;
|
|
67
69
|
const stopatIndex = offset + itemsLength - 1;
|
|
@@ -69,8 +71,8 @@ SequentialRepeater.prototype.patch = function (parent, items, ctrl) {
|
|
|
69
71
|
parent.removeChild(childNodes[i]);
|
|
70
72
|
}
|
|
71
73
|
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
+
if (offsetTracker) {
|
|
75
|
+
offsetTracker.set(initialIndex, itemsLength - 1);
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const toDateString = date => date.toISOString().slice(0, 10);
|
package/lib/types.d.ts
CHANGED
|
@@ -529,7 +529,8 @@ performance and bundle size:
|
|
|
529
529
|
2. allowCtrl - enables use of `ctrl` in components.
|
|
530
530
|
3. allowMethods - adds the `methods` helper to components.
|
|
531
531
|
4. allowParts - enables use of parts.
|
|
532
|
-
5.
|
|
532
|
+
5. allowRepeaterSiblings - allows repeaters to have siblings.
|
|
533
|
+
6. allowStubs - enables the use of stubs.
|
|
533
534
|
|
|
534
535
|
These flags default to true, unless you specify `flags` in the plugin config, in which
|
|
535
536
|
case they default to false and you need to explicitly enable those you want:
|
|
@@ -840,46 +841,29 @@ interface DirectiveAttributes extends AllDomEvents {
|
|
|
840
841
|
/**
|
|
841
842
|
* ## Wallace directive: bind
|
|
842
843
|
*
|
|
843
|
-
* Sets up two
|
|
844
|
-
*
|
|
845
|
-
* 1. It uses the expression as the element's value.
|
|
846
|
-
* 2. It assigns the value back to the expression when the element's `change` event
|
|
847
|
-
* fires.
|
|
848
|
-
*
|
|
849
|
-
* So this:
|
|
844
|
+
* Sets up two way binding between an input and data:
|
|
850
845
|
*
|
|
851
846
|
* ```
|
|
852
|
-
*
|
|
853
|
-
* <input type="text" bind={name}/>
|
|
854
|
-
* );
|
|
847
|
+
* <input type="text" bind={name} />
|
|
855
848
|
* ```
|
|
856
849
|
*
|
|
857
850
|
* Is the equivalent of this:
|
|
858
851
|
*
|
|
859
|
-
*```
|
|
860
|
-
* const MyComponent = ({name}, {event}) => (
|
|
861
|
-
* <input type="text" onChange={name = event.target.value} value={name}/>
|
|
862
|
-
* );
|
|
863
852
|
* ```
|
|
864
|
-
*
|
|
865
|
-
*
|
|
853
|
+
* <input type="text" value={name} onChange={name = event.target.value} />
|
|
854
|
+
* ```
|
|
855
|
+
* By default it watches the `change` event, but you can specify a different one using
|
|
856
|
+
* the `event` directive:
|
|
866
857
|
*
|
|
867
858
|
* ```
|
|
868
|
-
*
|
|
869
|
-
* <input type="checkbox" onChange={done = event.target.checked} checked={done}/>
|
|
870
|
-
* );
|
|
859
|
+
* <input type="text" bind={name} event:keyup />
|
|
871
860
|
* ```
|
|
872
861
|
*
|
|
873
|
-
* By
|
|
862
|
+
* By default it binds to `value` but you can set a different property:
|
|
874
863
|
*
|
|
875
864
|
*```
|
|
876
|
-
*
|
|
877
|
-
* <input type="text" bind:KeyUp={name} />
|
|
878
|
-
* );
|
|
865
|
+
* <input type="number" bind:valueAsNumber={name} />
|
|
879
866
|
* ```
|
|
880
|
-
*
|
|
881
|
-
* Note that destructured props are converted to member expressions, so these examples
|
|
882
|
-
* work even though it looks like you're setting a local variable.
|
|
883
867
|
*/
|
|
884
868
|
bind?: MustBeExpression;
|
|
885
869
|
|
|
@@ -922,6 +906,19 @@ interface DirectiveAttributes extends AllDomEvents {
|
|
|
922
906
|
*/
|
|
923
907
|
ctrl?: any;
|
|
924
908
|
|
|
909
|
+
/**
|
|
910
|
+
* ## Wallace directive: event
|
|
911
|
+
*
|
|
912
|
+
*
|
|
913
|
+
* Must be used with the `bind` directive, and causes it do watch a different event
|
|
914
|
+
* (the default is `change`)
|
|
915
|
+
*
|
|
916
|
+
* ```
|
|
917
|
+
* <input type="text" bind={name} event:keyup />
|
|
918
|
+
* ```
|
|
919
|
+
*/
|
|
920
|
+
event?: string;
|
|
921
|
+
|
|
925
922
|
/**
|
|
926
923
|
* ## Wallace directive: fixed
|
|
927
924
|
*
|
|
@@ -1085,6 +1082,7 @@ declare namespace JSX {
|
|
|
1085
1082
|
* - `class:xyz` defines a set of classes to be toggled.
|
|
1086
1083
|
* - `css` shorthand for `fixed:class`.
|
|
1087
1084
|
* - `ctrl` specifies ctrl for nested/repeated components.
|
|
1085
|
+
* - `event` changes the event which `bind` reacts to.
|
|
1088
1086
|
* - `fixed:xyz` sets a attribute from an expression at definition.
|
|
1089
1087
|
* - `hide` sets an element or component's hidden property.
|
|
1090
1088
|
* - `html` Set the element's `innnerHTML` property.
|
package/lib/watch.js
CHANGED
|
@@ -9,12 +9,13 @@ export function watch(target, callback) {
|
|
|
9
9
|
const handler = {
|
|
10
10
|
get(target, key) {
|
|
11
11
|
if (key == "isProxy") return true;
|
|
12
|
-
const prop = target[key]
|
|
13
|
-
|
|
14
|
-
if (
|
|
12
|
+
const prop = target[key],
|
|
13
|
+
propType = typeof prop;
|
|
14
|
+
if (propType == "undefined") return;
|
|
15
|
+
if (propType === "object") return new Proxy(prop, handler);
|
|
15
16
|
if (
|
|
16
|
-
Array.isArray(target) &&
|
|
17
17
|
typeof target[key] === "function" &&
|
|
18
|
+
Array.isArray(target) &&
|
|
18
19
|
MUTATING_METHODS.includes(key)
|
|
19
20
|
) {
|
|
20
21
|
return (...args) => {
|
|
@@ -23,6 +24,9 @@ export function watch(target, callback) {
|
|
|
23
24
|
return result;
|
|
24
25
|
};
|
|
25
26
|
}
|
|
27
|
+
if (target instanceof Date && propType === "function") {
|
|
28
|
+
return prop.bind(target);
|
|
29
|
+
}
|
|
26
30
|
return prop;
|
|
27
31
|
},
|
|
28
32
|
set(target, key, value) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wallace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"author": "Andrew Buchan",
|
|
5
5
|
"description": "An insanely small, fast, intuitive and extendable front-end framework",
|
|
6
6
|
"homepage": "https://wallace.js.org",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"test": "jest --clearCache && jest"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"babel-plugin-wallace": "^0.
|
|
18
|
+
"babel-plugin-wallace": "^0.14.1",
|
|
19
19
|
"browserify": "^17.0.1"
|
|
20
20
|
},
|
|
21
|
-
"gitHead": "
|
|
21
|
+
"gitHead": "c60384d682e38095780dd260004299e9c4038583"
|
|
22
22
|
}
|