cx 24.7.2 → 24.7.3

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.
@@ -1,29 +1,37 @@
1
- import {AugmentedViewBase} from "./AugmentedViewBase";
2
- import { isArray} from "../util/isArray";
1
+ import { AugmentedViewBase } from "./AugmentedViewBase";
2
+ import { isArray } from "../util/isArray";
3
+ import { Binding } from "./Binding";
3
4
 
4
5
  export class ArrayElementView extends AugmentedViewBase {
6
+ constructor(config) {
7
+ super(config);
8
+ this.hasNestedAliases =
9
+ this.recordAlias.indexOf(".") >= 0 || this.indexAlias.indexOf(".") >= 0 || this.lengthAlias.indexOf(".") >= 0;
10
+ this.recordBinding = Binding.get(this.recordAlias);
11
+ if (this.hasNestedAliases) {
12
+ this.indexBinding = Binding.get(this.indexAlias);
13
+ this.lengthAlias = Binding.get(this.lengthAlias);
14
+ }
15
+ }
5
16
 
6
- isExtraKey(key) {
7
- return key == this.recordAlias || key == this.indexAlias || key == this.lengthAlias;
17
+ getExtraKeyBinding(key) {
18
+ if (!key.startsWith(this.recordAlias)) return null;
19
+ if (key.length == this.recordAlias.length || key[this.recordAlias.length] == ".") return this.recordBinding;
20
+ return null;
8
21
  }
9
22
 
10
23
  deleteExtraKeyValue(key) {
11
- if (key != this.recordAlias)
12
- throw new Error(`Field ${key} cannot be deleted.`);
24
+ if (key != this.recordAlias) throw new Error(`Field ${key} cannot be deleted.`);
13
25
  const array = this.arrayAccessor.get(this.store.getData());
14
- if (!array)
15
- return false;
26
+ if (!array) return false;
16
27
  const newArray = [...array.slice(0, this.itemIndex), ...array.slice(this.itemIndex + 1)];
17
28
  return this.arrayAccessor.set(newArray, this.store);
18
29
  }
19
30
 
20
31
  setExtraKeyValue(key, value) {
21
- if (key != this.recordAlias)
22
- throw new Error(`Field ${key} is read-only.`);
23
-
32
+ if (key != this.recordAlias) throw new Error(`Field ${key} is read-only.`);
24
33
  const array = this.arrayAccessor.get(this.store.getData());
25
- if (!array || value === array[this.itemIndex])
26
- return false;
34
+ if (!array || value === array[this.itemIndex]) return false;
27
35
  const newArray = [...array.slice(0, this.itemIndex), value, ...array.slice(this.itemIndex + 1)];
28
36
  return this.arrayAccessor.set(newArray, this.store);
29
37
  }
@@ -31,9 +39,19 @@ export class ArrayElementView extends AugmentedViewBase {
31
39
  embedAugmentData(result, parentStoreData) {
32
40
  let array = this.arrayAccessor.get(parentStoreData);
33
41
  if (!isArray(array)) return;
34
- result[this.recordAlias] = array[this.itemIndex];
35
- result[this.indexAlias] = this.itemIndex;
36
- result[this.lengthAlias] = array.length;
42
+ if (!this.hasNestedAliases) {
43
+ result[this.recordAlias] = array[this.itemIndex];
44
+ result[this.indexAlias] = this.itemIndex;
45
+ result[this.lengthAlias] = array.length;
46
+ } else {
47
+ let copy = result;
48
+ copy = this.recordBinding.set(copy, array[this.itemIndex]);
49
+ copy = this.indexBinding.set(copy, this.itemIndex);
50
+ copy = this.lengthAlias.set(copy, array.length);
51
+ result[this.recordBinding.parts[0]] = copy[this.recordBinding.parts[0]];
52
+ result[this.indexBinding.parts[0]] = copy[this.indexBinding.parts[0]];
53
+ result[this.lengthAlias.parts[0]] = copy[this.lengthAlias.parts[0]];
54
+ }
37
55
  }
38
56
 
39
57
  setIndex(itemIndex) {
@@ -41,6 +59,6 @@ export class ArrayElementView extends AugmentedViewBase {
41
59
  }
42
60
  }
43
61
 
44
- ArrayElementView.prototype.recordAlias = '$record';
45
- ArrayElementView.prototype.indexAlias = '$index';
46
- ArrayElementView.prototype.lengthAlias = '$length';
62
+ ArrayElementView.prototype.recordAlias = "$record";
63
+ ArrayElementView.prototype.indexAlias = "$index";
64
+ ArrayElementView.prototype.lengthAlias = "$length";
@@ -41,6 +41,24 @@ describe("ArrayElementView", function () {
41
41
  assert.equal(record, letters[1]);
42
42
  });
43
43
 
44
+ it("aliases allow nesting", function () {
45
+ let letters = [{ letter: "A" }, { letter: "B" }];
46
+ let store = new Store({ data: { letters } });
47
+ let elementView = new ArrayElementView({
48
+ store,
49
+ itemIndex: 1,
50
+ arrayAccessor: getAccessor({ bind: "letters" }),
51
+ recordAlias: "$iter.letter",
52
+ indexAlias: "$iter.index.letter",
53
+ });
54
+ let record = elementView.get("$iter.letter");
55
+ assert.equal(record, letters[1]);
56
+ assert.equal(elementView.get("$iter.index.letter"), 1);
57
+
58
+ elementView.set("$iter.letter.letter", "C");
59
+ assert.equal(store.get("letters.1.letter"), "C");
60
+ });
61
+
44
62
  it("when immutable preserves the parent data object", function () {
45
63
  let letters = [{ letter: "A" }, { letter: "B" }];
46
64
  let store = new Store({ data: { letters } });
@@ -3,8 +3,7 @@ import { Binding } from "./Binding";
3
3
 
4
4
  export class AugmentedViewBase extends View {
5
5
  getData() {
6
- if (this.meta.version === this.cache.version && this.sealed)
7
- return this.cache.result;
6
+ if (this.meta.version === this.cache.version && this.sealed) return this.cache.result;
8
7
  let parentStoreData = this.store.getData();
9
8
  let result = this.getBaseData(parentStoreData);
10
9
  this.embedAugmentData(result, parentStoreData);
@@ -27,6 +26,12 @@ export class AugmentedViewBase extends View {
27
26
  throw new Error("abstract");
28
27
  }
29
28
 
29
+ // Stores which need to support nested aliases should override this method
30
+ getExtraKeyBinding(key) {
31
+ let binding = Binding.get(key);
32
+ return this.isExtraKey(binding.parts[0]) ? Binding.get(binding.parts[0]) : null;
33
+ }
34
+
30
35
  setExtraKeyValue(key, value) {
31
36
  throw new Error("abstract");
32
37
  }
@@ -36,29 +41,32 @@ export class AugmentedViewBase extends View {
36
41
  }
37
42
 
38
43
  setItem(path, value) {
39
- let binding = Binding.get(path);
40
- if (this.isExtraKey(binding.parts[0])) {
41
- let bindingRoot = binding.parts[0];
44
+ let extraKeyBinding = this.getExtraKeyBinding(path);
45
+ if (extraKeyBinding) {
46
+ let binding = Binding.get(path);
42
47
  let newValue = value;
43
- if (binding.parts.length > 1) {
48
+ if (binding.parts.length > extraKeyBinding.parts.length) {
44
49
  let data = {};
45
50
  this.embedAugmentData(data, this.store.getData());
46
- newValue = binding.set(data, value)[bindingRoot];
51
+ let binding = Binding.get(path);
52
+ data = binding.set(data, value);
53
+ newValue = extraKeyBinding.value(data);
47
54
  }
48
- return this.setExtraKeyValue(bindingRoot, newValue);
55
+ return this.setExtraKeyValue(extraKeyBinding.path, newValue);
49
56
  }
50
57
  return super.setItem(path, value);
51
58
  }
52
59
 
53
60
  deleteItem(path) {
54
- let binding = Binding.get(path);
55
- if (this.isExtraKey(binding.parts[0])) {
56
- let bindingRoot = binding.parts[0];
57
- if (binding.parts.length == 1) return this.deleteExtraKeyValue(bindingRoot);
61
+ let extraKeyBinding = this.getExtraKeyBinding(path);
62
+ if (extraKeyBinding) {
63
+ if (path == extraKeyBinding.path) return this.deleteExtraKeyValue(extraKeyBinding.path);
58
64
  let data = {};
59
65
  this.embedAugmentData(data, this.store.getData());
60
- let newValue = binding.delete(data)[bindingRoot];
61
- return this.setExtraKeyValue(bindingRoot, newValue);
66
+ let binding = Binding.get(path);
67
+ data = binding.delete(data);
68
+ let newValue = extraKeyBinding.value(data);
69
+ return this.setExtraKeyValue(extraKeyBinding.path, newValue);
62
70
  }
63
71
  return super.deleteItem(path);
64
72
  }
@@ -2,23 +2,36 @@ import * as Cx from '../core';
2
2
  import {TextualBoundedObject, TextualBoundedObjectProps} from './TextualBoundedObject';
3
3
 
4
4
  interface RectangleProps extends TextualBoundedObjectProps {
5
-
6
- /**
7
- * Index of the color in the default color palette. Setting this property will set
8
- * both fill and stroke on the object. Use `style` or a CSS class to remove stroke or fill
9
- * if they are not necessary.
5
+
6
+ /**
7
+ * Index of the color in the default color palette. Setting this property will set
8
+ * both fill and stroke on the object. Use `style` or a CSS class to remove stroke or fill
9
+ * if they are not necessary.
10
10
  */
11
11
  colorIndex?: Cx.NumberProp,
12
12
 
13
13
  /** A color used to paint the box. */
14
14
  fill?: Cx.StringProp,
15
-
15
+
16
16
  /** A color used to paint the outline of the box. */
17
17
  stroke?: Cx.StringProp,
18
18
 
19
19
  /** Base CSS class to be applied to the element. Defaults to `rectangle`. */
20
- baseClass?: string
20
+ baseClass?: string;
21
21
 
22
+ /**
23
+ * The horizontal corner radius of the rect. Defaults to ry if it is specified.
24
+ * Value type: <length>|<percentage>;
25
+ * If unit is not specified, it defaults to `px`.
26
+ */
27
+ rx?: Cx.StringProp | Cx.NumberProp;
28
+
29
+ /**
30
+ * The vertical corner radius of the rect. Defaults to rx if it is specified.
31
+ * Value type: <length>|<percentage>;
32
+ * If unit is not specified, it defaults to `px`.
33
+ */
34
+ ry?: Cx.StringProp | Cx.NumberProp;
22
35
  }
23
36
 
24
37
  export class Rectangle extends Cx.Widget<RectangleProps> {}
@@ -2,12 +2,13 @@ import {Widget, VDOM} from '../ui/Widget';
2
2
  import {TextualBoundedObject} from './TextualBoundedObject';
3
3
 
4
4
  export class Rectangle extends TextualBoundedObject {
5
-
6
5
  declareData() {
7
6
  super.declareData(...arguments, {
8
7
  colorIndex: undefined,
9
8
  fill: undefined,
10
- stroke: undefined
9
+ stroke: undefined,
10
+ rx: undefined,
11
+ ry: undefined,
11
12
  })
12
13
  }
13
14
 
@@ -25,6 +26,8 @@ export class Rectangle extends TextualBoundedObject {
25
26
  style={data.style}
26
27
  fill={data.fill}
27
28
  stroke={data.stroke}
29
+ rx={data.rx}
30
+ ry={data.ry}
28
31
  />
29
32
  {this.renderChildren(context, instance)}
30
33
  </g>;
@@ -33,5 +36,7 @@ export class Rectangle extends TextualBoundedObject {
33
36
 
34
37
  Rectangle.prototype.baseClass = 'rectangle';
35
38
  Rectangle.prototype.anchors = '0 1 1 0';
39
+ Rectangle.prototype.rx = undefined;
40
+ Rectangle.prototype.ry = undefined;
36
41
 
37
42
  Widget.alias('rectangle', Rectangle);
@@ -269,18 +269,20 @@ describe("DataProxy", () => {
269
269
 
270
270
  it("controllers set on the DataProxy can see calculated values", () => {
271
271
  let value;
272
- let widget = Widget.create(<cx>
273
- <DataProxy
274
- data={{
275
- $value: 5
276
- }}
277
- controller={{
278
- onInit() {
279
- value = this.store.get("$value")
280
- },
281
- }}
282
- />
283
- </cx>);
272
+ let widget = Widget.create(
273
+ <cx>
274
+ <DataProxy
275
+ data={{
276
+ $value: 5,
277
+ }}
278
+ controller={{
279
+ onInit() {
280
+ value = this.store.get("$value");
281
+ },
282
+ }}
283
+ />
284
+ </cx>,
285
+ );
284
286
 
285
287
  let store = new Store();
286
288
 
@@ -320,16 +322,17 @@ describe("DataProxy", () => {
320
322
 
321
323
  let tree = component.toJSON();
322
324
 
323
- assert.deepEqual(tree, [{
324
- type: "span",
325
- props: {},
326
- children: ["initial"],
327
- }, {
328
- type: "span",
329
- props: {},
330
- children: null,
331
- }]);
325
+ assert.deepEqual(tree, [
326
+ {
327
+ type: "span",
328
+ props: {},
329
+ children: ["initial"],
330
+ },
331
+ {
332
+ type: "span",
333
+ props: {},
334
+ children: null,
335
+ },
336
+ ]);
332
337
  });
333
-
334
-
335
338
  });