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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Wallace
2
2
 
3
- This package contains the library for the [Wallace](https://github.com/wallace-js/wallace) framework, which you import into your source files:
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://github.com/wallace-js/wallace).
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
- * The render function that gets called by parent components.
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
- * Updates the DOM and renders nested components.
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
- Object.defineProperty(ComponentFunction, "methods", {
138
- set: function (value) {
139
- Object.assign(proto, value);
140
- },
141
- get: function () {
142
- return proto;
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
- ComponentFunction.stubs = Object.assign({}, BaseComponentFunction.stubs);
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
- proto.base = ComponentPrototype;
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";
@@ -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 {function} keyFn - A function which obtains the key.
7
+ * @param {string} keyName - The name of the key property.
6
8
  */
7
- export function KeyedRepeater(componentDefinition, keyFn) {
9
+ export function KeyedRepeater(componentDefinition, keyName) {
8
10
  this.def = componentDefinition;
9
- this.keyFn = keyFn;
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
- keyFn = this.keyFn,
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 = keyFn(item);
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
- let keepIndex = itemsLength - 1;
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
- key,
559
- show,
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 an object which calls `callback` when it, or its nested objects
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
- * Foo
1062
+ * ## Wallace directive: unique
1063
+ *
1064
+ * Performance optimisation that can be applied to a component which is only used once.
1016
1065
  */
1017
- "class-a"?: string;
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` specifes props for a nested components.
1049
- * - `ref:xyz` saves a reference to an element or nested omponent.
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.10.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.10.0",
18
+ "babel-plugin-wallace": "^0.12.0",
18
19
  "browserify": "^17.0.1"
19
20
  },
20
- "gitHead": "5516e673ca0e4c0a01644701b914ca923e000580"
21
+ "gitHead": "bbaf61dd2313ba947efc3f35580626ca6f71fc84"
21
22
  }