wallace 0.12.2 → 0.14.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/lib/component.js +15 -19
- package/lib/createComponent.js +2 -2
- package/lib/detacher.js +12 -15
- package/lib/extend.js +2 -2
- package/lib/index.js +1 -1
- package/lib/mount.js +2 -2
- package/lib/nestComponent.js +2 -2
- package/lib/offsetter.js +8 -0
- package/lib/part.js +2 -2
- package/lib/refs.js +1 -3
- package/lib/repeaters/keyed.js +63 -22
- package/lib/repeaters/sequential.js +53 -19
- package/lib/router.js +2 -3
- package/lib/stubs.js +1 -3
- package/lib/toDateString.js +1 -0
- package/lib/types.d.ts +35 -39
- package/lib/watch.js +8 -4
- package/package.json +3 -3
- package/lib/repeaters/keyedFn.js +0 -81
package/lib/component.js
CHANGED
|
@@ -16,7 +16,7 @@ const ComponentPrototype = {
|
|
|
16
16
|
|
|
17
17
|
/*
|
|
18
18
|
COMPILER_MODS:
|
|
19
|
-
if useFlags is false this is deleted
|
|
19
|
+
if useFlags is false this is deleted, so `_u` can be renamed to `update`.
|
|
20
20
|
*/
|
|
21
21
|
update: function () {
|
|
22
22
|
this._u(0, this._l);
|
|
@@ -100,7 +100,7 @@ const ComponentBase = {
|
|
|
100
100
|
prototype: ComponentPrototype
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
-
if (wallaceConfig.flags.
|
|
103
|
+
if (wallaceConfig.flags.allowStubs) {
|
|
104
104
|
ComponentBase.stubs = {};
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -110,7 +110,7 @@ if (wallaceConfig.flags.useStubs) {
|
|
|
110
110
|
* @param {function} BaseComponentFunction - A Component definition function to inherit bits from.
|
|
111
111
|
* @returns the ComponentFunction with bits added.
|
|
112
112
|
*/
|
|
113
|
-
export
|
|
113
|
+
export const initConstructor = (ComponentFunction, BaseComponentFunction) => {
|
|
114
114
|
const proto = (ComponentFunction.prototype = Object.create(
|
|
115
115
|
BaseComponentFunction.prototype,
|
|
116
116
|
{
|
|
@@ -120,59 +120,55 @@ export function initConstructor(ComponentFunction, BaseComponentFunction) {
|
|
|
120
120
|
}
|
|
121
121
|
));
|
|
122
122
|
|
|
123
|
-
if (wallaceConfig.flags.
|
|
123
|
+
if (wallaceConfig.flags.allowMethods) {
|
|
124
124
|
Object.defineProperty(ComponentFunction, "methods", {
|
|
125
|
-
set:
|
|
126
|
-
|
|
127
|
-
},
|
|
128
|
-
get: function () {
|
|
129
|
-
return proto;
|
|
130
|
-
}
|
|
125
|
+
set: value => Object.assign(proto, value),
|
|
126
|
+
get: () => proto
|
|
131
127
|
});
|
|
132
128
|
} else {
|
|
133
129
|
if (process.env.NODE_ENV !== "production") {
|
|
134
130
|
Object.defineProperty(ComponentFunction, "name", {
|
|
135
131
|
set: function (value) {
|
|
136
132
|
throw new Error(
|
|
137
|
-
'Flag "
|
|
133
|
+
'Flag "allowMethods" must be set to true in the config for this feature.'
|
|
138
134
|
);
|
|
139
135
|
},
|
|
140
136
|
get: function () {
|
|
141
137
|
throw new Error(
|
|
142
|
-
'Flag "
|
|
138
|
+
'Flag "allowMethods" must be set to true in the config for this feature.'
|
|
143
139
|
);
|
|
144
140
|
}
|
|
145
141
|
});
|
|
146
142
|
}
|
|
147
143
|
}
|
|
148
144
|
|
|
149
|
-
if (wallaceConfig.flags.
|
|
145
|
+
if (wallaceConfig.flags.allowStubs) {
|
|
150
146
|
ComponentFunction.stubs = Object.assign({}, BaseComponentFunction.stubs);
|
|
151
147
|
}
|
|
152
148
|
|
|
153
149
|
return ComponentFunction;
|
|
154
|
-
}
|
|
150
|
+
};
|
|
155
151
|
|
|
156
|
-
export
|
|
152
|
+
export const defineComponent = (html, watches, queries, contructor, inheritFrom) => {
|
|
157
153
|
const ComponentDefinition = initConstructor(contructor, inheritFrom || ComponentBase);
|
|
158
154
|
const proto = ComponentDefinition.prototype;
|
|
159
155
|
throwAway.innerHTML = html;
|
|
160
156
|
proto._w = watches;
|
|
161
157
|
proto._q = queries;
|
|
162
158
|
proto._t = throwAway.content.firstChild;
|
|
163
|
-
if (wallaceConfig.flags.
|
|
159
|
+
if (wallaceConfig.flags.allowBase) {
|
|
164
160
|
proto.base = ComponentPrototype;
|
|
165
161
|
} else {
|
|
166
162
|
if (process.env.NODE_ENV !== "production") {
|
|
167
163
|
Object.defineProperty(proto, "base", {
|
|
168
164
|
set: function (value) {
|
|
169
165
|
throw new Error(
|
|
170
|
-
'Flag "
|
|
166
|
+
'Flag "allowBase" must be set to true in the config for this feature.'
|
|
171
167
|
);
|
|
172
168
|
},
|
|
173
169
|
get: function () {
|
|
174
170
|
throw new Error(
|
|
175
|
-
'Flag "
|
|
171
|
+
'Flag "allowBase" must be set to true in the config for this feature.'
|
|
176
172
|
);
|
|
177
173
|
}
|
|
178
174
|
});
|
|
@@ -180,4 +176,4 @@ export function defineComponent(html, watches, queries, contructor, inheritFrom)
|
|
|
180
176
|
}
|
|
181
177
|
|
|
182
178
|
return ComponentDefinition;
|
|
183
|
-
}
|
|
179
|
+
};
|
package/lib/createComponent.js
CHANGED
package/lib/detacher.js
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
|
+
import { countOffset } from "./offsetter";
|
|
1
2
|
/**
|
|
2
3
|
* Deals with conditionally detaching elements with the if directive.
|
|
3
4
|
*/
|
|
4
5
|
export function Detacher(i, e, s) {
|
|
5
6
|
this.i = i; // the initial element index.
|
|
6
|
-
this.e = e; // the
|
|
7
|
-
this.s = s; // the
|
|
7
|
+
this.e = e; // the parent element key.
|
|
8
|
+
this.s = s; // the stash key of the map of detached nodes.
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
Detacher.prototype.apply = function (element, shouldBeVisible, elements, stash) {
|
|
11
|
-
let adjustedIndex;
|
|
12
12
|
const index = this.i,
|
|
13
13
|
parent = elements[this.e],
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (shouldBeVisible &&
|
|
17
|
-
adjustedIndex =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}).length;
|
|
22
|
-
parent.insertBefore(detachedElement, parent.childNodes[adjustedIndex]);
|
|
23
|
-
detachedElements[index] = null;
|
|
24
|
-
} else if (!shouldBeVisible && !detachedElement) {
|
|
14
|
+
offsetTracker = stash[this.s];
|
|
15
|
+
let ownOffset = offsetTracker.get(index) || 0;
|
|
16
|
+
if (shouldBeVisible && ownOffset === -1) {
|
|
17
|
+
const adjustedIndex = countOffset(offsetTracker, index);
|
|
18
|
+
parent.insertBefore(element, parent.childNodes[adjustedIndex]);
|
|
19
|
+
ownOffset = 0;
|
|
20
|
+
} else if (!shouldBeVisible && ownOffset === 0) {
|
|
25
21
|
parent.removeChild(element);
|
|
26
|
-
|
|
22
|
+
ownOffset = -1;
|
|
27
23
|
}
|
|
24
|
+
offsetTracker.set(index, ownOffset);
|
|
28
25
|
};
|
package/lib/extend.js
CHANGED
|
@@ -11,7 +11,7 @@ import { initConstructor } from "./component";
|
|
|
11
11
|
*
|
|
12
12
|
* So it should never be called with 2nd arg in real life.
|
|
13
13
|
*/
|
|
14
|
-
export
|
|
14
|
+
export const extendComponent = (base, componentDef) => {
|
|
15
15
|
// This function call will have been replaced if 2nd arg is a valid component func.
|
|
16
16
|
// and therefore we would not receive it.
|
|
17
17
|
if (componentDef)
|
|
@@ -19,4 +19,4 @@ export function extendComponent(base, componentDef) {
|
|
|
19
19
|
return initConstructor(function () {
|
|
20
20
|
base.call(this);
|
|
21
21
|
}, base);
|
|
22
|
-
}
|
|
22
|
+
};
|
package/lib/index.js
CHANGED
|
@@ -7,9 +7,9 @@ export { nestComponent } from "./nestComponent";
|
|
|
7
7
|
export { saveRef } from "./refs";
|
|
8
8
|
export { savePart } from "./part";
|
|
9
9
|
export { KeyedRepeater } from "./repeaters/keyed";
|
|
10
|
-
export { KeyedFnRepeater } from "./repeaters/keyedFn";
|
|
11
10
|
export { SequentialRepeater } from "./repeaters/sequential";
|
|
12
11
|
export { Router, route } from "./router";
|
|
13
12
|
export { getStub } from "./stubs";
|
|
13
|
+
export { toDateString } from "./toDateString";
|
|
14
14
|
export { findElement, onEvent } from "./utils";
|
|
15
15
|
export { watch, protect } from "./watch";
|
package/lib/mount.js
CHANGED
|
@@ -7,11 +7,11 @@ import { replaceNode } from "./utils";
|
|
|
7
7
|
* @param {callable} componentDefinition The class of Component to create
|
|
8
8
|
* @param {object} props The props to pass to the component (optional)
|
|
9
9
|
*/
|
|
10
|
-
export
|
|
10
|
+
export const mount = (elementOrId, componentDefinition, props, ctrl) => {
|
|
11
11
|
const component = new componentDefinition();
|
|
12
12
|
component.render(props, ctrl);
|
|
13
13
|
const element =
|
|
14
14
|
typeof elementOrId === "string" ? document.getElementById(elementOrId) : elementOrId;
|
|
15
15
|
replaceNode(element, component.el);
|
|
16
16
|
return component;
|
|
17
|
-
}
|
|
17
|
+
};
|
package/lib/nestComponent.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { findElement, replaceNode } from "./utils";
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export const nestComponent = (rootElement, path, componentDefinition) => {
|
|
4
4
|
const el = findElement(rootElement, path),
|
|
5
5
|
child = new componentDefinition();
|
|
6
6
|
replaceNode(el, child.el);
|
|
7
7
|
return child;
|
|
8
|
-
}
|
|
8
|
+
};
|
package/lib/offsetter.js
ADDED
package/lib/part.js
CHANGED
|
@@ -11,7 +11,7 @@ Part.prototype.update = function () {
|
|
|
11
11
|
/**
|
|
12
12
|
* Saves a reference to a part of a component so it can be updated independently.
|
|
13
13
|
*/
|
|
14
|
-
export
|
|
14
|
+
export const savePart = (node, component, parts, name, start, end) => {
|
|
15
15
|
parts[name] = new Part(component, start, end);
|
|
16
16
|
return node;
|
|
17
|
-
}
|
|
17
|
+
};
|
package/lib/refs.js
CHANGED
package/lib/repeaters/keyed.js
CHANGED
|
@@ -1,16 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
import { countOffset } from "../offsetter";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Repeats nested components, reusing items based on key.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* COMPILER_MODS:
|
|
7
|
+
* if allowRepeaterSiblings is false the last two parameters are removed.
|
|
8
8
|
*/
|
|
9
|
-
export function KeyedRepeater(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
export function KeyedRepeater(
|
|
10
|
+
componentDefinition,
|
|
11
|
+
pool,
|
|
12
|
+
key,
|
|
13
|
+
adjustmentTracker,
|
|
14
|
+
initialIndex
|
|
15
|
+
) {
|
|
16
|
+
this.d = componentDefinition;
|
|
17
|
+
this.k = []; // array of keys as last set.
|
|
18
|
+
this.p = pool; // pool of component instances. Must be a Map.
|
|
19
|
+
if (typeof key === "function") {
|
|
20
|
+
this.f = key;
|
|
21
|
+
} else {
|
|
22
|
+
this.n = key;
|
|
23
|
+
}
|
|
24
|
+
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
25
|
+
this.a = adjustmentTracker;
|
|
26
|
+
this.i = initialIndex;
|
|
27
|
+
}
|
|
14
28
|
}
|
|
15
29
|
|
|
16
30
|
/**
|
|
@@ -22,20 +36,27 @@ export function KeyedRepeater(componentDefinition, keyName) {
|
|
|
22
36
|
* @param {any} ctrl - The parent item's controller.
|
|
23
37
|
*/
|
|
24
38
|
KeyedRepeater.prototype.patch = function (e, items, ctrl) {
|
|
25
|
-
const pool = this.
|
|
26
|
-
componentDefinition = this.
|
|
27
|
-
keyName = this.
|
|
39
|
+
const pool = this.p,
|
|
40
|
+
componentDefinition = this.d,
|
|
41
|
+
keyName = this.n,
|
|
42
|
+
keyFn = this.f,
|
|
43
|
+
useKeyName = keyName !== undefined,
|
|
28
44
|
childNodes = e.childNodes,
|
|
29
45
|
itemsLength = items.length,
|
|
30
|
-
previousKeys = this.
|
|
46
|
+
previousKeys = this.k,
|
|
31
47
|
previousKeysLength = previousKeys.length,
|
|
32
48
|
newKeys = [],
|
|
33
49
|
previousKeysSet = new Set(previousKeys),
|
|
34
50
|
frag = document.createDocumentFragment();
|
|
51
|
+
|
|
35
52
|
let item,
|
|
36
53
|
el,
|
|
37
|
-
|
|
54
|
+
itemKey,
|
|
38
55
|
component,
|
|
56
|
+
initialIndex,
|
|
57
|
+
offsetTracker,
|
|
58
|
+
endAnchor = null,
|
|
59
|
+
adjustment = 0,
|
|
39
60
|
anchor = null,
|
|
40
61
|
fragAnchor = null,
|
|
41
62
|
untouched = true,
|
|
@@ -43,39 +64,59 @@ KeyedRepeater.prototype.patch = function (e, items, ctrl) {
|
|
|
43
64
|
offset = previousKeysLength - itemsLength,
|
|
44
65
|
i = itemsLength - 1;
|
|
45
66
|
|
|
67
|
+
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
68
|
+
offsetTracker = this.a;
|
|
69
|
+
initialIndex = this.i;
|
|
70
|
+
if (offsetTracker) {
|
|
71
|
+
adjustment = countOffset(offsetTracker, initialIndex);
|
|
72
|
+
endAnchor = childNodes[previousKeysLength + adjustment] || null;
|
|
73
|
+
anchor = endAnchor;
|
|
74
|
+
untouched = false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
46
78
|
// Working backwards saves us having to track moves.
|
|
47
79
|
while (i >= 0) {
|
|
48
80
|
item = items[i];
|
|
49
|
-
|
|
50
|
-
component = pool
|
|
81
|
+
itemKey = useKeyName ? item[keyName] : keyFn(item);
|
|
82
|
+
if (!(component = pool.get(itemKey))) {
|
|
83
|
+
component = new componentDefinition();
|
|
84
|
+
pool.set(itemKey, component);
|
|
85
|
+
}
|
|
51
86
|
component.render(item, ctrl);
|
|
52
87
|
el = component.el;
|
|
53
|
-
if (untouched && !previousKeysSet.has(
|
|
88
|
+
if (untouched && !previousKeysSet.has(itemKey)) {
|
|
54
89
|
frag.insertBefore(el, fragAnchor);
|
|
55
90
|
fragAnchor = el;
|
|
56
91
|
append = true;
|
|
57
92
|
offset++;
|
|
58
93
|
} else {
|
|
59
|
-
if (
|
|
94
|
+
if (itemKey !== previousKeys[i + offset]) {
|
|
60
95
|
e.insertBefore(el, anchor);
|
|
61
96
|
untouched = false;
|
|
62
97
|
}
|
|
63
98
|
anchor = el;
|
|
64
99
|
}
|
|
65
|
-
newKeys.push(
|
|
66
|
-
previousKeysSet.delete(
|
|
100
|
+
newKeys.push(itemKey);
|
|
101
|
+
previousKeysSet.delete(itemKey);
|
|
67
102
|
i--;
|
|
68
103
|
}
|
|
69
104
|
|
|
70
105
|
if (append) {
|
|
71
|
-
e.
|
|
106
|
+
e.insertBefore(frag, endAnchor);
|
|
72
107
|
}
|
|
73
108
|
|
|
74
109
|
let toStrip = previousKeysSet.size;
|
|
75
110
|
while (toStrip > 0) {
|
|
76
|
-
e.removeChild(childNodes[
|
|
111
|
+
e.removeChild(childNodes[adjustment]);
|
|
77
112
|
toStrip--;
|
|
78
113
|
}
|
|
79
114
|
|
|
80
|
-
this.
|
|
115
|
+
this.k = newKeys.reverse();
|
|
116
|
+
|
|
117
|
+
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
118
|
+
if (offsetTracker) {
|
|
119
|
+
offsetTracker.set(initialIndex, itemsLength - 1);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
81
122
|
};
|
|
@@ -1,32 +1,60 @@
|
|
|
1
|
+
import { countOffset } from "../offsetter";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
* Repeats nested components, yielding from
|
|
4
|
+
* Repeats nested components, yielding from the pool sequentially.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
6
|
+
* COMPILER_MODS:
|
|
7
|
+
* if allowRepeaterSiblings is false the last two parameters are removed.
|
|
5
8
|
*/
|
|
6
|
-
export function SequentialRepeater(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
export function SequentialRepeater(
|
|
10
|
+
componentDefinition,
|
|
11
|
+
pool,
|
|
12
|
+
adjustmentTracker,
|
|
13
|
+
initialIndex
|
|
14
|
+
) {
|
|
15
|
+
this.d = componentDefinition;
|
|
16
|
+
this.p = pool; // pool of component instances. Must be an Array.
|
|
17
|
+
this.c = 0; // Child count
|
|
18
|
+
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
19
|
+
this.a = adjustmentTracker;
|
|
20
|
+
this.i = initialIndex;
|
|
21
|
+
}
|
|
10
22
|
}
|
|
11
23
|
|
|
12
24
|
/**
|
|
13
25
|
* Updates the element's childNodes to match the items.
|
|
14
26
|
* Performance is important.
|
|
15
27
|
*
|
|
16
|
-
* @param {DOMElement}
|
|
28
|
+
* @param {DOMElement} parent - The DOM element to patch.
|
|
17
29
|
* @param {Array} items - Array of items which will be passed as props.
|
|
18
30
|
* @param {any} ctrl - The parent item's controller.
|
|
19
31
|
*/
|
|
20
|
-
SequentialRepeater.prototype.patch = function (
|
|
21
|
-
const pool = this.
|
|
22
|
-
componentDefinition = this.
|
|
23
|
-
|
|
32
|
+
SequentialRepeater.prototype.patch = function (parent, items, ctrl) {
|
|
33
|
+
const pool = this.p,
|
|
34
|
+
componentDefinition = this.d,
|
|
35
|
+
previousChildCount = this.c,
|
|
24
36
|
itemsLength = items.length,
|
|
25
|
-
|
|
37
|
+
childNodes = parent.childNodes;
|
|
38
|
+
|
|
26
39
|
let i = 0,
|
|
40
|
+
offset = 0,
|
|
27
41
|
component,
|
|
42
|
+
nextElement,
|
|
43
|
+
initialIndex,
|
|
44
|
+
offsetTracker,
|
|
45
|
+
endOfRange = previousChildCount,
|
|
28
46
|
poolCount = pool.length;
|
|
29
47
|
|
|
48
|
+
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
49
|
+
initialIndex = this.i;
|
|
50
|
+
offsetTracker = this.a;
|
|
51
|
+
if (offsetTracker) {
|
|
52
|
+
// The repeat element has siblings
|
|
53
|
+
offset = countOffset(offsetTracker, initialIndex);
|
|
54
|
+
endOfRange += offset;
|
|
55
|
+
nextElement = childNodes[endOfRange] || null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
30
58
|
while (i < itemsLength) {
|
|
31
59
|
if (i < poolCount) {
|
|
32
60
|
component = pool[i];
|
|
@@ -36,15 +64,21 @@ SequentialRepeater.prototype.patch = function (e, items, ctrl) {
|
|
|
36
64
|
poolCount++;
|
|
37
65
|
}
|
|
38
66
|
component.render(items[i], ctrl);
|
|
39
|
-
if (i >=
|
|
40
|
-
|
|
67
|
+
if (i >= previousChildCount) {
|
|
68
|
+
parent.insertBefore(component.el, nextElement);
|
|
41
69
|
}
|
|
42
70
|
i++;
|
|
43
71
|
}
|
|
44
|
-
this.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
72
|
+
this.c = itemsLength;
|
|
73
|
+
|
|
74
|
+
let removeAtIndex = offset + previousChildCount - 1;
|
|
75
|
+
const stopatIndex = offset + itemsLength - 1;
|
|
76
|
+
for (let i = removeAtIndex; i > stopatIndex; i--) {
|
|
77
|
+
parent.removeChild(childNodes[i]);
|
|
78
|
+
}
|
|
79
|
+
if (wallaceConfig.flags.allowRepeaterSiblings) {
|
|
80
|
+
if (offsetTracker) {
|
|
81
|
+
offsetTracker.set(initialIndex, itemsLength - 1);
|
|
82
|
+
}
|
|
49
83
|
}
|
|
50
84
|
};
|
package/lib/router.js
CHANGED
|
@@ -17,9 +17,8 @@ const converters = {
|
|
|
17
17
|
date: v => new Date(v)
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
}
|
|
20
|
+
export const route = (path, componentDef, converter, cleanup) =>
|
|
21
|
+
new Route(path, componentDef, converter, cleanup);
|
|
23
22
|
|
|
24
23
|
export const Router = () => <div></div>;
|
|
25
24
|
|
package/lib/stubs.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const toDateString = date => date.toISOString().slice(0, 10);
|
package/lib/types.d.ts
CHANGED
|
@@ -204,6 +204,7 @@ const TaskList = (tasks) => (
|
|
|
204
204
|
Notes:
|
|
205
205
|
|
|
206
206
|
- You cannot use nest on the root element.
|
|
207
|
+
- You cannot use `if` on a nested element, only `show` and `hide`.
|
|
207
208
|
|
|
208
209
|
## 4. Repeating
|
|
209
210
|
|
|
@@ -239,8 +240,8 @@ const TaskList = (tasks) => (
|
|
|
239
240
|
|
|
240
241
|
Notes:
|
|
241
242
|
|
|
242
|
-
- You cannot repeat on the root element.
|
|
243
|
-
-
|
|
243
|
+
- You cannot use repeat on the root element.
|
|
244
|
+
- You cannot toggle visibility on the repeat element.
|
|
244
245
|
|
|
245
246
|
## 5. Directives
|
|
246
247
|
|
|
@@ -386,9 +387,7 @@ const TaskList: Uses<iTask[]> = (tasks) => (
|
|
|
386
387
|
<div>
|
|
387
388
|
First task:
|
|
388
389
|
<Task.nest props={tasks[0]} />
|
|
389
|
-
<
|
|
390
|
-
<Task.repeat items={tasks.slice(1)} />
|
|
391
|
-
</div>
|
|
390
|
+
<Task.repeat items={tasks.slice(1)} />
|
|
392
391
|
</div>
|
|
393
392
|
);
|
|
394
393
|
|
|
@@ -526,11 +525,12 @@ watchedObj[0] = 'foo'; // throws error.
|
|
|
526
525
|
You can toggle flags in your babel config to disable certain features for cutting edge
|
|
527
526
|
performance and bundle size:
|
|
528
527
|
|
|
529
|
-
1.
|
|
530
|
-
2.
|
|
531
|
-
3.
|
|
532
|
-
4.
|
|
533
|
-
5.
|
|
528
|
+
1. allowBase - enables use of `base` in components.
|
|
529
|
+
2. allowCtrl - enables use of `ctrl` in components.
|
|
530
|
+
3. allowMethods - adds the `methods` helper to components.
|
|
531
|
+
4. allowParts - enables use of parts.
|
|
532
|
+
5. allowRepeaterSiblings - allows repeaters to have siblings.
|
|
533
|
+
6. allowStubs - enables the use of stubs.
|
|
534
534
|
|
|
535
535
|
These flags default to true, unless you specify `flags` in the plugin config, in which
|
|
536
536
|
case they default to false and you need to explicitly enable those you want:
|
|
@@ -543,8 +543,8 @@ module.exports = {
|
|
|
543
543
|
"babel-plugin-wallace",
|
|
544
544
|
{
|
|
545
545
|
flags: {
|
|
546
|
-
|
|
547
|
-
|
|
546
|
+
allowCtrl: true,
|
|
547
|
+
allowStubs: false
|
|
548
548
|
},
|
|
549
549
|
}
|
|
550
550
|
],
|
|
@@ -841,46 +841,29 @@ interface DirectiveAttributes extends AllDomEvents {
|
|
|
841
841
|
/**
|
|
842
842
|
* ## Wallace directive: bind
|
|
843
843
|
*
|
|
844
|
-
* Sets up two
|
|
845
|
-
*
|
|
846
|
-
* 1. It uses the expression as the element's value.
|
|
847
|
-
* 2. It assigns the value back to the expression when the element's `change` event
|
|
848
|
-
* fires.
|
|
849
|
-
*
|
|
850
|
-
* So this:
|
|
844
|
+
* Sets up two way binding between an input and data:
|
|
851
845
|
*
|
|
852
846
|
* ```
|
|
853
|
-
*
|
|
854
|
-
* <input type="text" bind={name}/>
|
|
855
|
-
* );
|
|
847
|
+
* <input type="text" bind={name} />
|
|
856
848
|
* ```
|
|
857
849
|
*
|
|
858
850
|
* Is the equivalent of this:
|
|
859
851
|
*
|
|
860
|
-
*```
|
|
861
|
-
* const MyComponent = ({name}, {event}) => (
|
|
862
|
-
* <input type="text" onChange={name = event.target.value} value={name}/>
|
|
863
|
-
* );
|
|
864
852
|
* ```
|
|
865
|
-
*
|
|
866
|
-
*
|
|
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:
|
|
867
857
|
*
|
|
868
858
|
* ```
|
|
869
|
-
*
|
|
870
|
-
* <input type="checkbox" onChange={done = event.target.checked} checked={done}/>
|
|
871
|
-
* );
|
|
859
|
+
* <input type="text" bind={name} event:keyup />
|
|
872
860
|
* ```
|
|
873
861
|
*
|
|
874
|
-
* By
|
|
862
|
+
* By default it binds to `value` but you can set a different property:
|
|
875
863
|
*
|
|
876
864
|
*```
|
|
877
|
-
*
|
|
878
|
-
* <input type="text" bind:KeyUp={name} />
|
|
879
|
-
* );
|
|
865
|
+
* <input type="number" bind:valueAsNumber={name} />
|
|
880
866
|
* ```
|
|
881
|
-
*
|
|
882
|
-
* Note that destructured props are converted to member expressions, so these examples
|
|
883
|
-
* work even though it looks like you're setting a local variable.
|
|
884
867
|
*/
|
|
885
868
|
bind?: MustBeExpression;
|
|
886
869
|
|
|
@@ -923,6 +906,19 @@ interface DirectiveAttributes extends AllDomEvents {
|
|
|
923
906
|
*/
|
|
924
907
|
ctrl?: any;
|
|
925
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
|
+
|
|
926
922
|
/**
|
|
927
923
|
* ## Wallace directive: fixed
|
|
928
924
|
*
|
|
@@ -1078,7 +1074,6 @@ declare namespace JSX {
|
|
|
1078
1074
|
* <MyComponent.repeat items={arrayOfProps} key="id"/>
|
|
1079
1075
|
* <MyComponent.repeat items={arrayOfProps} key={(i) => i.id}/>
|
|
1080
1076
|
* ```
|
|
1081
|
-
* Note that repeated components may not have siblings.
|
|
1082
1077
|
*
|
|
1083
1078
|
* Available Wallace directives:
|
|
1084
1079
|
*
|
|
@@ -1087,6 +1082,7 @@ declare namespace JSX {
|
|
|
1087
1082
|
* - `class:xyz` defines a set of classes to be toggled.
|
|
1088
1083
|
* - `css` shorthand for `fixed:class`.
|
|
1089
1084
|
* - `ctrl` specifies ctrl for nested/repeated components.
|
|
1085
|
+
* - `event` changes the event which `bind` reacts to.
|
|
1090
1086
|
* - `fixed:xyz` sets a attribute from an expression at definition.
|
|
1091
1087
|
* - `hide` sets an element or component's hidden property.
|
|
1092
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.0",
|
|
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.0",
|
|
19
19
|
"browserify": "^17.0.1"
|
|
20
20
|
},
|
|
21
|
-
"gitHead": "
|
|
21
|
+
"gitHead": "94e0750d51118bf80ff69065fdb39a0f0f52dfc7"
|
|
22
22
|
}
|
package/lib/repeaters/keyedFn.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
// WARNING: Code here is near duplicated in keyedFn.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Repeats nested components, reusing items based on key.
|
|
5
|
-
*
|
|
6
|
-
* @param {function} componentDefinition - The ComponentDefinition to create.
|
|
7
|
-
* @param {function} keyFn - A function which obtains the key.
|
|
8
|
-
*/
|
|
9
|
-
export function KeyedFnRepeater(componentDefinition, keyFn) {
|
|
10
|
-
this.def = componentDefinition;
|
|
11
|
-
this.keyFn = keyFn;
|
|
12
|
-
this.keys = []; // array of keys as last set.
|
|
13
|
-
this.pool = {}; // pool of component instances.
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Updates the element's childNodes to match the items.
|
|
18
|
-
* Performance is important.
|
|
19
|
-
*
|
|
20
|
-
* @param {DOMElement} e - The DOM element to patch.
|
|
21
|
-
* @param {Array} items - Array of items which will be passed as props.
|
|
22
|
-
* @param {any} ctrl - The parent item's controller.
|
|
23
|
-
*/
|
|
24
|
-
KeyedFnRepeater.prototype.patch = function (e, items, ctrl) {
|
|
25
|
-
const pool = this.pool,
|
|
26
|
-
componentDefinition = this.def,
|
|
27
|
-
keyFn = this.keyFn,
|
|
28
|
-
childNodes = e.childNodes,
|
|
29
|
-
itemsLength = items.length,
|
|
30
|
-
previousKeys = this.keys,
|
|
31
|
-
previousKeysLength = previousKeys.length,
|
|
32
|
-
newKeys = [],
|
|
33
|
-
previousKeysSet = new Set(previousKeys),
|
|
34
|
-
frag = document.createDocumentFragment();
|
|
35
|
-
let item,
|
|
36
|
-
el,
|
|
37
|
-
key,
|
|
38
|
-
component,
|
|
39
|
-
anchor = null,
|
|
40
|
-
fragAnchor = null,
|
|
41
|
-
untouched = true,
|
|
42
|
-
append = false,
|
|
43
|
-
offset = previousKeysLength - itemsLength,
|
|
44
|
-
i = itemsLength - 1;
|
|
45
|
-
|
|
46
|
-
// Working backwards saves us having to track moves.
|
|
47
|
-
while (i >= 0) {
|
|
48
|
-
item = items[i];
|
|
49
|
-
key = keyFn(item);
|
|
50
|
-
component = pool[key] || (pool[key] = new componentDefinition());
|
|
51
|
-
component.render(item, ctrl);
|
|
52
|
-
el = component.el;
|
|
53
|
-
if (untouched && !previousKeysSet.has(key)) {
|
|
54
|
-
frag.insertBefore(el, fragAnchor);
|
|
55
|
-
fragAnchor = el;
|
|
56
|
-
append = true;
|
|
57
|
-
offset++;
|
|
58
|
-
} else {
|
|
59
|
-
if (key !== previousKeys[i + offset]) {
|
|
60
|
-
e.insertBefore(el, anchor);
|
|
61
|
-
untouched = false;
|
|
62
|
-
}
|
|
63
|
-
anchor = el;
|
|
64
|
-
}
|
|
65
|
-
newKeys.push(key);
|
|
66
|
-
previousKeysSet.delete(key);
|
|
67
|
-
i--;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (append) {
|
|
71
|
-
e.appendChild(frag);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
let toStrip = previousKeysSet.size;
|
|
75
|
-
while (toStrip > 0) {
|
|
76
|
-
e.removeChild(childNodes[0]);
|
|
77
|
-
toStrip--;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
this.keys = newKeys.reverse();
|
|
81
|
-
};
|