wallace 0.0.8 → 0.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/lib/component.js CHANGED
@@ -1,3 +1,5 @@
1
+ const ALWAYS_UPDATE = "__";
2
+
1
3
  /**
2
4
  * The base component.
3
5
  */
@@ -8,18 +10,59 @@ export function Component() {
8
10
  this.ref = {}; // user set references to elements or components.
9
11
  // Internal state objects
10
12
  this._e = {}; // The dynamic elements in the DOM.
11
- this._p = {}; // The previous values for watches to compare against.
12
13
  this._s = []; // A stash for misc objects.
14
+ this._p = {}; // The previous values for watches to compare against.
15
+ this._r = {}; // The current values read during an update.
13
16
  }
14
17
 
18
+ Component.stubs = {};
19
+
15
20
  var proto = Component.prototype;
16
21
 
17
22
  Object.defineProperty(proto, "hidden", {
18
23
  set: function (value) {
19
24
  this.el.hidden = value;
20
- },
25
+ }
21
26
  });
22
27
 
28
+ proto._gs = function (name) {
29
+ return this.constructor.stubs[name];
30
+ };
31
+
32
+ /**
33
+ * Reads a query during update, returns an array with (oldValue, newValue, changed)
34
+ * and saves the old value. Must reset this._r before each run.
35
+ */
36
+ proto._rq = function (props, key) {
37
+ const run = this._r;
38
+ if (run[key] === undefined) {
39
+ let oldValue = this._p[key];
40
+ const newValue = this._q[key](props, this);
41
+ this._p[key] = newValue;
42
+ const rtn = [newValue, oldValue, newValue !== oldValue];
43
+ run[key] = rtn;
44
+ return rtn;
45
+ }
46
+ return run[key];
47
+ };
48
+
49
+ /**
50
+ * Applies the callbacks.
51
+ */
52
+ proto._ac = function (props, element, callbacks) {
53
+ for (let key in callbacks) {
54
+ let callback = callbacks[key];
55
+ if (key === ALWAYS_UPDATE) {
56
+ callback(element, props, this);
57
+ } else {
58
+ const result = this._rq(props, key);
59
+ if (result[2]) {
60
+ callback(element, props, this, result[0]);
61
+ }
62
+ }
63
+ }
64
+ };
65
+
23
66
  /**
24
67
  * The render function that gets called by parent components.
25
68
  */
