wallace 0.10.0 → 0.12.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 +2 -2
- package/lib/component.js +70 -16
- package/lib/index.js +1 -0
- package/lib/repeaters/keyed.js +7 -5
- package/lib/repeaters/keyedFn.js +81 -0
- package/lib/repeaters/sequential.js +1 -1
- package/lib/types.d.ts +68 -17
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Wallace
|
|
2
2
|
|
|
3
|
-
This package contains the library for the [Wallace](https://
|
|
3
|
+
This package contains the library for the [Wallace](https://wallace.js.org) framework, which you import into your source files:
|
|
4
4
|
|
|
5
5
|
```jsx
|
|
6
6
|
import { mount } from 'wallace';
|
|
@@ -26,4 +26,4 @@ npx create-wallace-app
|
|
|
26
26
|
|
|
27
27
|
As that sets up your babel and webpack configurations for you.
|
|
28
28
|
|
|
29
|
-
For more detailed documentation see the [Wallace repository on github](https://
|
|
29
|
+
For more detailed documentation see the [Wallace repository on github](https://wallace.js.org/docs/).
|
package/lib/component.js
CHANGED
|
@@ -2,22 +2,33 @@ const throwAway = document.createElement("template");
|
|
|
2
2
|
const NO_LOOKUP = "__";
|
|
3
3
|
|
|
4
4
|
const ComponentPrototype = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
/*
|
|
6
|
+
COMPILER_MODS:
|
|
7
|
+
if useController is false:
|
|
8
|
+
- param `ctrl` is removed.
|
|
9
|
+
- `this.ctrl = ctrl` is removed.
|
|
10
|
+
*/
|
|
8
11
|
render: function (props, ctrl) {
|
|
9
12
|
this.props = props;
|
|
10
13
|
this.ctrl = ctrl;
|
|
11
14
|
this.update();
|
|
12
15
|
},
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
/*
|
|
18
|
+
COMPILER_MODS:
|
|
19
|
+
if useFlags is false this is deleted.
|
|
20
|
+
*/
|
|
17
21
|
update: function () {
|
|
18
22
|
this._u(0, this._l);
|
|
19
23
|
},
|
|
20
24
|
|
|
25
|
+
/*
|
|
26
|
+
COMPILER_MODS:
|
|
27
|
+
if useFlags is false:
|
|
28
|
+
- gets renamed to `update`
|
|
29
|
+
- parameters are removed
|
|
30
|
+
- add `i = 0, il = this._l` to variable declarator.
|
|
31
|
+
*/
|
|
21
32
|
_u: function (i, il) {
|
|
22
33
|
let watch,
|
|
23
34
|
element,
|
|
@@ -115,10 +126,13 @@ Object.defineProperty(ComponentPrototype, "hidden", {
|
|
|
115
126
|
});
|
|
116
127
|
|
|
117
128
|
const ComponentBase = {
|
|
118
|
-
stubs: {},
|
|
119
129
|
prototype: ComponentPrototype
|
|
120
130
|
};
|
|
121
131
|
|
|
132
|
+
if (wallaceConfig.flags.useStubs) {
|
|
133
|
+
ComponentBase.stubs = {};
|
|
134
|
+
}
|
|
135
|
+
|
|
122
136
|
/**
|
|
123
137
|
*
|
|
124
138
|
* @param {function} ComponentFunction - The Component definition function to add bits to.
|
|
@@ -134,15 +148,37 @@ export function initConstructor(ComponentFunction, BaseComponentFunction) {
|
|
|
134
148
|
}
|
|
135
149
|
}
|
|
136
150
|
));
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
151
|
+
|
|
152
|
+
if (wallaceConfig.flags.useMethods) {
|
|
153
|
+
Object.defineProperty(ComponentFunction, "methods", {
|
|
154
|
+
set: function (value) {
|
|
155
|
+
Object.assign(proto, value);
|
|
156
|
+
},
|
|
157
|
+
get: function () {
|
|
158
|
+
return proto;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
} else {
|
|
162
|
+
if (process.env.NODE_ENV !== "production") {
|
|
163
|
+
Object.defineProperty(ComponentFunction, "name", {
|
|
164
|
+
set: function (value) {
|
|
165
|
+
throw new Error(
|
|
166
|
+
'Flag "useMethods" must be set to true in the config for this feature.'
|
|
167
|
+
);
|
|
168
|
+
},
|
|
169
|
+
get: function () {
|
|
170
|
+
throw new Error(
|
|
171
|
+
'Flag "useMethods" must be set to true in the config for this feature.'
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
143
175
|
}
|
|
144
|
-
}
|
|
145
|
-
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (wallaceConfig.flags.useStubs) {
|
|
179
|
+
ComponentFunction.stubs = Object.assign({}, BaseComponentFunction.stubs);
|
|
180
|
+
}
|
|
181
|
+
|
|
146
182
|
return ComponentFunction;
|
|
147
183
|
}
|
|
148
184
|
|
|
@@ -153,6 +189,24 @@ export function defineComponent(html, watches, queries, contructor, inheritFrom)
|
|
|
153
189
|
proto._w = watches;
|
|
154
190
|
proto._q = queries;
|
|
155
191
|
proto._t = throwAway.content.firstChild;
|
|
156
|
-
|
|
192
|
+
if (wallaceConfig.flags.useBase) {
|
|
193
|
+
proto.base = ComponentPrototype;
|
|
194
|
+
} else {
|
|
195
|
+
if (process.env.NODE_ENV !== "production") {
|
|
196
|
+
Object.defineProperty(proto, "base", {
|
|
197
|
+
set: function (value) {
|
|
198
|
+
throw new Error(
|
|
199
|
+
'Flag "useBase" must be set to true in the config for this feature.'
|
|
200
|
+
);
|
|
201
|
+
},
|
|
202
|
+
get: function () {
|
|
203
|
+
throw new Error(
|
|
204
|
+
'Flag "useBase" must be set to true in the config for this feature.'
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
157
211
|
return ComponentDefinition;
|
|
158
212
|
}
|
package/lib/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export { nestComponent } from "./nestComponent";
|
|
|
6
6
|
export { saveRef } from "./refs";
|
|
7
7
|
export { savePart } from "./part";
|
|
8
8
|
export { KeyedRepeater } from "./repeaters/keyed";
|
|
9
|
+
export { KeyedFnRepeater } from "./repeaters/keyedFn";
|
|
9
10
|
export { SequentialRepeater } from "./repeaters/sequential";
|
|
10
11
|
export { Router, route } from "./router";
|
|
11
12
|
export { getStub } from "./stubs";
|
package/lib/repeaters/keyed.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
// WARNING: Code here is near duplicated in keyedFn.
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Repeats nested components, reusing items based on key.
|
|
3
5
|
*
|
|
4
6
|
* @param {function} componentDefinition - The ComponentDefinition to create.
|
|
5
|
-
* @param {
|
|
7
|
+
* @param {string} keyName - The name of the key property.
|
|
6
8
|
*/
|
|
7
|
-
export function KeyedRepeater(componentDefinition,
|
|
9
|
+
export function KeyedRepeater(componentDefinition, keyName) {
|
|
8
10
|
this.def = componentDefinition;
|
|
9
|
-
this.
|
|
11
|
+
this.keyName = keyName;
|
|
10
12
|
this.keys = []; // array of keys as last set.
|
|
11
13
|
this.pool = {}; // pool of component instances.
|
|
12
14
|
}
|
|
@@ -22,7 +24,7 @@ export function KeyedRepeater(componentDefinition, keyFn) {
|
|
|
22
24
|
KeyedRepeater.prototype.patch = function (e, items, ctrl) {
|
|
23
25
|
const pool = this.pool,
|
|
24
26
|
componentDefinition = this.def,
|
|
25
|
-
|
|
27
|
+
keyName = this.keyName,
|
|
26
28
|
childNodes = e.childNodes,
|
|
27
29
|
itemsLength = items.length,
|
|
28
30
|
previousKeys = this.keys,
|
|
@@ -44,7 +46,7 @@ KeyedRepeater.prototype.patch = function (e, items, ctrl) {
|
|
|
44
46
|
const frag = document.createDocumentFragment();
|
|
45
47
|
while (i >= 0) {
|
|
46
48
|
item = items[i];
|
|
47
|
-
key =
|
|
49
|
+
key = item[keyName];
|
|
48
50
|
component = pool[key] || (pool[key] = new componentDefinition());
|
|
49
51
|
component.render(item, ctrl);
|
|
50
52
|
el = component.el;
|
|
@@ -0,0 +1,81 @@
|
|
|
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
|
+
let item,
|
|
35
|
+
el,
|
|
36
|
+
key,
|
|
37
|
+
component,
|
|
38
|
+
anchor = null,
|
|
39
|
+
fragAnchor = null,
|
|
40
|
+
untouched = true,
|
|
41
|
+
append = false,
|
|
42
|
+
offset = previousKeysLength - itemsLength,
|
|
43
|
+
i = itemsLength - 1;
|
|
44
|
+
|
|
45
|
+
// Working backwards saves us having to track moves.
|
|
46
|
+
const frag = document.createDocumentFragment();
|
|
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
|
+
};
|
|
@@ -43,7 +43,7 @@ SequentialRepeater.prototype.patch = function (e, items, ctrl) {
|
|
|
43
43
|
}
|
|
44
44
|
this.count = itemsLength;
|
|
45
45
|
let lastIndex = childNodes.length - 1;
|
|
46
|
-
|
|
46
|
+
const keepIndex = itemsLength - 1;
|
|
47
47
|
for (let i = lastIndex; i > keepIndex; i--) {
|
|
48
48
|
e.removeChild(childNodes[i]);
|
|
49
49
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -18,8 +18,10 @@
|
|
|
18
18
|
8. Stubs
|
|
19
19
|
9. TypeScript
|
|
20
20
|
10. Helpers
|
|
21
|
+
11. Flags
|
|
22
|
+
|
|
23
|
+
For more detailed documentation go to https://wallace.js.org/docs/
|
|
21
24
|
|
|
22
|
-
For more detailed documentation go to https://github.com/wallace-js/wallace
|
|
23
25
|
|
|
24
26
|
## 1. Components
|
|
25
27
|
|
|
@@ -519,6 +521,42 @@ const protectedObj = protect([]);
|
|
|
519
521
|
watchedObj[0] = 'foo'; // throws error.
|
|
520
522
|
```
|
|
521
523
|
|
|
524
|
+
## 11. Flags
|
|
525
|
+
|
|
526
|
+
You can toggle flags in your babel config to disable certain features for cutting edge
|
|
527
|
+
performance and bundle size:
|
|
528
|
+
|
|
529
|
+
1. useBase - enables use of `base` in components.
|
|
530
|
+
2. useControllers - enables use of `ctrl` in components.
|
|
531
|
+
3. useMethods - adds the `methods` helper to components.
|
|
532
|
+
4. useParts - enables use of parts.
|
|
533
|
+
5. useStubs - enables the use of stubs.
|
|
534
|
+
|
|
535
|
+
These flags default to true, unless you specify `flags` in the plugin config, in which
|
|
536
|
+
case they default to false and you need to explicitly enable those you want:
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
```tsx
|
|
540
|
+
module.exports = {
|
|
541
|
+
plugins: [
|
|
542
|
+
[
|
|
543
|
+
"babel-plugin-wallace",
|
|
544
|
+
{
|
|
545
|
+
flags: {
|
|
546
|
+
useControllers: true,
|
|
547
|
+
useStubs: false
|
|
548
|
+
},
|
|
549
|
+
}
|
|
550
|
+
],
|
|
551
|
+
"@babel/plugin-syntax-jsx"
|
|
552
|
+
],
|
|
553
|
+
presets: ["@babel/preset-typescript", ...]
|
|
554
|
+
};
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
The types (and therefore tool tips) are unaffected by these flags, and will treat them
|
|
558
|
+
all as being true.
|
|
559
|
+
|
|
522
560
|
---
|
|
523
561
|
Report any issues to https://github.com/wallace-js/wallace (and please give it a ★)
|
|
524
562
|
|
|
@@ -550,19 +588,18 @@ declare module "wallace" {
|
|
|
550
588
|
hide
|
|
551
589
|
}: {
|
|
552
590
|
props?: Props;
|
|
591
|
+
ctrl?: Controller;
|
|
553
592
|
show?: boolean;
|
|
554
593
|
hide?: boolean;
|
|
555
594
|
}): JSX.Element;
|
|
556
595
|
repeat?({
|
|
557
596
|
items,
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
hide
|
|
597
|
+
ctrl,
|
|
598
|
+
key
|
|
561
599
|
}: {
|
|
562
600
|
items: Array<Props>;
|
|
601
|
+
ctrl?: Controller;
|
|
563
602
|
key?: string | ((item: Props) => any);
|
|
564
|
-
show?: boolean;
|
|
565
|
-
hide?: boolean;
|
|
566
603
|
}): JSX.Element;
|
|
567
604
|
methods?: ComponenMethods<Props, Controller> &
|
|
568
605
|
ThisType<ComponentInstance<Props, Controller, Methods>>;
|
|
@@ -716,7 +753,7 @@ declare module "wallace" {
|
|
|
716
753
|
type WatchCallback = (target: any, key: string, value: any) => void;
|
|
717
754
|
|
|
718
755
|
/**
|
|
719
|
-
* Returns a Proxy of
|
|
756
|
+
* Returns a Proxy of the target which calls `callback` when it, or its nested objects
|
|
720
757
|
* are modified:
|
|
721
758
|
*
|
|
722
759
|
* ```js
|
|
@@ -729,6 +766,9 @@ declare module "wallace" {
|
|
|
729
766
|
* obj.y = {}
|
|
730
767
|
* obj.y.z = 1000
|
|
731
768
|
* ```
|
|
769
|
+
*
|
|
770
|
+
* The original object is also modified.
|
|
771
|
+
*
|
|
732
772
|
* The callback accepts parameters:
|
|
733
773
|
*
|
|
734
774
|
* - `target` - the object which is being modified.
|
|
@@ -737,10 +777,6 @@ declare module "wallace" {
|
|
|
737
777
|
*
|
|
738
778
|
* The callback is called after the modification has occured.
|
|
739
779
|
*
|
|
740
|
-
* Some methods like `Array.push` set the index and then the length immediately after,
|
|
741
|
-
* so we use a timeout period to avoid calling the callback twice for what is really a
|
|
742
|
-
* single operation.
|
|
743
|
-
*
|
|
744
780
|
* @param {*} target - Any object, including arrays.
|
|
745
781
|
* @param {*} callback - A callback function.
|
|
746
782
|
* @returns a Proxy of the object.
|
|
@@ -876,6 +912,17 @@ interface DirectiveAttributes extends AllDomEvents {
|
|
|
876
912
|
*/
|
|
877
913
|
css?: string;
|
|
878
914
|
|
|
915
|
+
/**
|
|
916
|
+
* ## Wallace directive: ctrl
|
|
917
|
+
*
|
|
918
|
+
* Specifies ctrl for nested/repeated components.
|
|
919
|
+
*
|
|
920
|
+
* ```
|
|
921
|
+
* <MyComponent.nest ctrl={aController} />
|
|
922
|
+
* ```
|
|
923
|
+
*/
|
|
924
|
+
ctrl?: any;
|
|
925
|
+
|
|
879
926
|
/**
|
|
880
927
|
* ## Wallace directive: fixed
|
|
881
928
|
*
|
|
@@ -1012,9 +1059,11 @@ interface DirectiveAttributes extends AllDomEvents {
|
|
|
1012
1059
|
toggle?: string;
|
|
1013
1060
|
|
|
1014
1061
|
/**
|
|
1015
|
-
*
|
|
1062
|
+
* ## Wallace directive: unique
|
|
1063
|
+
*
|
|
1064
|
+
* Performance optimisation that can be applied to a component which is only used once.
|
|
1016
1065
|
*/
|
|
1017
|
-
|
|
1066
|
+
unique?: boolean;
|
|
1018
1067
|
}
|
|
1019
1068
|
|
|
1020
1069
|
declare namespace JSX {
|
|
@@ -1037,20 +1086,22 @@ declare namespace JSX {
|
|
|
1037
1086
|
* - `bind` updates a value when an input is changed.
|
|
1038
1087
|
* - `class:xyz` defines a set of classes to be toggled.
|
|
1039
1088
|
* - `css` shorthand for `fixed:class`.
|
|
1089
|
+
* - `ctrl` specifies ctrl for nested/repeated components.
|
|
1040
1090
|
* - `fixed:xyz` sets a attribute from an expression at definition.
|
|
1041
1091
|
* - `hide` sets an element or component's hidden property.
|
|
1042
1092
|
* - `html` Set the element's `innnerHTML` property.
|
|
1043
1093
|
* - `if` excludes an element from the DOM.
|
|
1044
1094
|
* - `key` specifies a key for repeated items.
|
|
1045
1095
|
* - `items` set items for repeated component, must be an array of props.
|
|
1046
|
-
* - `on[EventName]` creates an event handler (note the code is copied)
|
|
1047
|
-
* - `part:xyz` saves a reference to part of a component so it can be updated
|
|
1048
|
-
* - `props`
|
|
1049
|
-
* - `ref:xyz` saves a reference to an element or nested
|
|
1096
|
+
* - `on[EventName]` creates an event handler (note the code is copied).
|
|
1097
|
+
* - `part:xyz` saves a reference to part of a component so it can be updated.
|
|
1098
|
+
* - `props` specifies props for a nested components.
|
|
1099
|
+
* - `ref:xyz` saves a reference to an element or nested component.
|
|
1050
1100
|
* - `show` sets and element or component's hidden property.
|
|
1051
1101
|
* - `style:xyz` sets a specific style property.
|
|
1052
1102
|
* - `toggle:xyz` toggles `xyz` as defined by `class:xyz` on same element, or class
|
|
1053
1103
|
* `xyz`.
|
|
1104
|
+
* - `unique` can be set on components which are only used once for better performance.
|
|
1054
1105
|
*
|
|
1055
1106
|
* You will get more details by hovering on the directive itself, but unfortunetely
|
|
1056
1107
|
* the tool tip won't display when you use a qualifier, like `class:danger`. To see
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wallace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"author": "Andrew Buchan",
|
|
5
5
|
"description": "An insanely small, fast, intuitive and extendable front-end framework",
|
|
6
|
+
"homepage": "https://wallace.js.org",
|
|
6
7
|
"license": "ISC",
|
|
7
8
|
"main": "lib/index.js",
|
|
8
9
|
"files": [
|
|
@@ -14,8 +15,8 @@
|
|
|
14
15
|
"test": "jest --clearCache && jest"
|
|
15
16
|
},
|
|
16
17
|
"dependencies": {
|
|
17
|
-
"babel-plugin-wallace": "^0.
|
|
18
|
+
"babel-plugin-wallace": "^0.12.0",
|
|
18
19
|
"browserify": "^17.0.1"
|
|
19
20
|
},
|
|
20
|
-
"gitHead": "
|
|
21
|
+
"gitHead": "bbaf61dd2313ba947efc3f35580626ca6f71fc84"
|
|
21
22
|
}
|