@singularsystems/neo-react 1.4.2 → 1.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/CHANGELOG.md +14 -0
- package/dist/Modules/Types.d.ts +6 -2
- package/dist/ReactComponents/ColorPicker.js +1 -1
- package/dist/ReactComponents/ContextMenu/ContextMenu.js +1 -1
- package/dist/Routing/RouteProvider.d.ts +1 -4
- package/dist/Routing/RouteProvider.js +9 -14
- package/dist/Views/ViewBase.d.ts +2 -0
- package/dist/Views/ViewBase.js +3 -1
- package/package.json +1 -1
- package/styles/Button.scss +1 -1
- package/styles/ColorPicker.scss +3 -4
- package/styles/ContextMenu.scss +10 -9
- package/styles/DatePicker.scss +4 -3
- package/styles/Forms.scss +5 -5
- package/styles/Loader.scss +1 -1
- package/styles/Misc.scss +3 -3
- package/styles/Neo.scss +1 -0
- package/styles/Validation.scss +1 -1
- package/styles/Variables.scss +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
This file details all new features and changes to functionality. If you only need to see changes that require updates to your project, see the [breaking changes](./Breaking.md) readme.
|
|
4
4
|
|
|
5
|
+
## Version 1.5.0 (28 May 2026)
|
|
6
|
+
|
|
7
|
+
- Fixed routes with the same prefix, but different parameter counts not being registered.
|
|
8
|
+
- E.g. a products list view with path `/products`, and product item view with path `/products/{itemId}` were previously seen as a duplicate route.
|
|
9
|
+
- A url of `/products/123` would have matched against the first route.
|
|
10
|
+
- ViewBase - allow `viewParamsUpdated` to be called on initialise even if all the parameters have default values.
|
|
11
|
+
|
|
12
|
+
## Version 1.4.3 (22 April 2026)
|
|
13
|
+
|
|
14
|
+
- Fix variable usage in neo-react styles.
|
|
15
|
+
- Now uses bootstrap variable names instead of legacy custom variable names defined in end project.
|
|
16
|
+
- This change is to allow simplification of the variables file in the end project.
|
|
17
|
+
- Existing projects do not need to make changes to their variables files.
|
|
18
|
+
|
|
5
19
|
## Version 1.4.2 (20 April 2026)
|
|
6
20
|
|
|
7
21
|
- Navigation helper
|
package/dist/Modules/Types.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ declare const NeoReactTypes: {
|
|
|
42
42
|
};
|
|
43
43
|
Core: {
|
|
44
44
|
AutoRunnerFactory: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/Model/IAutoRunner").IAutoRunnerFactory>;
|
|
45
|
-
ConnectionManager: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/
|
|
45
|
+
ConnectionManager: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/Network").IConnectionManager>;
|
|
46
46
|
DecimalService: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/Numeric").IDecimalService<import("@singularsystems/neo-core/dist/Numeric").IDecimal>>;
|
|
47
47
|
ModelCreator: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/Model/IModelCreatorBase").default>;
|
|
48
48
|
};
|
|
@@ -50,9 +50,13 @@ declare const NeoReactTypes: {
|
|
|
50
50
|
LocalisationService: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/Localisation").ILocalisationService>;
|
|
51
51
|
};
|
|
52
52
|
Messaging: {
|
|
53
|
-
ConnectionManager: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/
|
|
53
|
+
ConnectionManager: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/Network").IConnectionManager>;
|
|
54
54
|
ServerMessageSubscriber: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/SignalR").IServerMessageSubscriber>;
|
|
55
55
|
};
|
|
56
|
+
Network: {
|
|
57
|
+
AppConnectionMonitor: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/Network/IAppConnectionMonitor").IAppConnectionMonitor>;
|
|
58
|
+
ConnectionManager: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/Network").IConnectionManager>;
|
|
59
|
+
};
|
|
56
60
|
Security: {
|
|
57
61
|
AuthenticationService: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/Security").IAuthenticationService>;
|
|
58
62
|
AuthorisationService: AppServices.ServiceIdentifier<import("@singularsystems/neo-core/dist/Security").IAuthorisationService>;
|
|
@@ -58,7 +58,7 @@ var ColorPicker = /** @class */ (function (_super) {
|
|
|
58
58
|
ColorPicker_1.render(this.state.selectedColor, this.handleChange),
|
|
59
59
|
React.createElement("div", { className: "action-container" },
|
|
60
60
|
React.createElement("div", { className: "btn btn-primary btn-sm", onClick: function () { return _this.accept(); } }, "Accept"),
|
|
61
|
-
React.createElement("div", { className: "btn btn-secondary btn-sm ml-1", onClick: function () { return _this.cancel(); } }, "Cancel"))))))));
|
|
61
|
+
React.createElement("div", { className: "btn btn-secondary btn-sm ml-1 ms-1", onClick: function () { return _this.cancel(); } }, "Cancel"))))))));
|
|
62
62
|
};
|
|
63
63
|
/** Renders the inner color picker components without the modal */
|
|
64
64
|
ColorPicker.render = function (color, onChange) {
|
|
@@ -74,7 +74,7 @@ var ContextMenu = /** @class */ (function (_super) {
|
|
|
74
74
|
item.icon && _this.iconFactory.getIconComponent(item.icon, { fixedWidth: true }),
|
|
75
75
|
item.text && React.createElement("span", { className: "neo-context-menu-text" }, item.text),
|
|
76
76
|
item.header && React.createElement("span", { className: "neo-context-menu-text" }, item.header),
|
|
77
|
-
item.items && React.createElement("i", { className: "fa-fw fa fa-angle-right child-indicator" }),
|
|
77
|
+
item.items && React.createElement("i", { className: "fa-fw fa fa-angle-right child-indicator neo-icon" }),
|
|
78
78
|
item.items && _this.hoverItem === item && React.createElement(ContextMenu_1, { menuItems: item.items, show: _this.hoverItem === item, onClick: _this.props.onClick })))); })));
|
|
79
79
|
};
|
|
80
80
|
var ContextMenu_1;
|
|
@@ -5,7 +5,6 @@ interface INamedRouteParameter extends IRouteParameter {
|
|
|
5
5
|
name: string;
|
|
6
6
|
}
|
|
7
7
|
export interface IProcessedRoute extends Routing.IRoute {
|
|
8
|
-
key: number;
|
|
9
8
|
/** Lower case base path without trailing / */
|
|
10
9
|
path: string;
|
|
11
10
|
/** Route params in order, excluding query parameters. */
|
|
@@ -29,8 +28,6 @@ export default class RouteProvider {
|
|
|
29
28
|
menuRoutes: Routing.IMenuRoute[];
|
|
30
29
|
pureRoutes?: Routing.IRoute[] | undefined;
|
|
31
30
|
notFoundComponent?: React.ComponentType | undefined;
|
|
32
|
-
private key;
|
|
33
|
-
private routeIndex;
|
|
34
31
|
private staticRoutes;
|
|
35
32
|
private parameterisedRoutes;
|
|
36
33
|
readonly allRoutes: IProcessedRoute[];
|
|
@@ -46,7 +43,7 @@ export default class RouteProvider {
|
|
|
46
43
|
private flatten;
|
|
47
44
|
/**
|
|
48
45
|
* Create a copy of the route info, and process it.
|
|
49
|
-
* Adds
|
|
46
|
+
* Adds route parameters extracted from the component static params object.
|
|
50
47
|
*/
|
|
51
48
|
private processRoute;
|
|
52
49
|
}
|
|
@@ -10,14 +10,12 @@ var RouteProvider = /** @class */ (function () {
|
|
|
10
10
|
this.menuRoutes = menuRoutes;
|
|
11
11
|
this.pureRoutes = pureRoutes;
|
|
12
12
|
this.notFoundComponent = notFoundComponent;
|
|
13
|
-
this.key = 1;
|
|
14
|
-
this.routeIndex = {};
|
|
15
13
|
this.staticRoutes = [];
|
|
16
14
|
this.parameterisedRoutes = [];
|
|
17
15
|
this.allRoutes = [];
|
|
18
|
-
this.flatten(
|
|
16
|
+
this.flatten(menuRoutes);
|
|
19
17
|
if (pureRoutes)
|
|
20
|
-
this.flatten(
|
|
18
|
+
this.flatten(pureRoutes);
|
|
21
19
|
this.staticRoutes = this.allRoutes.filter(function (c) { return c.params.length === 0; });
|
|
22
20
|
this.parameterisedRoutes = this.allRoutes
|
|
23
21
|
.filter(function (c) { return c.params.length > 0; })
|
|
@@ -84,7 +82,7 @@ var RouteProvider = /** @class */ (function () {
|
|
|
84
82
|
}
|
|
85
83
|
return null;
|
|
86
84
|
};
|
|
87
|
-
RouteProvider.prototype.flatten = function (
|
|
85
|
+
RouteProvider.prototype.flatten = function (routes, parent) {
|
|
88
86
|
var _a, _b;
|
|
89
87
|
for (var _i = 0, routes_1 = routes; _i < routes_1.length; _i++) {
|
|
90
88
|
var route = routes_1[_i];
|
|
@@ -93,20 +91,20 @@ var RouteProvider = /** @class */ (function () {
|
|
|
93
91
|
if (parent && !route.breadCrumbParent) {
|
|
94
92
|
route.breadCrumbParent = parent;
|
|
95
93
|
}
|
|
96
|
-
this.processRoute(
|
|
94
|
+
this.processRoute(route);
|
|
97
95
|
}
|
|
98
96
|
var menuRoute = route;
|
|
99
97
|
var children = __spreadArray(__spreadArray([], ((_a = route.routeChildren) !== null && _a !== void 0 ? _a : []), true), ((_b = menuRoute.children) !== null && _b !== void 0 ? _b : []), true);
|
|
100
|
-
this.flatten(
|
|
98
|
+
this.flatten(children, (hasComponent && menuRoute.showInBreadCrumb !== false) ? menuRoute : undefined);
|
|
101
99
|
}
|
|
102
100
|
};
|
|
103
101
|
/**
|
|
104
102
|
* Create a copy of the route info, and process it.
|
|
105
|
-
* Adds
|
|
103
|
+
* Adds route parameters extracted from the component static params object.
|
|
106
104
|
*/
|
|
107
|
-
RouteProvider.prototype.processRoute = function (
|
|
105
|
+
RouteProvider.prototype.processRoute = function (route) {
|
|
108
106
|
var _a;
|
|
109
|
-
var processed = __assign(__assign({}, route), { path: route.path, params: [],
|
|
107
|
+
var processed = __assign(__assign({}, route), { path: route.path, params: [], order: 0 });
|
|
110
108
|
processed.path = (_a = route.basePath) !== null && _a !== void 0 ? _a : route.path;
|
|
111
109
|
processed.path = processed.path.toLowerCase();
|
|
112
110
|
if (processed.path.length > 1 && processed.path.endsWith("/")) {
|
|
@@ -124,10 +122,7 @@ var RouteProvider = /** @class */ (function () {
|
|
|
124
122
|
}
|
|
125
123
|
}
|
|
126
124
|
}
|
|
127
|
-
|
|
128
|
-
this.routeIndex[processed.path] = true;
|
|
129
|
-
into.push(processed);
|
|
130
|
-
}
|
|
125
|
+
this.allRoutes.push(processed);
|
|
131
126
|
};
|
|
132
127
|
return RouteProvider;
|
|
133
128
|
}());
|
package/dist/Views/ViewBase.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ export default abstract class ViewBase<TViewModel extends IViewModel = EmptyView
|
|
|
32
32
|
navigation: import("../Routing").INavigationHelper;
|
|
33
33
|
private breadCrumbStartItems?;
|
|
34
34
|
protected viewState: ViewState<TViewModel, TParams>;
|
|
35
|
+
/** If true, viewParamsUpdated() will be called on initialisation even if all parameters have default values. */
|
|
36
|
+
protected callViewParamsUpdatedOnInitialise: boolean;
|
|
35
37
|
/**
|
|
36
38
|
* Creates a view
|
|
37
39
|
* @param props React props.
|
package/dist/Views/ViewBase.js
CHANGED
|
@@ -24,6 +24,8 @@ var ViewBase = /** @class */ (function (_super) {
|
|
|
24
24
|
_this.hasInitialised = false;
|
|
25
25
|
_this.routingState = Misc.Globals.appService.get(NeoReactTypes.Routing.GlobalRoutingState);
|
|
26
26
|
_this.navigation = Misc.Globals.appService.get(NeoReactTypes.Routing.NavigationHelper);
|
|
27
|
+
/** If true, viewParamsUpdated() will be called on initialisation even if all parameters have default values. */
|
|
28
|
+
_this.callViewParamsUpdatedOnInitialise = false;
|
|
27
29
|
if (typeof viewName !== "string") {
|
|
28
30
|
throw "Error: When inheriting ViewBase, you must pass the view name into the base constructor.";
|
|
29
31
|
}
|
|
@@ -85,7 +87,7 @@ var ViewBase = /** @class */ (function (_super) {
|
|
|
85
87
|
_a.sent();
|
|
86
88
|
_a.label = 2;
|
|
87
89
|
case 2:
|
|
88
|
-
if (!paramsUpdated) return [3 /*break*/, 4];
|
|
90
|
+
if (!(paramsUpdated || this.callViewParamsUpdatedOnInitialise)) return [3 /*break*/, 4];
|
|
89
91
|
return [4 /*yield*/, this.viewParamsUpdated()];
|
|
90
92
|
case 3:
|
|
91
93
|
_a.sent();
|
package/package.json
CHANGED
package/styles/Button.scss
CHANGED
package/styles/ColorPicker.scss
CHANGED
|
@@ -4,7 +4,7 @@ div.color-picker {
|
|
|
4
4
|
div.block-button {
|
|
5
5
|
width: 20px;
|
|
6
6
|
height: 20px;
|
|
7
|
-
border: 1px solid $
|
|
7
|
+
border: 1px solid $secondary;
|
|
8
8
|
cursor: pointer;
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -17,9 +17,8 @@ div.color-picker {
|
|
|
17
17
|
|
|
18
18
|
div.picker-block {
|
|
19
19
|
padding: 5px;
|
|
20
|
-
background-color:
|
|
20
|
+
background-color: white;
|
|
21
21
|
border-radius: 5px;
|
|
22
|
-
border: 1px solid $concrete;
|
|
23
22
|
|
|
24
23
|
div.action-container {
|
|
25
24
|
text-align: right;
|
|
@@ -38,7 +37,7 @@ div.color-picker {
|
|
|
38
37
|
top: 0;
|
|
39
38
|
left: 0;
|
|
40
39
|
z-index: 5000;
|
|
41
|
-
background-color: $
|
|
40
|
+
background-color: $modal-backdrop-bg;
|
|
42
41
|
opacity: 0.2;
|
|
43
42
|
cursor: pointer;
|
|
44
43
|
}
|
package/styles/ContextMenu.scss
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
.neo-context-menu {
|
|
2
2
|
position: absolute;
|
|
3
3
|
z-index: 1100;
|
|
4
|
-
border: 1px solid
|
|
4
|
+
border: 1px solid $dropdown-border-color;
|
|
5
5
|
background: #fff;
|
|
6
|
-
color:
|
|
6
|
+
color: initial;
|
|
7
7
|
padding: 5px;
|
|
8
8
|
border-radius: 2px;
|
|
9
9
|
left: 100%;
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
padding-right: 15px;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
>
|
|
36
|
-
color:
|
|
35
|
+
> .neo-icon {
|
|
36
|
+
color: $body-secondary-color;
|
|
37
37
|
font-size: 12px;
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -51,17 +51,17 @@
|
|
|
51
51
|
cursor: pointer;
|
|
52
52
|
|
|
53
53
|
&:hover {
|
|
54
|
-
background: transparentize($
|
|
54
|
+
background: transparentize($primary, 0.75);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
&.header {
|
|
59
59
|
background: rgba(0,0,0,0.65);
|
|
60
|
-
color:
|
|
60
|
+
color: white;
|
|
61
61
|
padding: 5px 4px;
|
|
62
62
|
|
|
63
|
-
>
|
|
64
|
-
color:
|
|
63
|
+
> .neo-icon {
|
|
64
|
+
color: white;
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -72,8 +72,9 @@
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
hr {
|
|
75
|
-
border-top: 1px dashed
|
|
75
|
+
border-top: 1px dashed $dropdown-border-color;
|
|
76
76
|
margin: 1px 4px 1px 28px;
|
|
77
|
+
opacity: 1;
|
|
77
78
|
}
|
|
78
79
|
}
|
|
79
80
|
}
|
package/styles/DatePicker.scss
CHANGED
|
@@ -125,15 +125,16 @@ $neo-include-datepicker: true !default;
|
|
|
125
125
|
|
|
126
126
|
&.selectable:hover {
|
|
127
127
|
cursor: pointer;
|
|
128
|
-
background-color: adjust-color($
|
|
128
|
+
background-color: adjust-color($primary, $lightness: 15%);
|
|
129
|
+
color: #fff;
|
|
129
130
|
}
|
|
130
131
|
|
|
131
132
|
&.today {
|
|
132
|
-
border: 1px solid $
|
|
133
|
+
border: 1px solid $primary;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
&.selected, &.selected:hover {
|
|
136
|
-
background-color: $
|
|
137
|
+
background-color: $primary;
|
|
137
138
|
color: #fff;
|
|
138
139
|
}
|
|
139
140
|
}
|
package/styles/Forms.scss
CHANGED
|
@@ -39,7 +39,7 @@ div.neo-form-group-floating {
|
|
|
39
39
|
color: #495057;
|
|
40
40
|
border: none;
|
|
41
41
|
outline: none;
|
|
42
|
-
border-bottom: 1px solid $
|
|
42
|
+
border-bottom: 1px solid $input-border-color;
|
|
43
43
|
transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1);
|
|
44
44
|
width: 100%;
|
|
45
45
|
padding: 5px 0 3px 0;
|
|
@@ -56,7 +56,7 @@ div.neo-form-group-floating {
|
|
|
56
56
|
position: absolute;
|
|
57
57
|
transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1);
|
|
58
58
|
width: 100%;
|
|
59
|
-
border-bottom: 3px solid $
|
|
59
|
+
border-bottom: 3px solid rgba($input-focus-border-color, 0.15);
|
|
60
60
|
transform: scale(0);
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -65,10 +65,10 @@ div.neo-form-group-floating {
|
|
|
65
65
|
transform: scale(1);
|
|
66
66
|
}
|
|
67
67
|
label.neo-floating-label {
|
|
68
|
-
color: color.adjust($
|
|
68
|
+
color: color.adjust($input-focus-border-color, $lightness: -15%);
|
|
69
69
|
}
|
|
70
70
|
.neo-forms-editor {
|
|
71
|
-
border-bottom: 1px solid $
|
|
71
|
+
border-bottom: 1px solid $input-focus-border-color;
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -109,7 +109,7 @@ div.neo-form-group-floating {
|
|
|
109
109
|
|
|
110
110
|
.input-group.file-editor {
|
|
111
111
|
.file-placeholder {
|
|
112
|
-
color: $
|
|
112
|
+
color: $input-placeholder-color;
|
|
113
113
|
user-select: none;
|
|
114
114
|
padding: 0;
|
|
115
115
|
|
package/styles/Loader.scss
CHANGED
package/styles/Misc.scss
CHANGED
|
@@ -44,7 +44,7 @@ div.collapsable {
|
|
|
44
44
|
position: absolute;
|
|
45
45
|
top: -1000px;
|
|
46
46
|
left: -1000px;
|
|
47
|
-
background-color: $
|
|
47
|
+
background-color: $dark;
|
|
48
48
|
color: #fff;
|
|
49
49
|
z-index: 1060;
|
|
50
50
|
font-size: 0.8rem;
|
|
@@ -118,11 +118,11 @@ div.tabs-header {
|
|
|
118
118
|
|
|
119
119
|
/* File drop */
|
|
120
120
|
.neo-file-drop {
|
|
121
|
-
border: 2px dashed $
|
|
121
|
+
border: 2px dashed $input-border-color;
|
|
122
122
|
padding: 15px;
|
|
123
123
|
|
|
124
124
|
&.dragging {
|
|
125
|
-
border-color: $
|
|
125
|
+
border-color: $primary;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
button {
|
package/styles/Neo.scss
CHANGED
package/styles/Validation.scss
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Legacy mappings:
|
|
2
|
+
$body-secondary-color: #6c757d !default;
|
|
3
|
+
|
|
4
|
+
$modal-backdrop-bg: black !default;
|
|
5
|
+
$dropdown-border-color: #ccc !default;
|
|
6
|
+
$input-border-color: $form-border !default;
|
|
7
|
+
$input-focus-border-color: $form-focused-border !default;
|
|
8
|
+
$input-placeholder-color: #dddddd !default;
|