@@ -40,10 +83,8 @@ proto.update = function () {
40
83
  parent,
41
84
  displayToggle,
42
85
  detacher,
43
- lookupReturn,
44
86
  lookupTrue,
45
87
  shouldBeVisible,
46
- visibilityChanged,
47
88
  detachedElements,
48
89
  detachedElement,
49
90
  index,
@@ -51,11 +92,10 @@ proto.update = function () {
51
92
  thisElement;
52
93
 
53
94
  const watches = this._w;
54
- const lookup = this._l;
55
95
  const props = this.props;
56
- lookup.reset();
57
96
  const il = watches.length;
58
- /*
97
+ this._r = {};
98
+ /*
59
99
  Watches is an array of objects with keys:
60
100
  e: the element reference (string)
61
101
  c: the callbacks (object)
@@ -79,10 +119,8 @@ proto.update = function () {
79
119
  i++;
80
120
  shouldBeVisible = true;
81
121
  if (displayToggle) {
82
- lookupReturn = lookup.get(this, props, displayToggle.q);
83
- lookupTrue = !!lookupReturn.n;
122
+ lookupTrue = !!this._rq(props, displayToggle.q)[0];
84
123
  shouldBeVisible = displayToggle.r ? lookupTrue : !lookupTrue;
85
- visibilityChanged = lookupTrue != !!lookupReturn.o;
86
124
  detacher = displayToggle.d;
87
125
  if (detacher) {
88
126
  index = detacher.i;
@@ -95,10 +133,7 @@ proto.update = function () {
95
133
  Object.keys(detachedElements).filter(function (k) {
96
134
  return k < index && detachedElements[k];
97
135
  }).length;
98
- parent.insertBefore(
99
- detachedElement,
100
- parent.childNodes[adjustedIndex],
101
- );
136
+ parent.insertBefore(detachedElement, parent.childNodes[adjustedIndex]);
102
137
  detachedElements[index] = null;
103
138
  } else if (!shouldBeVisible && !detachedElement) {
104
139
  thisElement = this._e[watch.e];
@@ -113,7 +148,7 @@ proto.update = function () {
113
148
  }
114
149
  }
115
150
  if (shouldBeVisible) {
116
- lookup.applyCallbacks(this, props, element, watch.c);
151
+ this._ac(props, element, watch.c);
117
152
  }
118
153
  }
119
154
  };
package/lib/index.js CHANGED
@@ -1,26 +1,22 @@
1
- import { createComponent, watch, mount } from "./utils";
1
+ import { mount, watch } from "./utils";
2
2
  import { Component } from "./component";
3
3
  import { KeyedRepeater, SequentialRepeater } from "./repeaters";
4
4
  import {
5
5
  extendComponent,
6
+ defineComponent,
6
7
  findElement,
7
8
  getKeyedRepeater,
8
9
  getSequentialRepeater,
9
10
  onEvent,
10
11
  nestComponent,
11
- defineComponent,
12
- extendPrototype,
13
- stashMisc,
14
12
  saveRef,
13
+ stashMisc
15
14
  } from "./initCalls";
16
15
 
17
16
  export {
18
- extendComponent,
19
17
  Component,
20
- createComponent,
21
- watch,
22
18
  defineComponent,
23
- extendPrototype,
19
+ extendComponent,
24
20
  findElement,
25
21
  getKeyedRepeater,
26
22
  getSequentialRepeater,
@@ -28,7 +24,8 @@ export {
28
24
  mount,
29
25
  nestComponent,
30
26
  onEvent,
31
- stashMisc,
32
27
  saveRef,
33
28
  SequentialRepeater,
29
+ stashMisc,
30
+ watch
34
31
  };
package/lib/initCalls.js CHANGED
@@ -1,103 +1,92 @@
1
1
  import { Component } from "./component";
2
- import { Lookup } from "./lookup";
3
2
  import { buildComponent, replaceNode } from "./utils";
4
3
  import { KeyedRepeater, SequentialRepeater } from "./repeaters";
5
4
  const throwAway = document.createElement("template");
6
5
 
7
6
  /**
8
- * Create an element from html string
7
+ * Create an element from html string.
9
8
  */
10
9
  function makeEl(html) {
11
10
  throwAway.innerHTML = html;
12
11
  return throwAway.content.firstChild;
13
12
  }
14
13
 
15
- export const getProps = (component) => {
16
- return component.props;
17
- };
18
-
19
- export const findElement = (rootElement, path) => {
14
+ export function findElement(rootElement, path) {
20
15
  return path.reduce((acc, index) => acc.childNodes[index], rootElement);
21
- };
16
+ }
22
17
 
23
- export const nestComponent = (rootElement, path, cls) => {
18
+ export function nestComponent(rootElement, path, cls) {
24
19
  const el = findElement(rootElement, path),
25
20
  child = buildComponent(cls);
26
21
  replaceNode(el, child.el);
27
22
  return child;
28
- };
23
+ }
29
24
 
30
25
  /**
31
26
  * Saves a reference to element or nested component. Returns the element.
32
27
  */
33
- export const saveRef = (element, component, name) => {
28
+ export function saveRef(element, component, name) {
34
29
  component.ref[name] = element;
35
30
  return element;
36
- };
31
+ }
37
32
 
38
33
  /**
39
34
  * Stash something on the component. Returns the element.
40
35
  * The generated code is expected to keep track of the position.
41
36
  */
42
- export const stashMisc = (element, component, object) => {
37
+ export function stashMisc(element, component, object) {
43
38
  component._s.push(object);
44
39
  return element;
45
- };
40
+ }
46
41
 
47
- export const onEvent = (element, eventName, callback) => {
42
+ export function onEvent(element, eventName, callback) {
48
43
  element.addEventListener(eventName, callback);
49
44
  return element;
50
- };
45
+ }
51
46
 
52
- export const getKeyedRepeater = (cls, keyFn) => {
47
+ export function getKeyedRepeater(cls, keyFn) {
53
48
  return new KeyedRepeater(cls, keyFn);
54
- };
49
+ }
55
50
 
56
- export const getSequentialRepeater = (cls) => {
51
+ export function getSequentialRepeater(cls) {
57
52
  return new SequentialRepeater(cls);
58
- };
53
+ }
59
54
 
60
- export function defineComponent(
61
- html,
62
- watches,
63
- lookups,
64
- buildFunction,
65
- inheritFrom,
66
- prototypeExtras,
67
- ) {
68
- const Constructor = extendPrototype(
69
- inheritFrom || Component,
70
- prototypeExtras,
71
- );
72
- extendComponent(Constructor.prototype, html, watches, lookups, buildFunction);
73
- return Constructor;
55
+ export function extendComponent(base, componentDef) {
56
+ // This function call will have been replaced if 2nd arg is a valid component func.
57
+ // and therefor we would not receive it.
58
+ if (componentDef)
59
+ throw new Error("2nd arg to extendComponent must be a JSX arrow function");
60
+ return _createConstructor(base);
74
61
  }
75
62
 
76
- export function extendComponent(
77
- prototype,
78
- html,
79
- watches,
80
- lookups,
81
- buildFunction,
82
- ) {
63
+ export function defineComponent(html, watches, queries, buildFunction, inheritFrom) {
64
+ const ComponentDefinition = _createConstructor(inheritFrom || Component);
65
+ const prototype = ComponentDefinition.prototype;
83
66
  //Ensure these do not clash with fields on the component itself.
84
67
  prototype._w = watches;
85
- prototype._l = new Lookup(lookups);
68
+ prototype._q = queries;
86
69
  prototype._b = buildFunction;
87
70
  prototype._n = makeEl(html);
71
+ return ComponentDefinition;
88
72
  }
89
73
 
90
- export function extendPrototype(base, prototypeExtras) {
91
- const Constructor = function () {
74
+ function _createConstructor(base) {
75
+ const ComponentDefinition = function () {
92
76
  base.call(this);
93
77
  };
94
- Constructor.prototype = Object.create(base && base.prototype, {
78
+ ComponentDefinition.stubs = {};
79
+ Object.assign(ComponentDefinition.stubs, base.stubs);
80
+ // This is a helper function for the user.
81
+ ComponentDefinition.methods = function (obj) {
82
+ Object.assign(ComponentDefinition.prototype, obj);
83
+ };
84
+ ComponentDefinition.prototype = Object.create(base && base.prototype, {
95
85
  constructor: {
96
- value: Constructor,
86
+ value: ComponentDefinition,
97
87
  writable: true,
98
- configurable: true,
99
- },
88
+ configurable: true
89
+ }
100
90
  });
101
- Object.assign(Constructor.prototype, prototypeExtras);
102
- return Constructor;
91
+ return ComponentDefinition;
103
92
  }
package/lib/repeaters.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createComponent } from "./utils";
1
+ import { buildComponent } from "./utils";
2
2
 
3
3
  /*
4
4
  * Gets a component from the pool.
@@ -7,11 +7,11 @@ function getComponent(pool, componentDefinition, ctrl, key, props) {
7
7
  let component;
8
8
  if (pool.hasOwnProperty(key)) {
9
9
  component = pool[key];
10
- component.render(props, ctrl);
11
10
  } else {
12
- component = createComponent(componentDefinition, props, ctrl);
11
+ component = buildComponent(componentDefinition);
13
12
  pool[key] = component;
14
13
  }
14
+ component.render(props, ctrl);
15
15
  return component;
16
16
  }
17
17
 
@@ -50,10 +50,10 @@ function pull(arr, item, to) {
50
50
  * @param {function} keyFn - A function which obtains the key.
51
51
  */
52
52
  export function KeyedRepeater(componentDefinition, keyFn) {
53
- this._v = componentDefinition;
54
- this._f = keyFn;
55
- this._k = []; // keys
56
- this._p = {}; // pool of component instances
53
+ this.def = componentDefinition;
54
+ this.keyFn = keyFn;
55
+ this.keys = []; // keys
56
+ this.pool = {}; // pool of component instances
57
57
  }
58
58
  const proto = KeyedRepeater.prototype;
59
59
 
@@ -64,7 +64,7 @@ const proto = KeyedRepeater.prototype;
64
64
  * @param {Object} item - The item which will be passed as props.
65
65
  */
66
66
  proto.getOne = function (item, ctrl) {
67
- return getComponent(this._p, this._v, ctrl, this._f(item), item);
67
+ return getComponent(this.pool, this.def, ctrl, this.keyFn(item), item);
68
68
  };
69
69
 
70
70
  /**
@@ -77,12 +77,12 @@ proto.getOne = function (item, ctrl) {
77
77
  proto.patch = function (e, items, ctrl) {
78
78
  // Attempt to speed up by reducing lookups. Does this even do anything?
79
79
  // Does webpack undo this/do it for for me? Does the engine?
80
- const pool = this._p;
81
- const componentDefinition = this._v;
82
- const keyFn = this._f;
80
+ const pool = this.pool;
81
+ const componentDefinition = this.def;
82
+ const keyFn = this.keyFn;
83
83
  const childNodes = e.childNodes;
84
84
  const itemsLength = items.length;
85
- const oldKeySequence = this._k;
85
+ const oldKeySequence = this.keys;
86
86
  const newKeys = [];
87
87
  let item,
88
88
  key,
@@ -100,7 +100,7 @@ proto.patch = function (e, items, ctrl) {
100
100
  pull(oldKeySequence, key, i);
101
101
  }
102
102
  }
103
- this._k = newKeys;
103
+ this.keys = newKeys;
104
104
  trimChildren(e, childNodes, itemsLength);
105
105
  };
106
106
 
@@ -110,9 +110,9 @@ proto.patch = function (e, items, ctrl) {
110
110
  * @param {componentDefinition} componentDefinition - The class ComponentDefinition to create.
111
111
  */
112
112
  export function SequentialRepeater(componentDefinition) {
113
- this._v = componentDefinition;
114
- this._p = []; // pool of component instances
115
- this._c = 0; // Child element count
113
+ this.def = componentDefinition;
114
+ this.pool = []; // pool of component instances
115
+ this.count = 0; // Child element count
116
116
  }
117
117
 
118
118
  /**
@@ -124,29 +124,27 @@ export function SequentialRepeater(componentDefinition) {
124
124
  * @param {any} ctrl - The parent item's controller.
125
125
  */
126
126
  SequentialRepeater.prototype.patch = function (e, items, ctrl) {
127
- const pool = this._p;
128
- const componentDefinition = this._v;
127
+ const pool = this.pool;
128
+ const componentDefinition = this.def;
129
129
  const childNodes = e.childNodes;
130
130
  const itemsLength = items.length;
131
- let item,
132
- component,
131
+ let component,
133
132
  poolCount = pool.length,
134
- childElementCount = this._c;
133
+ childElementCount = this.count;
135
134
 
136
135
  for (let i = 0; i < itemsLength; i++) {
137
- item = items[i];
138
136
  if (i < poolCount) {
139
137
  component = pool[i];
140
- component.render(item, ctrl);
141
138
  } else {
142
- component = createComponent(componentDefinition, item, ctrl);
139
+ component = buildComponent(componentDefinition);
143
140
  pool.push(component);
144
141
  poolCount++;
145
142
  }
143
+ component.render(items[i], ctrl);
146
144
  if (i >= childElementCount) {
147
145
  e.appendChild(component.el);
148
146
  }
149
147
  }
150
- this._c = itemsLength;
148
+ this.count = itemsLength;
151
149
  trimChildren(e, childNodes, itemsLength);
152
150
  };