@singularsystems/neo-react 1.0.0-alpha.1 → 1.0.0-alpha.2

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.
@@ -0,0 +1,3 @@
1
+ declare namespace React {
2
+ type StatelessComponent<P> = React.FunctionComponent<P>;
3
+ }
File without changes
@@ -1,22 +1,10 @@
1
1
  import { AppServices, Utils } from '@singularsystems/neo-core';
2
- import { runInAction } from 'mobx';
2
+ import { configure, runInAction, untracked } from 'mobx';
3
3
  import ViewBase from '../Views/ViewBase';
4
4
  import React from 'react';
5
5
  export function runReactSetup(container) {
6
6
  Utils.peek = function (target, propertyName) {
7
- var mobXData = target.$mobx;
8
- if (mobXData) {
9
- var mobXVar = mobXData.values[propertyName];
10
- if (mobXVar) {
11
- return mobXVar.value;
12
- }
13
- else {
14
- throw Error("Cannot peek property " + propertyName.toString());
15
- }
16
- }
17
- else {
18
- return target[propertyName];
19
- }
7
+ return untracked(function () { return target[propertyName]; });
20
8
  };
21
9
  Utils.suppressHtmlEncode = function (html) {
22
10
  return React.createElement("div", { dangerouslySetInnerHTML: { __html: html } });
@@ -25,4 +13,5 @@ export function runReactSetup(container) {
25
13
  window.addEventListener("beforeunload", function (e) {
26
14
  container.get(AppServices.NeoTypes.Routing.PageLeaveHandler).onWindowUnload(ViewBase.currentView, e);
27
15
  });
16
+ configure({ enforceActions: "never", useProxies: "never" });
28
17
  }
@@ -1,9 +1,7 @@
1
1
  import React from 'react';
2
2
  import { Data } from '@singularsystems/neo-core';
3
- Data.DataViewBase.useFrameworkSortCompareFn =
4
- function (item, propertyKey) { var _a; return ((_a = item.$mobx) === null || _a === void 0 ? void 0 : _a.values[propertyKey]) !== undefined; };
5
- // access raw values so we dont create dependencies.
6
- Data.DataViewBase.frameworkSortValueFn = function (propertyName) { return function (c) { return c.$mobx.values[propertyName].value; }; };
3
+ import { untracked } from 'mobx';
4
+ Data.DataViewBase.unTrackedSort = untracked;
7
5
  var DataViewContextParams = /** @class */ (function () {
8
6
  function DataViewContextParams() {
9
7
  }
@@ -1,4 +1,5 @@
1
1
  import { createObservableList } from './Utils';
2
+ // TODO : remove this
2
3
  /**
3
4
  * Makes a list observable. Use this only when the property is not part of a NeoModel. E.g. it is defined directly on a component.
4
5
  */
@@ -5,6 +5,7 @@ export declare class ReactModelCreator extends ModelCreatorBase {
5
5
  convertInstance(instance: {}): {};
6
6
  setupModel(typeInfo: NeoTypeInfo, model: Model.IModelBase): void;
7
7
  setupObject(typeInfo: NeoTypeInfo, object: any): void;
8
- private convertToObservable;
8
+ private setMobxObservableType;
9
9
  private addChangeTracking;
10
+ private setupList;
10
11
  }
@@ -1,7 +1,6 @@
1
1
  import { __extends } from "tslib";
2
- import { observable, computed, intercept, reaction } from 'mobx';
3
- import { createObservableList } from './Utils';
4
- import { Misc, Validation, Utils } from '@singularsystems/neo-core';
2
+ import { observable, computed, intercept, reaction, makeObservable } from 'mobx';
3
+ import { List, Misc, Validation, Utils } from '@singularsystems/neo-core';
5
4
  import { ModelCreatorBase } from '@singularsystems/neo-core/dist/Model/ModelCreatorBase';
6
5
  import PropertyInstance from '@singularsystems/neo-core/dist/Model/PropertyInstance';
7
6
  var hasConvertedSymbol = Symbol("hasConvertedModel");
@@ -32,14 +31,16 @@ var ReactModelCreator = /** @class */ (function (_super) {
32
31
  model.isSuspended = false;
33
32
  };
34
33
  ReactModelCreator.prototype.setupObject = function (typeInfo, object) {
34
+ var annotations = {};
35
+ var observables = {};
35
36
  for (var _i = 0, _a = typeInfo.properties; _i < _a.length; _i++) {
36
37
  var propertyInfo = _a[_i];
37
38
  if (propertyInfo.isObservable !== false) {
38
- var propertyName = propertyInfo.propertyName, makeObservable = this.typeInfo.inheritsModelBase || propertyInfo.isObservable === true;
39
+ var propertyName = propertyInfo.propertyName, makeObservable_1 = this.typeInfo.inheritsModelBase || propertyInfo.isObservable === true;
39
40
  var propertyInstance = void 0;
40
41
  if (this.typeInfo.inheritsBindableBase) {
41
42
  var model = object;
42
- propertyInstance = new PropertyInstance(model, propertyInfo, makeObservable);
43
+ propertyInstance = new PropertyInstance(model, propertyInfo, makeObservable_1);
43
44
  model.meta[propertyName] = propertyInstance;
44
45
  // Rules
45
46
  if (propertyInfo.rules.length > 0 && model.validator) {
@@ -48,42 +49,54 @@ var ReactModelCreator = /** @class */ (function (_super) {
48
49
  }
49
50
  if (propertyInfo.isComputed !== null) {
50
51
  if (propertyInfo.descriptor && propertyInfo.isComputed) {
51
- computed({ keepAlive: true })(object, propertyName, propertyInfo.descriptor, true);
52
+ annotations[propertyName] = computed({ keepAlive: true });
52
53
  }
53
54
  }
54
- else if (makeObservable) {
55
- var observable_1 = this.convertToObservable(object, propertyName, propertyInfo);
56
- this.addChangeTracking(object, propertyName, propertyInfo, observable_1, propertyInstance);
55
+ else if (makeObservable_1) {
56
+ var property = { propertyInfo: propertyInfo, propertyInstance: propertyInstance };
57
+ observables[propertyName] = property;
58
+ this.setMobxObservableType(object, propertyName, property, annotations);
57
59
  }
58
60
  }
59
61
  }
62
+ // Run mobx's setup for this instance.
63
+ makeObservable(object, annotations, { proxy: false });
64
+ // Setup once properties have been converted to observables.
65
+ for (var propertyKey in observables) {
66
+ var property = observables[propertyKey];
67
+ this.addChangeTracking(object, propertyKey, property);
68
+ if (property.convertList) {
69
+ this.setupList(object, propertyKey, property.convertList);
70
+ }
71
+ }
60
72
  };
61
- ReactModelCreator.prototype.convertToObservable = function (object, propertyName, propertyInfo) {
62
- var propertyValue = object[propertyName];
73
+ ReactModelCreator.prototype.setMobxObservableType = function (object, propertyName, property, annotations) {
74
+ var propertyValue = object[propertyName], propertyInfo = property.propertyInfo;
63
75
  this.ensureChildInfo(object, propertyInfo);
64
76
  if (propertyInfo.relationType === Misc.RelationType.ChildList) {
65
- createObservableList(object, propertyName, propertyValue);
77
+ annotations[propertyName] = observable.shallow;
78
+ property.convertList = propertyValue;
66
79
  }
67
80
  else if (propertyValue instanceof Array) {
68
- observable.shallow(object, propertyName, { value: propertyValue }, true);
81
+ annotations[propertyName] = observable.shallow;
69
82
  }
70
83
  else {
71
- // make the property an observable
72
- // this overload is not part of the typescript typings. The true tells it to create the observable immediately
73
- // otherwise we need to keep track of all the properties that need to be observable in a dictionary using observables[propertyName] = observable;
74
- // then call decorate(model, observables) after this loop.
75
- observable.ref(object, propertyName, { value: propertyValue }, true);
84
+ annotations[propertyName] = observable.ref;
76
85
  }
77
- return object.$mobx.values[propertyName];
78
86
  };
79
- ReactModelCreator.prototype.addChangeTracking = function (object, propertyName, propertyInfo, observable, propertyInstance) {
87
+ ReactModelCreator.prototype.addChangeTracking = function (object, propertyName, property) {
80
88
  var _this = this;
89
+ var propertyInfo = property.propertyInfo, propertyInstance = property.propertyInstance;
81
90
  var trackProperty = this.typeInfo.inheritsModelBase && !propertyInfo.noTrack && propertyInfo.relationType !== Misc.RelationType.ChildList;
82
91
  var onChangedOptions = propertyInfo && propertyInfo.onChangedOptions;
83
- if (trackProperty || propertyInfo.propertyType === Misc.DataType.Date || (onChangedOptions && onChangedOptions.requiresOldValue)) {
92
+ if (onChangedOptions && onChangedOptions.requiresOldValue && !propertyInstance) {
93
+ throw Error("Cannot use previous value for OnChanged on property: ".concat(propertyName, ". Model does not extend BindableBase."));
94
+ }
95
+ if (propertyInstance && (trackProperty || propertyInfo.propertyType === Misc.DataType.Date || (onChangedOptions && onChangedOptions.requiresOldValue))) {
84
96
  intercept(object, propertyName, function (onChange) {
85
- if (propertyInstance !== undefined && !object.isSuspended) {
86
- if (trackProperty && onChange.newValue !== observable.value)
97
+ var currentValue = object[propertyName];
98
+ if (!object.isSuspended) {
99
+ if (trackProperty && onChange.newValue !== currentValue)
87
100
  object.isSelfDirty = true;
88
101
  if (propertyInfo.propertyType === Misc.DataType.Date) {
89
102
  if (typeof onChange.newValue === "string") {
@@ -91,7 +104,7 @@ var ReactModelCreator = /** @class */ (function (_super) {
91
104
  }
92
105
  }
93
106
  }
94
- observable.previousValue = observable.value;
107
+ propertyInstance.previousValue = currentValue;
95
108
  return onChange;
96
109
  });
97
110
  }
@@ -113,11 +126,37 @@ var ReactModelCreator = /** @class */ (function (_super) {
113
126
  return newValue_1;
114
127
  }, function () {
115
128
  if (!_this.typeInfo.inheritsBindableBase || !object.isSuspended) {
116
- onChanged.call(object, observable.previousValue, newValue_1);
129
+ onChanged.call(object, propertyInstance === null || propertyInstance === void 0 ? void 0 : propertyInstance.previousValue, newValue_1);
117
130
  }
118
131
  });
119
132
  }
120
133
  };
134
+ ReactModelCreator.prototype.setupList = function (object, propertyName, originalList) {
135
+ var obsArray = object[propertyName];
136
+ List.copyMethods(obsArray);
137
+ originalList.setupProxy(obsArray, object);
138
+ // Don't allow list to change, just change the list contents.
139
+ intercept(object, propertyName, function (onChange) {
140
+ var newValue = onChange.newValue, currentValue = object[propertyName];
141
+ if (!newValue) {
142
+ currentValue.length = 0;
143
+ }
144
+ else {
145
+ if (newValue.childObjectType && newValue.setParent) {
146
+ // Cannot re-assign this property, so we have to clear the array, and copy the items from the source array.
147
+ Utils.batchUpdate(function () {
148
+ currentValue.length = 0;
149
+ currentValue.push.apply(currentValue, newValue);
150
+ });
151
+ }
152
+ else {
153
+ throw "Do not assign a plain array to a List property. Either call ".concat(propertyName, ".set(...) or ").concat(propertyName, ".update(...)");
154
+ }
155
+ }
156
+ // Instruct mobx to ignore the set.
157
+ return null;
158
+ });
159
+ };
121
160
  return ReactModelCreator;
122
161
  }(ModelCreatorBase));
123
162
  export { ReactModelCreator };
@@ -56,11 +56,11 @@ var ErrorHandler = /** @class */ (function (_super) {
56
56
  };
57
57
  ModalUtils.showModal(errorDisplay.header, React.createElement(Observer, null, function () {
58
58
  var _a;
59
- return ((_a = _this.hidingErrorList) !== null && _a !== void 0 ? _a : _this.errorList).map(function (errorGroup, index) { return (React.createElement("div", { key: index, className: "neo-error-modal-body" },
59
+ return React.createElement(React.Fragment, null, ((_a = _this.hidingErrorList) !== null && _a !== void 0 ? _a : _this.errorList).map(function (errorGroup, index) { return (React.createElement("div", { key: index, className: "neo-error-modal-body" },
60
60
  React.createElement("div", { className: "neo-error-modal-body-icon" }, errorGroup.count === 1 ?
61
61
  React.createElement("i", { className: _this.getIcon(errorGroup.errorDisplay) }) :
62
62
  React.createElement("span", { className: "badge badge-danger" }, errorGroup.count)),
63
- React.createElement("div", null, errorGroup.errorDisplay.body))); });
63
+ React.createElement("div", null, errorGroup.errorDisplay.body))); }));
64
64
  }), modalOptions);
65
65
  }
66
66
  if (this.errorList.length < 5) {
@@ -1,13 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import { Components, Model } from '@singularsystems/neo-core';
3
- import { ItemCallback } from './PropTypes';
4
3
  export interface IFormProps<T extends Model.IModelBase> extends React.FormHTMLAttributes<HTMLElement>, Components.IFormOptions<T> {
5
4
  /**
6
5
  * Called when the form is submitted, but the model is not valid.
7
6
  * The justValidated parameter will be true if the validationDisplayMode is 'AfterSubmit', and this is the first submit attempt.
8
7
  */
9
8
  onInvalid?: (e: React.FormEvent, justValidated?: boolean) => void;
10
- children: React.ReactNode | React.ReactNode[] | ItemCallback<T>;
9
+ children: React.ReactNode;
11
10
  }
12
11
  export default class Form<T extends Model.IModelBase> extends React.Component<IFormProps<T>> {
13
12
  private reactionDisposer?;
@@ -17,7 +17,7 @@ export declare class GridContextParams<T> {
17
17
  get inBody(): boolean;
18
18
  }
19
19
  export declare const GridContext: React.Context<GridContextParams<unknown>>;
20
- export interface IGridProps<T> extends React.HTMLProps<HTMLTableElement> {
20
+ interface IGridProps<T> extends React.HTMLProps<HTMLTableElement> {
21
21
  /**
22
22
  * Datasource of the Grid. Usually a neo List, but can be a js array. This is not required if the grid is nested in
23
23
  * a DataViewProvider like a Pager or DataScroller
@@ -51,7 +51,6 @@ export interface IGridProps<T> extends React.HTMLProps<HTMLTableElement> {
51
51
  */
52
52
  initialSort?: keyof T | (keyof T)[];
53
53
  initialSortAscending?: boolean | boolean[];
54
- children: ItemCallback<T>;
55
54
  /**
56
55
  * When specified, the default bootstrap table borders (sides and cells) will be added.
57
56
  * This is the default unless overridden in Misc.Settings.grid
@@ -73,14 +72,19 @@ export interface IGridProps<T> extends React.HTMLProps<HTMLTableElement> {
73
72
  * Set `showAddButton = false` if you don't want the default button.
74
73
  */
75
74
  footerButtons?: () => React.ReactNode;
75
+ children: any;
76
+ }
77
+ interface GridPropsWithChildren<T> extends IGridProps<T> {
78
+ children: ItemCallback<T>;
76
79
  }
77
- export default class Grid<T> extends React.Component<IGridProps<T>> {
80
+ export default class Grid<T> extends React.Component<GridPropsWithChildren<T>> {
78
81
  static contextType: React.Context<import("../../React/DataView").DataViewContextParams<unknown>>;
79
82
  context: React.ContextType<typeof DataViewContext>;
80
83
  private gridContext;
81
84
  private prevItems?;
82
85
  private headerItem;
83
- constructor(props: IGridProps<T>);
86
+ constructor(props: GridPropsWithChildren<T>);
84
87
  render(): JSX.Element;
85
88
  private setInitialSort;
86
89
  }
90
+ export {};
@@ -90,12 +90,12 @@ var Grid = /** @class */ (function (_super) {
90
90
  React.createElement(GridContext.Provider, { value: this.gridContext },
91
91
  React.createElement(TableSection, { type: "header" }, this.headerItem && this.props.children(this.headerItem, this.headerItem.meta)),
92
92
  React.createElement(TableSection, { type: "body" }, this.gridContext.dataView.getItems().map(function (item) { return (React.createElement(ItemGroup, { item: item, key: keyProperty ? item[keyProperty] : item.entityIdentifier, template: _this.props.children })); })),
93
- React.createElement(Observer, null, function () { return (showAddButton || addButton || footerButtons || _this.gridContext.hasSummaries || footerContent !== undefined) &&
93
+ React.createElement(Observer, null, function () { return (showAddButton || addButton || footerButtons || _this.gridContext.hasSummaries || footerContent !== undefined) ?
94
94
  React.createElement(TableSection, { type: "footer" },
95
95
  _this.gridContext.hasSummaries && _this.headerItem && _this.props.children(_this.headerItem, _this.headerItem.meta),
96
96
  footerContent !== undefined && footerContent(_this.gridContext.dataView.getItems()),
97
97
  (showAddButton || addButton || footerButtons) &&
98
- React.createElement(AddButtonRow, { addButton: addButton, showAddButton: showAddButton, additionalContent: footerButtons })); }))));
98
+ React.createElement(AddButtonRow, { addButton: addButton, showAddButton: showAddButton, additionalContent: footerButtons })) : null; }))));
99
99
  };
100
100
  Grid.prototype.setInitialSort = function (initialSort, initialSortAscending) {
101
101
  var _a;
@@ -6,7 +6,7 @@ export interface IPagerBaseProps<TCriteria extends ValueObject, TModel extends M
6
6
  /** Page manager which controls this component. */
7
7
  pageManager: Data.PageManager<TCriteria, TModel>;
8
8
  /** Child can either be a component which works with a dataview (like Neo.Grid), or a callback which will be passed the items of the current page. */
9
- children: ((data: TModel[]) => JSX.Element) | JSX.Element;
9
+ children: React.ReactNode;
10
10
  /** Where to put the page controls? */
11
11
  pageControls?: "none" | "top" | "bottom" | "topAndBottom";
12
12
  /** True if the built in loader component should be hidden. */
package/dist/index.d.ts CHANGED
@@ -6,6 +6,5 @@ import * as Routing from './Routing';
6
6
  import * as Views from './Views/';
7
7
  import * as Managers from './ReactComponents/_Managers';
8
8
  import { TooltipHelper } from './ReactComponents/TooltipHelper';
9
- export * from './React/Decorators';
10
9
  export { Managers, NeoReactModule, NeoReactTypes, Neo, NeoGrid, Routing, Views, TooltipHelper, };
11
10
  export { ICancellableEvent } from './ReactComponents/Misc';
package/dist/index.js CHANGED
@@ -6,5 +6,4 @@ import * as Routing from './Routing';
6
6
  import * as Views from './Views/';
7
7
  import * as Managers from './ReactComponents/_Managers';
8
8
  import { TooltipHelper } from './ReactComponents/TooltipHelper';
9
- export * from './React/Decorators';
10
9
  export { Managers, NeoReactModule, NeoReactTypes, Neo, NeoGrid, Routing, Views, TooltipHelper, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@singularsystems/neo-react",
3
- "version": "1.0.0-alpha.1",
3
+ "version": "1.0.0-alpha.2",
4
4
  "description": "React application logic and components for the Neo client library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -20,28 +20,28 @@
20
20
  "@types/jest": "^28.1.1",
21
21
  "@types/memoize-one": "5.1.2",
22
22
  "@types/node": "17.0.15",
23
- "@types/rc-slider": "^8.6.5",
24
23
  "@types/react": "17.0.39",
25
- "@types/react-color": "^3.0.1",
26
24
  "@types/react-custom-scrollbars": "^4.0.6",
27
25
  "@types/react-dom": "17.0.11",
28
26
  "@types/react-router": "^5.1.17",
29
27
  "@types/react-router-dom": "^5.3.3",
30
- "@types/react-select": "3.1.0",
31
28
  "jest": "28.1.1",
32
29
  "react-scripts": "5.0.1",
33
30
  "ts-jest": "28.0.4",
34
31
  "typescript": "4.7.3"
35
32
  },
36
33
  "dependencies": {
37
- "@singularsystems/neo-core": "^1.0.0-alpha.1",
34
+ "@singularsystems/neo-core": "^1.0.0-alpha.2",
35
+ "@types/rc-slider": "^8.6.5",
36
+ "@types/react-color": "^3.0.1",
37
+ "@types/react-select": "3.1.0",
38
38
  "axios": "^0.27.2",
39
39
  "decimal.js-light": "^2.5.1",
40
40
  "history": "4.10.1",
41
41
  "inversify": "^6.0.1",
42
42
  "memoize-one": "6.0.0",
43
- "mobx": "4.9.2",
44
- "mobx-react": "5.4.3",
43
+ "mobx": "6.6.1",
44
+ "mobx-react": "7.5.2",
45
45
  "react": "^17.0.2",
46
46
  "react-custom-scrollbars": "^4.2.1",
47
47
  "react-dom": "^17.0.2",