cx 22.1.4 → 22.3.2
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/dist/manifest.js +547 -547
- package/dist/ui.js +1 -4
- package/dist/widgets.js +11 -1
- package/package.json +1 -1
- package/src/core.d.ts +41 -6
- package/src/data/Binding.d.ts +4 -3
- package/src/data/Binding.js +12 -8
- package/src/data/Store.d.ts +5 -5
- package/src/data/Store.js +2 -2
- package/src/data/StoreRef.js +2 -0
- package/src/data/StructuredSelector.js +43 -57
- package/src/data/StructuredSelector.spec.js +54 -39
- package/src/data/View.d.ts +40 -16
- package/src/data/View.js +27 -19
- package/src/data/computable.d.ts +27 -4
- package/src/data/computable.js +2 -1
- package/src/data/computable.spec.js +8 -0
- package/src/data/createAccessorModelProxy.d.ts +6 -0
- package/src/data/createAccessorModelProxy.js +24 -0
- package/src/data/createAccessorModelProxy.spec.tsx +23 -0
- package/src/data/createStructuredSelector.js +9 -8
- package/src/data/getAccessor.js +24 -15
- package/src/data/getSelector.js +4 -1
- package/src/data/getSelector.spec.js +7 -0
- package/src/data/index.d.ts +2 -0
- package/src/data/index.js +2 -0
- package/src/ui/Controller.d.ts +13 -8
- package/src/ui/Instance.d.ts +6 -6
- package/src/ui/Instance.js +6 -5
- package/src/ui/Repeater.d.ts +25 -15
- package/src/ui/Restate.spec.js +0 -1
- package/src/ui/adapter/ArrayAdapter.d.ts +9 -10
- package/src/ui/adapter/ArrayAdapter.js +30 -37
- package/src/ui/adapter/TreeAdapter.js +27 -34
- package/src/ui/bind.d.ts +3 -2
- package/src/ui/bind.js +4 -3
- package/src/ui/expr.d.ts +23 -2
- package/src/ui/expr.js +16 -4
- package/src/widgets/AccessorBindings.spec.tsx +66 -0
- package/src/widgets/HtmlElement.d.ts +1 -1
- package/src/widgets/List.d.ts +21 -23
- package/src/widgets/form/Checkbox.d.ts +22 -18
- package/src/widgets/form/Checkbox.js +6 -0
- package/src/widgets/form/ValidationGroup.spec.js +1 -1
- package/src/widgets/grid/Grid.d.ts +86 -68
- package/src/widgets/grid/Grid.js +9 -3
package/dist/ui.js
CHANGED
|
@@ -5022,14 +5022,11 @@ var TreeAdapter = /*#__PURE__*/ (function(_ArrayAdapter) {
|
|
|
5022
5022
|
_proto.processList = function processList(context, instance, level, parentKey, nodes, result) {
|
|
5023
5023
|
var _this = this;
|
|
5024
5024
|
|
|
5025
|
-
var nonLeafs = [],
|
|
5026
|
-
leafs = [];
|
|
5027
5025
|
nodes.forEach(function(record) {
|
|
5028
5026
|
record.key = parentKey + record.key;
|
|
5029
5027
|
|
|
5030
|
-
_this.processNode(context, instance, level,
|
|
5028
|
+
_this.processNode(context, instance, level, result, record);
|
|
5031
5029
|
});
|
|
5032
|
-
result.push.apply(result, nonLeafs.concat(leafs));
|
|
5033
5030
|
};
|
|
5034
5031
|
|
|
5035
5032
|
_proto.processNode = function processNode(context, instance, level, result, record) {
|
package/dist/widgets.js
CHANGED
|
@@ -8328,7 +8328,8 @@ var Checkbox = /*#__PURE__*/ (function(_Field) {
|
|
|
8328
8328
|
readOnly: undefined,
|
|
8329
8329
|
disabled: undefined,
|
|
8330
8330
|
enabled: undefined,
|
|
8331
|
-
required: undefined
|
|
8331
|
+
required: undefined,
|
|
8332
|
+
viewText: undefined
|
|
8332
8333
|
}
|
|
8333
8334
|
].concat(Array.prototype.slice.call(arguments))
|
|
8334
8335
|
);
|
|
@@ -8433,6 +8434,15 @@ var Checkbox = /*#__PURE__*/ (function(_Field) {
|
|
|
8433
8434
|
]);
|
|
8434
8435
|
};
|
|
8435
8436
|
|
|
8437
|
+
_proto.renderValue = function renderValue(context, _ref) {
|
|
8438
|
+
var data = _ref.data;
|
|
8439
|
+
if (!data.viewText) return _Field.prototype.renderValue.apply(this, arguments);
|
|
8440
|
+
return /*#__PURE__*/ jsx("span", {
|
|
8441
|
+
className: this.CSS.element(this.baseClass, "view-text"),
|
|
8442
|
+
children: data.viewText
|
|
8443
|
+
});
|
|
8444
|
+
};
|
|
8445
|
+
|
|
8436
8446
|
_proto.formatValue = function formatValue(context, instance) {
|
|
8437
8447
|
var data = instance.data;
|
|
8438
8448
|
return data.value && (data.text || this.renderChildren(context, instance));
|
package/package.json
CHANGED
package/src/core.d.ts
CHANGED
|
@@ -13,12 +13,10 @@ declare namespace Cx {
|
|
|
13
13
|
|
|
14
14
|
type Tpl = {
|
|
15
15
|
tpl: string;
|
|
16
|
-
defaultValue?: any;
|
|
17
16
|
};
|
|
18
17
|
|
|
19
18
|
type Expr = {
|
|
20
19
|
expr: string;
|
|
21
|
-
defaultValue?: any;
|
|
22
20
|
};
|
|
23
21
|
|
|
24
22
|
type Binding = Bind | Tpl | Expr;
|
|
@@ -29,7 +27,13 @@ declare namespace Cx {
|
|
|
29
27
|
[prop: string]: Selector<any>;
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
type
|
|
30
|
+
type AccessorChain<M> = {
|
|
31
|
+
toString(): string;
|
|
32
|
+
} & {
|
|
33
|
+
[prop in keyof M]: AccessorChain<M[prop]>;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type Prop<T> = T | Binding | Selector<T> | AccessorChain<T>;
|
|
33
37
|
|
|
34
38
|
interface Record {
|
|
35
39
|
[prop: string]: any;
|
|
@@ -51,6 +55,8 @@ declare namespace Cx {
|
|
|
51
55
|
type RecordsProp = Prop<Record[]>;
|
|
52
56
|
type SortersProp = Prop<Sorter[]>;
|
|
53
57
|
|
|
58
|
+
type RecordAlias<V = any> = string | AccessorChain<V[]>;
|
|
59
|
+
|
|
54
60
|
interface WidgetProps {
|
|
55
61
|
/** Inner layout used to display children inside the widget. */
|
|
56
62
|
layout?: any;
|
|
@@ -122,7 +128,7 @@ declare namespace Cx {
|
|
|
122
128
|
style?: StyleProp;
|
|
123
129
|
|
|
124
130
|
/** Style object applied to the element */
|
|
125
|
-
styles?:
|
|
131
|
+
styles?: StyleProp;
|
|
126
132
|
}
|
|
127
133
|
|
|
128
134
|
interface HtmlElementProps extends StyledContainerProps {
|
|
@@ -130,7 +136,7 @@ declare namespace Cx {
|
|
|
130
136
|
id?: string | number | Binding | Selector<string | number>;
|
|
131
137
|
|
|
132
138
|
/** Inner text contents. */
|
|
133
|
-
text?:
|
|
139
|
+
text?: Cx.StringProp | Cx.NumberProp;
|
|
134
140
|
|
|
135
141
|
/** Tooltip configuration. */
|
|
136
142
|
tooltip?: StringProp | StructuredProp;
|
|
@@ -176,6 +182,35 @@ declare global {
|
|
|
176
182
|
interface IntrinsicElements {
|
|
177
183
|
cx: any;
|
|
178
184
|
}
|
|
185
|
+
|
|
186
|
+
interface IntrinsicAttributes {
|
|
187
|
+
/** Inner layout used to display children inside the widget. */
|
|
188
|
+
layout?: any;
|
|
189
|
+
|
|
190
|
+
/** Outer (wrapper) layout used to display the widget in. */
|
|
191
|
+
outerLayout?: any;
|
|
192
|
+
|
|
193
|
+
/** Name of the ContentPlaceholder that should be used to display the widget. */
|
|
194
|
+
putInto?: string;
|
|
195
|
+
|
|
196
|
+
/** Name of the ContentPlaceholder that should be used to display the widget. */
|
|
197
|
+
contentFor?: string;
|
|
198
|
+
|
|
199
|
+
/** Controller. */
|
|
200
|
+
controller?: any;
|
|
201
|
+
|
|
202
|
+
/** Visibility of the widget. Defaults to `true`. */
|
|
203
|
+
visible?: Cx.BooleanProp;
|
|
204
|
+
|
|
205
|
+
/** Visibility of the widget. Defaults to `true`. */
|
|
206
|
+
if?: Cx.BooleanProp;
|
|
207
|
+
|
|
208
|
+
/** Appearance modifier. For example, mod="big" will add the CSS class `.cxm-big` to the block element. */
|
|
209
|
+
mod?: Cx.StringProp | Cx.Prop<string[]> | Cx.StructuredProp;
|
|
210
|
+
|
|
211
|
+
/** Cache render output. Default is `true`. */
|
|
212
|
+
memoize?: Cx.BooleanProp;
|
|
213
|
+
}
|
|
179
214
|
}
|
|
180
215
|
}
|
|
181
216
|
|
|
@@ -183,7 +218,7 @@ declare module "react" {
|
|
|
183
218
|
interface ClassAttributes<T> extends Cx.PureContainerProps {
|
|
184
219
|
class?: Cx.ClassProp;
|
|
185
220
|
styles?: Cx.StyleProp;
|
|
186
|
-
text?: Cx.StringProp;
|
|
221
|
+
text?: Cx.StringProp | Cx.NumberProp;
|
|
187
222
|
innerText?: Cx.StringProp;
|
|
188
223
|
html?: Cx.StringProp;
|
|
189
224
|
innerHtml?: Cx.StringProp;
|
package/src/data/Binding.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { Record } from "../core";
|
|
1
|
+
import { Record, AccessorChain } from "../core";
|
|
2
2
|
|
|
3
|
-
export class Binding {
|
|
3
|
+
export class Binding<V = any> {
|
|
4
4
|
constructor(path: string);
|
|
5
5
|
|
|
6
|
-
set(state: Record, value:
|
|
6
|
+
set(state: Record, value: V): Record;
|
|
7
7
|
|
|
8
8
|
delete(state: Record): Record;
|
|
9
9
|
|
|
10
10
|
value(state: Record): any;
|
|
11
11
|
|
|
12
12
|
static get(path: string): Binding;
|
|
13
|
+
static get<V>(chain: AccessorChain<V>): Binding<V>;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export function isBinding(value: any): boolean;
|
package/src/data/Binding.js
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
let bindingCache = {};
|
|
2
2
|
import { isString } from "../util/isString";
|
|
3
3
|
import { isObject } from "../util/isObject";
|
|
4
|
+
import { isAccessorChain } from "./createAccessorModelProxy";
|
|
4
5
|
|
|
5
6
|
export class Binding {
|
|
6
7
|
constructor(path) {
|
|
7
8
|
this.path = path;
|
|
8
9
|
this.parts = path.split(".");
|
|
9
|
-
let
|
|
10
|
-
let
|
|
10
|
+
let body = "return (x";
|
|
11
|
+
let selector = "x";
|
|
11
12
|
|
|
12
13
|
for (let i = 0; i < this.parts.length; i++) {
|
|
13
|
-
if (this.parts[i][0] >= "0" && this.parts[i][0] <= "9")
|
|
14
|
-
else
|
|
14
|
+
if (this.parts[i][0] >= "0" && this.parts[i][0] <= "9") selector += "[" + this.parts[i] + "]";
|
|
15
|
+
else selector += "." + this.parts[i];
|
|
15
16
|
|
|
16
|
-
if (i + 1 < this.parts.length)
|
|
17
|
-
else
|
|
17
|
+
if (i + 1 < this.parts.length) body += " && " + selector;
|
|
18
|
+
else body += " ? " + selector + " : undefined";
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
this.value = new Function("x",
|
|
21
|
+
body += ")";
|
|
22
|
+
this.value = new Function("x", body);
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
set(state, value) {
|
|
@@ -72,11 +73,14 @@ export class Binding {
|
|
|
72
73
|
|
|
73
74
|
if (path instanceof Binding) return path;
|
|
74
75
|
|
|
76
|
+
if (isAccessorChain(path)) return this.get(path.toString());
|
|
77
|
+
|
|
75
78
|
throw new Error("Invalid binding definition provided.");
|
|
76
79
|
}
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
export function isBinding(value) {
|
|
80
83
|
if (isObject(value) && isString(value.bind)) return true;
|
|
84
|
+
if (value && value.isAccessorChain) return true;
|
|
81
85
|
return value instanceof Binding;
|
|
82
86
|
}
|
package/src/data/Store.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {View, ViewConfig} from
|
|
1
|
+
import { View, ViewConfig } from "./View";
|
|
2
2
|
|
|
3
|
-
interface StoreConfig extends ViewConfig {
|
|
3
|
+
interface StoreConfig<D = any> extends ViewConfig {
|
|
4
4
|
async?: boolean;
|
|
5
|
-
data?:
|
|
5
|
+
data?: D;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export class Store extends View {
|
|
9
|
-
constructor(config?: StoreConfig);
|
|
8
|
+
export class Store<D = any> extends View<D> {
|
|
9
|
+
constructor(config?: StoreConfig<D>);
|
|
10
10
|
|
|
11
11
|
unsubscribeAll(): void;
|
|
12
12
|
|
package/src/data/Store.js
CHANGED
|
@@ -24,7 +24,7 @@ export class Store extends SubscribableView {
|
|
|
24
24
|
}
|
|
25
25
|
return false;
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
deleteItem(path) {
|
|
29
29
|
let next = Binding.get(path).delete(this.data);
|
|
30
30
|
if (next != this.data) {
|
|
@@ -35,7 +35,7 @@ export class Store extends SubscribableView {
|
|
|
35
35
|
}
|
|
36
36
|
return false;
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
clear() {
|
|
40
40
|
this.data = {};
|
|
41
41
|
this.meta.version++;
|
package/src/data/StoreRef.js
CHANGED
|
@@ -1,94 +1,83 @@
|
|
|
1
|
-
import {Binding} from
|
|
2
|
-
import {Expression} from
|
|
3
|
-
import {StringTemplate} from
|
|
4
|
-
import {createStructuredSelector} from
|
|
5
|
-
import {getSelector} from
|
|
6
|
-
import {isFunction} from
|
|
7
|
-
import {isUndefined} from
|
|
8
|
-
import {isDefined} from
|
|
9
|
-
import {isArray} from
|
|
1
|
+
import { Binding } from "./Binding";
|
|
2
|
+
import { Expression } from "./Expression";
|
|
3
|
+
import { StringTemplate } from "./StringTemplate";
|
|
4
|
+
import { createStructuredSelector } from "../data/createStructuredSelector";
|
|
5
|
+
import { getSelector } from "../data/getSelector";
|
|
6
|
+
import { isFunction } from "../util/isFunction";
|
|
7
|
+
import { isUndefined } from "../util/isUndefined";
|
|
8
|
+
import { isDefined } from "../util/isDefined";
|
|
9
|
+
import { isArray } from "../util/isArray";
|
|
10
|
+
import { isAccessorChain } from "./createAccessorModelProxy";
|
|
10
11
|
|
|
11
12
|
function defaultValue(pv) {
|
|
12
|
-
if (typeof pv ==
|
|
13
|
-
return pv.defaultValue;
|
|
13
|
+
if (typeof pv == "object" && pv && pv.structured) return pv.defaultValue;
|
|
14
14
|
|
|
15
15
|
return pv;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function getSelectorConfig(props, values, nameMap) {
|
|
19
|
-
|
|
20
19
|
let functions = {},
|
|
21
20
|
structures = {},
|
|
22
21
|
defaultValues = {},
|
|
23
|
-
constants,
|
|
22
|
+
constants,
|
|
23
|
+
p,
|
|
24
|
+
v,
|
|
25
|
+
pv,
|
|
24
26
|
constant = true;
|
|
25
27
|
|
|
26
28
|
for (p in props) {
|
|
27
29
|
v = values[p];
|
|
28
30
|
pv = props[p];
|
|
29
31
|
|
|
30
|
-
if (isUndefined(v) && pv && (pv.bind || pv.tpl || pv.expr))
|
|
31
|
-
v = pv;
|
|
32
|
+
if (isUndefined(v) && pv && (pv.bind || pv.tpl || pv.expr)) v = pv;
|
|
32
33
|
|
|
33
34
|
if (v === null) {
|
|
34
|
-
if (!constants)
|
|
35
|
-
constants = {};
|
|
35
|
+
if (!constants) constants = {};
|
|
36
36
|
constants[p] = null;
|
|
37
|
-
}
|
|
38
|
-
else if (typeof v == 'object') {
|
|
37
|
+
} else if (typeof v == "object") {
|
|
39
38
|
if (v.bind) {
|
|
40
|
-
if (isUndefined(v.defaultValue) && v != pv)
|
|
41
|
-
|
|
42
|
-
if (isDefined(v.defaultValue))
|
|
43
|
-
defaultValues[v.bind] = v.defaultValue;
|
|
39
|
+
if (isUndefined(v.defaultValue) && v != pv) v.defaultValue = defaultValue(pv);
|
|
40
|
+
if (isDefined(v.defaultValue)) defaultValues[v.bind] = v.defaultValue;
|
|
44
41
|
nameMap[p] = v.bind;
|
|
45
42
|
functions[p] = Binding.get(v.bind).value;
|
|
46
43
|
constant = false;
|
|
47
|
-
}
|
|
48
|
-
else if (v.expr) {
|
|
44
|
+
} else if (v.expr) {
|
|
49
45
|
functions[p] = Expression.get(v.expr);
|
|
50
46
|
constant = false;
|
|
51
|
-
}
|
|
52
|
-
else if (v.get) {
|
|
47
|
+
} else if (v.get) {
|
|
53
48
|
functions[p] = v.get;
|
|
54
49
|
constant = false;
|
|
55
|
-
}
|
|
56
|
-
else if (v.tpl) {
|
|
50
|
+
} else if (v.tpl) {
|
|
57
51
|
functions[p] = StringTemplate.get(v.tpl);
|
|
58
52
|
constant = false;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (isArray(v))
|
|
62
|
-
functions[p] = getSelector(v);
|
|
53
|
+
} else if (pv && typeof pv == "object" && pv.structured) {
|
|
54
|
+
if (isArray(v)) functions[p] = getSelector(v);
|
|
63
55
|
else {
|
|
64
56
|
let s = getSelectorConfig(v, v, {});
|
|
65
57
|
structures[p] = s;
|
|
66
58
|
Object.assign(defaultValues, s.defaultValues);
|
|
67
59
|
}
|
|
68
60
|
constant = false;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (!constants)
|
|
72
|
-
constants = {};
|
|
61
|
+
} else {
|
|
62
|
+
if (!constants) constants = {};
|
|
73
63
|
constants[p] = v;
|
|
74
64
|
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
65
|
+
} else if (isFunction(v)) {
|
|
66
|
+
if (isAccessorChain(v)) {
|
|
67
|
+
let path = v.toString();
|
|
68
|
+
nameMap[p] = path;
|
|
69
|
+
functions[p] = Binding.get(path).value;
|
|
70
|
+
} else functions[p] = v;
|
|
78
71
|
constant = false;
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
72
|
+
} else {
|
|
81
73
|
if (isUndefined(v)) {
|
|
82
|
-
if (isUndefined(pv))
|
|
83
|
-
continue;
|
|
74
|
+
if (isUndefined(pv)) continue;
|
|
84
75
|
v = defaultValue(pv);
|
|
85
76
|
}
|
|
86
77
|
|
|
87
|
-
if (isUndefined(v))
|
|
88
|
-
continue;
|
|
78
|
+
if (isUndefined(v)) continue;
|
|
89
79
|
|
|
90
|
-
if (!constants)
|
|
91
|
-
constants = {};
|
|
80
|
+
if (!constants) constants = {};
|
|
92
81
|
|
|
93
82
|
constants[p] = v;
|
|
94
83
|
}
|
|
@@ -99,7 +88,7 @@ function getSelectorConfig(props, values, nameMap) {
|
|
|
99
88
|
structures,
|
|
100
89
|
defaultValues,
|
|
101
90
|
constants,
|
|
102
|
-
constant
|
|
91
|
+
constant,
|
|
103
92
|
};
|
|
104
93
|
}
|
|
105
94
|
|
|
@@ -110,15 +99,13 @@ function createSelector({ functions, structures, constants, defaultValues }) {
|
|
|
110
99
|
selector[n] = functions[n];
|
|
111
100
|
}
|
|
112
101
|
|
|
113
|
-
for (let n in structures)
|
|
114
|
-
selector[n] = createSelector(structures[n]);
|
|
102
|
+
for (let n in structures) selector[n] = createSelector(structures[n]);
|
|
115
103
|
|
|
116
104
|
return createStructuredSelector(selector, constants);
|
|
117
105
|
}
|
|
118
106
|
|
|
119
107
|
export class StructuredSelector {
|
|
120
|
-
|
|
121
|
-
constructor({props, values}) {
|
|
108
|
+
constructor({ props, values }) {
|
|
122
109
|
this.nameMap = {};
|
|
123
110
|
this.config = getSelectorConfig(props, values, this.nameMap);
|
|
124
111
|
}
|
|
@@ -129,17 +116,16 @@ export class StructuredSelector {
|
|
|
129
116
|
|
|
130
117
|
create() {
|
|
131
118
|
let selector = createSelector(this.config);
|
|
132
|
-
if (selector.memoize)
|
|
133
|
-
return selector.memoize();
|
|
119
|
+
if (selector.memoize) return selector.memoize();
|
|
134
120
|
return selector;
|
|
135
121
|
}
|
|
136
122
|
|
|
137
123
|
createStoreSelector() {
|
|
138
124
|
if (this.config.constant) {
|
|
139
|
-
let result = {...this.config.constants};
|
|
125
|
+
let result = { ...this.config.constants };
|
|
140
126
|
return () => result;
|
|
141
127
|
}
|
|
142
128
|
let selector = this.create();
|
|
143
|
-
return store => selector(store.getData());
|
|
129
|
+
return (store) => selector(store.getData());
|
|
144
130
|
}
|
|
145
131
|
}
|
|
@@ -1,93 +1,94 @@
|
|
|
1
|
-
import {StructuredSelector} from
|
|
2
|
-
import assert from
|
|
1
|
+
import { StructuredSelector } from "./StructuredSelector";
|
|
2
|
+
import assert from "assert";
|
|
3
|
+
import { createAccessorModelProxy } from "./createAccessorModelProxy";
|
|
3
4
|
|
|
4
|
-
describe(
|
|
5
|
-
describe(
|
|
6
|
-
it(
|
|
5
|
+
describe("StructuredSelector", function () {
|
|
6
|
+
describe("#create()", function () {
|
|
7
|
+
it("constants", function () {
|
|
7
8
|
var x = {};
|
|
8
9
|
var s = new StructuredSelector({
|
|
9
10
|
props: {
|
|
10
11
|
a: undefined,
|
|
11
|
-
b: undefined
|
|
12
|
+
b: undefined,
|
|
12
13
|
},
|
|
13
14
|
values: {
|
|
14
15
|
a: 1,
|
|
15
|
-
b: 2
|
|
16
|
-
}
|
|
16
|
+
b: 2,
|
|
17
|
+
},
|
|
17
18
|
}).create(x);
|
|
18
19
|
|
|
19
|
-
assert.deepEqual(s(x), {a: 1, b: 2});
|
|
20
|
+
assert.deepEqual(s(x), { a: 1, b: 2 });
|
|
20
21
|
});
|
|
21
22
|
|
|
22
|
-
it(
|
|
23
|
+
it("bindings", function () {
|
|
23
24
|
var x = { a: 1, b: 2 };
|
|
24
25
|
var s = new StructuredSelector({
|
|
25
26
|
props: {
|
|
26
27
|
a: undefined,
|
|
27
|
-
b: undefined
|
|
28
|
+
b: undefined,
|
|
28
29
|
},
|
|
29
30
|
values: {
|
|
30
|
-
a: { bind:
|
|
31
|
-
b: { bind:
|
|
32
|
-
}
|
|
31
|
+
a: { bind: "b" },
|
|
32
|
+
b: { bind: "a" },
|
|
33
|
+
},
|
|
33
34
|
}).create(x);
|
|
34
35
|
|
|
35
|
-
assert.deepEqual(s(x), {a: 2, b: 1});
|
|
36
|
+
assert.deepEqual(s(x), { a: 2, b: 1 });
|
|
36
37
|
});
|
|
37
38
|
|
|
38
|
-
it(
|
|
39
|
-
var x = {a: 1, b: 2};
|
|
39
|
+
it("templates", function () {
|
|
40
|
+
var x = { a: 1, b: 2 };
|
|
40
41
|
var s = new StructuredSelector({
|
|
41
42
|
props: {
|
|
42
43
|
a: undefined,
|
|
43
|
-
b: undefined
|
|
44
|
+
b: undefined,
|
|
44
45
|
},
|
|
45
46
|
values: {
|
|
46
|
-
a: {tpl:
|
|
47
|
-
b: {tpl:
|
|
48
|
-
}
|
|
47
|
+
a: { tpl: "b{a}" },
|
|
48
|
+
b: { tpl: "a{b}" },
|
|
49
|
+
},
|
|
49
50
|
}).create(x);
|
|
50
51
|
|
|
51
|
-
assert.deepEqual(s(x), {a:
|
|
52
|
+
assert.deepEqual(s(x), { a: "b1", b: "a2" });
|
|
52
53
|
});
|
|
53
54
|
|
|
54
|
-
it(
|
|
55
|
-
var x = {a: 1, b: 2};
|
|
55
|
+
it("structured", function () {
|
|
56
|
+
var x = { a: 1, b: 2 };
|
|
56
57
|
var s = new StructuredSelector({
|
|
57
58
|
props: {
|
|
58
59
|
a: {
|
|
59
|
-
structured: true
|
|
60
|
+
structured: true,
|
|
60
61
|
},
|
|
61
|
-
b: undefined
|
|
62
|
+
b: undefined,
|
|
62
63
|
},
|
|
63
64
|
values: {
|
|
64
65
|
a: {
|
|
65
|
-
x: { expr:
|
|
66
|
-
y: { expr:
|
|
66
|
+
x: { expr: "{a} == 1" },
|
|
67
|
+
y: { expr: "{b} == 1" },
|
|
67
68
|
},
|
|
68
|
-
b: {tpl:
|
|
69
|
-
}
|
|
69
|
+
b: { tpl: "a{b}" },
|
|
70
|
+
},
|
|
70
71
|
}).create(x);
|
|
71
72
|
|
|
72
|
-
assert.deepEqual(s(x), {a: { x: true, y: false }, b:
|
|
73
|
+
assert.deepEqual(s(x), { a: { x: true, y: false }, b: "a2" });
|
|
73
74
|
});
|
|
74
75
|
});
|
|
75
76
|
|
|
76
|
-
it(
|
|
77
|
-
var x = {a: 1, b: 2};
|
|
77
|
+
it("structures do not change if data doesn't change", function () {
|
|
78
|
+
var x = { a: 1, b: 2 };
|
|
78
79
|
var s = new StructuredSelector({
|
|
79
80
|
props: {
|
|
80
81
|
a: {
|
|
81
|
-
structured: true
|
|
82
|
-
}
|
|
82
|
+
structured: true,
|
|
83
|
+
},
|
|
83
84
|
},
|
|
84
85
|
values: {
|
|
85
86
|
a: {
|
|
86
|
-
x: { expr:
|
|
87
|
-
y: { expr:
|
|
87
|
+
x: { expr: "{a} == 1" },
|
|
88
|
+
y: { expr: "{b} == 1" },
|
|
88
89
|
},
|
|
89
|
-
b: {tpl:
|
|
90
|
-
}
|
|
90
|
+
b: { tpl: "a{b}" },
|
|
91
|
+
},
|
|
91
92
|
}).create(x);
|
|
92
93
|
|
|
93
94
|
let r1 = s(x);
|
|
@@ -95,4 +96,18 @@ describe('StructuredSelector', function() {
|
|
|
95
96
|
|
|
96
97
|
assert.equal(r1, r2);
|
|
97
98
|
});
|
|
99
|
+
|
|
100
|
+
it("structures do not change if data doesn't change", function () {
|
|
101
|
+
var x = { a: { b: 2 } };
|
|
102
|
+
var m = createAccessorModelProxy();
|
|
103
|
+
var s = new StructuredSelector({
|
|
104
|
+
props: {
|
|
105
|
+
b: undefined,
|
|
106
|
+
},
|
|
107
|
+
values: {
|
|
108
|
+
b: m.a.b,
|
|
109
|
+
},
|
|
110
|
+
}).create(x);
|
|
111
|
+
assert.deepEqual(s(x), { b: 2 });
|
|
112
|
+
});
|
|
98
113
|
});
|