cx 23.5.1 → 23.6.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.
@@ -1,222 +1,252 @@
1
- import { BoundedObject } from '../../svg/BoundedObject'
2
- import { VDOM } from '../../ui/Widget';
3
- import { isUndefined } from '../../util/isUndefined';
4
- import { parseStyle } from '../../util/parseStyle';
5
-
6
- export class Axis extends BoundedObject {
7
-
8
- init() {
9
- if (this.labelAnchor == 'auto')
10
- this.labelAnchor = this.vertical ? this.secondary ? 'start' : 'end' : 'middle';
11
-
12
- if (this.labelDx == 'auto')
13
- this.labelDx = 0;
14
-
15
- if (this.labelDy == 'auto')
16
- this.labelDy = this.vertical ? '0.4em' : this.secondary ? 0 : '0.8em';
17
-
18
- if (isUndefined(this.minLabelDistance))
19
- this.minLabelDistance = this.vertical ? this.minLabelDistanceVertical : this.minLabelDistanceHorizontal;
20
-
21
- if (this.labelLineCountDyFactor == 'auto')
22
- this.labelLineCountDyFactor = this.vertical ? -0.5 : this.secondary ? -1 : 0;
23
-
24
- this.lineStyle = parseStyle(this.lineStyle);
25
- this.tickStyle = parseStyle(this.tickStyle);
26
- this.labelStyle = parseStyle(this.labelStyle);
27
-
28
- super.init();
29
- }
30
-
31
- declareData() {
32
- super.declareData({
33
- anchors: undefined,
34
- hideLabels: undefined,
35
- hideLine: undefined,
36
- hideTicks: undefined,
37
- labelRotation: undefined,
38
- labelAnchor: undefined,
39
- lineStyle: undefined,
40
- lineClass: undefined,
41
- labelStyle: undefined,
42
- labelClass: undefined,
43
- tickStyle: undefined,
44
- tickClass: undefined
45
- }, ...arguments)
46
- }
47
-
48
- report(context, instance) {
49
- return instance.calculator;
50
- }
51
-
52
- renderTicksAndLabels(context, instance, valueFormatter) {
53
-
54
- if (this.hidden)
55
- return false;
56
-
57
- var { data, calculator } = instance;
58
- var { bounds } = data;
59
- let { CSS, baseClass } = this;
60
- var size = calculator.findTickSize(this.minLabelDistance);
61
-
62
- var labelClass = CSS.expand(CSS.element(baseClass, 'label'), data.labelClass);
63
- var offsetClass = CSS.element(baseClass, 'label-offset');
64
-
65
- var x1, y1, x2, y2, tickSize = this.tickSize;
66
-
67
- if (this.vertical) {
68
- x1 = x2 = this.secondary ? bounds.r : bounds.l;
69
- y1 = bounds.b;
70
- y2 = bounds.t;
71
- } else {
72
- x1 = bounds.l;
73
- x2 = bounds.r;
74
- y1 = y2 = this.secondary ? bounds.t : bounds.b;
75
- }
76
-
77
- var res = [null, null];
78
-
79
- if (!data.hideLine) {
80
- res[0] = (
81
- <line
82
- key="line"
83
- className={CSS.expand(CSS.element(baseClass, "line"), data.lineClass)}
84
- style={data.lineStyle}
85
- x1={x1} y1={y1} x2={x2} y2={y2}
86
- />
87
- )
88
- }
89
-
90
- var t = [];
91
- if (size > 0 && !data.hideLabels) {
92
- var ticks = calculator.getTicks([size]);
93
- ticks.forEach((serie, si) => {
94
- serie.forEach((v, i) => {
95
- var s = calculator.map(v);
96
-
97
- if (this.secondary) {
98
- x1 = this.vertical ? bounds.r : s;
99
- y1 = this.vertical ? s : bounds.t;
100
- x2 = this.vertical ? bounds.r + tickSize : s;
101
- y2 = this.vertical ? s : bounds.t - tickSize;
102
- } else {
103
- x1 = this.vertical ? bounds.l : s;
104
- y1 = this.vertical ? s : bounds.b;
105
- x2 = this.vertical ? bounds.l - tickSize : s;
106
- y2 = this.vertical ? s : bounds.b + tickSize;
107
- }
108
-
109
- t.push(`M ${x1} ${y1} L ${x2} ${y2}`);
110
-
111
- var x, y;
112
- if (this.secondary) {
113
- x = this.vertical ? bounds.r + this.labelOffset : s;
114
- y = this.vertical ? s : bounds.t - this.labelOffset;
115
- } else {
116
- x = this.vertical ? bounds.l - this.labelOffset : s;
117
- y = this.vertical ? s : bounds.b + this.labelOffset;
118
- }
119
-
120
- var transform = data.labelRotation ? `rotate(${data.labelRotation} ${x} ${y})` : null;
121
- res.push(
122
- <text key={`label-${si}-${i}`}
123
- className={labelClass}
124
- style={data.labelStyle}
125
- x={x}
126
- y={y}
127
- dx={this.labelDx}
128
- textAnchor={data.labelAnchor}
129
- transform={transform}>
130
- {this.wrapLines(valueFormatter(v), x, this.labelDy, offsetClass)}
131
- </text>
132
- );
133
- });
134
- });
135
- }
136
-
137
- if (!data.hideTicks) {
138
- res[1] = <path key="ticks" className={CSS.expand(CSS.element(baseClass, "ticks"), data.tickClass)} style={data.tickStyle} d={t.join(' ')} />;
139
- }
140
-
141
- return res;
142
- }
143
-
144
- wrapLines(str, x, dy, offsetClass) {
145
- if (!this.labelWrap || typeof str != 'string')
146
- return <tspan x={x} dy={dy}>{str}</tspan>;
147
-
148
- let parts = str.split(' ');
149
- if (parts.length == 0)
150
- return null;
151
-
152
- let lines = [];
153
- let line = null;
154
- for (let i = 0; i < parts.length; i++) {
155
- if (!line)
156
- line = parts[i];
157
- else if (parts[i].length + line.length < this.labelMaxLineLength)
158
- line += ' ' + parts[i];
159
- else {
160
- lines.push(line);
161
- line = parts[i];
162
- }
163
- }
164
- lines.push(line);
165
-
166
- if (lines.length == 1)
167
- return <tspan x={x} dy={dy}>{str}</tspan>;
168
-
169
- let offset = this.labelLineCountDyFactor * (lines.length - 1);
170
- let result = [dy != null && <tspan key={-2} className={offsetClass} dy={dy}>_</tspan>];
171
-
172
- lines.forEach((p, i) => {
173
- result.push(<tspan key={i} dy={`${i == 0 ? offset : 1}em`} x={x}>{p}</tspan>)
174
- });
175
-
176
- return result;
177
- }
178
-
179
- prepare(context, instance) {
180
- super.prepare(context, instance);
181
- var { bounds } = instance.data;
182
- var [a, b] = !this.vertical ? [bounds.l, bounds.r] : [bounds.b, bounds.t];
183
- instance.calculator.measure(a, b);
184
- if (this.onMeasured)
185
- instance.invoke("onMeasured", instance.calculator.hash(), instance);
186
- if (!instance.calculator.isSame(instance.cached.axis))
187
- instance.markShouldUpdate(context);
188
- }
189
-
190
- cleanup(context, instance) {
191
- var { cached, calculator } = instance;
192
- cached.axis = calculator.hash();
193
- }
194
- }
195
-
196
- Axis.prototype.anchors = '0 1 1 0';
197
- Axis.prototype.styled = true;
198
- Axis.prototype.vertical = false;
199
- Axis.prototype.secondary = false;
200
- Axis.prototype.inverted = false;
201
- Axis.prototype.hidden = false;
202
- Axis.prototype.hideLabels = false;
203
- Axis.prototype.hideTicks = false;
204
- Axis.prototype.hideLine = false;
205
-
206
- Axis.prototype.tickSize = 3;
207
- Axis.prototype.minTickDistance = 25;
208
- Axis.prototype.minLabelDistanceVertical = 40;
209
- Axis.prototype.minLabelDistanceHorizontal = 50;
210
- Axis.prototype.labelOffset = 10;
211
- Axis.prototype.labelRotation = 0;
212
- Axis.prototype.labelAnchor = 'auto';
213
- Axis.prototype.labelDx = 'auto';
214
- Axis.prototype.labelDy = 'auto';
215
- Axis.prototype.labelWrap = false;
216
- Axis.prototype.labelLineCountDyFactor = 'auto';
217
- Axis.prototype.labelMaxLineLength = 10;
218
-
219
- Axis.namespace = 'ui.svg.chart.axis';
220
-
221
-
222
-
1
+ import { BoundedObject } from "../../svg/BoundedObject";
2
+ import { VDOM } from "../../ui/Widget";
3
+ import { isUndefined } from "../../util/isUndefined";
4
+ import { parseStyle } from "../../util/parseStyle";
5
+
6
+ export class Axis extends BoundedObject {
7
+ init() {
8
+ if (this.labelAnchor == "auto") this.labelAnchor = this.vertical ? (this.secondary ? "start" : "end") : "middle";
9
+
10
+ if (this.labelDx == "auto") this.labelDx = 0;
11
+
12
+ if (this.labelDy == "auto") this.labelDy = this.vertical ? "0.4em" : this.secondary ? 0 : "0.8em";
13
+
14
+ if (isUndefined(this.minLabelDistance))
15
+ this.minLabelDistance = this.vertical ? this.minLabelDistanceVertical : this.minLabelDistanceHorizontal;
16
+
17
+ if (this.labelLineCountDyFactor == "auto")
18
+ this.labelLineCountDyFactor = this.vertical ? -this.labelLineHeight / 2 : this.secondary ? -1 : 0;
19
+
20
+ this.lineStyle = parseStyle(this.lineStyle);
21
+ this.tickStyle = parseStyle(this.tickStyle);
22
+ this.labelStyle = parseStyle(this.labelStyle);
23
+
24
+ super.init();
25
+ }
26
+
27
+ declareData() {
28
+ super.declareData(
29
+ {
30
+ anchors: undefined,
31
+ hideLabels: undefined,
32
+ hideLine: undefined,
33
+ hideTicks: undefined,
34
+ labelRotation: undefined,
35
+ labelAnchor: undefined,
36
+ lineStyle: undefined,
37
+ lineClass: undefined,
38
+ labelStyle: undefined,
39
+ labelClass: undefined,
40
+ tickStyle: undefined,
41
+ tickClass: undefined,
42
+ },
43
+ ...arguments
44
+ );
45
+ }
46
+
47
+ prepareData(context, instance) {
48
+ super.prepareData(context, instance);
49
+ if (this.onCreateLabelFormatter)
50
+ instance.labelFormatter = instance.invoke("onCreateLabelFormatter", context, instance);
51
+ }
52
+
53
+ report(context, instance) {
54
+ return instance.calculator;
55
+ }
56
+
57
+ renderTicksAndLabels(context, instance, valueFormatter) {
58
+ if (this.hidden) return false;
59
+
60
+ var { data, calculator, labelFormatter } = instance;
61
+ var { bounds } = data;
62
+ let { CSS, baseClass } = this;
63
+ var size = calculator.findTickSize(this.minLabelDistance);
64
+
65
+ var labelClass = CSS.expand(CSS.element(baseClass, "label"), data.labelClass);
66
+ var offsetClass = CSS.element(baseClass, "label-offset");
67
+
68
+ var x1,
69
+ y1,
70
+ x2,
71
+ y2,
72
+ tickSize = this.tickSize;
73
+
74
+ if (this.vertical) {
75
+ x1 = x2 = this.secondary ? bounds.r : bounds.l;
76
+ y1 = bounds.b;
77
+ y2 = bounds.t;
78
+ } else {
79
+ x1 = bounds.l;
80
+ x2 = bounds.r;
81
+ y1 = y2 = this.secondary ? bounds.t : bounds.b;
82
+ }
83
+
84
+ var res = [null, null];
85
+
86
+ if (!data.hideLine) {
87
+ res[0] = (
88
+ <line
89
+ key="line"
90
+ className={CSS.expand(CSS.element(baseClass, "line"), data.lineClass)}
91
+ style={data.lineStyle}
92
+ x1={x1}
93
+ y1={y1}
94
+ x2={x2}
95
+ y2={y2}
96
+ />
97
+ );
98
+ }
99
+
100
+ var t = [];
101
+ if (size > 0 && !data.hideLabels) {
102
+ var ticks = calculator.getTicks([size]);
103
+ ticks.forEach((serie, si) => {
104
+ serie.forEach((v, i) => {
105
+ var s = calculator.map(v);
106
+
107
+ if (this.secondary) {
108
+ x1 = this.vertical ? bounds.r : s;
109
+ y1 = this.vertical ? s : bounds.t;
110
+ x2 = this.vertical ? bounds.r + tickSize : s;
111
+ y2 = this.vertical ? s : bounds.t - tickSize;
112
+ } else {
113
+ x1 = this.vertical ? bounds.l : s;
114
+ y1 = this.vertical ? s : bounds.b;
115
+ x2 = this.vertical ? bounds.l - tickSize : s;
116
+ y2 = this.vertical ? s : bounds.b + tickSize;
117
+ }
118
+
119
+ t.push(`M ${x1} ${y1} L ${x2} ${y2}`);
120
+
121
+ var x, y;
122
+ if (this.secondary) {
123
+ x = this.vertical ? bounds.r + this.labelOffset : s;
124
+ y = this.vertical ? s : bounds.t - this.labelOffset;
125
+ } else {
126
+ x = this.vertical ? bounds.l - this.labelOffset : s;
127
+ y = this.vertical ? s : bounds.b + this.labelOffset;
128
+ }
129
+
130
+ var transform = data.labelRotation ? `rotate(${data.labelRotation} ${x} ${y})` : null;
131
+ var formattedValue = valueFormatter(v);
132
+ var lines = labelFormatter ? labelFormatter(formattedValue, v) : this.wrapLines(formattedValue);
133
+ res.push(
134
+ <text
135
+ key={`label-${si}-${i}`}
136
+ className={labelClass}
137
+ style={data.labelStyle}
138
+ x={x}
139
+ y={y}
140
+ textAnchor={data.labelAnchor}
141
+ transform={transform}
142
+ >
143
+ {this.renderLabels(lines, x, this.labelDy, this.labelDx, offsetClass)}
144
+ </text>
145
+ );
146
+ });
147
+ });
148
+ }
149
+
150
+ if (!data.hideTicks) {
151
+ res[1] = (
152
+ <path
153
+ key="ticks"
154
+ className={CSS.expand(CSS.element(baseClass, "ticks"), data.tickClass)}
155
+ style={data.tickStyle}
156
+ d={t.join(" ")}
157
+ />
158
+ );
159
+ }
160
+
161
+ return res;
162
+ }
163
+
164
+ wrapLines(str) {
165
+ if (!this.labelWrap || typeof str != "string") return [{ text: str }];
166
+
167
+ let parts = str.split(" ");
168
+ if (parts.length == 0) return null;
169
+
170
+ let lines = [];
171
+ let line = null;
172
+ for (let i = 0; i < parts.length; i++) {
173
+ if (!line) line = parts[i];
174
+ else if (parts[i].length + line.length < this.labelMaxLineLength) line += " " + parts[i];
175
+ else {
176
+ lines.push({ text: line });
177
+ line = parts[i];
178
+ }
179
+ }
180
+ lines.push({ text: line });
181
+ return lines;
182
+ }
183
+
184
+ renderLabels(lines, x, dy, dx, offsetClass) {
185
+ let offset = this.labelLineCountDyFactor * (lines.length - 1);
186
+ let result = [];
187
+
188
+ if (lines.length > 1 && dy != null) {
189
+ result.push(
190
+ <tspan key={-2} className={offsetClass} dy={dy}>
191
+ _
192
+ </tspan>
193
+ );
194
+ }
195
+
196
+ lines.forEach((p, i) => {
197
+ result.push(
198
+ <tspan
199
+ key={i}
200
+ dy={lines.length > 1 ? `${i == 0 ? offset : this.labelLineHeight}em` : dy}
201
+ x={x}
202
+ style={p.style}
203
+ className={p.className}
204
+ dx={dx}
205
+ >
206
+ {p.text}
207
+ </tspan>
208
+ );
209
+ });
210
+ return result;
211
+ }
212
+
213
+ prepare(context, instance) {
214
+ super.prepare(context, instance);
215
+ var { bounds } = instance.data;
216
+ var [a, b] = !this.vertical ? [bounds.l, bounds.r] : [bounds.b, bounds.t];
217
+ instance.calculator.measure(a, b);
218
+ if (this.onMeasured) instance.invoke("onMeasured", instance.calculator.hash(), instance);
219
+ if (!instance.calculator.isSame(instance.cached.axis)) instance.markShouldUpdate(context);
220
+ }
221
+
222
+ cleanup(context, instance) {
223
+ var { cached, calculator } = instance;
224
+ cached.axis = calculator.hash();
225
+ }
226
+ }
227
+
228
+ Axis.prototype.anchors = "0 1 1 0";
229
+ Axis.prototype.styled = true;
230
+ Axis.prototype.vertical = false;
231
+ Axis.prototype.secondary = false;
232
+ Axis.prototype.inverted = false;
233
+ Axis.prototype.hidden = false;
234
+ Axis.prototype.hideLabels = false;
235
+ Axis.prototype.hideTicks = false;
236
+ Axis.prototype.hideLine = false;
237
+
238
+ Axis.prototype.tickSize = 3;
239
+ Axis.prototype.minTickDistance = 25;
240
+ Axis.prototype.minLabelDistanceVertical = 40;
241
+ Axis.prototype.minLabelDistanceHorizontal = 50;
242
+ Axis.prototype.labelOffset = 10;
243
+ Axis.prototype.labelRotation = 0;
244
+ Axis.prototype.labelAnchor = "auto";
245
+ Axis.prototype.labelDx = "auto";
246
+ Axis.prototype.labelDy = "auto";
247
+ Axis.prototype.labelWrap = false;
248
+ Axis.prototype.labelLineCountDyFactor = "auto";
249
+ Axis.prototype.labelLineHeight = 1;
250
+ Axis.prototype.labelMaxLineLength = 10;
251
+
252
+ Axis.namespace = "ui.svg.chart.axis";
@@ -1,23 +1,42 @@
1
- var Grouper = require('./Grouper').Grouper;
2
- import assert from 'assert';
1
+ var Grouper = require("./Grouper").Grouper;
2
+ import assert from "assert";
3
3
 
