wallace 0.4.0 → 0.5.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 +29 -0
- package/lib/component.js +12 -8
- package/lib/index.js +2 -5
- package/lib/initCalls.js +28 -20
- package/lib/repeaters.js +2 -4
- package/lib/types.d.ts +98 -35
- package/lib/utils.js +28 -35
- package/package.json +3 -3
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Wallace
|
|
2
|
+
|
|
3
|
+
This package contains the library for the [Wallace](https://github.com/wallace-js/wallace) framework, which you import into your source files:
|
|
4
|
+
|
|
5
|
+
```jsx
|
|
6
|
+
import { mount } from "wallace";
|
|
7
|
+
|
|
8
|
+
const MyComponent = () => <div>Hello world</div>;
|
|
9
|
+
|
|
10
|
+
mount("main", Component);
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
It requires the [babel-plugin-wallace](https://www.npmjs.com/package/babel-plugin-wallace) to work, which is a dependency of this package, always at the same version.
|
|
14
|
+
|
|
15
|
+
Although you can install these packages with:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
npm i wallace -D
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
You are better off creating an empty project with:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
npx create-wallace-app
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
As that sets up your babel and webpack configurations for you.
|
|
28
|
+
|
|
29
|
+
For more detailed documentation see the [Wallace repository on github](https://github.com/wallace-js/wallace).
|
package/lib/component.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
const NO_LOOKUP = "__";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* The base component.
|
|
4
|
+
* The base component constructor.
|
|
5
5
|
*/
|
|
6
6
|
export function Component() {
|
|
7
|
-
this.ctrl = undefined;
|
|
8
|
-
this.props = undefined;
|
|
9
|
-
|
|
10
|
-
this.
|
|
11
|
-
// Internal state objects
|
|
12
|
-
this._e = {}; // The dynamic elements in the DOM.
|
|
13
|
-
this._s = []; // A stash for misc objects.
|
|
7
|
+
this.ctrl = undefined;
|
|
8
|
+
this.props = undefined;
|
|
9
|
+
// Internal state objects (_e is created during build)
|
|
10
|
+
this._s = []; // A stash for misc objects like repeaters.
|
|
14
11
|
this._p = {}; // The previous values for watches to compare against.
|
|
15
12
|
this._r = {}; // The current values read during an update.
|
|
13
|
+
const root = this._n.cloneNode(true);
|
|
14
|
+
this.el = root;
|
|
15
|
+
this.ref = {};
|
|
16
|
+
this._b(this, root);
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
Component.stubs = {};
|
|
@@ -25,6 +26,9 @@ Object.defineProperty(proto, "hidden", {
|
|
|
25
26
|
}
|
|
26
27
|
});
|
|
27
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Gets a stub by name.
|
|
31
|
+
*/
|
|
28
32
|
proto._gs = function (name) {
|
|
29
33
|
return this.constructor.stubs[name];
|
|
30
34
|
};
|
package/lib/index.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { mount, watch } from "./utils";
|
|
1
|
+
import { mount, watch, protect } from "./utils";
|
|
2
2
|
import { Component } from "./component";
|
|
3
3
|
import { KeyedRepeater, SequentialRepeater } from "./repeaters";
|
|
4
4
|
import {
|
|
5
5
|
extendComponent,
|
|
6
6
|
defineComponent,
|
|
7
7
|
findElement,
|
|
8
|
-
getKeyedRepeater,
|
|
9
|
-
getSequentialRepeater,
|
|
10
8
|
onEvent,
|
|
11
9
|
nestComponent,
|
|
12
10
|
saveRef,
|
|
@@ -18,12 +16,11 @@ export {
|
|
|
18
16
|
defineComponent,
|
|
19
17
|
extendComponent,
|
|
20
18
|
findElement,
|
|
21
|
-
getKeyedRepeater,
|
|
22
|
-
getSequentialRepeater,
|
|
23
19
|
KeyedRepeater,
|
|
24
20
|
mount,
|
|
25
21
|
nestComponent,
|
|
26
22
|
onEvent,
|
|
23
|
+
protect,
|
|
27
24
|
saveRef,
|
|
28
25
|
SequentialRepeater,
|
|
29
26
|
stashMisc,
|
package/lib/initCalls.js
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* Everything in here is used by or modified by the Babel plugin.
|
|
3
3
|
*/
|
|
4
4
|
import { Component } from "./component";
|
|
5
|
-
import {
|
|
6
|
-
import { KeyedRepeater, SequentialRepeater } from "./repeaters";
|
|
5
|
+
import { replaceNode } from "./utils";
|
|
7
6
|
|
|
8
7
|
const throwAway = document.createElement("template");
|
|
9
8
|
|
|
@@ -37,9 +36,9 @@ export function findElement(rootElement, path) {
|
|
|
37
36
|
return path.reduce((acc, index) => acc.childNodes[index], rootElement);
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
export function nestComponent(rootElement, path,
|
|
39
|
+
export function nestComponent(rootElement, path, componentDefinition) {
|
|
41
40
|
const el = findElement(rootElement, path),
|
|
42
|
-
child =
|
|
41
|
+
child = new componentDefinition();
|
|
43
42
|
replaceNode(el, child.el);
|
|
44
43
|
return child;
|
|
45
44
|
}
|
|
@@ -66,14 +65,6 @@ export function onEvent(element, eventName, callback) {
|
|
|
66
65
|
return element;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
export function getKeyedRepeater(cls, keyFn) {
|
|
70
|
-
return new KeyedRepeater(cls, keyFn);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function getSequentialRepeater(cls) {
|
|
74
|
-
return new SequentialRepeater(cls);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
68
|
export function defineComponent(html, watches, queries, buildFunction, inheritFrom) {
|
|
78
69
|
const ComponentDefinition = _createConstructor(inheritFrom || Component);
|
|
79
70
|
const prototype = ComponentDefinition.prototype;
|
|
@@ -86,23 +77,40 @@ export function defineComponent(html, watches, queries, buildFunction, inheritFr
|
|
|
86
77
|
return ComponentDefinition;
|
|
87
78
|
}
|
|
88
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Creates a new component definition.
|
|
82
|
+
*
|
|
83
|
+
* @param {*} base - a component definition to inherit from - defaults to Component.
|
|
84
|
+
* @returns the newly created component definition function.
|
|
85
|
+
*/
|
|
89
86
|
function _createConstructor(base) {
|
|
90
87
|
const ComponentDefinition = function () {
|
|
91
88
|
base.call(this);
|
|
92
89
|
};
|
|
93
|
-
|
|
94
|
-
Object.assign(ComponentDefinition.stubs, base.stubs);
|
|
95
|
-
// This is a helper function for the user.
|
|
96
|
-
ComponentDefinition.methods = function (obj) {
|
|
97
|
-
Object.assign(ComponentDefinition.prototype, obj);
|
|
98
|
-
};
|
|
99
|
-
ComponentDefinition.prototype = Object.create(base && base.prototype, {
|
|
90
|
+
const proto = Object.create(base && base.prototype, {
|
|
100
91
|
constructor: {
|
|
101
92
|
value: ComponentDefinition,
|
|
102
93
|
writable: true,
|
|
103
94
|
configurable: true
|
|
104
95
|
}
|
|
105
96
|
});
|
|
106
|
-
ComponentDefinition.prototype
|
|
97
|
+
ComponentDefinition.prototype = proto;
|
|
98
|
+
|
|
99
|
+
// methods lets us assign to prototype without replacing it.
|
|
100
|
+
Object.defineProperty(ComponentDefinition, "methods", {
|
|
101
|
+
set: function (value) {
|
|
102
|
+
Object.assign(proto, value);
|
|
103
|
+
},
|
|
104
|
+
get: function () {
|
|
105
|
+
return proto;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Set up stubs
|
|
110
|
+
ComponentDefinition.stubs = {};
|
|
111
|
+
Object.assign(ComponentDefinition.stubs, base.stubs);
|
|
112
|
+
|
|
113
|
+
// Helper to access base prototype.
|
|
114
|
+
proto.base = Component.prototype;
|
|
107
115
|
return ComponentDefinition;
|
|
108
116
|
}
|
package/lib/repeaters.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { buildComponent } from "./utils";
|
|
2
|
-
|
|
3
1
|
/*
|
|
4
2
|
* Gets a component from the pool.
|
|
5
3
|
*/
|
|
@@ -8,7 +6,7 @@ function getComponent(pool, componentDefinition, ctrl, key, props) {
|
|
|
8
6
|
if (pool.hasOwnProperty(key)) {
|
|
9
7
|
component = pool[key];
|
|
10
8
|
} else {
|
|
11
|
-
component =
|
|
9
|
+
component = new componentDefinition();
|
|
12
10
|
pool[key] = component;
|
|
13
11
|
}
|
|
14
12
|
component.render(props, ctrl);
|
|
@@ -136,7 +134,7 @@ SequentialRepeater.prototype.patch = function (e, items, ctrl) {
|
|
|
136
134
|
if (i < poolCount) {
|
|
137
135
|
component = pool[i];
|
|
138
136
|
} else {
|
|
139
|
-
component =
|
|
137
|
+
component = new componentDefinition();
|
|
140
138
|
pool.push(component);
|
|
141
139
|
poolCount++;
|
|
142
140
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
6. Inheritance
|
|
17
17
|
7. Stubs
|
|
18
18
|
8. TypeScript
|
|
19
|
-
9.
|
|
19
|
+
9. Helpers
|
|
20
20
|
|
|
21
21
|
For more detailed documentation go to https://github.com/wallace-js/wallace
|
|
22
22
|
|
|
@@ -71,7 +71,7 @@ The arguments are:
|
|
|
71
71
|
3. props for the element (optional)
|
|
72
72
|
4. controller (optional)
|
|
73
73
|
|
|
74
|
-
`mount` returns the component instance, allowing you to call
|
|
74
|
+
`mount` returns the component instance, allowing you to call its methods:
|
|
75
75
|
|
|
76
76
|
```tsx
|
|
77
77
|
root.update();
|
|
@@ -100,11 +100,11 @@ places.
|
|
|
100
100
|
|
|
101
101
|
#### Overriding
|
|
102
102
|
|
|
103
|
-
You can override these methods, and add new ones using `methods`
|
|
103
|
+
You can override these methods, and add new ones using `methods` property of the
|
|
104
104
|
component definition:
|
|
105
105
|
|
|
106
106
|
```tsx
|
|
107
|
-
MyComponent.methods
|
|
107
|
+
MyComponent.methods = {
|
|
108
108
|
render(props) {
|
|
109
109
|
this.ctrl = new MyController(this, props);
|
|
110
110
|
this.update();
|
|
@@ -112,7 +112,7 @@ MyComponent.methods({
|
|
|
112
112
|
getName() {
|
|
113
113
|
return 'wallace';
|
|
114
114
|
}
|
|
115
|
-
}
|
|
115
|
+
};
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
This has the same effect as setting them on the prototype:
|
|
@@ -124,11 +124,11 @@ MyComponent.prototype.render = function () {};
|
|
|
124
124
|
You can use `this.base` to access methods on the base `Component` class:
|
|
125
125
|
|
|
126
126
|
```tsx
|
|
127
|
-
MyComponent.methods
|
|
127
|
+
MyComponent.methods = {
|
|
128
128
|
render(props) {
|
|
129
129
|
this.base.render.call(this, props, ctrl);
|
|
130
130
|
}
|
|
131
|
-
}
|
|
131
|
+
};
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
Note that `base` is not the same as `super` in classes which access the lowest override.
|
|
@@ -201,11 +201,22 @@ Notes:
|
|
|
201
201
|
|
|
202
202
|
## 4. Directives
|
|
203
203
|
|
|
204
|
-
Directives are attributes with special behaviours
|
|
204
|
+
Directives are attributes with special behaviours.
|
|
205
|
+
|
|
206
|
+
You can see the list of available directives by hovering over any JSX element, like
|
|
207
|
+
a `div`
|
|
208
|
+
|
|
209
|
+
You will get more details by hovering on the directive itself, but unfortunetely the
|
|
210
|
+
tool tip won't display when you use a qualifier, like `class:danger`. To see it you can
|
|
211
|
+
temporarily change it to something `class x:danger`.
|
|
212
|
+
|
|
213
|
+
You can define your own directives in your babel config.
|
|
214
|
+
|
|
215
|
+
Each has more
|
|
205
216
|
detailed information on its JSDoc, which should display as a tool tip\* when you hover
|
|
206
217
|
over it in your IDE.
|
|
207
218
|
|
|
208
|
-
You can also
|
|
219
|
+
You can also
|
|
209
220
|
|
|
210
221
|
- `apply` runs a callback to modify an element.
|
|
211
222
|
- `bind` updates a value when an input is changed.
|
|
@@ -221,7 +232,6 @@ an array.
|
|
|
221
232
|
- `style:xyz` sets a specific style property.
|
|
222
233
|
- `toggle:xyz` toggles `xyz` as defined by `class:xyz` on same element, or class `xyz`.
|
|
223
234
|
|
|
224
|
-
\* The tool tip won't display when you use a qualifier, like `class:danger`.
|
|
225
235
|
|
|
226
236
|
## 5. Controllers
|
|
227
237
|
|
|
@@ -266,12 +276,12 @@ const TaskList = (_, {ctrl}) => (
|
|
|
266
276
|
</div>
|
|
267
277
|
);
|
|
268
278
|
|
|
269
|
-
TaskList.methods
|
|
279
|
+
TaskList.methods = {
|
|
270
280
|
render(_, ctrl) {
|
|
271
281
|
this.ctrl = new TaskController(this, ctrl);
|
|
272
282
|
this.update();
|
|
273
283
|
}
|
|
274
|
-
}
|
|
284
|
+
};
|
|
275
285
|
```
|
|
276
286
|
|
|
277
287
|
## 6. Inheritance
|
|
@@ -392,12 +402,12 @@ const Task: Uses<null, null, TaskMethods> = (_, { self }) => (
|
|
|
392
402
|
<div>{self.getName()}</div>
|
|
393
403
|
));
|
|
394
404
|
|
|
395
|
-
Task.methods
|
|
405
|
+
Task.methods = {
|
|
396
406
|
getName() { return 'wallace' },
|
|
397
407
|
render(props, ctrl) { // types are already known
|
|
398
408
|
this.props = { ...props, notallowed: 1 }; // type error
|
|
399
409
|
}
|
|
400
|
-
}
|
|
410
|
+
};
|
|
401
411
|
```
|
|
402
412
|
|
|
403
413
|
The type will pass into the object passed into `methods` so it recognises custom methods
|
|
@@ -445,7 +455,7 @@ Wallace defines some other types you may use:
|
|
|
445
455
|
constructor, not a class)
|
|
446
456
|
- `ComponentInstance<Props, Controller, Methods>` - a component instance.
|
|
447
457
|
|
|
448
|
-
##
|
|
458
|
+
## 9. Helpers
|
|
449
459
|
|
|
450
460
|
Each of these has their own JSDoc, we just lsit them here.
|
|
451
461
|
|
|
@@ -469,11 +479,24 @@ mount("elementId", MyComponent, props, ctrl);
|
|
|
469
479
|
|
|
470
480
|
### watch
|
|
471
481
|
|
|
472
|
-
Returns a Proxy of an object which calls `callback` when
|
|
482
|
+
Returns a Proxy of an object which calls `callback` when it, or its nested objects are
|
|
483
|
+
modified:
|
|
484
|
+
|
|
485
|
+
```
|
|
486
|
+
const watchedObj = watch([], () => console.log('obj modified));
|
|
487
|
+
watchedObj[0] = 'foo; // Calls callback.
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### protect
|
|
491
|
+
|
|
492
|
+
Returns a Proxy of an object which throws an error if it, or its nested objects are
|
|
493
|
+
modified.
|
|
473
494
|
|
|
474
495
|
```
|
|
475
|
-
|
|
496
|
+
const protectedObj = protect([]);
|
|
497
|
+
watchedObj[0] = 'foo'; // throws error.
|
|
476
498
|
```
|
|
499
|
+
|
|
477
500
|
---
|
|
478
501
|
Report any issues to https://github.com/wallace-js/wallace (and please give it a ★)
|
|
479
502
|
|
|
@@ -495,9 +518,7 @@ declare module "wallace" {
|
|
|
495
518
|
ctrl: Controller;
|
|
496
519
|
self: ComponentInstance<Props, Controller, Methods>;
|
|
497
520
|
event: Event;
|
|
498
|
-
ev: Event;
|
|
499
521
|
element: HTMLElement;
|
|
500
|
-
el: HTMLElement;
|
|
501
522
|
}
|
|
502
523
|
): JSX.Element;
|
|
503
524
|
nest?({
|
|
@@ -518,10 +539,8 @@ declare module "wallace" {
|
|
|
518
539
|
show?: boolean;
|
|
519
540
|
hide?: boolean;
|
|
520
541
|
}): JSX.Element;
|
|
521
|
-
methods
|
|
522
|
-
|
|
523
|
-
ThisType<ComponentInstance<Props, Controller, Methods>>
|
|
524
|
-
): void;
|
|
542
|
+
// methods?: ComponenMethods<Props, Controller> &
|
|
543
|
+
// ThisType<ComponentInstance<Props, Controller, Methods>>;
|
|
525
544
|
readonly prototype?: ComponenMethods<Props, Controller> &
|
|
526
545
|
ThisType<ComponentInstance<Props, Controller, Methods>>;
|
|
527
546
|
// Methods will not be available on nested component, so omit.
|
|
@@ -643,8 +662,21 @@ declare module "wallace" {
|
|
|
643
662
|
): ComponentInstance<Props, Controller, Methods>;
|
|
644
663
|
|
|
645
664
|
/**
|
|
646
|
-
* Returns a Proxy of an object which
|
|
647
|
-
*
|
|
665
|
+
* Returns a Proxy of an object which throws an error when it, or its nested objects
|
|
666
|
+
* are modified:
|
|
667
|
+
*
|
|
668
|
+
* ```js
|
|
669
|
+
* const protectedObj = protect([]);
|
|
670
|
+
* watchedObj[0] = 'foo'; // throws error.
|
|
671
|
+
* ```
|
|
672
|
+
*/
|
|
673
|
+
export function protect<T>(target: T): T;
|
|
674
|
+
|
|
675
|
+
type WatchCallback = (target: any, key: string, value: any) => void;
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Returns a Proxy of an object which calls `callback` when it, or its nested objects
|
|
679
|
+
* are modified:
|
|
648
680
|
*
|
|
649
681
|
* ```js
|
|
650
682
|
* ar = watch([], callback)
|
|
@@ -656,18 +688,23 @@ declare module "wallace" {
|
|
|
656
688
|
* obj.y = {}
|
|
657
689
|
* obj.y.z = 1000
|
|
658
690
|
* ```
|
|
659
|
-
* The callback
|
|
691
|
+
* The callback accepts parameters:
|
|
692
|
+
*
|
|
693
|
+
* - `target` - the object which is being modified.
|
|
694
|
+
* - `key` - the key being set.
|
|
695
|
+
* - `value` - the value it is being set to.
|
|
696
|
+
*
|
|
697
|
+
* The callback is called after the modification has occured.
|
|
660
698
|
*
|
|
661
699
|
* Some methods like `Array.push` set the index and then the length immediately after,
|
|
662
700
|
* so we use a timeout period to avoid calling the callback twice for what is really a
|
|
663
701
|
* single operation.
|
|
664
702
|
*
|
|
665
703
|
* @param {*} target - Any object, including arrays.
|
|
666
|
-
* @param {*} timeout - Any value in ms. Defaults to 100.
|
|
667
704
|
* @param {*} callback - A callback function.
|
|
668
705
|
* @returns a Proxy of the object.
|
|
669
706
|
*/
|
|
670
|
-
export function watch<T>(target: T, callback:
|
|
707
|
+
export function watch<T>(target: T, callback: WatchCallback): T;
|
|
671
708
|
}
|
|
672
709
|
|
|
673
710
|
type MustBeExpression = Exclude<any, string>;
|
|
@@ -739,8 +776,6 @@ interface DirectiveAttributes extends AllDomEvents {
|
|
|
739
776
|
* );
|
|
740
777
|
* ```
|
|
741
778
|
*
|
|
742
|
-
* Unfortunately you lose the tooltip in that format.
|
|
743
|
-
*
|
|
744
779
|
* Note that destructured props are converted to member expressions, so these examples
|
|
745
780
|
* work even though it looks like you're setting a local variable.
|
|
746
781
|
*/
|
|
@@ -760,11 +795,34 @@ interface DirectiveAttributes extends AllDomEvents {
|
|
|
760
795
|
* ```
|
|
761
796
|
* <div class:danger="danger red" toggle:danger={expr}></div>
|
|
762
797
|
* ```
|
|
763
|
-
*
|
|
764
|
-
* Unfortunately you lose the tooltip in that format.
|
|
765
798
|
*/
|
|
766
799
|
class?: any;
|
|
767
800
|
|
|
801
|
+
/**
|
|
802
|
+
* ## Wallace directive: css
|
|
803
|
+
*
|
|
804
|
+
* Shorthand for `fixed:class`:
|
|
805
|
+
*
|
|
806
|
+
* ```
|
|
807
|
+
* <div css={foo} ></div>
|
|
808
|
+
* ```
|
|
809
|
+
*/
|
|
810
|
+
css?: string;
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* ## Wallace directive: fixed
|
|
814
|
+
*
|
|
815
|
+
* Sets the value of an attribute from an expression at point of component definition,
|
|
816
|
+
* as such the expression may not access props or xargs. See also `css` directive.
|
|
817
|
+
*
|
|
818
|
+
* Requires a qualifer, which is the name of the attribute to set.
|
|
819
|
+
*
|
|
820
|
+
* ```
|
|
821
|
+
* <div fixed:class={foo} ></div>
|
|
822
|
+
* ```
|
|
823
|
+
*/
|
|
824
|
+
fixed?: string;
|
|
825
|
+
|
|
768
826
|
/** ## Wallace directive: hide
|
|
769
827
|
*
|
|
770
828
|
* Set the element's `hidden` property and if true, does not render dynamic elements
|
|
@@ -876,13 +934,15 @@ declare namespace JSX {
|
|
|
876
934
|
* <MyComponent.nest props={singleProps} />
|
|
877
935
|
* <MyComponent.repeat items={arrayOfProps} />
|
|
878
936
|
* ```
|
|
879
|
-
*
|
|
937
|
+
* Note that repeated components must not have siblings.
|
|
880
938
|
*
|
|
881
939
|
* Available Wallace directives:
|
|
882
940
|
*
|
|
883
941
|
* - `apply` runs a callback to modify an element.
|
|
884
942
|
* - `bind` updates a value when an input is changed.
|
|
885
943
|
* - `class:xyz` defines a set of classes to be toggled.
|
|
944
|
+
* - `css` shorthand for `fixed:class`.
|
|
945
|
+
* - `fixed:xyz` sets a attribute from an expression at definition.
|
|
886
946
|
* - `hide` sets an element or component's hidden property.
|
|
887
947
|
* - `html` Set the element's `innnerHTML` property.
|
|
888
948
|
* - `if` excludes an element from the DOM.
|
|
@@ -892,9 +952,12 @@ declare namespace JSX {
|
|
|
892
952
|
* - `ref` saves a reference to an element or nested component.
|
|
893
953
|
* - `show` sets and element or component's hidden property.
|
|
894
954
|
* - `style:xyz` sets a specific style property.
|
|
895
|
-
* - `toggle:xyz` toggles `xyz` as defined by `class:xyz` on same element, or class
|
|
955
|
+
* - `toggle:xyz` toggles `xyz` as defined by `class:xyz` on same element, or class
|
|
956
|
+
* `xyz`.
|
|
896
957
|
*
|
|
897
|
-
*
|
|
958
|
+
* You will get more details by hovering on the directive itself, but unfortunetely
|
|
959
|
+
* the tool tip won't display when you use a qualifier, like `class:danger`. To see
|
|
960
|
+
* it you cantemporarily change it to something `class x:danger`.
|
|
898
961
|
*/
|
|
899
962
|
[elemName: string]: DirectiveAttributes & Record<string, any>;
|
|
900
963
|
}
|
package/lib/utils.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param {object} props The props to pass to the component (optional)
|
|
7
7
|
*/
|
|
8
8
|
export function mount(elementOrId, componentDefinition, props, ctrl) {
|
|
9
|
-
const component =
|
|
9
|
+
const component = new componentDefinition();
|
|
10
10
|
component.render(props, ctrl);
|
|
11
11
|
replaceNode(getElement(elementOrId), component.el);
|
|
12
12
|
return component;
|
|
@@ -22,52 +22,45 @@ export function getElement(elementOrId) {
|
|
|
22
22
|
: elementOrId;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
const MUTATING_METHODS = ["push", "pop", "shift", "unshift", "splice", "reverse", "sort"];
|
|
25
26
|
/**
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// if "componentDefinition is not a constructor" then we're probably missing a stub.
|
|
31
|
-
const component = new componentDefinition();
|
|
32
|
-
const proto = componentDefinition.prototype;
|
|
33
|
-
const dom = proto._n.cloneNode(true);
|
|
34
|
-
component.el = dom;
|
|
35
|
-
proto._b(component, dom);
|
|
36
|
-
return component;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* See types for docs. Set grace to 0 for testing.
|
|
27
|
+
* Returns a proxy which calls a callback when the object or its nested objects are
|
|
28
|
+
* modified.
|
|
29
|
+
*
|
|
30
|
+
* Note that proxies have property `isProxy` set to true.
|
|
41
31
|
*/
|
|
42
|
-
export function watch(target, callback
|
|
43
|
-
let active = false;
|
|
44
|
-
if (grace === undefined) grace = 100;
|
|
32
|
+
export function watch(target, callback) {
|
|
45
33
|
const handler = {
|
|
46
34
|
get(target, key) {
|
|
47
35
|
if (key == "isProxy") return true;
|
|
48
36
|
const prop = target[key];
|
|
49
37
|
if (typeof prop == "undefined") return;
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
target
|
|
53
|
-
|
|
38
|
+
if (typeof prop === "object") return new Proxy(prop, handler);
|
|
39
|
+
if (
|
|
40
|
+
Array.isArray(target) &&
|
|
41
|
+
typeof target[key] === "function" &&
|
|
42
|
+
MUTATING_METHODS.includes(key)
|
|
43
|
+
) {
|
|
44
|
+
return (...args) => {
|
|
45
|
+
const result = target[key](...args);
|
|
46
|
+
callback(target, key, args);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return prop;
|
|
54
51
|
},
|
|
55
|
-
|
|
56
52
|
set(target, key, value) {
|
|
57
53
|
target[key] = value;
|
|
58
|
-
|
|
59
|
-
if (!active) {
|
|
60
|
-
setTimeout(() => {
|
|
61
|
-
active = false;
|
|
62
|
-
}, grace);
|
|
63
|
-
active = true;
|
|
64
|
-
callback();
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
callback();
|
|
68
|
-
}
|
|
54
|
+
callback(target, key, value);
|
|
69
55
|
return true;
|
|
70
56
|
}
|
|
71
57
|
};
|
|
72
58
|
return new Proxy(target, handler);
|
|
73
59
|
}
|
|
60
|
+
|
|
61
|
+
export function protect(obj) {
|
|
62
|
+
return watch(obj, (target, key, value) => {
|
|
63
|
+
console.log("target", target, "key", key, "value", value);
|
|
64
|
+
throw new Error("Attempted to modify protected object");
|
|
65
|
+
});
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wallace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"author": "Andrew Buchan",
|
|
5
5
|
"description": "The framework that brings you FREEDOM!!",
|
|
6
6
|
"license": "ISC",
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"test": "jest --clearCache && jest"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"babel-plugin-wallace": "^0.
|
|
16
|
+
"babel-plugin-wallace": "^0.5.0",
|
|
17
17
|
"browserify": "^17.0.1"
|
|
18
18
|
},
|
|
19
|
-
"gitHead": "
|
|
19
|
+
"gitHead": "12194040c835faf9d4f29e105dd908bacdbbb944"
|
|
20
20
|
}
|