cx 22.4.1 → 22.5.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/dist/util.js CHANGED
@@ -660,7 +660,7 @@ function getScrollerBoundingClientRect(scrollEl, topLevel) {
660
660
  return topLevel ? getTopLevelBoundingClientRect(scrollEl) : scrollEl.getBoundingClientRect();
661
661
  }
662
662
 
663
- function scrollElementIntoView(el, vertical, horizontal, inflate) {
663
+ function scrollElementIntoView(el, vertical, horizontal, inflate, scrollContainer) {
664
664
  if (vertical === void 0) {
665
665
  vertical = true;
666
666
  }
@@ -673,8 +673,12 @@ function scrollElementIntoView(el, vertical, horizontal, inflate) {
673
673
  inflate = 0;
674
674
  }
675
675
 
676
+ if (scrollContainer === void 0) {
677
+ scrollContainer = null;
678
+ }
679
+
676
680
  if (horizontal) {
677
- var parentEl = findScrollableParent(el, true);
681
+ var parentEl = scrollContainer || findScrollableParent(el, true);
678
682
 
679
683
  if (parentEl) {
680
684
  var pr = getScrollerBoundingClientRect(parentEl);
@@ -688,7 +692,7 @@ function scrollElementIntoView(el, vertical, horizontal, inflate) {
688
692
  }
689
693
 
690
694
  if (vertical) {
691
- var _parentEl = findScrollableParent(el);
695
+ var _parentEl = scrollContainer || findScrollableParent(el);
692
696
 
693
697
  if (_parentEl) {
694
698
  var _pr = getScrollerBoundingClientRect(_parentEl);
@@ -1200,15 +1204,17 @@ var lastTouchEvent = 0;
1200
1204
  var isTouchDetectionEnabled = false;
1201
1205
  function enableTouchEventDetection() {
1202
1206
  if (isTouchDevice() && !isTouchDetectionEnabled) {
1203
- var options;
1207
+ var options = true; //capture
1208
+
1204
1209
  if (browserSupportsPassiveEventHandlers())
1205
1210
  options = {
1206
- passive: true
1211
+ passive: true,
1212
+ capture: true
1207
1213
  };
1208
1214
  document.addEventListener(
1209
1215
  "touchstart",
1210
1216
  function() {
1211
- lastTouchEvent = new Date().getTime();
1217
+ lastTouchEvent = Date.now();
1212
1218
  },
1213
1219
  options
1214
1220
  );
@@ -1216,14 +1222,14 @@ function enableTouchEventDetection() {
1216
1222
  "touchmove",
1217
1223
  function() {
1218
1224
  //console.log('TOUCHMOVE');
1219
- lastTouchEvent = new Date().getTime();
1225
+ lastTouchEvent = Date.now();
1220
1226
  },
1221
1227
  options
1222
1228
  );
1223
1229
  document.addEventListener(
1224
1230
  "touchend",
1225
1231
  function() {
1226
- lastTouchEvent = new Date().getTime(); //console.log('TOUCHEND');
1232
+ lastTouchEvent = Date.now(); //console.log('TOUCHEND');
1227
1233
  },
1228
1234
  options
1229
1235
  );
@@ -1231,7 +1237,7 @@ function enableTouchEventDetection() {
1231
1237
  }
1232
1238
  }
1233
1239
  function isTouchEvent() {
1234
- return isTouchDevice() && (!isTouchDetectionEnabled || new Date().getTime() - lastTouchEvent < 1000);
1240
+ return isTouchDevice() && (!isTouchDetectionEnabled || Date.now() - lastTouchEvent < 1000);
1235
1241
  } //enable touch event detection if there is no performance penalty on scrolling
1236
1242
 
1237
1243
  if (isTouchDevice() && browserSupportsPassiveEventHandlers()) enableTouchEventDetection();
package/dist/widgets.js CHANGED
@@ -1810,7 +1810,7 @@ var ListComponent = /*#__PURE__*/ (function(_VDOM$Component) {
1810
1810
  var firstSelectedRow = this.el.querySelector(selectedRowSelector);
1811
1811
 
1812
1812
  if (firstSelectedRow != this.selectedEl) {
1813
- if (firstSelectedRow) scrollElementIntoView(firstSelectedRow);
1813
+ if (firstSelectedRow) scrollElementIntoView(firstSelectedRow, true, false, 0, this.el);
1814
1814
  this.selectedEl = firstSelectedRow;
1815
1815
  }
1816
1816
  };
@@ -8258,7 +8258,7 @@ var Input = /*#__PURE__*/ (function(_VDOM$Component) {
8258
8258
  immediate: immediate
8259
8259
  })
8260
8260
  ) {
8261
- if (text != this.trimmed(this.input.value)) this.input.value = text;
8261
+ if (text != this.input.value && immediate) this.input.value = text;
8262
8262
  } else {
8263
8263
  if (value)
8264
8264
  instance.setState({
@@ -9355,12 +9355,23 @@ var CalendarCmp = /*#__PURE__*/ (function(_VDOM$Component) {
9355
9355
  _proto2.getPage = function getPage(refDate) {
9356
9356
  refDate = monthStart(refDate); //make a copy
9357
9357
 
9358
+ var startWithMonday = this.props.instance.widget.startWithMonday;
9359
+ var startDay = startWithMonday ? 1 : 0;
9358
9360
  var startDate = new Date(refDate);
9359
- startDate.setDate(1 - startDate.getDay());
9361
+
9362
+ while (startDate.getDay() != startDay) {
9363
+ startDate.setDate(startDate.getDate() - 1);
9364
+ }
9365
+
9360
9366
  var endDate = new Date(refDate);
9361
9367
  endDate.setMonth(refDate.getMonth() + 1);
9362
9368
  endDate.setDate(endDate.getDate() - 1);
9363
- endDate.setDate(endDate.getDate() + 6 - endDate.getDay());
9369
+ var endDay = startWithMonday ? 0 : 6;
9370
+
9371
+ while (endDate.getDay() != endDay) {
9372
+ endDate.setDate(endDate.getDate() + 1);
9373
+ }
9374
+
9364
9375
  return {
9365
9376
  refDate: refDate,
9366
9377
  startDate: startDate,
@@ -9574,16 +9585,19 @@ var CalendarCmp = /*#__PURE__*/ (function(_VDOM$Component) {
9574
9585
  baseClass = widget.baseClass,
9575
9586
  disabledDaysOfWeek = widget.disabledDaysOfWeek,
9576
9587
  startWithMonday = widget.startWithMonday;
9577
- var refDate = this.state.refDate;
9588
+
9589
+ var _this$getPage = this.getPage(this.state.refDate),
9590
+ refDate = _this$getPage.refDate,
9591
+ startDate = _this$getPage.startDate,
9592
+ endDate = _this$getPage.endDate;
9593
+
9578
9594
  var month = refDate.getMonth();
9579
9595
  var year = refDate.getFullYear();
9580
- var startDate = new Date(year, month, 1);
9581
- startDate.setDate(1 - startDate.getDay() + (startWithMonday ? 1 : 0));
9582
9596
  var weeks = [];
9583
9597
  var date = startDate;
9584
9598
  var today = zeroTime(new Date());
9585
9599
 
9586
- while (date < refDate || date.getMonth() == month) {
9600
+ while (date >= startDate && date <= endDate) {
9587
9601
  var days = [];
9588
9602
 
9589
9603
  for (var i = 0; i < 7; i++) {
@@ -17210,7 +17224,7 @@ var GridRowComponent = /*#__PURE__*/ (function(_VDOM$Component) {
17210
17224
  e.preventDefault();
17211
17225
  e.stopPropagation(); //close context menu
17212
17226
 
17213
- unfocusElement(e.target);
17227
+ unfocusElement(e.target, false);
17214
17228
  }
17215
17229
  }
17216
17230
 
@@ -18373,7 +18387,8 @@ var Grid = /*#__PURE__*/ (function(_Widget) {
18373
18387
  baseClass = this.baseClass;
18374
18388
  var data = store.getData();
18375
18389
  var skip = 0;
18376
- var header = instance.header;
18390
+ var header = instance.header,
18391
+ state = instance.state;
18377
18392
  var rowStyle = {};
18378
18393
  var lines = [];
18379
18394
  header.children.forEach(function(line, lineIndex) {
@@ -18383,7 +18398,7 @@ var Grid = /*#__PURE__*/ (function(_Widget) {
18383
18398
  if (Boolean(ci.data.fixed) != fixedColumns) return null;
18384
18399
  var v,
18385
18400
  c = ci.widget,
18386
- colSpan,
18401
+ colSpan = 1,
18387
18402
  pad,
18388
18403
  cls = "",
18389
18404
  style = null;
@@ -18419,7 +18434,18 @@ var Grid = /*#__PURE__*/ (function(_Widget) {
18419
18434
 
18420
18435
  if (cls) cls += " ";
18421
18436
  if (c.align) cls += CSS.state("aligned-" + c.align);
18422
- if (pad !== false) cls += (cls ? " " : "") + CSS.state("pad");
18437
+ if (pad !== false) cls += (cls ? " " : "") + CSS.state("pad"); // apply column width to footers too, but only if colSpan == 1,
18438
+ // otherwise set 1px so that the footer is not participating in the layout
18439
+
18440
+ var maxWidth = 1;
18441
+ if (colSpan == 1) maxWidth = state.colWidth[c.uniqueColumnId];
18442
+ style = _objectSpread2(
18443
+ _objectSpread2({}, style),
18444
+ {},
18445
+ {
18446
+ maxWidth: maxWidth
18447
+ }
18448
+ );
18423
18449
  return /*#__PURE__*/ jsx(
18424
18450
  "td",
18425
18451
  {
@@ -20128,7 +20154,7 @@ var GridComponent = /*#__PURE__*/ (function(_VDOM$Component) {
20128
20154
  if (!futureState.cellEdit && wasCellEditing) {
20129
20155
  //If cell editing is in progress, moving the cursor may cause that the cell editor is unmounted before
20130
20156
  //the blur event which may cause data loss for components which do not have reactOn=change set, e.g. NumberField.
20131
- unfocusElement();
20157
+ unfocusElement(null, false);
20132
20158
 
20133
20159
  var record = _this11.getRecordAt(prevState.cursor);
20134
20160
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cx",
3
- "version": "22.4.1",
3
+ "version": "22.5.0",
4
4
  "description": "Advanced JavaScript UI framework for admin and dashboard applications with ready to use grid, form and chart components.",
5
5
  "main": "index.js",
6
6
  "jsnext:main": "src/index.js",
package/src/core.d.ts CHANGED
@@ -29,6 +29,8 @@ declare namespace Cx {
29
29
 
30
30
  type AccessorChain<M> = {
31
31
  toString(): string;
32
+ valueOf(): string;
33
+ nameOf(): string;
32
34
  } & {
33
35
  [prop in keyof M]: AccessorChain<M[prop]>;
34
36
  };
@@ -1,38 +1,38 @@
1
- import {sorter} from './comparer';
2
- import assert from 'assert';
1
+ import { sorter } from "./comparer";
2
+ import assert from "assert";
3
3
 
4
- describe('comparer', function() {
5
- describe('sorter', function() {
6
- it('orders by numeric values ASC', function () {
4
+ describe("comparer", function () {
5
+ describe("sorter", function () {
6
+ it("orders by numeric values ASC", function () {
7
7
  let records = [
8
- {value: 3, id: 1},
9
- {value: -1, id: 2},
10
- {value: 2, id: 3},
11
- {value: null, id: 4},
12
- {value: null, id: 5},
8
+ { value: 3, id: 1 },
9
+ { value: -1, id: 2 },
10
+ { value: 2, id: 3 },
11
+ { value: null, id: 4 },
12
+ { value: null, id: 5 },
13
13
  ];
14
14
 
15
- let sort = sorter([{value: {bind: 'value'}, direction: 'ASC'}]);
15
+ let sort = sorter([{ value: { bind: "value" }, direction: "ASC" }]);
16
16
 
17
17
  let sorted = sort(records);
18
18
 
19
- assert.equal(sorted[0].value, null);
20
- assert.equal(sorted[1].value, null);
21
- assert.equal(sorted[2].value, -1);
22
- assert.equal(sorted[3].value, 2);
23
- assert.equal(sorted[4].value, 3);
19
+ assert.equal(sorted[0].value, -1);
20
+ assert.equal(sorted[1].value, 2);
21
+ assert.equal(sorted[2].value, 3);
22
+ assert.equal(sorted[3].value, null);
23
+ assert.equal(sorted[4].value, null);
24
24
  });
25
25
 
26
- it('orders by numeric values DESC', function () {
26
+ it("orders by numeric values DESC", function () {
27
27
  let records = [
28
- {value: 3, id: 1},
29
- {value: 1, id: 2},
30
- {value: -2, id: 3},
31
- {value: null, id: 4},
32
- {value: null, id: 5},
28
+ { value: 3, id: 1 },
29
+ { value: 1, id: 2 },
30
+ { value: -2, id: 3 },
31
+ { value: null, id: 4 },
32
+ { value: null, id: 5 },
33
33
  ];
34
34
 
35
- let sort = sorter([{value: {bind: 'value'}, direction: 'DESC'}]);
35
+ let sort = sorter([{ value: { bind: "value" }, direction: "DESC" }]);
36
36
 
37
37
  let sorted = sort(records);
38
38
 
@@ -43,14 +43,14 @@ describe('comparer', function() {
43
43
  assert.equal(sorted[4].value, null);
44
44
  });
45
45
 
46
- it('supports field', function () {
46
+ it("supports field", function () {
47
47
  let records = [
48
- {value: 3, id: 1},
49
- {value: 1, id: 2},
50
- {value: 2, id: 3}
48
+ { value: 3, id: 1 },
49
+ { value: 1, id: 2 },
50
+ { value: 2, id: 3 },
51
51
  ];
52
52
 
53
- let sort = sorter([{field: 'value', direction: 'ASC'}]);
53
+ let sort = sorter([{ field: "value", direction: "ASC" }]);
54
54
  let sorted = sort(records);
55
55
  assert.equal(sorted[0].value, 1);
56
56
  assert.equal(sorted[1].value, 2);
@@ -1,21 +1,43 @@
1
+ const emptyFn = () => {};
2
+
1
3
  export function createAccessorModelProxy(chain = "") {
2
- const proxy = new Proxy(() => {}, {
3
- get: (target, name) => {
4
- if (name === "isAccessorChain") return true;
5
- if (typeof name !== "string") return this;
6
- if (name === "toString" || name === "valueOf") return proxy;
4
+ let lastOp = null;
5
+ let lastName = null;
6
+
7
+ const proxy = new Proxy(emptyFn, {
8
+ get: (_, name) => {
9
+ if (typeof name !== "string") return proxy;
10
+
11
+ switch (name) {
12
+ case "isAccessorChain":
13
+ return true;
14
+
15
+ case "toString":
16
+ case "valueOf":
17
+ case "nameOf":
18
+ lastOp = name;
19
+ return proxy;
20
+ }
7
21
 
8
22
  let newChain = chain;
9
23
  if (newChain.length > 0) newChain += ".";
10
24
  newChain += name;
25
+ lastName = name;
11
26
  return createAccessorModelProxy(newChain);
12
27
  },
13
28
 
14
29
  apply() {
15
- return chain;
30
+ switch (lastOp) {
31
+ case "nameOf":
32
+ if (lastName != null) return lastName;
33
+ const lastDotIndex = chain.lastIndexOf(".");
34
+ return lastDotIndex > 0 ? chain.substring(lastDotIndex + 1) : chain;
35
+
36
+ default:
37
+ return chain;
38
+ }
16
39
  },
17
40
  });
18
- proxy.isAccessorChain = true;
19
41
  return proxy;
20
42
  }
21
43
 
@@ -5,19 +5,33 @@ interface Model {
5
5
  firstName: string;
6
6
  address: {
7
7
  city: string;
8
+ streetNumber: number;
8
9
  };
9
10
  }
10
11
 
11
12
  describe("createAccessorModelProxy", () => {
12
13
  it("generates correct paths", () => {
13
- var model = createAccessorModelProxy<Model>();
14
+ let model = createAccessorModelProxy<Model>();
14
15
  assert.strictEqual(model.firstName.toString(), "firstName");
15
16
  assert.strictEqual(model.address.toString(), "address");
16
17
  assert.strictEqual(model.address.city.toString(), "address.city");
17
18
  });
18
19
 
19
20
  it("can be used in string templates", () => {
20
- var model = createAccessorModelProxy<Model>();
21
+ let model = createAccessorModelProxy<Model>();
21
22
  assert.strictEqual("address.city", `${model.address.city}`);
23
+ assert.strictEqual("address.city", "" + model.address.city);
24
+ assert.strictEqual("address.city.suffix", model.address.city + ".suffix");
25
+ });
26
+
27
+ it("nameOf returns name of the last prop ", () => {
28
+ let model = createAccessorModelProxy<Model>();
29
+ assert.strictEqual(model.firstName.nameOf(), "firstName");
30
+ assert.strictEqual(model.address.nameOf(), "address");
31
+ assert.strictEqual(model.address.city.nameOf(), "city");
32
+
33
+ let { streetNumber, city } = model.address;
34
+ assert.strictEqual(streetNumber.nameOf(), "streetNumber");
35
+ assert.strictEqual(city.nameOf(), "city");
22
36
  });
23
37
  });
@@ -18,6 +18,26 @@ export class Controller<D = any> {
18
18
  store: View<D>;
19
19
  widget: any;
20
20
 
21
+ addTrigger<V1>(name: string, args: [Cx.AccessorChain<V1>], callback: (v1: V1) => void, autoRun?: boolean): void;
22
+ addTrigger<V1, V2>(
23
+ name: string,
24
+ args: [Cx.AccessorChain<V1>, Cx.AccessorChain<V2>],
25
+ callback: (v1: V1, v2: V2) => void,
26
+ autoRun?: boolean
27
+ ): void;
28
+ addTrigger<V1, V2, V3>(
29
+ name: string,
30
+ args: [Cx.AccessorChain<V1>, Cx.AccessorChain<V2>, Cx.AccessorChain<V3>],
31
+ callback: (v1: V1, v2: V2, v3: V3) => void,
32
+ autoRun?: boolean
33
+ ): void;
34
+ addTrigger<V1, V2, V3, V4>(
35
+ name: string,
36
+ args: [Cx.AccessorChain<V1>, Cx.AccessorChain<V2>, Cx.AccessorChain<V3>, Cx.AccessorChain<V4>],
37
+ callback: (v1: V1, v2: V2, v3: V3, v4: V4) => void,
38
+ autoRun?: boolean
39
+ ): void;
40
+
21
41
  addTrigger(
22
42
  name: string,
23
43
  args: (string | Cx.AccessorChain<any>)[],
@@ -25,7 +45,24 @@ export class Controller<D = any> {
25
45
  autoRun?: boolean
26
46
  ): void;
27
47
 
28
- addComputable(name: string, args: string[], callback: (...args) => any): void;
48
+ addComputable<V1, R>(path: Cx.AccessorChain<R>, args: [Cx.AccessorChain<V1>], callback: (v1: V1) => R): void;
49
+ addComputable<V1, V2, R>(
50
+ path: Cx.AccessorChain<R>,
51
+ args: [Cx.AccessorChain<V1>, Cx.AccessorChain<V2>],
52
+ callback: (v1: V1, v2: V2) => R
53
+ ): void;
54
+ addComputable<V1, V2, V3, R>(
55
+ path: Cx.AccessorChain<R>,
56
+ args: [Cx.AccessorChain<V1>, Cx.AccessorChain<V2>, Cx.AccessorChain<V3>],
57
+ callback: (v1: V1, v2: V2, v3: V3) => R
58
+ ): void;
59
+ addComputable<V1, V2, V3, V4, R>(
60
+ path: Cx.AccessorChain<R>,
61
+ args: [Cx.AccessorChain<V1>, Cx.AccessorChain<V2>, Cx.AccessorChain<V3>, Cx.AccessorChain<V4>],
62
+ callback: (v1: V1, v2: V2, v3: V3, v4: V4) => R
63
+ ): void;
64
+
65
+ addComputable(path: string, args: (string | Cx.AccessorChain<any>)[], callback: (...args) => any): void;
29
66
 
30
67
  removeTrigger(name: string): void;
31
68
 
@@ -41,6 +41,9 @@ interface RepeaterProps extends PureContainerProps {
41
41
 
42
42
  /** Options for data sorting. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator */
43
43
  sortOptions?: CollatorOptions;
44
+
45
+ /** A field used to get the unique identifier of the record. Setting keyField improves performance on sort operations as the widget is able to movement of records inside the collection. */
46
+ keyField: StringProp;
44
47
  }
45
48
 
46
49
  export class Repeater extends Widget<RepeaterProps> {}
@@ -1,11 +1,14 @@
1
- import * as Cx from '../../core';
1
+ import * as Cx from "../../core";
2
2
 
3
3
  interface ContentProps extends Cx.PureContainerProps {
4
+ /** Placeholder name where the content is rendered. */
5
+ name?: string;
4
6
 
5
- name?: string,
6
- putInto?: string,
7
- isContent?: boolean
7
+ /** Placeholder name where the content is rendered. */
8
+ for?: string;
8
9
 
10
+ /** Placeholder name where the content is rendered. */
11
+ putInto?: string;
9
12
  }
10
13
 
11
14
  export class Content extends Cx.Widget<ContentProps> {}
@@ -1,5 +1,5 @@
1
- import { browserSupportsPassiveEventHandlers } from './browserSupportsPassiveEventHandlers';
2
- import { isTouchDevice } from './isTouchDevice';
1
+ import { browserSupportsPassiveEventHandlers } from "./browserSupportsPassiveEventHandlers";
2
+ import { isTouchDevice } from "./isTouchDevice";
3
3
 
4
4
  // This is primarily used for tooltips which behave differently on touch.
5
5
  // For example, tooltips are commonly toggled on touch or disabled completely.
@@ -15,38 +15,50 @@ let isTouchDetectionEnabled = false;
15
15
 
16
16
  export function enableTouchEventDetection() {
17
17
  if (isTouchDevice() && !isTouchDetectionEnabled) {
18
- let options;
18
+ let options = true; //capture
19
19
 
20
20
  if (browserSupportsPassiveEventHandlers())
21
21
  options = {
22
- passive: true
22
+ passive: true,
23
+ capture: true,
23
24
  };
24
25
 
25
- document.addEventListener('touchstart', () => {
26
- insideTouchEvent++;
27
- //console.log('TOUCHSTART');
28
- lastTouchEvent = new Date().getTime();
29
- }, options);
26
+ document.addEventListener(
27
+ "touchstart",
28
+ () => {
29
+ insideTouchEvent++;
30
+ //console.log('TOUCHSTART');
31
+ lastTouchEvent = Date.now();
32
+ },
33
+ options
34
+ );
30
35
 
31
- document.addEventListener('touchmove', () => {
32
- //console.log('TOUCHMOVE');
33
- lastTouchEvent = new Date().getTime();
34
- }, options);
36
+ document.addEventListener(
37
+ "touchmove",
38
+ () => {
39
+ //console.log('TOUCHMOVE');
40
+ lastTouchEvent = Date.now();
41
+ },
42
+ options
43
+ );
35
44
 
36
- document.addEventListener('touchend', () => {
37
- insideTouchEvent--;
38
- lastTouchEvent = new Date().getTime();
39
- //console.log('TOUCHEND');
40
- }, options);
45
+ document.addEventListener(
46
+ "touchend",
47
+ () => {
48
+ insideTouchEvent--;
49
+ lastTouchEvent = Date.now();
50
+ //console.log('TOUCHEND');
51
+ },
52
+ options
53
+ );
41
54
 
42
55
  isTouchDetectionEnabled = true;
43
56
  }
44
57
  }
45
58
 
46
59
  export function isTouchEvent() {
47
- return isTouchDevice() && (!isTouchDetectionEnabled || (new Date().getTime() - lastTouchEvent) < 1000);
60
+ return isTouchDevice() && (!isTouchDetectionEnabled || Date.now() - lastTouchEvent < 1000);
48
61
  }
49
62
 
50
63
  //enable touch event detection if there is no performance penalty on scrolling
51
- if (isTouchDevice() && browserSupportsPassiveEventHandlers())
52
- enableTouchEventDetection();
64
+ if (isTouchDevice() && browserSupportsPassiveEventHandlers()) enableTouchEventDetection();
@@ -2,5 +2,6 @@ export function scrollElementIntoView(
2
2
  el: Element,
3
3
  vertical?: boolean,
4
4
  horizontal?: boolean,
5
- inflate?: number
5
+ inflate?: number,
6
+ scrollContainer?: HTMLElement
6
7
  ): void;
@@ -1,59 +1,34 @@
1
1
  import { findScrollableParent } from "./findScrollableParent";
2
2
  import { getScrollerBoundingClientRect } from "./getScrollerBoundingClientRect";
3
3
 
4
- export function scrollElementIntoView(
5
- el,
6
- vertical = true,
7
- horizontal = false,
8
- inflate = 0
9
- ) {
4
+ export function scrollElementIntoView(el, vertical = true, horizontal = false, inflate = 0, scrollContainer = null) {
10
5
  if (horizontal) {
11
- let parentEl = findScrollableParent(el, true);
6
+ let parentEl = scrollContainer || findScrollableParent(el, true);
12
7
  if (parentEl) {
13
8
  let pr = getScrollerBoundingClientRect(parentEl);
14
9
  let er = el.getBoundingClientRect();
15
10
  let scrollbarWidth = parentEl.offsetWidth - parentEl.clientWidth;
16
11
 
17
12
  if (er.right + inflate > pr.right - scrollbarWidth)
18
- parentEl.scrollLeft = Math.max(
19
- 0,
20
- parentEl.scrollLeft +
21
- er.right +
22
- inflate -
23
- pr.right +
24
- scrollbarWidth
25
- );
13
+ parentEl.scrollLeft = Math.max(0, parentEl.scrollLeft + er.right + inflate - pr.right + scrollbarWidth);
26
14
 
27
15
  if (er.left - inflate < pr.left)
28
- parentEl.scrollLeft = Math.max(
29
- 0,
30
- parentEl.scrollLeft + er.left - inflate - pr.left
31
- );
16
+ parentEl.scrollLeft = Math.max(0, parentEl.scrollLeft + er.left - inflate - pr.left);
32
17
  }
33
18
  }
34
19
 
35
20
  if (vertical) {
36
- let parentEl = findScrollableParent(el);
21
+ let parentEl = scrollContainer || findScrollableParent(el);
37
22
  if (parentEl) {
38
23
  let pr = getScrollerBoundingClientRect(parentEl);
39
24
  let er = el.getBoundingClientRect();
40
25
  let scrollbarHeight = parentEl.offsetHeight - parentEl.clientHeight;
41
26
 
42
27
  if (er.bottom + inflate > pr.bottom - scrollbarHeight)
43
- parentEl.scrollTop = Math.max(
44
- 0,
45
- parentEl.scrollTop +
46
- er.bottom +
47
- inflate -
48
- pr.bottom +
49
- scrollbarHeight
50
- );
28
+ parentEl.scrollTop = Math.max(0, parentEl.scrollTop + er.bottom + inflate - pr.bottom + scrollbarHeight);
51
29
 
52
30
  if (er.top - inflate < pr.top)
53
- parentEl.scrollTop = Math.max(
54
- 0,
55
- parentEl.scrollTop + er.top - inflate - pr.top
56
- );
31
+ parentEl.scrollTop = Math.max(0, parentEl.scrollTop + er.top - inflate - pr.top);
57
32
  }
58
33
  }
59
34
  }
@@ -4,7 +4,8 @@ interface DocumentTitleProps extends Cx.WidgetProps {
4
4
 
5
5
  value?: Cx.StringProp,
6
6
  append?: boolean,
7
- action?: 'append' | 'replace' | 'prepend'
7
+ action?: 'append' | 'replace' | 'prepend',
8
+ separator?: Cx.StringProp
8
9
  }
9
10
 
10
11
  export class DocumentTitle extends Cx.Widget<DocumentTitleProps> {}
@@ -1,3 +1,4 @@
1
+ import * as React from "react";
1
2
  import {
2
3
  BooleanProp,
3
4
  ClassProp,
@@ -11,7 +12,7 @@ import {
11
12
  StructuredProp,
12
13
  StyledContainerProps,
13
14
  StyleProp,
14
- Widget,
15
+ Widget
15
16
  } from "../core";
16
17
  import { Instance } from "./../ui/Instance";
17
18
 
@@ -79,6 +80,8 @@ interface ListProps extends StyledContainerProps {
79
80
 
80
81
  /** Callback to be invoked when the list is being scrolled. Useful for loading additional items. */
81
82
  onScroll?: (event: Event, instance: Instance) => void;
83
+
84
+ onItemClick?: string | ((e: React.SyntheticEvent<any>, instance: Instance) => void);
82
85
  }
83
86
 
84
87
  export class List extends Widget<ListProps> {}