wallace 0.2.0 → 0.4.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 +2 -2
- package/lib/initCalls.js +29 -13
- package/lib/types.d.ts +164 -34
- package/package.json +3 -3
package/lib/component.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const NO_LOOKUP = "__";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The base component.
|
|
@@ -52,7 +52,7 @@ proto._rq = function (props, key) {
|
|
|
52
52
|
proto._ac = function (props, element, callbacks) {
|
|
53
53
|
for (let key in callbacks) {
|
|
54
54
|
let callback = callbacks[key];
|
|
55
|
-
if (key ===
|
|
55
|
+
if (key === NO_LOOKUP) {
|
|
56
56
|
callback(element, props, this);
|
|
57
57
|
} else {
|
|
58
58
|
const result = this._rq(props, key);
|
package/lib/initCalls.js
CHANGED
|
@@ -1,16 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything in here is used by or modified by the Babel plugin.
|
|
3
|
+
*/
|
|
1
4
|
import { Component } from "./component";
|
|
2
5
|
import { buildComponent, replaceNode } from "./utils";
|
|
3
6
|
import { KeyedRepeater, SequentialRepeater } from "./repeaters";
|
|
7
|
+
|
|
4
8
|
const throwAway = document.createElement("template");
|
|
5
9
|
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
11
|
+
* A utility function that has to be in here because it needs _createConstructor and
|
|
12
|
+
* we'd otherwise get cirular inmports.
|
|
13
|
+
*
|
|
14
|
+
* Calls to this function which provide the 2nd argument:
|
|
15
|
+
*
|
|
16
|
+
* const Foo = extendComponent(Bar, () => <div></div>))
|
|
17
|
+
*
|
|
18
|
+
* Are modified by the Babel plugin to become this:
|
|
19
|
+
*
|
|
20
|
+
* const Foo = defineComponent(,,,,Bar);
|
|
21
|
+
*
|
|
22
|
+
* So it should never be called with 2nd arg in real life.
|
|
8
23
|
*/
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
24
|
+
export function extendComponent(base, componentDef) {
|
|
25
|
+
// This function call will have been replaced if 2nd arg is a valid component func.
|
|
26
|
+
// and therefor we would not receive it.
|
|
27
|
+
if (componentDef)
|
|
28
|
+
throw new Error("2nd arg to extendComponent must be a JSX arrow function");
|
|
29
|
+
return _createConstructor(base);
|
|
12
30
|
}
|
|
13
31
|
|
|
32
|
+
/*
|
|
33
|
+
Everything after this is used by code generated by the Babel plugin.
|
|
34
|
+
*/
|
|
35
|
+
|
|
14
36
|
export function findElement(rootElement, path) {
|
|
15
37
|
return path.reduce((acc, index) => acc.childNodes[index], rootElement);
|
|
16
38
|
}
|
|
@@ -52,22 +74,15 @@ export function getSequentialRepeater(cls) {
|
|
|
52
74
|
return new SequentialRepeater(cls);
|
|
53
75
|
}
|
|
54
76
|
|
|
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);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
77
|
export function defineComponent(html, watches, queries, buildFunction, inheritFrom) {
|
|
64
78
|
const ComponentDefinition = _createConstructor(inheritFrom || Component);
|
|
65
79
|
const prototype = ComponentDefinition.prototype;
|
|
80
|
+
throwAway.innerHTML = html;
|
|
66
81
|
//Ensure these do not clash with fields on the component itself.
|
|
67
82
|
prototype._w = watches;
|
|
68
83
|
prototype._q = queries;
|
|
69
84
|
prototype._b = buildFunction;
|
|
70
|
-
prototype._n =
|
|
85
|
+
prototype._n = throwAway.content.firstChild;
|
|
71
86
|
return ComponentDefinition;
|
|
72
87
|
}
|
|
73
88
|
|
|
@@ -88,5 +103,6 @@ function _createConstructor(base) {
|
|
|
88
103
|
configurable: true
|
|
89
104
|
}
|
|
90
105
|
});
|
|
106
|
+
ComponentDefinition.prototype.base = Component.prototype;
|
|
91
107
|
return ComponentDefinition;
|
|
92
108
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
6. Inheritance
|
|
17
17
|
7. Stubs
|
|
18
18
|
8. TypeScript
|
|
19
|
+
9. Utility functions
|
|
19
20
|
|
|
20
21
|
For more detailed documentation go to https://github.com/wallace-js/wallace
|
|
21
22
|
|
|
@@ -97,7 +98,10 @@ render(props, ctrl) {
|
|
|
97
98
|
Updates the DOM. Only called internally by `render`, but you can call it from other
|
|
98
99
|
places.
|
|
99
100
|
|
|
100
|
-
|
|
101
|
+
#### Overriding
|
|
102
|
+
|
|
103
|
+
You can override these methods, and add new ones using `methods` directly on the
|
|
104
|
+
component definition:
|
|
101
105
|
|
|
102
106
|
```tsx
|
|
103
107
|
MyComponent.methods({
|
|
@@ -117,7 +121,21 @@ This has the same effect as setting them on the prototype:
|
|
|
117
121
|
MyComponent.prototype.render = function () {};
|
|
118
122
|
```
|
|
119
123
|
|
|
120
|
-
You
|
|
124
|
+
You can use `this.base` to access methods on the base `Component` class:
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
MyComponent.methods({
|
|
128
|
+
render(props) {
|
|
129
|
+
this.base.render.call(this, props, ctrl);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Note that `base` is not the same as `super` in classes which access the lowest override.
|
|
135
|
+
|
|
136
|
+
You access the instance as `this` in methods, but cannot use `this` in arrow functions,
|
|
137
|
+
so use `self` from the **xargs** in component functions.
|
|
138
|
+
|
|
121
139
|
|
|
122
140
|
### 1.4 Fields
|
|
123
141
|
|
|
@@ -170,7 +188,7 @@ const TopTasks = (tasks) => (
|
|
|
170
188
|
|
|
171
189
|
const TaskList = (tasks) => (
|
|
172
190
|
<div>
|
|
173
|
-
<Task.repeat
|
|
191
|
+
<Task.repeat items={tasks} />
|
|
174
192
|
</div>
|
|
175
193
|
);
|
|
176
194
|
```
|
|
@@ -189,9 +207,11 @@ over it in your IDE.
|
|
|
189
207
|
|
|
190
208
|
You can also display this list by hovering over any JSX element, like `div`.
|
|
191
209
|
|
|
210
|
+
- `apply` runs a callback to modify an element.
|
|
192
211
|
- `bind` updates a value when an input is changed.
|
|
193
212
|
- `class:xyz` defines a set of classes to be toggled.
|
|
194
|
-
- `hide` sets
|
|
213
|
+
- `hide` sets an element or component's hidden property.
|
|
214
|
+
- `html` Set the element's `innnerHTML` property.
|
|
195
215
|
- `if` excludes an element from the DOM.
|
|
196
216
|
- `on[EventName]` creates an event handler (note the code is copied)
|
|
197
217
|
- `props` specifes props for a nested or repeated component, in which case it must be
|
|
@@ -242,7 +262,7 @@ const Task = (task) => (<div>{task.name}</div>);
|
|
|
242
262
|
|
|
243
263
|
const TaskList = (_, {ctrl}) => (
|
|
244
264
|
<div>
|
|
245
|
-
<Task.repeat
|
|
265
|
+
<Task.repeat items={ctrl.getTasks()} />
|
|
246
266
|
</div>
|
|
247
267
|
);
|
|
248
268
|
|
|
@@ -305,7 +325,7 @@ Notes:
|
|
|
305
325
|
|
|
306
326
|
## 8. TypeScript
|
|
307
327
|
|
|
308
|
-
|
|
328
|
+
The main type is `Uses` which must be placed right after the comonent name:
|
|
309
329
|
|
|
310
330
|
```tsx
|
|
311
331
|
import { Uses } from 'wallace';
|
|
@@ -327,8 +347,7 @@ const Task: Uses<null> = () => <div>Hello</div>;
|
|
|
327
347
|
|
|
328
348
|
### Props
|
|
329
349
|
|
|
330
|
-
TypeScript will ensure you pass correct props during mounting or nesting
|
|
331
|
-
including repeat, which expects an arry of the type:
|
|
350
|
+
TypeScript will ensure you pass correct props during mounting or nesting:
|
|
332
351
|
|
|
333
352
|
```
|
|
334
353
|
const TaskList: Uses<iTask[]> = (tasks) => (
|
|
@@ -336,7 +355,7 @@ const TaskList: Uses<iTask[]> = (tasks) => (
|
|
|
336
355
|
First task:
|
|
337
356
|
<Task.nest props={tasks[0]} />
|
|
338
357
|
<div>
|
|
339
|
-
<Task.repeat
|
|
358
|
+
<Task.repeat items={tasks.slice(1)} />
|
|
340
359
|
</div>
|
|
341
360
|
</div>
|
|
342
361
|
);
|
|
@@ -418,6 +437,43 @@ const Child = extendComponent<newProps, Controller, Methods>(Parent);
|
|
|
418
437
|
to `any`.
|
|
419
438
|
2. Each type must extend its corresponding type on base.
|
|
420
439
|
|
|
440
|
+
### Other types:
|
|
441
|
+
|
|
442
|
+
Wallace defines some other types you may use:
|
|
443
|
+
|
|
444
|
+
- `Component<Props, Controller, Methods>` - the base component class (it is a
|
|
445
|
+
constructor, not a class)
|
|
446
|
+
- `ComponentInstance<Props, Controller, Methods>` - a component instance.
|
|
447
|
+
|
|
448
|
+
## Utility functions
|
|
449
|
+
|
|
450
|
+
Each of these has their own JSDoc, we just lsit them here.
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
### extendComponent
|
|
454
|
+
|
|
455
|
+
Define a new componend by extending another one:
|
|
456
|
+
|
|
457
|
+
```
|
|
458
|
+
const Foo = extendComponent(Base);
|
|
459
|
+
const Bar = extendComponent(Base, () => <div></div>);
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### mount
|
|
463
|
+
|
|
464
|
+
Mounts an instance of a component to the DOM:
|
|
465
|
+
|
|
466
|
+
```
|
|
467
|
+
mount("elementId", MyComponent, props, ctrl);
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### watch
|
|
471
|
+
|
|
472
|
+
Returns a Proxy of an object which calls `callback` when keys are set:
|
|
473
|
+
|
|
474
|
+
```
|
|
475
|
+
watch(obj, () => console.log('obj modified);
|
|
476
|
+
```
|
|
421
477
|
---
|
|
422
478
|
Report any issues to https://github.com/wallace-js/wallace (and please give it a ★)
|
|
423
479
|
|
|
@@ -435,10 +491,13 @@ declare module "wallace" {
|
|
|
435
491
|
> {
|
|
436
492
|
(
|
|
437
493
|
props: Props,
|
|
438
|
-
|
|
494
|
+
xargs?: {
|
|
439
495
|
ctrl: Controller;
|
|
440
496
|
self: ComponentInstance<Props, Controller, Methods>;
|
|
441
497
|
event: Event;
|
|
498
|
+
ev: Event;
|
|
499
|
+
element: HTMLElement;
|
|
500
|
+
el: HTMLElement;
|
|
442
501
|
}
|
|
443
502
|
): JSX.Element;
|
|
444
503
|
nest?({
|
|
@@ -451,11 +510,11 @@ declare module "wallace" {
|
|
|
451
510
|
hide?: boolean;
|
|
452
511
|
}): JSX.Element;
|
|
453
512
|
repeat?({
|
|
454
|
-
|
|
513
|
+
items,
|
|
455
514
|
show,
|
|
456
515
|
hide
|
|
457
516
|
}: {
|
|
458
|
-
|
|
517
|
+
items: Array<Props>;
|
|
459
518
|
show?: boolean;
|
|
460
519
|
hide?: boolean;
|
|
461
520
|
}): JSX.Element;
|
|
@@ -476,7 +535,7 @@ declare module "wallace" {
|
|
|
476
535
|
};
|
|
477
536
|
|
|
478
537
|
/**
|
|
479
|
-
* A type which
|
|
538
|
+
* A type which must be placed as shown:
|
|
480
539
|
*
|
|
481
540
|
* ```tsx
|
|
482
541
|
* const Task: Uses<iTask> = ({text}) => <div>{text}</div>;
|
|
@@ -504,19 +563,53 @@ declare module "wallace" {
|
|
|
504
563
|
Controller = any,
|
|
505
564
|
Methods extends object = {}
|
|
506
565
|
> = {
|
|
507
|
-
update(): void;
|
|
508
|
-
render(props: Props, ctrl?: Controller): void;
|
|
509
566
|
el: HTMLElement;
|
|
510
567
|
props: Props;
|
|
511
568
|
ctrl: Controller;
|
|
512
|
-
|
|
569
|
+
ref: { [key: string]: HTMLElement };
|
|
570
|
+
base: Component<Props, Controller>;
|
|
571
|
+
} & Component<Props, Controller> &
|
|
572
|
+
Methods;
|
|
513
573
|
|
|
514
574
|
/**
|
|
515
575
|
* The component constructor function (typed as a class, but isn't).
|
|
516
576
|
*/
|
|
517
|
-
export class
|
|
518
|
-
update(): void;
|
|
577
|
+
export class Component<Props = any, Controller = any> {
|
|
519
578
|
render(props: Props, ctrl?: Controller): void;
|
|
579
|
+
/**
|
|
580
|
+
* The base render method looks like this:
|
|
581
|
+
*
|
|
582
|
+
* ```
|
|
583
|
+
* render(props?: Props, ctrl?: Controller) {
|
|
584
|
+
* this.props = props;
|
|
585
|
+
* this.ctrl = ctrl;
|
|
586
|
+
* this.update();
|
|
587
|
+
* }
|
|
588
|
+
* ```
|
|
589
|
+
*
|
|
590
|
+
* You can override like so:
|
|
591
|
+
*
|
|
592
|
+
* ```
|
|
593
|
+
* render(props?: Props, ctrl?: Controller) {
|
|
594
|
+
* // do your thing
|
|
595
|
+
* this.base.render.call(this, props, ctrl);
|
|
596
|
+
* }
|
|
597
|
+
* ```
|
|
598
|
+
*/
|
|
599
|
+
render(props?: Props, ctrl?: Controller): void;
|
|
600
|
+
/**
|
|
601
|
+
* Updates the DOM.
|
|
602
|
+
*
|
|
603
|
+
* You can override like so:
|
|
604
|
+
*
|
|
605
|
+
* ```
|
|
606
|
+
* update() {
|
|
607
|
+
* // do your thing
|
|
608
|
+
* this.base.update.call(this);
|
|
609
|
+
* }
|
|
610
|
+
* ```
|
|
611
|
+
*/
|
|
612
|
+
update(): void;
|
|
520
613
|
}
|
|
521
614
|
|
|
522
615
|
/**
|
|
@@ -566,15 +659,15 @@ declare module "wallace" {
|
|
|
566
659
|
* The callback does not indicate the data has changed, only that a key was set.
|
|
567
660
|
*
|
|
568
661
|
* Some methods like `Array.push` set the index and then the length immediately after,
|
|
569
|
-
* so we use a
|
|
662
|
+
* so we use a timeout period to avoid calling the callback twice for what is really a
|
|
570
663
|
* single operation.
|
|
571
664
|
*
|
|
572
665
|
* @param {*} target - Any object, including arrays.
|
|
573
|
-
* @param {*}
|
|
666
|
+
* @param {*} timeout - Any value in ms. Defaults to 100.
|
|
574
667
|
* @param {*} callback - A callback function.
|
|
575
668
|
* @returns a Proxy of the object.
|
|
576
669
|
*/
|
|
577
|
-
export function watch<T>(target: T, callback: CallableFunction,
|
|
670
|
+
export function watch<T>(target: T, callback: CallableFunction, timeout?: number): T;
|
|
578
671
|
}
|
|
579
672
|
|
|
580
673
|
type MustBeExpression = Exclude<any, string>;
|
|
@@ -585,14 +678,25 @@ type MustBeExpression = Exclude<any, string>;
|
|
|
585
678
|
*/
|
|
586
679
|
interface DirectiveAttributes extends AllDomEvents {
|
|
587
680
|
/**
|
|
588
|
-
* ## Wallace directive:
|
|
681
|
+
* ## Wallace directive: apply
|
|
682
|
+
*
|
|
683
|
+
* Applies a callback, typically to modify its element, which is accessible via
|
|
684
|
+
* **xargs**.
|
|
589
685
|
*
|
|
590
|
-
*
|
|
686
|
+
* Note that you can use `element` from **xargs** multiple times and each will refer
|
|
687
|
+
* to the element where it is used.
|
|
688
|
+
*
|
|
689
|
+
* ```
|
|
690
|
+
* const MyComponent = (_, { element }) => (
|
|
691
|
+
* <div>
|
|
692
|
+
* <div apply={doSomething(element)}></div>
|
|
693
|
+
* <div apply={doSomethingElse(element)}></div>
|
|
694
|
+
* </div>
|
|
695
|
+
* );
|
|
696
|
+
* ```
|
|
591
697
|
*
|
|
592
|
-
* This allows you to inherit methods and override stubs.
|
|
593
|
-
* Must be an expression returning a component definition.
|
|
594
698
|
*/
|
|
595
|
-
|
|
699
|
+
apply?: MustBeExpression;
|
|
596
700
|
|
|
597
701
|
/**
|
|
598
702
|
* ## Wallace directive: bind
|
|
@@ -668,17 +772,34 @@ interface DirectiveAttributes extends AllDomEvents {
|
|
|
668
772
|
*/
|
|
669
773
|
hide?: MustBeExpression;
|
|
670
774
|
|
|
671
|
-
/** Wallace
|
|
672
|
-
*
|
|
775
|
+
/** ## Wallace directive: html
|
|
776
|
+
*
|
|
777
|
+
* Set the element's `innnerHTML` property.
|
|
778
|
+
*/
|
|
779
|
+
html?: MustBeExpression;
|
|
780
|
+
|
|
781
|
+
/** ## Wallace directive: if
|
|
782
|
+
*
|
|
783
|
+
* Excludes this element from the DOM completely if the condition is false,
|
|
784
|
+
* and does not render dynamic elements underneath.
|
|
785
|
+
* When the condition becomes true, the element is reattached.
|
|
786
|
+
*/
|
|
673
787
|
if?: MustBeExpression;
|
|
674
788
|
|
|
789
|
+
/**
|
|
790
|
+
* ## Wallace directive: items
|
|
791
|
+
*
|
|
792
|
+
* Specifies items for repeated component. Must be an array of the props which the
|
|
793
|
+
* nested item accepts.
|
|
794
|
+
*
|
|
795
|
+
*/
|
|
796
|
+
items?: MustBeExpression;
|
|
797
|
+
|
|
675
798
|
/**
|
|
676
799
|
* ## Wallace directive: props
|
|
677
800
|
*
|
|
678
|
-
* Specifies props for a nested
|
|
801
|
+
* Specifies props for a nested component.
|
|
679
802
|
*
|
|
680
|
-
* If it is a repeated component, the props should be an array of whatever type it
|
|
681
|
-
* accepts.
|
|
682
803
|
*/
|
|
683
804
|
props?: MustBeExpression;
|
|
684
805
|
|
|
@@ -750,15 +871,24 @@ declare namespace JSX {
|
|
|
750
871
|
|
|
751
872
|
interface IntrinsicElements {
|
|
752
873
|
/**
|
|
874
|
+
* Nesting syntax:
|
|
875
|
+
* ```
|
|
876
|
+
* <MyComponent.nest props={singleProps} />
|
|
877
|
+
* <MyComponent.repeat items={arrayOfProps} />
|
|
878
|
+
* ```
|
|
879
|
+
* But note that repeat must not have siblings.
|
|
880
|
+
*
|
|
753
881
|
* Available Wallace directives:
|
|
754
882
|
*
|
|
883
|
+
* - `apply` runs a callback to modify an element.
|
|
755
884
|
* - `bind` updates a value when an input is changed.
|
|
756
885
|
* - `class:xyz` defines a set of classes to be toggled.
|
|
757
|
-
* - `hide` sets
|
|
886
|
+
* - `hide` sets an element or component's hidden property.
|
|
887
|
+
* - `html` Set the element's `innnerHTML` property.
|
|
758
888
|
* - `if` excludes an element from the DOM.
|
|
889
|
+
* - `items` set items for repeated component, must be an array of props.
|
|
759
890
|
* - `on[EventName]` creates an event handler (note the code is copied)
|
|
760
|
-
* - `props` specifes props for a nested
|
|
761
|
-
* an array.
|
|
891
|
+
* - `props` specifes props for a nested components.
|
|
762
892
|
* - `ref` saves a reference to an element or nested component.
|
|
763
893
|
* - `show` sets and element or component's hidden property.
|
|
764
894
|
* - `style:xyz` sets a specific style property.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wallace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.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.4.0",
|
|
17
17
|
"browserify": "^17.0.1"
|
|
18
18
|
},
|
|
19
|
-
"gitHead": "
|
|
19
|
+
"gitHead": "286a00b51777c4b7fed9a778b93e9727ed905e2a"
|
|
20
20
|
}
|