cx 26.4.3 → 26.5.1
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/build/charts/axis/Axis.d.ts +8 -0
- package/build/charts/axis/Axis.d.ts.map +1 -1
- package/build/charts/axis/Axis.js +18 -1
- package/build/charts/axis/TimeAxis.js +1 -0
- package/build/data/AugmentedViewBase.d.ts.map +1 -1
- package/build/data/AugmentedViewBase.js +5 -4
- package/build/data/View.d.ts +0 -1
- package/build/data/View.d.ts.map +1 -1
- package/build/data/View.js +1 -3
- package/build/ui/Format.d.ts.map +1 -1
- package/build/ui/Format.js +26 -2
- package/build/util/Format.d.ts.map +1 -1
- package/build/util/Format.js +6 -0
- package/build/util/date/dateQuarter.d.ts +7 -0
- package/build/util/date/dateQuarter.d.ts.map +1 -0
- package/build/util/date/dateQuarter.js +8 -0
- package/build/util/date/dayBefore.d.ts +12 -0
- package/build/util/date/dayBefore.d.ts.map +1 -0
- package/build/util/date/dayBefore.js +15 -0
- package/build/util/date/index.d.ts +2 -0
- package/build/util/date/index.d.ts.map +1 -1
- package/build/util/date/index.js +2 -0
- package/build/widgets/form/DateTimePicker.d.ts.map +1 -1
- package/build/widgets/form/DateTimePicker.js +53 -31
- package/build/widgets/form/Field.d.ts.map +1 -1
- package/build/widgets/form/Field.js +2 -1
- package/build/widgets/form/LookupField.js +2 -1
- package/build/widgets/form/Wheel.d.ts +8 -0
- package/build/widgets/form/Wheel.d.ts.map +1 -1
- package/build/widgets/form/Wheel.js +30 -7
- package/build/widgets/grid/Grid.d.ts +1 -1
- package/build/widgets/grid/Grid.d.ts.map +1 -1
- package/dist/charts.css +6 -0
- package/dist/charts.js +18 -1
- package/dist/data.js +5 -4
- package/dist/manifest.js +772 -763
- package/dist/ui.js +33 -1
- package/dist/util.js +32 -0
- package/dist/widgets.css +9 -3
- package/dist/widgets.js +230 -174
- package/package.json +1 -1
- package/src/charts/RangeMarker.scss +3 -0
- package/src/charts/axis/Axis.tsx +31 -1
- package/src/charts/axis/TimeAxis.tsx +1 -0
- package/src/charts/index.scss +1 -0
- package/src/data/AugmentedViewBase.ts +5 -4
- package/src/data/View.ts +16 -61
- package/src/ui/DataProxy.ts +55 -55
- package/src/ui/Format.spec.ts +32 -0
- package/src/ui/Format.ts +27 -2
- package/src/ui/Rescope.ts +50 -50
- package/src/ui/adapter/ArrayAdapter.ts +229 -229
- package/src/ui/exprHelpers.ts +96 -96
- package/src/util/Format.spec.ts +11 -0
- package/src/util/Format.ts +7 -0
- package/src/util/date/dateQuarter.ts +8 -0
- package/src/util/date/dayBefore.ts +15 -0
- package/src/util/date/index.ts +2 -0
- package/src/widgets/Sandbox.ts +104 -104
- package/src/widgets/form/ColorField.scss +112 -112
- package/src/widgets/form/DateTimeField.scss +111 -111
- package/src/widgets/form/DateTimePicker.tsx +453 -392
- package/src/widgets/form/Field.tsx +2 -1
- package/src/widgets/form/LookupField.maps.scss +26 -26
- package/src/widgets/form/LookupField.scss +10 -3
- package/src/widgets/form/LookupField.tsx +4 -1
- package/src/widgets/form/MonthField.scss +113 -113
- package/src/widgets/form/NumberField.scss +72 -72
- package/src/widgets/form/Select.scss +104 -104
- package/src/widgets/form/TextField.scss +66 -66
- package/src/widgets/form/ValidationGroup.spec.tsx +30 -1
- package/src/widgets/form/Wheel.tsx +36 -7
- package/src/widgets/grid/Grid.tsx +1 -1
- package/src/widgets/nav/MenuItem.tsx +525 -525
package/dist/widgets.js
CHANGED
|
@@ -6708,6 +6708,7 @@ class Field extends PureContainerBase {
|
|
|
6708
6708
|
data._readOnly = data.readOnly;
|
|
6709
6709
|
data._viewMode = data.mode === "view" || data.viewMode;
|
|
6710
6710
|
data._tabOnEnterKey = data.tabOnEnterKey;
|
|
6711
|
+
data._visited = data.visited;
|
|
6711
6712
|
data.validationValue = this.getValidationValue(data);
|
|
6712
6713
|
instance.parentDisabled = context.parentDisabled;
|
|
6713
6714
|
instance.parentReadOnly = context.parentReadOnly;
|
|
@@ -6745,7 +6746,7 @@ class Field extends PureContainerBase {
|
|
|
6745
6746
|
data._tabOnEnterKey,
|
|
6746
6747
|
context.parentTabOnEnterKey,
|
|
6747
6748
|
);
|
|
6748
|
-
data.visited = coalesce(context.parentStrict ? context.parentVisited : null, data.
|
|
6749
|
+
data.visited = coalesce(context.parentStrict ? context.parentVisited : null, data._visited, context.parentVisited);
|
|
6749
6750
|
if (!data.error && !data.disabled && !data.viewMode) this.validate(context, instance);
|
|
6750
6751
|
if (data.visited && !state?.visited) {
|
|
6751
6752
|
//feels hacky but it should be ok since we're in the middle of a new render cycle
|
|
@@ -9153,7 +9154,11 @@ class LookupComponent extends VDOM.Component {
|
|
|
9153
9154
|
text = this.getPlaceholder(data.placeholder);
|
|
9154
9155
|
}
|
|
9155
9156
|
} else {
|
|
9156
|
-
|
|
9157
|
+
let content = !data.empty ? data.text || this.getPlaceholder() : this.getPlaceholder(data.placeholder);
|
|
9158
|
+
text = jsx("span", {
|
|
9159
|
+
className: CSS.element(baseClass, "text"),
|
|
9160
|
+
children: content,
|
|
9161
|
+
});
|
|
9157
9162
|
}
|
|
9158
9163
|
let states = {
|
|
9159
9164
|
visited: state.visited,
|
|
@@ -13160,6 +13165,9 @@ class Wheel extends PureContainerBase {
|
|
|
13160
13165
|
Wheel.prototype.baseClass = "wheel";
|
|
13161
13166
|
Wheel.prototype.size = 3;
|
|
13162
13167
|
Wheel.prototype.styled = true;
|
|
13168
|
+
/** A cyclic wheel renders its option list this many times, leaving scroll
|
|
13169
|
+
* headroom on both sides of the centre copy. */
|
|
13170
|
+
const WHEEL_BUFFER_COPIES = 3;
|
|
13163
13171
|
class WheelComponent extends VDOM.Component {
|
|
13164
13172
|
index;
|
|
13165
13173
|
wheelEl;
|
|
@@ -13181,28 +13189,34 @@ class WheelComponent extends VDOM.Component {
|
|
|
13181
13189
|
wheelRef;
|
|
13182
13190
|
scrollRef;
|
|
13183
13191
|
render() {
|
|
13184
|
-
let { size, children, CSS, baseClass, active, className, style, onMouseDown } = this.props;
|
|
13192
|
+
let { size, children, CSS, baseClass, active, className, style, onMouseDown, cycle } = this.props;
|
|
13185
13193
|
let optionClass = CSS.element(baseClass, "option");
|
|
13186
13194
|
let dummyClass = CSS.element(baseClass, "option", {
|
|
13187
13195
|
dummy: true,
|
|
13188
13196
|
});
|
|
13197
|
+
// A cyclic wheel repeats the option list so it can scroll past either end.
|
|
13198
|
+
let options = children;
|
|
13199
|
+
if (cycle) {
|
|
13200
|
+
options = [];
|
|
13201
|
+
for (let i = 0; i < WHEEL_BUFFER_COPIES; i++) options.push(...children);
|
|
13202
|
+
}
|
|
13189
13203
|
let tpad = [],
|
|
13190
13204
|
bpad = [];
|
|
13191
13205
|
for (let i = 0; i < (size - 1) / 2; i++) {
|
|
13192
13206
|
tpad.push({
|
|
13193
13207
|
key: -1 - i,
|
|
13194
|
-
child:
|
|
13208
|
+
child: options[0],
|
|
13195
13209
|
cls: dummyClass,
|
|
13196
13210
|
});
|
|
13197
13211
|
bpad.push({
|
|
13198
13212
|
key: -100 - i,
|
|
13199
|
-
child:
|
|
13213
|
+
child: options[0],
|
|
13200
13214
|
cls: dummyClass,
|
|
13201
13215
|
});
|
|
13202
13216
|
}
|
|
13203
13217
|
let displayedOptions = [
|
|
13204
13218
|
...tpad,
|
|
13205
|
-
...
|
|
13219
|
+
...options.map((c, i) => ({
|
|
13206
13220
|
key: i,
|
|
13207
13221
|
child: c,
|
|
13208
13222
|
cls: optionClass,
|
|
@@ -13310,7 +13324,19 @@ class WheelComponent extends VDOM.Component {
|
|
|
13310
13324
|
if (this.props.onPipeKeyDown) this.props.onPipeKeyDown(this.onKeyDown);
|
|
13311
13325
|
}
|
|
13312
13326
|
UNSAFE_componentWillReceiveProps(props) {
|
|
13313
|
-
|
|
13327
|
+
let newIndex = props.index || 0;
|
|
13328
|
+
// A cyclic wheel renders the option list several times, so the same value
|
|
13329
|
+
// appears in several copies. Snap to the copy nearest the wheel's current
|
|
13330
|
+
// position rather than the one `props.index` names — a wrap then scrolls
|
|
13331
|
+
// one item into the adjacent (identical) copy with no jump, instead of
|
|
13332
|
+
// animating all the way back to the centre copy.
|
|
13333
|
+
if (props.cycle) {
|
|
13334
|
+
let period = props.children.length;
|
|
13335
|
+
let value = ((newIndex % period) + period) % period;
|
|
13336
|
+
newIndex = value + period * Math.round((this.index - value) / period);
|
|
13337
|
+
newIndex = Math.max(0, Math.min(period * WHEEL_BUFFER_COPIES - 1, newIndex));
|
|
13338
|
+
}
|
|
13339
|
+
this.index = newIndex;
|
|
13314
13340
|
this.scrollTo();
|
|
13315
13341
|
}
|
|
13316
13342
|
componentWillUnmount() {
|
|
@@ -13347,8 +13373,9 @@ class WheelComponent extends VDOM.Component {
|
|
|
13347
13373
|
}
|
|
13348
13374
|
}
|
|
13349
13375
|
select(newIndex) {
|
|
13350
|
-
let { children } = this.props;
|
|
13351
|
-
|
|
13376
|
+
let { children, cycle } = this.props;
|
|
13377
|
+
let length = children.length * (cycle ? WHEEL_BUFFER_COPIES : 1);
|
|
13378
|
+
newIndex = Math.max(0, Math.min(length - 1, newIndex));
|
|
13352
13379
|
if (this.index !== newIndex) {
|
|
13353
13380
|
this.index = newIndex;
|
|
13354
13381
|
this.props.onChange(newIndex);
|
|
@@ -13404,6 +13431,24 @@ DateTimePicker.prototype.size = 3;
|
|
|
13404
13431
|
DateTimePicker.prototype.autoFocus = false;
|
|
13405
13432
|
DateTimePicker.prototype.segment = "datetime";
|
|
13406
13433
|
DateTimePicker.prototype.showSeconds = false;
|
|
13434
|
+
// Builds the option spans for a numeric wheel — one zero-padded span per value.
|
|
13435
|
+
// Pass the result to a WheelComponent with `cycle` set to make it scroll
|
|
13436
|
+
// endlessly; centre the current value by passing `index = value + range`.
|
|
13437
|
+
function buildNumberWheel(range, startAt) {
|
|
13438
|
+
return Array.from(
|
|
13439
|
+
{
|
|
13440
|
+
length: range,
|
|
13441
|
+
},
|
|
13442
|
+
(_, j) =>
|
|
13443
|
+
jsx(
|
|
13444
|
+
"span",
|
|
13445
|
+
{
|
|
13446
|
+
children: String(j + startAt).padStart(2, "0"),
|
|
13447
|
+
},
|
|
13448
|
+
j,
|
|
13449
|
+
),
|
|
13450
|
+
);
|
|
13451
|
+
}
|
|
13407
13452
|
class DateTimePickerComponent extends VDOM.Component {
|
|
13408
13453
|
el;
|
|
13409
13454
|
keyDownPipes;
|
|
@@ -13415,6 +13460,7 @@ class DateTimePickerComponent extends VDOM.Component {
|
|
|
13415
13460
|
date: date,
|
|
13416
13461
|
activeWheel: null,
|
|
13417
13462
|
};
|
|
13463
|
+
this.century = (date.getFullYear() / 100) | 0;
|
|
13418
13464
|
let { widget } = props.instance;
|
|
13419
13465
|
let pickerWidget = widget;
|
|
13420
13466
|
this.handleChange = this.handleChange.bind(this);
|
|
@@ -13477,56 +13523,37 @@ class DateTimePickerComponent extends VDOM.Component {
|
|
|
13477
13523
|
let date = this.state.date;
|
|
13478
13524
|
let culture = Culture.getDateTimeCulture();
|
|
13479
13525
|
let monthNames = culture.getMonthNames("short");
|
|
13480
|
-
|
|
13481
|
-
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
"span",
|
|
13498
|
-
{
|
|
13499
|
-
children: day < 10 ? "0" + day : day,
|
|
13500
|
-
},
|
|
13501
|
-
day,
|
|
13502
|
-
),
|
|
13503
|
-
);
|
|
13504
|
-
start.setDate(start.getDate() + 1);
|
|
13505
|
-
}
|
|
13506
|
-
let hours = [];
|
|
13507
|
-
for (let h = 0; h < 24; h++) {
|
|
13508
|
-
hours.push(
|
|
13509
|
-
jsx(
|
|
13510
|
-
"span",
|
|
13511
|
-
{
|
|
13512
|
-
children: h < 10 ? "0" + h : h,
|
|
13513
|
-
},
|
|
13514
|
-
h,
|
|
13515
|
-
),
|
|
13516
|
-
);
|
|
13517
|
-
}
|
|
13518
|
-
let minutes = [];
|
|
13519
|
-
for (let m = 0; m < 60; m++) {
|
|
13520
|
-
minutes.push(
|
|
13521
|
-
jsx(
|
|
13522
|
-
"span",
|
|
13523
|
-
{
|
|
13524
|
-
children: m < 10 ? "0" + m : m,
|
|
13525
|
-
},
|
|
13526
|
-
m,
|
|
13527
|
-
),
|
|
13528
|
-
);
|
|
13526
|
+
// Years: a window spanning the current century, rebuilt when it changes.
|
|
13527
|
+
let currentCentury = (date.getFullYear() / 100) | 0;
|
|
13528
|
+
if (!this.years || this.century !== currentCentury) {
|
|
13529
|
+
this.century = currentCentury;
|
|
13530
|
+
this.firstYear = currentCentury * 100 - 3;
|
|
13531
|
+
let lastYear = (currentCentury + 1) * 100 + 5;
|
|
13532
|
+
this.years = [];
|
|
13533
|
+
for (let y = this.firstYear; y <= lastYear; y++)
|
|
13534
|
+
this.years.push(
|
|
13535
|
+
jsx(
|
|
13536
|
+
"span",
|
|
13537
|
+
{
|
|
13538
|
+
children: y,
|
|
13539
|
+
},
|
|
13540
|
+
y,
|
|
13541
|
+
),
|
|
13542
|
+
);
|
|
13529
13543
|
}
|
|
13544
|
+
let years = this.years;
|
|
13545
|
+
// Day/hour/minute wheels use a 3x buffer (see buildNumberWheel). The day
|
|
13546
|
+
// buffer depends on the month length, so it is rebuilt when that changes.
|
|
13547
|
+
const numberOfDaysInMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
13548
|
+
if (!this.days || this.numberOfDaysInMonth !== numberOfDaysInMonth) {
|
|
13549
|
+
this.numberOfDaysInMonth = numberOfDaysInMonth;
|
|
13550
|
+
this.days = buildNumberWheel(numberOfDaysInMonth, 1);
|
|
13551
|
+
}
|
|
13552
|
+
let days = this.days;
|
|
13553
|
+
if (!this.hours) this.hours = buildNumberWheel(24, 0);
|
|
13554
|
+
let hours = this.hours;
|
|
13555
|
+
if (!this.minutes) this.minutes = buildNumberWheel(60, 0);
|
|
13556
|
+
let minutes = this.minutes;
|
|
13530
13557
|
return jsxs("div", {
|
|
13531
13558
|
tabIndex: 0,
|
|
13532
13559
|
ref: (el) => {
|
|
@@ -13538,30 +13565,34 @@ class DateTimePickerComponent extends VDOM.Component {
|
|
|
13538
13565
|
onKeyDown: this.onKeyDown,
|
|
13539
13566
|
children: [
|
|
13540
13567
|
this.wheels.year &&
|
|
13541
|
-
jsx(
|
|
13542
|
-
|
|
13543
|
-
|
|
13544
|
-
|
|
13545
|
-
|
|
13546
|
-
|
|
13547
|
-
|
|
13548
|
-
this.
|
|
13549
|
-
|
|
13550
|
-
|
|
13551
|
-
|
|
13552
|
-
|
|
13553
|
-
|
|
13554
|
-
|
|
13555
|
-
|
|
13556
|
-
|
|
13557
|
-
|
|
13558
|
-
|
|
13559
|
-
|
|
13560
|
-
|
|
13561
|
-
|
|
13568
|
+
jsx(
|
|
13569
|
+
WheelComponent,
|
|
13570
|
+
{
|
|
13571
|
+
size: size,
|
|
13572
|
+
CSS: CSS,
|
|
13573
|
+
active: this.state.activeWheel === "year",
|
|
13574
|
+
baseClass: baseClass + "-wheel",
|
|
13575
|
+
index: date.getFullYear() - this.firstYear,
|
|
13576
|
+
onChange: (newIndex) => {
|
|
13577
|
+
this.setState(
|
|
13578
|
+
(state) => ({
|
|
13579
|
+
date: this.setDateComponent(state.date, "year", newIndex + this.firstYear),
|
|
13580
|
+
}),
|
|
13581
|
+
this.handleChange,
|
|
13582
|
+
);
|
|
13583
|
+
},
|
|
13584
|
+
onPipeKeyDown: (kd) => {
|
|
13585
|
+
this.keyDownPipes["year"] = kd;
|
|
13586
|
+
},
|
|
13587
|
+
onMouseDown: () => {
|
|
13588
|
+
this.setState({
|
|
13589
|
+
activeWheel: "year",
|
|
13590
|
+
});
|
|
13591
|
+
},
|
|
13592
|
+
children: years,
|
|
13562
13593
|
},
|
|
13563
|
-
|
|
13564
|
-
|
|
13594
|
+
`years-${this.century}`,
|
|
13595
|
+
),
|
|
13565
13596
|
this.wheels.year &&
|
|
13566
13597
|
this.wheels.month &&
|
|
13567
13598
|
jsx("span", {
|
|
@@ -13577,7 +13608,7 @@ class DateTimePickerComponent extends VDOM.Component {
|
|
|
13577
13608
|
onChange: (newIndex) => {
|
|
13578
13609
|
this.setState(
|
|
13579
13610
|
(state) => ({
|
|
13580
|
-
date: this.setDateComponent(
|
|
13611
|
+
date: this.setDateComponent(state.date, "month", newIndex),
|
|
13581
13612
|
}),
|
|
13582
13613
|
this.handleChange,
|
|
13583
13614
|
);
|
|
@@ -13606,120 +13637,144 @@ class DateTimePickerComponent extends VDOM.Component {
|
|
|
13606
13637
|
children: "-",
|
|
13607
13638
|
}),
|
|
13608
13639
|
this.wheels.date &&
|
|
13609
|
-
jsx(
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
-
|
|
13620
|
-
this.
|
|
13621
|
-
|
|
13622
|
-
|
|
13623
|
-
|
|
13624
|
-
|
|
13625
|
-
|
|
13626
|
-
|
|
13627
|
-
|
|
13628
|
-
|
|
13629
|
-
}
|
|
13640
|
+
jsx(
|
|
13641
|
+
WheelComponent,
|
|
13642
|
+
{
|
|
13643
|
+
size: size,
|
|
13644
|
+
CSS: CSS,
|
|
13645
|
+
cycle: true,
|
|
13646
|
+
active: this.state.activeWheel === "date",
|
|
13647
|
+
baseClass: baseClass + "-wheel",
|
|
13648
|
+
index: date.getDate() - 1 + this.numberOfDaysInMonth,
|
|
13649
|
+
onChange: (rawIndex) => {
|
|
13650
|
+
let day = rawIndex % this.numberOfDaysInMonth;
|
|
13651
|
+
this.setState(
|
|
13652
|
+
(state) => ({
|
|
13653
|
+
date: this.setDateComponent(state.date, "date", day + 1),
|
|
13654
|
+
}),
|
|
13655
|
+
this.handleChange,
|
|
13656
|
+
);
|
|
13657
|
+
},
|
|
13658
|
+
onPipeKeyDown: (kd) => {
|
|
13659
|
+
this.keyDownPipes["date"] = kd;
|
|
13660
|
+
},
|
|
13661
|
+
onMouseDown: () => {
|
|
13662
|
+
this.setState({
|
|
13663
|
+
activeWheel: "date",
|
|
13664
|
+
});
|
|
13665
|
+
},
|
|
13666
|
+
children: days,
|
|
13630
13667
|
},
|
|
13631
|
-
|
|
13632
|
-
|
|
13668
|
+
"date",
|
|
13669
|
+
),
|
|
13633
13670
|
this.wheels.hours &&
|
|
13634
13671
|
this.wheels.year &&
|
|
13635
13672
|
jsx("span", {
|
|
13636
13673
|
className: CSS.element(baseClass, "spacer"),
|
|
13637
13674
|
}),
|
|
13638
13675
|
this.wheels.hours &&
|
|
13639
|
-
jsx(
|
|
13640
|
-
|
|
13641
|
-
|
|
13642
|
-
|
|
13643
|
-
|
|
13644
|
-
|
|
13645
|
-
|
|
13646
|
-
|
|
13647
|
-
|
|
13648
|
-
|
|
13649
|
-
|
|
13650
|
-
this.
|
|
13651
|
-
|
|
13652
|
-
|
|
13653
|
-
|
|
13654
|
-
|
|
13655
|
-
|
|
13656
|
-
|
|
13657
|
-
|
|
13658
|
-
|
|
13659
|
-
}
|
|
13676
|
+
jsx(
|
|
13677
|
+
WheelComponent,
|
|
13678
|
+
{
|
|
13679
|
+
size: size,
|
|
13680
|
+
CSS: CSS,
|
|
13681
|
+
cycle: true,
|
|
13682
|
+
active: this.state.activeWheel === "hours",
|
|
13683
|
+
baseClass: baseClass + "-wheel",
|
|
13684
|
+
index: date.getHours() + 24,
|
|
13685
|
+
onChange: (rawIndex) => {
|
|
13686
|
+
let hour = rawIndex % 24;
|
|
13687
|
+
this.setState(
|
|
13688
|
+
(state) => ({
|
|
13689
|
+
date: this.setDateComponent(state.date, "hours", hour),
|
|
13690
|
+
}),
|
|
13691
|
+
this.handleChange,
|
|
13692
|
+
);
|
|
13693
|
+
},
|
|
13694
|
+
onPipeKeyDown: (kd) => {
|
|
13695
|
+
this.keyDownPipes["hours"] = kd;
|
|
13696
|
+
},
|
|
13697
|
+
onMouseDown: () => {
|
|
13698
|
+
this.setState({
|
|
13699
|
+
activeWheel: "hours",
|
|
13700
|
+
});
|
|
13701
|
+
},
|
|
13702
|
+
children: hours,
|
|
13660
13703
|
},
|
|
13661
|
-
|
|
13662
|
-
|
|
13704
|
+
"hours",
|
|
13705
|
+
),
|
|
13663
13706
|
this.wheels.hours &&
|
|
13664
13707
|
this.wheels.minutes &&
|
|
13665
13708
|
jsx("span", {
|
|
13666
13709
|
children: ":",
|
|
13667
13710
|
}),
|
|
13668
13711
|
this.wheels.minutes &&
|
|
13669
|
-
jsx(
|
|
13670
|
-
|
|
13671
|
-
|
|
13672
|
-
|
|
13673
|
-
|
|
13674
|
-
|
|
13675
|
-
|
|
13676
|
-
this.
|
|
13677
|
-
|
|
13678
|
-
|
|
13679
|
-
|
|
13680
|
-
this.
|
|
13681
|
-
|
|
13682
|
-
|
|
13683
|
-
|
|
13684
|
-
|
|
13685
|
-
|
|
13686
|
-
|
|
13687
|
-
|
|
13688
|
-
|
|
13689
|
-
}
|
|
13712
|
+
jsx(
|
|
13713
|
+
WheelComponent,
|
|
13714
|
+
{
|
|
13715
|
+
size: size,
|
|
13716
|
+
CSS: CSS,
|
|
13717
|
+
cycle: true,
|
|
13718
|
+
baseClass: baseClass + "-wheel",
|
|
13719
|
+
active: this.state.activeWheel === "minutes",
|
|
13720
|
+
index: date.getMinutes() + 60,
|
|
13721
|
+
onChange: (rawIndex) => {
|
|
13722
|
+
let minute = rawIndex % 60;
|
|
13723
|
+
this.setState(
|
|
13724
|
+
(state) => ({
|
|
13725
|
+
date: this.setDateComponent(state.date, "minutes", minute),
|
|
13726
|
+
}),
|
|
13727
|
+
this.handleChange,
|
|
13728
|
+
);
|
|
13729
|
+
},
|
|
13730
|
+
onPipeKeyDown: (kd) => {
|
|
13731
|
+
this.keyDownPipes["minutes"] = kd;
|
|
13732
|
+
},
|
|
13733
|
+
onMouseDown: () => {
|
|
13734
|
+
this.setState({
|
|
13735
|
+
activeWheel: "minutes",
|
|
13736
|
+
});
|
|
13737
|
+
},
|
|
13738
|
+
children: minutes,
|
|
13690
13739
|
},
|
|
13691
|
-
|
|
13692
|
-
|
|
13740
|
+
"minutes",
|
|
13741
|
+
),
|
|
13693
13742
|
this.wheels.minutes &&
|
|
13694
13743
|
this.wheels.seconds &&
|
|
13695
13744
|
jsx("span", {
|
|
13696
13745
|
children: ":",
|
|
13697
13746
|
}),
|
|
13698
13747
|
this.wheels.seconds &&
|
|
13699
|
-
jsx(
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
this.
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13710
|
-
this.
|
|
13711
|
-
|
|
13712
|
-
|
|
13713
|
-
|
|
13714
|
-
|
|
13715
|
-
|
|
13716
|
-
|
|
13717
|
-
|
|
13718
|
-
|
|
13719
|
-
}
|
|
13748
|
+
jsx(
|
|
13749
|
+
WheelComponent,
|
|
13750
|
+
{
|
|
13751
|
+
size: size,
|
|
13752
|
+
CSS: CSS,
|
|
13753
|
+
cycle: true,
|
|
13754
|
+
baseClass: baseClass + "-wheel",
|
|
13755
|
+
active: this.state.activeWheel === "seconds",
|
|
13756
|
+
index: date.getSeconds() + 60,
|
|
13757
|
+
onChange: (rawIndex) => {
|
|
13758
|
+
let second = rawIndex % 60;
|
|
13759
|
+
this.setState(
|
|
13760
|
+
(state) => ({
|
|
13761
|
+
date: this.setDateComponent(state.date, "seconds", second),
|
|
13762
|
+
}),
|
|
13763
|
+
this.handleChange,
|
|
13764
|
+
);
|
|
13765
|
+
},
|
|
13766
|
+
onPipeKeyDown: (kd) => {
|
|
13767
|
+
this.keyDownPipes["seconds"] = kd;
|
|
13768
|
+
},
|
|
13769
|
+
onMouseDown: () => {
|
|
13770
|
+
this.setState({
|
|
13771
|
+
activeWheel: "seconds",
|
|
13772
|
+
});
|
|
13773
|
+
},
|
|
13774
|
+
children: minutes,
|
|
13720
13775
|
},
|
|
13721
|
-
|
|
13722
|
-
|
|
13776
|
+
"seconds",
|
|
13777
|
+
),
|
|
13723
13778
|
],
|
|
13724
13779
|
});
|
|
13725
13780
|
}
|
|
@@ -18582,6 +18637,7 @@ export {
|
|
|
18582
18637
|
ValidationError,
|
|
18583
18638
|
ValidationGroup,
|
|
18584
18639
|
Validator,
|
|
18640
|
+
WHEEL_BUFFER_COPIES,
|
|
18585
18641
|
Wheel,
|
|
18586
18642
|
WheelComponent,
|
|
18587
18643
|
Window,
|
package/package.json
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
@use "sass:map";
|
|
2
|
+
@use "../util/scss/besm.scss" as *;
|
|
3
|
+
@use "../util/scss/include.scss" as *;
|
|
4
|
+
@use "./variables" as *;
|
|
2
5
|
|
|
3
6
|
@mixin cx-rangemarker($name: "rangemarker", $besm: $cx-besm, $range-marker-color: $cx-default-range-marker-color) {
|
|
4
7
|
$block: map.get($besm, block);
|
package/src/charts/axis/Axis.tsx
CHANGED
|
@@ -74,6 +74,14 @@ export interface AxisConfig extends BoundedObjectConfig {
|
|
|
74
74
|
/** Set to true to hide the axis labels. */
|
|
75
75
|
hideLabels?: boolean;
|
|
76
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Set to `true` to drop a boundary (first/last) label, together with its tick,
|
|
79
|
+
* when the label would not fit within the chart and get clipped at the edge.
|
|
80
|
+
* Minor ticks are unaffected. Only affects horizontal axes. Defaults to `false`,
|
|
81
|
+
* except on `TimeAxis` where it defaults to `true`.
|
|
82
|
+
*/
|
|
83
|
+
hideClippedLabels?: boolean;
|
|
84
|
+
|
|
77
85
|
/** Set to true to hide the axis line. */
|
|
78
86
|
hideLine?: boolean;
|
|
79
87
|
|
|
@@ -131,6 +139,7 @@ export class Axis extends BoundedObject<AxisConfig, AxisInstance> {
|
|
|
131
139
|
declare inverted: boolean;
|
|
132
140
|
declare hidden: boolean;
|
|
133
141
|
declare hideLabels: boolean;
|
|
142
|
+
declare hideClippedLabels: boolean;
|
|
134
143
|
declare hideTicks: boolean;
|
|
135
144
|
declare hideLine: boolean;
|
|
136
145
|
declare tickSize: number;
|
|
@@ -185,6 +194,7 @@ export class Axis extends BoundedObject<AxisConfig, AxisInstance> {
|
|
|
185
194
|
{
|
|
186
195
|
anchors: undefined,
|
|
187
196
|
hideLabels: undefined,
|
|
197
|
+
hideClippedLabels: undefined,
|
|
188
198
|
hideLine: undefined,
|
|
189
199
|
hideTicks: undefined,
|
|
190
200
|
labelRotation: undefined,
|
|
@@ -259,10 +269,27 @@ export class Axis extends BoundedObject<AxisConfig, AxisInstance> {
|
|
|
259
269
|
var t: string[] = [];
|
|
260
270
|
if (!!size && !data.hideLabels) {
|
|
261
271
|
var ticks = calculator.getTicks([size]);
|
|
272
|
+
|
|
273
|
+
// A boundary label is dropped when it would be clipped at the chart edge.
|
|
274
|
+
// How far a label reaches toward an edge depends only on its text anchor
|
|
275
|
+
// and minLabelDistance, so it is resolved once here rather than per tick.
|
|
276
|
+
// Chart bounds (parentRect) are used rather than axis bounds, since an
|
|
277
|
+
// axis can be inset within its chart and one Svg may host several charts.
|
|
278
|
+
let chartBounds = instance.parentRect;
|
|
279
|
+
let clipBoundaryLabels = !this.vertical && !!data.hideClippedLabels && !!chartBounds;
|
|
280
|
+
let reach = minLabelDistance * 0.8;
|
|
281
|
+
let leftReach = data.labelAnchor == "end" ? reach : data.labelAnchor == "middle" ? reach / 2 : 0;
|
|
282
|
+
let rightReach = data.labelAnchor == "start" ? reach : data.labelAnchor == "middle" ? reach / 2 : 0;
|
|
283
|
+
|
|
262
284
|
ticks.forEach((serie: any[], si: number) => {
|
|
263
285
|
serie.forEach((v: any, i: number) => {
|
|
264
286
|
var s = calculator.map(v);
|
|
265
287
|
|
|
288
|
+
// Drop this boundary label (and its major tick) if it would be
|
|
289
|
+
// clipped at the chart edge; minor ticks render separately and stay.
|
|
290
|
+
let clipped =
|
|
291
|
+
clipBoundaryLabels && (s + rightReach > chartBounds.r || s - leftReach < chartBounds.l);
|
|
292
|
+
|
|
266
293
|
if (this.secondary) {
|
|
267
294
|
x1 = this.vertical ? bounds.r + tickOffset : s;
|
|
268
295
|
y1 = this.vertical ? s : bounds.t - tickOffset;
|
|
@@ -275,7 +302,9 @@ export class Axis extends BoundedObject<AxisConfig, AxisInstance> {
|
|
|
275
302
|
y2 = this.vertical ? s : bounds.b + tickOffset + tickSize;
|
|
276
303
|
}
|
|
277
304
|
|
|
278
|
-
if (!this.useGridlineTicks) t.push(`M ${x1} ${y1} L ${x2} ${y2}`);
|
|
305
|
+
if (!this.useGridlineTicks && !clipped) t.push(`M ${x1} ${y1} L ${x2} ${y2}`);
|
|
306
|
+
|
|
307
|
+
if (clipped) return;
|
|
279
308
|
|
|
280
309
|
var x, y;
|
|
281
310
|
let labelOffset =
|
|
@@ -422,6 +451,7 @@ Axis.prototype.secondary = false;
|
|
|
422
451
|
Axis.prototype.inverted = false;
|
|
423
452
|
Axis.prototype.hidden = false;
|
|
424
453
|
Axis.prototype.hideLabels = false;
|
|
454
|
+
Axis.prototype.hideClippedLabels = false;
|
|
425
455
|
Axis.prototype.hideTicks = false;
|
|
426
456
|
Axis.prototype.hideLine = false;
|
|
427
457
|
|
|
@@ -212,6 +212,7 @@ TimeAxis.prototype.minLabelDistance = 60;
|
|
|
212
212
|
TimeAxis.prototype.minTickDistance = 60;
|
|
213
213
|
TimeAxis.prototype.minTickUnit = "second";
|
|
214
214
|
TimeAxis.prototype.useLabelDistanceFormatOverrides = false;
|
|
215
|
+
TimeAxis.prototype.hideClippedLabels = true;
|
|
215
216
|
TimeAxis.prototype.minLabelDistanceFormatOverrideDefaults = {
|
|
216
217
|
[TimeFormats.fullDateAndTime]: 150,
|
|
217
218
|
[TimeFormats.shortMonthDate]: 90,
|
package/src/charts/index.scss
CHANGED
|
@@ -19,11 +19,12 @@ export class AugmentedViewBase<D = any> extends View<D> {
|
|
|
19
19
|
let parentStoreData = this.store.getData();
|
|
20
20
|
let result = this.getBaseData(parentStoreData);
|
|
21
21
|
this.embedAugmentData(result, parentStoreData);
|
|
22
|
-
this.
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
if (this.sealed) {
|
|
23
|
+
this.cache.result = result;
|
|
24
|
+
this.cache.version = this.meta.version;
|
|
25
|
+
}
|
|
25
26
|
this.meta = this.store.meta;
|
|
26
|
-
return
|
|
27
|
+
return result;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
protected getBaseData(parentStoreData: any): any {
|