@singularsystems/neo-core 1.0.12 → 1.0.13

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.
@@ -10,7 +10,7 @@ export default class DatePicker {
10
10
  private headerAnimationHelper;
11
11
  private inputHasChanged;
12
12
  private input;
13
- private popup;
13
+ private popup?;
14
14
  private headerContainer;
15
15
  private currentHeaderLabel;
16
16
  private prevButton;
@@ -22,6 +22,7 @@ export default class DatePicker {
22
22
  private boundDateNoTime;
23
23
  private today;
24
24
  private currentViewDate;
25
+ private positionHelper?;
25
26
  constructor(container: HTMLDivElement, options?: IPartialDateProps);
26
27
  static mustShowInput(options?: IPartialDateProps): boolean | undefined;
27
28
  inputFocused(e: FocusEvent): void;
@@ -1,7 +1,7 @@
1
1
  import DateUtils from '../../Dates/DateUtils';
2
2
  import AnimationHelper from '../AnimationHelper';
3
3
  import { YearsInYearView, ProcessedDatePickerOptions } from './DatePickerOptions';
4
- import PositionHelper from '../PositionHelper';
4
+ import { FixedPositionHelper } from '../PositionHelper';
5
5
  // TODO: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
6
6
  // TODO: Allow input to be shown with inline picker, and specify position.
7
7
  var ViewType;
@@ -114,6 +114,7 @@ var DatePicker = /** @class */ (function () {
114
114
  }
115
115
  };
116
116
  DatePicker.prototype.removePopup = function (animate) {
117
+ var _a;
117
118
  if (this.popup && !this.options.alwaysShow) {
118
119
  if (animate) {
119
120
  AnimationHelper.scale(this.popup, DatePicker.AnimationClassName, 1, 0);
@@ -124,7 +125,9 @@ var DatePicker = /** @class */ (function () {
124
125
  }
125
126
  this.currentHeaderLabel = null;
126
127
  this.currentContentTable = null;
127
- this.popup = null;
128
+ this.popup = undefined;
129
+ (_a = this.positionHelper) === null || _a === void 0 ? void 0 : _a.dispose();
130
+ this.positionHelper = undefined;
128
131
  }
129
132
  };
130
133
  DatePicker.prototype.setBindValue = function (dateValue, options) {
@@ -140,7 +143,7 @@ var DatePicker = /** @class */ (function () {
140
143
  if (options.close) {
141
144
  this.removePopup(true);
142
145
  }
143
- if (!options.close || this.options.alwaysShow) {
146
+ if (!options.close || options.forceDraw) {
144
147
  this.resetCurrentViewDate();
145
148
  this.populateContentContainer(true);
146
149
  }
@@ -173,9 +176,12 @@ var DatePicker = /** @class */ (function () {
173
176
  }
174
177
  };
175
178
  DatePicker.prototype.positionPopup = function (fromBottom) {
176
- if (this.popup) {
179
+ if (this.popup && !this.options.alwaysShow) {
177
180
  var textAlign = this.options.popupAlignRight ? undefined : window.getComputedStyle(this.input).textAlign;
178
- PositionHelper.checkScreenBounds(this.container, this.popup, fromBottom, this.options.popupAlignRight, textAlign);
181
+ if (!this.positionHelper) {
182
+ this.positionHelper = new FixedPositionHelper(this.container, this.popup);
183
+ }
184
+ this.positionHelper.positionPopup(this.options.popupAlignRight, textAlign, fromBottom);
179
185
  }
180
186
  };
181
187
  /**
@@ -234,15 +240,15 @@ var DatePicker = /** @class */ (function () {
234
240
  this.popup.addEventListener("mouseenter", function () { return _this.positionPopup(false); });
235
241
  this.popup.addEventListener("mouseleave", function () { return _this.positionPopup(true); });
236
242
  }
237
- this.createHeader();
238
- this.createContentContainer();
243
+ this.createHeader(this.popup);
244
+ this.createContentContainer(this.popup);
239
245
  }
240
246
  else {
241
247
  this.populateContentContainer(true);
242
248
  }
243
249
  };
244
- DatePicker.prototype.createHeader = function () {
245
- var header = this.createAndAppend(this.popup, "div", "neo-datepicker-header");
250
+ DatePicker.prototype.createHeader = function (parent) {
251
+ var header = this.createAndAppend(parent, "div", "neo-datepicker-header");
246
252
  header.addEventListener("mousedown", function (e) { return e.preventDefault(); });
247
253
  this.prevButton = this.createAndAppend(header, "button", "left-button");
248
254
  this.prevButton.type = "button";
@@ -258,7 +264,7 @@ var DatePicker = /** @class */ (function () {
258
264
  this.nextButton.tabIndex = -1;
259
265
  this.nextButton.addEventListener("mousedown", this.nextClick.bind(this));
260
266
  };
261
- DatePicker.prototype.createHeaderLabel = function () {
267
+ DatePicker.prototype.createHeaderLabel = function (displayImmediately) {
262
268
  this.currentHeaderLabel = this.createAndAppend(this.headerContainer, "div", "header-text");
263
269
  if (this.currentViewType == ViewType.Days) {
264
270
  this.currentHeaderLabel.innerText = DateUtils.format(this.currentViewDate, "MMMM yyyy");
@@ -273,10 +279,15 @@ var DatePicker = /** @class */ (function () {
273
279
  this.currentHeaderLabel.className += " selectable";
274
280
  }
275
281
  this.headerAnimationHelper.addChild(this.currentHeaderLabel, false);
276
- this.headerAnimationHelper.fade();
282
+ if (displayImmediately) {
283
+ this.headerAnimationHelper.replace();
284
+ }
285
+ else {
286
+ this.headerAnimationHelper.fade();
287
+ }
277
288
  };
278
- DatePicker.prototype.createContentContainer = function () {
279
- this.contentContainer = this.createAndAppend(this.popup, "div", "neo-datepicker-content");
289
+ DatePicker.prototype.createContentContainer = function (parent) {
290
+ this.contentContainer = this.createAndAppend(parent, "div", "neo-datepicker-content");
280
291
  this.contentContainer.addEventListener("mousedown", this.contentClick.bind(this));
281
292
  this.contentAnimationHelper = new AnimationHelper(this.contentContainer, DatePicker.AnimationClassName);
282
293
  this.populateContentContainer(!!this.options.alwaysShow);
@@ -298,7 +309,7 @@ var DatePicker = /** @class */ (function () {
298
309
  this.currentViewDate.setFullYear(this.currentViewDate.getFullYear() - this.options.yearsBeforeInYearView);
299
310
  this.createYearsView();
300
311
  }
301
- this.createHeaderLabel();
312
+ this.createHeaderLabel(displayImmediately);
302
313
  this.contentAnimationHelper.addChild(this.currentContentTable, true);
303
314
  if (displayImmediately) {
304
315
  this.contentAnimationHelper.replace();
@@ -412,12 +423,12 @@ var DatePicker = /** @class */ (function () {
412
423
  };
413
424
  DatePicker.prototype.dayClicked = function (datePartsString) {
414
425
  var dateParts = datePartsString.split(",");
415
- this.setBindValue(new Date(parseInt(dateParts[0]), parseInt(dateParts[1]), parseInt(dateParts[2])), { preserveTime: true, close: true });
426
+ this.setBindValue(new Date(parseInt(dateParts[0]), parseInt(dateParts[1]), parseInt(dateParts[2])), { preserveTime: true, close: true, forceDraw: this.options.alwaysShow });
416
427
  };
417
428
  DatePicker.prototype.monthClicked = function (monthString) {
418
429
  this.currentViewDate.setMonth(parseInt(monthString));
419
430
  if (this.options.monthView) {
420
- this.setBindValue(this.currentViewDate, { preserveTime: true, close: true });
431
+ this.setBindValue(this.currentViewDate, { preserveTime: true, close: true, forceDraw: this.options.alwaysShow });
421
432
  }
422
433
  else {
423
434
  this.currentViewType = ViewType.Days;
@@ -428,7 +439,7 @@ var DatePicker = /** @class */ (function () {
428
439
  DatePicker.prototype.yearClicked = function (yearString) {
429
440
  this.currentViewDate.setFullYear(parseInt(yearString));
430
441
  if (this.options.yearView) {
431
- this.setBindValue(this.currentViewDate, { preserveTime: true, close: true });
442
+ this.setBindValue(this.currentViewDate, { preserveTime: true, close: true, forceDraw: this.options.alwaysShow });
432
443
  }
433
444
  else {
434
445
  this.currentViewType = ViewType.Months;
@@ -17,6 +17,10 @@ export default class PositionHelper {
17
17
  * @param hAlign Horizontal alignment of the popup edge relative to the anchor edge. Overrides alignRight
18
18
  */
19
19
  static checkScreenBounds(anchor: HTMLElement, popup: HTMLElement, fromBottom?: boolean, alignRight?: boolean, hAlign?: "left" | "center" | "right"): void;
20
+ /**
21
+ * Used internally by neo. Use `checkScreenBounds` instead of this method.
22
+ */
23
+ static positionElement(popup: HTMLElement, position: IRelativePosition, fromBottom?: boolean): void;
20
24
  /**
21
25
  * Ensures that a popup element is positioned so that it remains in the bounds of the screen by left/right/top/bottom aligning it relative to the anchor element.
22
26
  * @param anchor The element to which the popup is anchored
@@ -26,14 +30,19 @@ export default class PositionHelper {
26
30
  */
27
31
  static getRelativePosition(anchor: HTMLElement, popup: HTMLElement, alignRight?: boolean, hAlign?: "left" | "center" | "right"): IRelativePosition;
28
32
  }
29
- /** Helper used to position elements with position: fixed relative to another element, while maintaining position on scroll. */
33
+ /**
34
+ * Helper used to position elements with position: fixed relative to another element, while maintaining position on scroll.
35
+ * If popupElement has a display of 'absolute', then normal positioning is performed.
36
+ */
30
37
  export declare class FixedPositionHelper implements IDisposable {
31
38
  private anchorElement;
32
39
  private popupElement;
40
+ private isFixed;
33
41
  private topOffset;
34
42
  private positionInfo;
35
- constructor(anchorElement: HTMLElement, popupElement: HTMLElement, alignRight?: boolean, hAlign?: "left" | "center" | "right");
36
- private positionPopup;
43
+ constructor(anchorElement: HTMLElement, popupElement: HTMLElement);
44
+ positionPopup(alignRight?: boolean, hAlign?: "left" | "center" | "right", fromBottom?: boolean): void;
45
+ private positionFixedPopup;
37
46
  dispose(): void;
38
47
  }
39
48
  export {};
@@ -13,6 +13,13 @@ var PositionHelper = /** @class */ (function () {
13
13
  if (fromBottom === void 0) { fromBottom = true; }
14
14
  if (alignRight === void 0) { alignRight = false; }
15
15
  var position = this.getRelativePosition(anchor, popup, alignRight, hAlign);
16
+ this.positionElement(popup, position, fromBottom);
17
+ };
18
+ /**
19
+ * Used internally by neo. Use `checkScreenBounds` instead of this method.
20
+ */
21
+ PositionHelper.positionElement = function (popup, position, fromBottom) {
22
+ if (fromBottom === void 0) { fromBottom = true; }
16
23
  if (position.onTop) {
17
24
  if (fromBottom) {
18
25
  popup.style.top = "auto";
@@ -84,28 +91,45 @@ var PositionHelper = /** @class */ (function () {
84
91
  return PositionHelper;
85
92
  }());
86
93
  export default PositionHelper;
87
- /** Helper used to position elements with position: fixed relative to another element, while maintaining position on scroll. */
94
+ /**
95
+ * Helper used to position elements with position: fixed relative to another element, while maintaining position on scroll.
96
+ * If popupElement has a display of 'absolute', then normal positioning is performed.
97
+ */
88
98
  var FixedPositionHelper = /** @class */ (function () {
89
- function FixedPositionHelper(anchorElement, popupElement, alignRight, hAlign) {
90
- if (alignRight === void 0) { alignRight = false; }
99
+ function FixedPositionHelper(anchorElement, popupElement) {
91
100
  this.anchorElement = anchorElement;
92
101
  this.popupElement = popupElement;
102
+ this.isFixed = false;
93
103
  this.topOffset = 0;
94
- this.positionInfo = PositionHelper.getRelativePosition(anchorElement, popupElement, alignRight, hAlign);
95
- if (this.positionInfo.onTop) {
96
- var style = window.getComputedStyle(popupElement);
97
- var marginHeight = parseFloat(style.marginBottom) + parseFloat(style.marginTop);
98
- this.topOffset = -(this.positionInfo.popupHeight + marginHeight);
104
+ if (window.getComputedStyle(popupElement).position === "fixed") {
105
+ this.isFixed = true;
106
+ window.addEventListener("scroll", this.positionFixedPopup.bind(this), { capture: true });
107
+ }
108
+ }
109
+ FixedPositionHelper.prototype.positionPopup = function (alignRight, hAlign, fromBottom) {
110
+ if (alignRight === void 0) { alignRight = false; }
111
+ if (fromBottom === void 0) { fromBottom = true; }
112
+ this.positionInfo = PositionHelper.getRelativePosition(this.anchorElement, this.popupElement, alignRight, hAlign);
113
+ if (this.isFixed) {
114
+ // Fixed, need to add scroll listener.
115
+ if (this.positionInfo.onTop) {
116
+ var style = window.getComputedStyle(this.popupElement);
117
+ var marginHeight = parseFloat(style.marginBottom) + parseFloat(style.marginTop);
118
+ this.topOffset = -(this.positionInfo.popupHeight + marginHeight);
119
+ }
120
+ else {
121
+ this.topOffset = this.positionInfo.anchorHeight;
122
+ }
123
+ this.positionFixedPopup();
99
124
  }
100
125
  else {
101
- this.topOffset = this.positionInfo.anchorHeight;
126
+ // Simple positioning relative to container.
127
+ PositionHelper.positionElement(this.popupElement, this.positionInfo, fromBottom);
102
128
  }
103
- window.addEventListener("scroll", this.positionPopup.bind(this), { capture: true });
104
- this.positionPopup();
105
- }
106
- FixedPositionHelper.prototype.positionPopup = function () {
129
+ };
130
+ FixedPositionHelper.prototype.positionFixedPopup = function () {
107
131
  var rect = this.anchorElement.getBoundingClientRect();
108
- this.popupElement.style.top = (rect.top + this.topOffset) + "px";
132
+ this.popupElement.style.top = (Math.floor(rect.top) + this.topOffset) + "px";
109
133
  this.popupElement.style.right = "auto";
110
134
  if (this.positionInfo.left !== undefined) {
111
135
  this.popupElement.style.left = (rect.left + this.positionInfo.left) + "px";
@@ -115,7 +139,9 @@ var FixedPositionHelper = /** @class */ (function () {
115
139
  }
116
140
  };
117
141
  FixedPositionHelper.prototype.dispose = function () {
118
- window.removeEventListener("scroll", this.positionPopup);
142
+ if (this.isFixed) {
143
+ window.removeEventListener("scroll", this.positionFixedPopup);
144
+ }
119
145
  };
120
146
  return FixedPositionHelper;
121
147
  }());
@@ -227,7 +227,7 @@ var Deserialiser = /** @class */ (function () {
227
227
  from.entityIdentifier && from.entityIdentifier.indexOf('000000000000') === -1) {
228
228
  toModel.entityIdentifier = from.entityIdentifier;
229
229
  }
230
- if (!this.options.isMap) {
230
+ if (!this.options.isMap && to.isSelfDirty !== undefined) {
231
231
  if (!from.trackingState) {
232
232
  toModel.isSelfDirty = false;
233
233
  toModel.isNew = false;
@@ -7,3 +7,11 @@ export declare class ObservableValue<T> implements IObservableValue<T> {
7
7
  constructor(initialValue: T);
8
8
  get peek(): T;
9
9
  }
10
+ /**
11
+ * Creates a wrapper around a value with a getter and setter for reading and writing the value.
12
+ */
13
+ export declare class ValueWrapper<T> implements IObservableValue<T> {
14
+ constructor(getter: () => T, setter: (value: T) => void);
15
+ value: T;
16
+ get peek(): T;
17
+ }
@@ -24,3 +24,20 @@ var ObservableValue = /** @class */ (function () {
24
24
  return ObservableValue;
25
25
  }());
26
26
  export { ObservableValue };
27
+ /**
28
+ * Creates a wrapper around a value with a getter and setter for reading and writing the value.
29
+ */
30
+ var ValueWrapper = /** @class */ (function () {
31
+ function ValueWrapper(getter, setter) {
32
+ Object.defineProperty(this, "value", { get: getter, set: setter });
33
+ }
34
+ Object.defineProperty(ValueWrapper.prototype, "peek", {
35
+ get: function () {
36
+ return this.value;
37
+ },
38
+ enumerable: false,
39
+ configurable: true
40
+ });
41
+ return ValueWrapper;
42
+ }());
43
+ export { ValueWrapper };
@@ -2,7 +2,7 @@ export { IBindableBase, IModelBase, NeoModelConstructor, PlainObject, PlainTrack
2
2
  export { ILookupBase } from './LookupBase';
3
3
  export { IPropertyInstance, PropertyAccessor } from './PropertyInstance';
4
4
  import PropertyInfo from './PropertyInfo';
5
- export { IObservableValue, ObservableValue } from './ObservableValue';
5
+ export { IObservableValue, ObservableValue, ValueWrapper } from './ObservableValue';
6
6
  export { ObservableProperty } from './ObservableProperty';
7
7
  export { ISelectedItem } from './Misc';
8
8
  export { ModelFieldInfo, IModelFieldInfoContainer } from './ModelFieldInfo';
@@ -1,6 +1,6 @@
1
1
  export { PropertyAccessor } from './PropertyInstance';
2
2
  import PropertyInfo from './PropertyInfo';
3
- export { ObservableValue } from './ObservableValue';
3
+ export { ObservableValue, ValueWrapper } from './ObservableValue';
4
4
  export { ObservableProperty } from './ObservableProperty';
5
5
  export { ModelFieldInfo } from './ModelFieldInfo';
6
6
  import * as GraphTraverser from './ModelGraphTraverser';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@singularsystems/neo-core",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "Core functionality for the Neo client library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",