4
- describe('Grouper', function() {
5
- describe('grouping', function () {
6
- it('should work', function () {
7
- var data = [{
8
- key: 1,
9
- value: 1
10
- }, {
11
- key: 2,
12
- value: 2
13
- }];
4
+ describe("Grouper", function () {
5
+ describe("single grouping", function () {
6
+ it("should work", function () {
7
+ var data = [
8
+ { name: "John", age: 12 },
9
+ { name: "Jane", age: 12 },
10
+ ];
14
11
 
15
- var grouper = new Grouper({ key: {bind:'key'}});
12
+ var grouper = new Grouper({ name: { bind: "name" } });
16
13
  grouper.processAll(data);
17
14
 
18
15
  var results = grouper.getResults();
19
- //console.log(results);
16
+ // console.log(results);
20
17
  assert.equal(results.length, 2);
21
18
  });
22
19
  });
23
- });
20
+
21
+ describe("multi grouping", function () {
22
+ it("should work", function () {
23
+ var data = [
24
+ { name: "John", age: 12 },
25
+ { name: "John", age: 12 },
26
+ { name: "John", age: 13 },
27
+ { name: "John", age: 14 },
28
+ { name: "Jane", age: 12 },
29
+ { name: "Jane", age: 13 },
30
+ { name: "Jane", age: 14 },
31
+ ];
32
+
33
+ var grouper = new Grouper({ name: { bind: "name" }, age: { bind: "age" } });
34
+ grouper.processAll(data);
35
+
36
+ var results = grouper.getResults();
37
+ // console.log(results);
38
+ assert.equal(results.length, 6);
39
+ assert.equal(results[0].records.length, 2);
40
+ });
41
+ });
42
+ });
@@ -41,7 +41,7 @@ export class Field extends PureContainer {
41
41
  }
42
42
 
43
43
  init() {
44
- if (this.validationMode == 'tooltip' && isUndefined(this.errorTooltip)) {
44
+ if (this.validationMode == "tooltip" && isUndefined(this.errorTooltip)) {
45
45
  this.errorTooltip = {
46
46
  text: { bind: "$error" },
47
47
  mod: "error",
@@ -243,7 +243,11 @@ export class Field extends PureContainer {
243
243
  if (!data.error) {
244
244
  if (state.inputError) data.error = state.inputError;
245
245
  else if (state.validating && !empty) data.error = this.validatingText;
246
- else if (state.validationError && data.value === state.lastValidatedValue && shallowEquals(data.validationParams, state.lastValidationParams))
246
+ else if (
247
+ state.validationError &&
248
+ data.value === state.lastValidatedValue &&
249
+ shallowEquals(data.validationParams, state.lastValidationParams)
250
+ )
247
251
  data.error = state.validationError;
248
252
  else if (data.required) data.error = this.validateRequired(context, instance);
249
253
  }
@@ -253,7 +257,9 @@ export class Field extends PureContainer {
253
257
  !state.validating &&
254
258
  !data.error &&
255
259
  this.onValidate &&
256
- (!state.previouslyValidated || data.value != state.lastValidatedValue || data.validationParams != state.lastValidationParams)
260
+ (!state.previouslyValidated ||
261
+ data.value != state.lastValidatedValue ||
262
+ data.validationParams != state.lastValidationParams)
257
263
  ) {
258
264
  let result = instance.invoke("onValidate", data.value, instance, data.validationParams);
259
265
  if (isPromise(result)) {
@@ -262,14 +268,16 @@ export class Field extends PureContainer {
262
268
  validating: true,
263
269
  lastValidatedValue: data.value,
264
270
  previouslyValidated: true,
265
- lastValidationParams: data.validationParams
271
+ lastValidationParams: data.validationParams,
266
272
  });
267
273
  result
268
274
  .then((r) => {
269
275
  let { data, state } = instance;
270
- let error = data.value == state.lastValidatedValue && shallowEquals(data.validationParams, state.lastValidationParams)
271
- ? r
272
- : this.validatingText; //parameters changed, this will be revalidated
276
+ let error =
277
+ data.value == state.lastValidatedValue &&
278
+ shallowEquals(data.validationParams, state.lastValidationParams)
279
+ ? r
280
+ : this.validatingText; //parameters changed, this will be revalidated
273
281
 
274
282
  instance.setState({
275
283
  validating: false,
@@ -416,4 +424,3 @@ export function getFieldTooltip(instance) {
416
424
  ];
417
425
  return [instance, widget.tooltip];
418
426
  }
419
-