@singularsystems/neo-react 1.0.22 → 1.1.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +15 -1
  2. package/README.md +1 -1
  3. package/dist/Modules/NeoReactModule.js +1 -1
  4. package/dist/Modules/ReactSetup.js +1 -5
  5. package/dist/Modules/Types.d.ts +3 -2
  6. package/dist/Modules/Types.js +1 -1
  7. package/dist/React/ReactModelCreator.js +1 -1
  8. package/dist/ReactComponents/FileManager/FileInput.js +3 -1
  9. package/dist/ReactComponents/Form.js +3 -5
  10. package/dist/ReactComponents/Grid/Grid.js +7 -9
  11. package/dist/ReactComponents/IColorPicker.d.ts +0 -1
  12. package/dist/ReactComponents/Icons/IIconFactory.d.ts +0 -1
  13. package/dist/ReactComponents/Icons/Icon.js +1 -1
  14. package/dist/ReactComponents/Link.d.ts +7 -0
  15. package/dist/ReactComponents/Link.js +39 -6
  16. package/dist/ReactComponents/Modal/Modal.js +2 -2
  17. package/dist/ReactComponents/StateObserver.d.ts +0 -1
  18. package/dist/ReactComponents/Tabs/Tab.js +5 -1
  19. package/dist/ReactComponents/Tabs/TabContainer.d.ts +6 -2
  20. package/dist/ReactComponents/Tabs/TabContainer.js +25 -17
  21. package/dist/ReactComponents/Tabs/TabManager.d.ts +0 -12
  22. package/dist/ReactComponents/Tabs/TabManager.js +3 -3
  23. package/dist/ReactComponents/Transitions/Transition.d.ts +10 -0
  24. package/dist/ReactComponents/Transitions/Transition.js +13 -0
  25. package/dist/ReactComponents/Transitions/TransitionContainer.d.ts +22 -0
  26. package/dist/ReactComponents/Transitions/TransitionContainer.js +34 -0
  27. package/dist/ReactComponents/Transitions/TransitionController.d.ts +33 -0
  28. package/dist/ReactComponents/Transitions/TransitionController.js +231 -0
  29. package/dist/ReactComponents/Transitions/TransitionPanel.d.ts +37 -0
  30. package/dist/ReactComponents/Transitions/TransitionPanel.js +64 -0
  31. package/dist/ReactComponents/Transitions/TransitionReplacer.d.ts +15 -0
  32. package/dist/ReactComponents/Transitions/TransitionReplacer.js +52 -0
  33. package/dist/ReactComponents/Transitions/TransitionSwitcher.d.ts +15 -0
  34. package/dist/ReactComponents/Transitions/TransitionSwitcher.js +55 -0
  35. package/dist/ReactComponents/Transitions/_Exports.d.ts +2 -0
  36. package/dist/ReactComponents/Transitions/_Exports.js +2 -0
  37. package/dist/ReactComponents/_Exports.d.ts +3 -1
  38. package/dist/ReactComponents/_Exports.js +3 -1
  39. package/dist/Routing/BreadCrumbItem.d.ts +0 -1
  40. package/dist/Routing/IRouteChangedProps.d.ts +5 -3
  41. package/dist/Routing/NavigationHelper.d.ts +9 -8
  42. package/dist/Routing/NavigationHelper.js +121 -25
  43. package/dist/Routing/PageLeaveHandler.d.ts +26 -9
  44. package/dist/Routing/PageLeaveHandler.js +16 -39
  45. package/dist/Routing/RouteProvider.d.ts +28 -7
  46. package/dist/Routing/RouteProvider.js +81 -42
  47. package/dist/Routing/RouteView.d.ts +5 -27
  48. package/dist/Routing/RouteView.js +18 -92
  49. package/dist/Routing/RoutingState.d.ts +10 -13
  50. package/dist/Routing/RoutingState.js +35 -18
  51. package/dist/Routing/ViewParameter.d.ts +0 -1
  52. package/dist/Routing/ViewParameterList.d.ts +0 -7
  53. package/dist/Routing/ViewParameterList.js +3 -5
  54. package/dist/Views/ViewBase.d.ts +4 -4
  55. package/dist/Views/ViewBase.js +6 -5
  56. package/dist/index.d.ts +3 -1
  57. package/dist/index.js +3 -1
  58. package/package.json +19 -26
  59. package/styles/Button.scss +6 -0
  60. package/styles/DatePicker.scss +3 -1
  61. package/styles/Forms.scss +3 -1
  62. package/styles/Grid.scss +4 -0
  63. package/styles/Misc.scss +25 -0
@@ -1,20 +1,72 @@
1
- import { __decorate, __metadata, __param } from "tslib";
1
+ import { __awaiter, __decorate, __generator, __metadata, __param } from "tslib";
2
2
  import { ViewParameterList } from './ViewParameterList';
3
3
  import { injectable, inject } from 'inversify';
4
4
  import { NeoReactTypes } from '../Modules/Types';
5
5
  import { RoutingState } from './RoutingState';
6
6
  var NavigationHelper = /** @class */ (function () {
7
- function NavigationHelper(routingState) {
7
+ function NavigationHelper(routingState, pageLeaveHandler) {
8
8
  this.routingState = routingState;
9
+ this.pageLeaveHandler = pageLeaveHandler;
10
+ // PrevUrls is required since the popstate event tells you the new path, not the previous path
11
+ this.prevUrls = [];
12
+ this.isPrompting = false;
13
+ window.addEventListener("beforeunload", this.windowUnload.bind(this));
14
+ window.addEventListener("popstate", this.historyPopState.bind(this));
9
15
  }
10
- NavigationHelper.prototype.navigateInternal = function (url, replace) {
11
- if (replace === void 0) { replace = false; }
12
- if (replace) {
13
- this.currentRouteProps.history.replace(url);
14
- }
15
- else {
16
- this.currentRouteProps.history.push(url);
17
- }
16
+ NavigationHelper.prototype.navigateInternal = function (url_1) {
17
+ return __awaiter(this, arguments, void 0, function (url, replace) {
18
+ var basePath, prevUrl, path, route, leavePrompt, canNavigate;
19
+ if (replace === void 0) { replace = false; }
20
+ return __generator(this, function (_a) {
21
+ switch (_a.label) {
22
+ case 0:
23
+ basePath = this.routingState.basePath;
24
+ prevUrl = this.prevUrls.length === 0 ? undefined : this.prevUrls[this.prevUrls.length - 1];
25
+ path = url;
26
+ if (basePath) {
27
+ if (path.startsWith(basePath)) {
28
+ path = path.substring(basePath.length);
29
+ }
30
+ else {
31
+ url = basePath + url;
32
+ }
33
+ }
34
+ if (!(prevUrl !== url)) return [3 /*break*/, 5];
35
+ route = this.routingState.appRouteProvider.getRouteForPath(path);
36
+ if (!this.routingState.currentRoute) return [3 /*break*/, 4];
37
+ leavePrompt = this.beforeLocationChanged(route, false);
38
+ if (!(leavePrompt !== undefined)) return [3 /*break*/, 4];
39
+ _a.label = 1;
40
+ case 1:
41
+ _a.trys.push([1, , 3, 4]);
42
+ this.isPrompting = true;
43
+ return [4 /*yield*/, this.pageLeaveHandler.onLeavePage(this.routingState.currentView, leavePrompt)];
44
+ case 2:
45
+ canNavigate = _a.sent();
46
+ if (!canNavigate) {
47
+ return [2 /*return*/, false];
48
+ }
49
+ return [3 /*break*/, 4];
50
+ case 3:
51
+ this.isPrompting = false;
52
+ return [7 /*endfinally*/];
53
+ case 4:
54
+ this.routingState.updateRoute(route);
55
+ if (replace) {
56
+ if (this.prevUrls.length > 0) {
57
+ this.prevUrls[this.prevUrls.length - 1] = url;
58
+ }
59
+ window.history.replaceState(null, "", url);
60
+ }
61
+ else {
62
+ this.prevUrls.push(url);
63
+ window.history.pushState(null, "", url);
64
+ }
65
+ _a.label = 5;
66
+ case 5: return [2 /*return*/, true];
67
+ }
68
+ });
69
+ });
18
70
  };
19
71
  NavigationHelper.prototype.navigateToView = function (view, paramValues) {
20
72
  this.navigateInternal(this.getPathForView(view, paramValues));
@@ -34,27 +86,71 @@ var NavigationHelper = /** @class */ (function () {
34
86
  }
35
87
  };
36
88
  NavigationHelper.prototype.getCurrentViewPath = function () {
37
- var basePath = this.currentRouteProps.match.path;
38
- var paramIndex = basePath.indexOf(":");
39
- if (paramIndex > 0) {
40
- basePath = basePath.substring(0, paramIndex);
41
- if (basePath.endsWith("/")) {
42
- basePath = basePath.substring(0, basePath.length - 1);
89
+ if (this.routingState.currentRoute) {
90
+ return this.routingState.currentRoute.route.path;
91
+ }
92
+ else {
93
+ return "";
94
+ }
95
+ };
96
+ NavigationHelper.prototype.historyPopState = function (e) {
97
+ return __awaiter(this, void 0, void 0, function () {
98
+ var _a;
99
+ return __generator(this, function (_b) {
100
+ switch (_b.label) {
101
+ case 0:
102
+ _a = this.isPrompting;
103
+ if (_a) return [3 /*break*/, 2];
104
+ return [4 /*yield*/, this.navigateInternal(window.location.pathname, true)];
105
+ case 1:
106
+ _a = !(_b.sent());
107
+ _b.label = 2;
108
+ case 2:
109
+ if (_a) {
110
+ // cancel navigation by pushing the previous state back into history.
111
+ window.history.pushState(null, "", this.prevUrls[this.prevUrls.length - 1]);
112
+ }
113
+ else {
114
+ // remove our state to match browsers state.
115
+ this.prevUrls.pop();
116
+ }
117
+ return [2 /*return*/];
118
+ }
119
+ });
120
+ });
121
+ };
122
+ NavigationHelper.prototype.windowUnload = function (e) {
123
+ var leavePrompt = this.beforeLocationChanged(null, true);
124
+ if (leavePrompt !== undefined) {
125
+ this.pageLeaveHandler.onWindowUnload(this.routingState.currentView, leavePrompt, e);
126
+ }
127
+ };
128
+ NavigationHelper.prototype.beforeLocationChanged = function (newRoute, isUnload) {
129
+ var _a;
130
+ var currentRoute = this.routingState.currentRoute;
131
+ var changeProps = {
132
+ isNewView: !currentRoute || currentRoute.route !== (newRoute === null || newRoute === void 0 ? void 0 : newRoute.route),
133
+ isUnload: isUnload !== null && isUnload !== void 0 ? isUnload : false,
134
+ currentView: (_a = this.routingState.currentView) !== null && _a !== void 0 ? _a : undefined,
135
+ newRoute: newRoute === null || newRoute === void 0 ? void 0 : newRoute.route,
136
+ params: newRoute === null || newRoute === void 0 ? void 0 : newRoute.params
137
+ };
138
+ if (this.routingState.currentView) {
139
+ this.routingState.currentView.beforeRouteChanged(changeProps);
140
+ if (changeProps.leavePrompt === undefined && (changeProps.isNewView || changeProps.isUnload)) {
141
+ changeProps.leavePrompt = this.routingState.currentView.onLeave();
43
142
  }
44
143
  }
45
- return basePath;
144
+ if (changeProps.isNewView) {
145
+ this.pageLeaveHandler.beforeLeavePage(changeProps);
146
+ }
147
+ return changeProps.leavePrompt;
46
148
  };
47
- Object.defineProperty(NavigationHelper.prototype, "currentRouteProps", {
48
- get: function () {
49
- return this.routingState.currentRouteProps;
50
- },
51
- enumerable: false,
52
- configurable: true
53
- });
54
149
  NavigationHelper = __decorate([
55
150
  injectable(),
56
151
  __param(0, inject(NeoReactTypes.Routing.GlobalRoutingState.symbol)),
57
- __metadata("design:paramtypes", [RoutingState])
152
+ __param(1, inject(NeoReactTypes.Routing.PageLeaveHandler.symbol)),
153
+ __metadata("design:paramtypes", [RoutingState, Object])
58
154
  ], NavigationHelper);
59
155
  return NavigationHelper;
60
156
  }());
@@ -1,13 +1,30 @@
1
- import { Routing, Views } from '@singularsystems/neo-core';
1
+ import { Views } from '@singularsystems/neo-core';
2
2
  import { RoutingState } from './RoutingState';
3
- export declare class PageLeaveHandler implements Routing.IPageLeaveHandler {
4
- private routingState;
5
- constructor(routingState: RoutingState);
3
+ import { IViewBase } from "../Views/ViewBase";
4
+ import { IRouteChangedProps, RouteChangedLeavePrompt } from "./IRouteChangedProps";
5
+ export interface IPageLeaveHandler {
6
6
  /**
7
- * Handler for react-routers BrowserRouter.getUserConfirmation
7
+ * Called after `ViewBase.beforeRouteChanged` and `ViewBase.onLeave` are called.
8
+ * @param changeProps
8
9
  */
9
- static showNavigationConfirmation(prompt: string, callback: (ok: boolean) => void): Promise<void>;
10
- onWindowUnload(view: Views.IViewBase | null, e: BeforeUnloadEvent): void;
11
- onLeavePage(view: Views.IViewBase | null, prompt: string, location: Routing.NavigateLocation): Promise<boolean>;
12
- protected showDefaultConfirmation(view: Views.IViewBase | null, prompt: string, location: Routing.NavigateLocation): Promise<boolean>;
10
+ beforeLeavePage(changeProps: IRouteChangedProps): void;
11
+ /**
12
+ * Called when the user tries to leave the page, and the page / leave handler has indicated the user must be prompted.
13
+ * @returns A boolean promise with a value indicating whether the user wants to leave the page.
14
+ */
15
+ onLeavePage(view: Views.IViewBase | null, leavePrompt: RouteChangedLeavePrompt): Promise<boolean>;
16
+ /**
17
+ * Called when the windows beforeunload event fires, and the page / leave handler has indicated the user must be prompted.
18
+ * @param view The currently active view.
19
+ * @param e beforeunload event.
20
+ */
21
+ onWindowUnload(view: IViewBase | null, leavePrompt: RouteChangedLeavePrompt, e: BeforeUnloadEvent): void;
22
+ }
23
+ export declare class PageLeaveHandler implements IPageLeaveHandler {
24
+ private routingState;
25
+ constructor(routingState: RoutingState);
26
+ beforeLeavePage(changeProps: IRouteChangedProps): void;
27
+ onLeavePage(view: Views.IViewBase | null, leavePrompt: RouteChangedLeavePrompt): Promise<boolean>;
28
+ onWindowUnload(view: Views.IViewBase | null, leavePrompt: RouteChangedLeavePrompt, e: BeforeUnloadEvent): void;
29
+ protected showDefaultConfirmation(view: Views.IViewBase | null, prompt: string): Promise<boolean>;
13
30
  }
@@ -1,5 +1,5 @@
1
1
  import { __awaiter, __decorate, __generator, __metadata, __param } from "tslib";
2
- import { Routing, ModalUtils, Misc, AppServices } from '@singularsystems/neo-core';
2
+ import { ModalUtils, Misc } from '@singularsystems/neo-core';
3
3
  import { inject, injectable } from 'inversify';
4
4
  import { NeoReactTypes } from '../Modules/Types';
5
5
  import { RoutingState } from './RoutingState';
@@ -7,55 +7,32 @@ var PageLeaveHandler = /** @class */ (function () {
7
7
  function PageLeaveHandler(routingState) {
8
8
  this.routingState = routingState;
9
9
  }
10
- /**
11
- * Handler for react-routers BrowserRouter.getUserConfirmation
12
- */
13
- PageLeaveHandler.showNavigationConfirmation = function (prompt, callback) {
10
+ PageLeaveHandler.prototype.beforeLeavePage = function (changeProps) {
11
+ };
12
+ PageLeaveHandler.prototype.onLeavePage = function (view, leavePrompt) {
14
13
  return __awaiter(this, void 0, void 0, function () {
15
- var pageLeaveHandler, routingState, result;
14
+ var result;
16
15
  return __generator(this, function (_a) {
17
16
  switch (_a.label) {
18
17
  case 0:
19
- pageLeaveHandler = Misc.Globals.appService.get(AppServices.NeoTypes.Routing.PageLeaveHandler), routingState = Misc.Globals.appService.get(NeoReactTypes.Routing.GlobalRoutingState);
20
- return [4 /*yield*/, pageLeaveHandler.onLeavePage(routingState.currentView, prompt, Routing.NavigateLocation.Internal)];
18
+ if (!(leavePrompt === false)) return [3 /*break*/, 1];
19
+ return [2 /*return*/, Promise.resolve(false)];
21
20
  case 1:
21
+ if (!(typeof leavePrompt === "string")) return [3 /*break*/, 2];
22
+ return [2 /*return*/, this.showDefaultConfirmation(view, leavePrompt)];
23
+ case 2: return [4 /*yield*/, leavePrompt];
24
+ case 3:
22
25
  result = _a.sent();
23
- callback(result);
24
- return [2 /*return*/];
26
+ return [2 /*return*/, result === true || result === Misc.ModalResult.Yes];
25
27
  }
26
28
  });
27
29
  });
28
30
  };
29
- PageLeaveHandler.prototype.onWindowUnload = function (view, e) {
30
- if (view) {
31
- var routeView = Misc.Globals.appService.get(NeoReactTypes.Routing.GlobalRoutingState).currentRouteView;
32
- var prompt_1 = routeView.beforeLocationChanged(undefined, "PUSH", true);
33
- if (prompt_1 || prompt_1 === false || prompt_1 === "") {
34
- e.preventDefault();
35
- e.returnValue = !prompt_1 ? "Are you sure you want to continue?" : prompt_1;
36
- }
37
- }
38
- };
39
- PageLeaveHandler.prototype.onLeavePage = function (view, prompt, location) {
40
- if (this.routingState.leavePromise) {
41
- var promise_1 = this.routingState.leavePromise;
42
- this.routingState.leavePromise = undefined;
43
- return new Promise(function (resolve) {
44
- promise_1.then(function (result) {
45
- if (result) {
46
- resolve(result === true || result === Misc.ModalResult.Yes);
47
- }
48
- else {
49
- resolve(false);
50
- }
51
- });
52
- });
53
- }
54
- else {
55
- return this.showDefaultConfirmation(view, prompt, location);
56
- }
31
+ PageLeaveHandler.prototype.onWindowUnload = function (view, leavePrompt, e) {
32
+ e.preventDefault();
33
+ e.returnValue = typeof leavePrompt === "string" ? leavePrompt : "Are you sure you want to continue?";
57
34
  };
58
- PageLeaveHandler.prototype.showDefaultConfirmation = function (view, prompt, location) {
35
+ PageLeaveHandler.prototype.showDefaultConfirmation = function (view, prompt) {
59
36
  var title = view ? view.viewName : "Un-saved Changes";
60
37
  return new Promise(function (resolve) {
61
38
  ModalUtils.showModal(title, prompt, {
@@ -1,25 +1,45 @@
1
1
  import { Routing } from '@singularsystems/neo-core';
2
2
  import React from 'react';
3
+ import { IRouteParameter } from "./IRouteParameter";
4
+ interface INamedRouteParameter extends IRouteParameter {
5
+ name: string;
6
+ }
3
7
  export interface IProcessedRoute extends Routing.IRoute {
4
8
  key: number;
5
- /** Path including parameters */
6
- routePath: string;
9
+ /** Lower case base path without trailing / */
10
+ path: string;
11
+ /** Route params in order, excluding query parameters. */
12
+ params: INamedRouteParameter[];
13
+ }
14
+ type ParamsObject = {
15
+ [index: string]: string | undefined;
16
+ };
17
+ /**
18
+ * A route which has matched, with its parameter values populated from the path.
19
+ */
20
+ export interface IMatchedRoute {
21
+ route: IProcessedRoute;
22
+ /** Path used for the route match. Including parameter path values. Will not include the query string. */
23
+ path: string;
24
+ /** Param values matched from the path. */
25
+ params?: ParamsObject;
7
26
  }
8
27
  export default class RouteProvider {
9
28
  menuRoutes: Routing.IMenuRoute[];
10
29
  pureRoutes?: Routing.IRoute[] | undefined;
11
- notFoundRoute?: React.ComponentType<{}> | undefined;
30
+ notFoundComponent?: React.ComponentType | undefined;
12
31
  private key;
13
32
  private routeIndex;
14
- private paramRoutes;
15
- flattenedRoutes: IProcessedRoute[];
33
+ private staticRoutes;
34
+ private parameterisedRoutes;
35
+ readonly allRoutes: IProcessedRoute[];
16
36
  /**
17
37
  * Creates a route provider which provides a list of flattened routes.
18
38
  * @param menuRoutes Routes which appear on the main menu.
19
39
  * @param pureRoutes Routes which don't have a menu item.
20
- * @param notFoundRoute Route to render when the url doesn't match any of the above routes.
40
+ * @param notFoundComponent Component to render when the url doesn't match any of the above routes.
21
41
  */
22
- constructor(menuRoutes: Routing.IMenuRoute[], pureRoutes?: Routing.IRoute[] | undefined, notFoundRoute?: React.ComponentType<{}> | undefined);
42
+ constructor(menuRoutes: Routing.IMenuRoute[], pureRoutes?: Routing.IRoute[] | undefined, notFoundComponent?: React.ComponentType | undefined);
23
43
  /** Gets the path the component is bound to. If the component is bound to multiple paths, the first path is returned. */
24
44
  getPathForComponent(component: any): string | undefined;
25
45
  private flatten;
@@ -29,3 +49,4 @@ export default class RouteProvider {
29
49
  */
30
50
  private processRoute;
31
51
  }
52
+ export {};
@@ -5,39 +5,85 @@ var RouteProvider = /** @class */ (function () {
5
5
  * Creates a route provider which provides a list of flattened routes.
6
6
  * @param menuRoutes Routes which appear on the main menu.
7
7
  * @param pureRoutes Routes which don't have a menu item.
8
- * @param notFoundRoute Route to render when the url doesn't match any of the above routes.
8
+ * @param notFoundComponent Component to render when the url doesn't match any of the above routes.
9
9
  */
10
- function RouteProvider(menuRoutes, pureRoutes, notFoundRoute) {
11
- var _a;
10
+ function RouteProvider(menuRoutes, pureRoutes, notFoundComponent) {
12
11
  this.menuRoutes = menuRoutes;
13
12
  this.pureRoutes = pureRoutes;
14
- this.notFoundRoute = notFoundRoute;
13
+ this.notFoundComponent = notFoundComponent;
15
14
  this.key = 1;
16
15
  this.routeIndex = {};
17
- this.paramRoutes = [];
18
- this.flattenedRoutes = [];
19
- this.flatten(menuRoutes);
16
+ this.staticRoutes = [];
17
+ this.parameterisedRoutes = [];
18
+ this.allRoutes = [];
19
+ this.flatten(this.allRoutes, menuRoutes);
20
20
  if (pureRoutes)
21
- this.flatten(pureRoutes);
22
- /*
23
- Routes with template parameters must be added last so concrete routes resolve first.
24
- E.g.
25
- /clients/subview - SubViewComponent
26
- /clients/:param - ClientsComponent
27
-
28
- If the above was swapped around, ClientsComponent would match instead of SubViewComponent for /clients/subview.
29
- */
30
- (_a = this.flattenedRoutes).push.apply(_a, this.paramRoutes.sortBy("order", "desc").map(function (c) { return c.route; }));
31
- if (notFoundRoute) {
32
- this.flattenedRoutes.push({ component: notFoundRoute, key: -1, allowAnonymous: true, routePath: "" });
33
- }
21
+ this.flatten(this.allRoutes, pureRoutes);
22
+ this.staticRoutes = this.allRoutes.filter(function (c) { return c.params.length === 0; });
23
+ this.parameterisedRoutes = this.allRoutes
24
+ .filter(function (c) { return c.params.length > 0; })
25
+ .map(function (route) { return ({ route: route, order: route.path.split("/").length }); })
26
+ .sortBy(function (c) { return c.order; }, "desc")
27
+ .map(function (c) { return c.route; });
34
28
  }
35
29
  /** Gets the path the component is bound to. If the component is bound to multiple paths, the first path is returned. */
36
30
  RouteProvider.prototype.getPathForComponent = function (component) {
37
31
  var _a;
38
- return (_a = this.flattenedRoutes.find(function (c) { return c.component === component; })) === null || _a === void 0 ? void 0 : _a.path;
32
+ return (_a = this.allRoutes.find(function (c) { return c.component === component; })) === null || _a === void 0 ? void 0 : _a.path;
33
+ };
34
+ /** @internal */
35
+ RouteProvider.prototype.getRouteForPath = function (path) {
36
+ return RouteProvider.getRouteForPath(this.staticRoutes, this.parameterisedRoutes, path);
39
37
  };
40
- RouteProvider.prototype.flatten = function (routes, parent) {
38
+ /** @internal */
39
+ RouteProvider.getRouteForPath = function (staticRoutes, parameterisedRoutes, path) {
40
+ var queryIndex = path.indexOf("?");
41
+ if (queryIndex >= 0) {
42
+ path = path.substring(0, queryIndex);
43
+ }
44
+ var lcPath = path.toLowerCase();
45
+ var found = staticRoutes.find(function (route) { return route.path === lcPath; });
46
+ if (found) {
47
+ return { route: found, path: path };
48
+ }
49
+ if (path.endsWith("/")) {
50
+ // special case for where an extra "/" is added to the url by mistake.
51
+ var trimmedPath_1 = lcPath.substring(0, path.length - 1);
52
+ var found_1 = staticRoutes.find(function (route) { return route.path === trimmedPath_1; });
53
+ if (found_1) {
54
+ return { route: found_1, path: path };
55
+ }
56
+ }
57
+ var matches = parameterisedRoutes.filter(function (route) { return lcPath.startsWith(route.path); });
58
+ for (var _i = 0, matches_1 = matches; _i < matches_1.length; _i++) {
59
+ var match = matches_1[_i];
60
+ var paramString = path.substring(match.path.length);
61
+ var parts = paramString.split("/").slice(1);
62
+ var partCount = parts.length;
63
+ // Allow extra "/"
64
+ if (partCount > 0 && parts[partCount - 1] === "") {
65
+ partCount -= 1;
66
+ }
67
+ if (match.params.length >= partCount) {
68
+ var paramValues = {};
69
+ var isValid = true;
70
+ for (var i = 0; i < match.params.length; i++) {
71
+ var param = match.params[i];
72
+ var value = parts[i];
73
+ paramValues[param.name] = value;
74
+ if (param.required && !value) {
75
+ isValid = false;
76
+ break;
77
+ }
78
+ }
79
+ if (isValid) {
80
+ return { route: match, path: path, params: paramValues };
81
+ }
82
+ }
83
+ }
84
+ return null;
85
+ };
86
+ RouteProvider.prototype.flatten = function (into, routes, parent) {
41
87
  var _a, _b;
42
88
  for (var _i = 0, routes_1 = routes; _i < routes_1.length; _i++) {
43
89
  var route = routes_1[_i];
@@ -46,45 +92,38 @@ var RouteProvider = /** @class */ (function () {
46
92
  if (parent && !route.breadCrumbParent) {
47
93
  route.breadCrumbParent = parent;
48
94
  }
49
- this.processRoute(route);
95
+ this.processRoute(into, route);
50
96
  }
51
97
  var menuRoute = route;
52
98
  var children = __spreadArray(__spreadArray([], ((_a = route.routeChildren) !== null && _a !== void 0 ? _a : []), true), ((_b = menuRoute.children) !== null && _b !== void 0 ? _b : []), true);
53
- this.flatten(children, (hasComponent && menuRoute.showInBreadCrumb !== false) ? menuRoute : undefined);
99
+ this.flatten(into, children, (hasComponent && menuRoute.showInBreadCrumb !== false) ? menuRoute : undefined);
54
100
  }
55
101
  };
56
102
  /**
57
103
  * Create a copy of the route info, and process it.
58
104
  * Adds a unique key, and adds route parameters extracted from the component static params object.
59
105
  */
60
- RouteProvider.prototype.processRoute = function (route) {
61
- var processed = __assign(__assign({}, route), { routePath: route.path, key: this.key++ });
62
- var isParamRoute = false;
106
+ RouteProvider.prototype.processRoute = function (into, route) {
107
+ var processed = __assign(__assign({}, route), { path: route.path, params: [], key: this.key++ });
63
108
  if (route instanceof MenuRoute) {
64
- processed.routePath = route.basePath;
109
+ processed.path = route.basePath;
110
+ }
111
+ processed.path = processed.path.toLowerCase();
112
+ if (processed.path.length > 1 && processed.path.endsWith("/")) {
113
+ processed.path = processed.path.substring(0, processed.path.length - 1);
65
114
  }
66
115
  var viewBaseComponent = route.component;
67
116
  if (viewBaseComponent.params) {
68
- if (processed.routePath.endsWith("/")) {
69
- processed.routePath = processed.routePath.substring(0, processed.routePath.length - 1);
70
- }
71
117
  for (var param in viewBaseComponent.params) {
72
118
  var routeParam = viewBaseComponent.params[param];
73
119
  if (!routeParam.isQuery) {
74
- isParamRoute = true;
75
- processed.routePath += "/:" + param + (routeParam.required ? "" : "?");
120
+ processed.params.push(__assign(__assign({}, routeParam), { name: param }));
76
121
  }
77
122
  }
78
123
  }
79
- if (!this.routeIndex[processed.routePath]) {
80
- this.routeIndex[processed.routePath] = true;
81
- if (isParamRoute) {
82
- // Must be ordered later by the number of slashes in the path. Root path is a special case.
83
- this.paramRoutes.push({ route: processed, order: route.path === "/" ? 0 : (route.path.match(/\//g) || []).length });
84
- }
85
- else {
86
- this.flattenedRoutes.push(processed);
87
- }
124
+ if (!this.routeIndex[processed.path]) {
125
+ this.routeIndex[processed.path] = true;
126
+ into.push(processed);
88
127
  }
89
128
  };
90
129
  return RouteProvider;
@@ -1,40 +1,18 @@
1
1
  import * as React from 'react';
2
- import { RouteComponentProps, Switch, Route } from 'react-router';
3
- import { Location, Action } from 'history';
4
2
  import { Routing } from '@singularsystems/neo-core';
5
3
  import RouteProvider from './RouteProvider';
6
- import { IRouteChangedProps } from './IRouteChangedProps';
7
- export interface IRouteViewInternal {
8
- beforeLocationChanged(location: Location | undefined, action: Action, isUnload?: boolean): string | false | void;
9
- }
10
- export default abstract class RouteView extends React.Component<RouteComponentProps> {
11
- private historyListenDisposer?;
12
- private historyBlockDisposer?;
13
- protected switchComponent: typeof Switch;
14
- protected routeComponent: typeof Route;
4
+ export default abstract class RouteView extends React.Component<unknown> {
5
+ private routeProvider;
6
+ private hasMounted;
15
7
  protected _routes: RouteProvider;
16
8
  protected getForbiddenComponent: (route: Routing.IRoute) => JSX.Element;
17
9
  protected getSigningInComponent: (route: Routing.IRoute) => JSX.Element;
18
10
  protected securityService: import("@singularsystems/neo-core/dist/Security/ISecurityService").default;
19
11
  protected routeSecurityService: Routing.IRouteSecurityService;
20
12
  protected routingState: import("./RoutingState").RoutingState;
21
- constructor(props: RouteComponentProps);
22
- get routes(): RouteProvider;
23
- set routes(value: RouteProvider);
13
+ constructor(props: unknown, routeProvider: RouteProvider);
24
14
  componentDidMount(): void;
25
- componentDidUpdate(): void;
26
- componentWillUnmount(): void;
27
- private beforeLocationChanged;
28
- /**
29
- * Called when the url changes, before the router renders the new view.
30
- * Return a string to block navigation.
31
- * @param isNewView True if the view is changing. False if a view parameter value is changing.
32
- * @param currentView The current view before change.
33
- */
34
- protected beforeRouteChanged(props: IRouteChangedProps): void;
35
- private getMatch;
36
- static isExact(route: Routing.IRoute): boolean;
37
- render(): React.CElement<import("react-router").SwitchProps, Switch>;
15
+ render(): JSX.Element | null;
38
16
  private getRouteComponent;
39
17
  /**
40
18
  * Creates the routes component after authentication and authorisation checks have been done.