@lwrjs/router 0.10.0-alpha.1 → 0.10.0-alpha.10

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 (97) hide show
  1. package/build/bundle/prod/lwr/navigation/es/modules/lwr/currentView/currentView.d.ts +28 -0
  2. package/build/bundle/prod/lwr/navigation/navigation.js +1 -1
  3. package/build/bundle/prod/lwr/router/es/modules/lwr/currentView/currentView.d.ts +28 -0
  4. package/build/bundle/prod/lwr/router/router.js +1 -1
  5. package/build/bundle/prod/lwr/routerContainer/es/modules/lwr/currentView/currentView.d.ts +28 -0
  6. package/build/bundle/prod/lwr/routerContainer/routerContainer.js +1 -1
  7. package/build/cjs/modules/lwr/outlet/outlet.cjs +4 -1
  8. package/build/es/modules/lwr/contextProvider/contextProvider.js +30 -0
  9. package/build/es/modules/lwr/contextUtils/contextInfo.js +93 -0
  10. package/build/es/modules/lwr/contextUtils/contextUtils.js +77 -0
  11. package/build/es/modules/lwr/contextUtils/navigationApiStore.js +46 -0
  12. package/build/{modules → es/modules}/lwr/currentPageReference/currentPageReference.d.ts +1 -1
  13. package/build/es/modules/lwr/currentPageReference/currentPageReference.js +14 -0
  14. package/build/{modules → es/modules}/lwr/currentView/currentView.d.ts +2 -2
  15. package/build/es/modules/lwr/currentView/currentView.js +62 -0
  16. package/build/{modules → es/modules}/lwr/domRouter/domRouter.d.ts +2 -2
  17. package/build/es/modules/lwr/domRouter/domRouter.js +441 -0
  18. package/build/es/modules/lwr/domRouterUtils/domRouterUtils.js +3 -0
  19. package/build/es/modules/lwr/domRouterUtils/historyUtils.js +30 -0
  20. package/build/{modules → es/modules}/lwr/domRouterUtils/types.d.ts +1 -1
  21. package/build/es/modules/lwr/domRouterUtils/types.js +2 -0
  22. package/build/es/modules/lwr/domRouterUtils/uriUtils.js +69 -0
  23. package/build/es/modules/lwr/historyRouter/historyRouter.js +88 -0
  24. package/build/es/modules/lwr/navigation/navigation.js +20 -0
  25. package/build/es/modules/lwr/navigation/navigationApi.js +27 -0
  26. package/build/es/modules/lwr/navigation/navigationMixin.js +76 -0
  27. package/build/{modules → es/modules}/lwr/navigationContext/navigationContext.d.ts +2 -2
  28. package/build/es/modules/lwr/navigationContext/navigationContext.js +10 -0
  29. package/build/es/modules/lwr/navigationMixinHacks/navigationMixinHacks.d.ts +7 -0
  30. package/build/es/modules/lwr/navigationMixinHacks/navigationMixinHacks.js +5 -0
  31. package/build/es/modules/lwr/observable/observable.js +71 -0
  32. package/build/{modules → es/modules}/lwr/outlet/outlet.d.ts +1 -0
  33. package/build/es/modules/lwr/outlet/outlet.js +69 -0
  34. package/build/es/modules/lwr/router/router.js +201 -0
  35. package/build/es/modules/lwr/routerBridge/routerBridge.js +85 -0
  36. package/build/es/modules/lwr/routerContainer/routerContainer.js +116 -0
  37. package/build/es/modules/lwr/routerContainer/utils.js +83 -0
  38. package/build/es/modules/lwr/routerErrors/routerErrors.js +154 -0
  39. package/build/es/modules/lwr/routerUtils/domUtils.js +3 -0
  40. package/build/{modules → es/modules}/lwr/routerUtils/filterUtils.d.ts +1 -1
  41. package/build/es/modules/lwr/routerUtils/filterUtils.js +74 -0
  42. package/build/es/modules/lwr/routerUtils/parseUtils.js +182 -0
  43. package/build/{modules → es/modules}/lwr/routerUtils/pathToRegexp.d.ts +5 -5
  44. package/build/es/modules/lwr/routerUtils/pathToRegexp.js +415 -0
  45. package/build/es/modules/lwr/routerUtils/routeDefUtils.js +204 -0
  46. package/build/es/modules/lwr/routerUtils/routeUtils.js +239 -0
  47. package/build/es/modules/lwr/routerUtils/routerUtils.js +19 -0
  48. package/build/es/modules/lwr/routerUtils/typeUtils.js +112 -0
  49. package/build/{modules → es/modules}/lwr/routerUtils/types.d.ts +23 -23
  50. package/build/es/modules/lwr/routerUtils/types.js +2 -0
  51. package/build/es/modules/lwr/routerUtils/uriUtils.js +134 -0
  52. package/build/modules/lwr/contextUtils/contextUtils.js +5 -0
  53. package/build/modules/lwr/contextUtils/navigationApiStore.js +7 -0
  54. package/build/modules/lwr/domRouter/domRouter.js +6 -0
  55. package/build/modules/lwr/domRouterUtils/historyUtils.js +0 -1
  56. package/build/modules/lwr/outlet/outlet.css +1 -1
  57. package/build/modules/lwr/outlet/outlet.html +2 -2
  58. package/build/modules/lwr/outlet/outlet.js +3 -4
  59. package/build/modules/lwr/router/router.js +3 -0
  60. package/build/modules/lwr/routerContainer/utils.js +1 -3
  61. package/build/modules/lwr/routerUtils/pathToRegexp.js +17 -0
  62. package/build/modules/lwr/routerUtils/typeUtils.js +0 -1
  63. package/package.json +17 -9
  64. package/pageObjects/outlet.cjs +21 -4
  65. package/pageObjects/outlet.d.ts +10 -2
  66. package/pageObjects/outlet.js +22 -5
  67. package/build/modules/lwr/navigationMixinHacks/navigationMixinHacks.d.ts +0 -7
  68. /package/build/{modules → es/modules}/lwr/contextProvider/contextProvider.d.ts +0 -0
  69. /package/build/{modules → es/modules}/lwr/contextUtils/contextInfo.d.ts +0 -0
  70. /package/build/{modules → es/modules}/lwr/contextUtils/contextUtils.d.ts +0 -0
  71. /package/build/{modules → es/modules}/lwr/contextUtils/navigationApiStore.d.ts +0 -0
  72. /package/build/{modules → es/modules}/lwr/domRouterUtils/domRouterUtils.d.ts +0 -0
  73. /package/build/{modules → es/modules}/lwr/domRouterUtils/historyUtils.d.ts +0 -0
  74. /package/build/{modules → es/modules}/lwr/domRouterUtils/uriUtils.d.ts +0 -0
  75. /package/build/{modules → es/modules}/lwr/historyRouter/historyRouter.d.ts +0 -0
  76. /package/build/{modules → es/modules}/lwr/navigation/navigation.d.ts +0 -0
  77. /package/build/{modules → es/modules}/lwr/navigation/navigationApi.d.ts +0 -0
  78. /package/build/{modules → es/modules}/lwr/navigation/navigationMixin.d.ts +0 -0
  79. /package/build/{modules → es/modules}/lwr/observable/observable.d.ts +0 -0
  80. /package/build/{modules → es/modules}/lwr/router/router.d.ts +0 -0
  81. /package/build/{modules → es/modules}/lwr/routerBridge/routerBridge.d.ts +0 -0
  82. /package/build/{modules → es/modules}/lwr/routerContainer/routerContainer.d.ts +0 -0
  83. /package/build/{modules → es/modules}/lwr/routerContainer/utils.d.ts +0 -0
  84. /package/build/{modules → es/modules}/lwr/routerErrors/routerErrors.d.ts +0 -0
  85. /package/build/{modules → es/modules}/lwr/routerUtils/domUtils.d.ts +0 -0
  86. /package/build/{modules → es/modules}/lwr/routerUtils/parseUtils.d.ts +0 -0
  87. /package/build/{modules → es/modules}/lwr/routerUtils/routeDefUtils.d.ts +0 -0
  88. /package/build/{modules → es/modules}/lwr/routerUtils/routeUtils.d.ts +0 -0
  89. /package/build/{modules → es/modules}/lwr/routerUtils/routerUtils.d.ts +0 -0
  90. /package/build/{modules → es/modules}/lwr/routerUtils/typeUtils.d.ts +0 -0
  91. /package/build/{modules → es/modules}/lwr/routerUtils/uriUtils.d.ts +0 -0
  92. /package/build/{services → es/services}/index.d.ts +0 -0
  93. /package/build/{services → es/services}/index.js +0 -0
  94. /package/build/{services → es/services}/module-provider/index.d.ts +0 -0
  95. /package/build/{services → es/services}/module-provider/index.js +0 -0
  96. /package/build/{services → es/services}/module-provider/utils.d.ts +0 -0
  97. /package/build/{services → es/services}/module-provider/utils.js +0 -0
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Copyright (c) 2019, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: MIT
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
6
+ */
7
+ import { DomRouterImpl } from 'lwr/domRouter';
8
+ import { getRelativeUrl, replace, set } from 'lwr/domRouterUtils';
9
+ import { hasDocument } from 'lwr/routerUtils';
10
+ /*
11
+ * Provides a Router rooted to the window, which controls the browser history by default.
12
+ */
13
+ export class HistoryRouter extends DomRouterImpl {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.historyDisabled = false;
17
+ }
18
+ /**
19
+ * Override.
20
+ * Initialize with the current route and listen to the popstate event for future changes.
21
+ */
22
+ connect() {
23
+ super.connect();
24
+ if (!this.historyDisabled) {
25
+ // Subscribe to the Window.popstate event to listen for URL changes.
26
+ hasDocument && window.addEventListener('popstate', this.onpopstate.bind(this));
27
+ // Initialize using the current URL state
28
+ this.onpopstate();
29
+ }
30
+ }
31
+ onpopstate() {
32
+ // Only the root should update the url since it has the full context
33
+ if (!this.parent && hasDocument) {
34
+ this.catchBrowserUpdate(getRelativeUrl(document.location.href));
35
+ }
36
+ }
37
+ disconnect() {
38
+ super.disconnect();
39
+ hasDocument && window.removeEventListener('popstate', this.onpopstate);
40
+ }
41
+ /**
42
+ * Override.
43
+ * Update the browser history if the preNavigate hooks.
44
+ *
45
+ * @param {string} url - The URL to go to
46
+ * @param {boolean} shouldReplace - True if the current history state should be replaced
47
+ * @param {boolean} updateHistory - True if the browser history should be updated with the new URL
48
+ *
49
+ * @returns {boolean} - True if the processing was NOT blocked by a preNavigate listener
50
+ */
51
+ async process(url, shouldReplace, updateHistory = true) {
52
+ // Run the preNavigate hooks to check if this event should be processed.
53
+ const canContinue = await super.process(url);
54
+ // Update the window location if this router is connected and is the root router
55
+ if (canContinue && !this.historyDisabled && updateHistory && this.connected && !this.parent) {
56
+ // Update the window history.
57
+ if (shouldReplace) {
58
+ replace(url);
59
+ }
60
+ else {
61
+ set(url);
62
+ }
63
+ }
64
+ return canContinue;
65
+ }
66
+ /**
67
+ * Update the root route, and trickle down the router tree.
68
+ * Redirect to use the base path, if it is missing.
69
+ *
70
+ * @param {string} url - The URL to go to
71
+ */
72
+ catchBrowserUpdate(url) {
73
+ this.process(url, false, false);
74
+ }
75
+ }
76
+ /**
77
+ * Create a new root Router, attach to the Window.
78
+ * This is the public, programmitic API for root router creation.
79
+ * An application can only have ONE root router.
80
+ *
81
+ * @param {object} config - The router config object
82
+ *
83
+ * @returns {object} - { addPreNavigate, addPostNavigate, addErrorNavigate, connect, disconnect }
84
+ */
85
+ export function createHistoryRouter(config, router, target) {
86
+ return new HistoryRouter(config, router, target);
87
+ }
88
+ //# sourceMappingURL=historyRouter.js.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) 2019, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: MIT
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
6
+ */
7
+ // Wires and their return types
8
+ export { NavigationContext } from 'lwr/navigationContext'; // provides ContextId
9
+ export { CurrentPageReference } from 'lwr/currentPageReference'; // provides PageReference
10
+ export { CurrentView } from 'lwr/currentView'; // Provides Constructable
11
+ // The LWR Navigation context singleton (i.e. CACHE in lwr/contextUtils#navigationApiStore)
12
+ // These functions and classes must only be included in an app ONCE:
13
+ // - 'lwr/navigation' must be excluded from bundling
14
+ // - ALWAYS import these from 'lwr/navigation', even internally
15
+ export { ContextInfo, getNavigationHelm, registerNavigationHelm, generateContextualWireAdapter, } from 'lwr/contextUtils';
16
+ // NavigationMixin has a dependency on navigate and generateUrl
17
+ // They need to be sibling exports in order to avoid a circular dependency
18
+ export { navigate, generateUrl } from './navigationApi';
19
+ export { NavigationMixin } from './navigationMixin';
20
+ //# sourceMappingURL=navigation.js.map
@@ -0,0 +1,27 @@
1
+ import { getNavigationHelm } from 'lwr/contextUtils';
2
+ /**
3
+ * Navigate programmatically.
4
+ * The Promise used within is deliberately not returned.
5
+ *
6
+ * @param {HTMLElement} context - The navigation context
7
+ * @param {object | string} loc - A route or URL for navigating
8
+ * @param {*} options - Usually a boolean; when true the previous browser history
9
+ * entry should be replaced by this one
10
+ */
11
+ export function navigate(context, pageReference, replace) {
12
+ const api = getNavigationHelm(context);
13
+ api.navigate(pageReference, replace);
14
+ }
15
+ /**
16
+ * Generate a URL for the given route.
17
+ *
18
+ * @param {HTMLElement} context - The navigation context
19
+ * @param {object} route - A route
20
+ *
21
+ * @returns {Promise<string>}
22
+ */
23
+ export function generateUrl(context, pageReference) {
24
+ const api = getNavigationHelm(context);
25
+ return api.generateUrl(pageReference);
26
+ }
27
+ //# sourceMappingURL=navigationApi.js.map
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Copyright (c) 2019, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: MIT
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
6
+ */
7
+ // TODO: The way NavigationMixin is currently set up, we need to use unique
8
+ // symbols as indexes, which typescript does not like, necessitating 'any'
9
+ /* eslint-disable @typescript-eslint/no-explicit-any */
10
+ import { invariant, generateMessage, messages } from 'lwr/routerErrors';
11
+ import { generateUrl, navigate } from './navigationApi';
12
+ import { CONTEXT_ID_BACKDOOR } from 'lwr/navigationMixinHacks';
13
+ /*
14
+ * Exports the NavigationMixin and CurrentPageReference wire adapter.
15
+ * Uses the NavigationContext wire to retrieve the current navigation context/node.
16
+ */
17
+ /**
18
+ * Provides navigate() and generateUrl() functionality.
19
+ * Here, navigate() can take either a route OR a string URL.
20
+ * Functionality pulled in from the current navigation context.
21
+ * Used by components as a Mixin to extend their own functionality.
22
+ *
23
+ * @param {HTMLElement} Base - A class instance
24
+ */
25
+ const Navigate = Symbol('Navigate');
26
+ const GenerateUrl = Symbol('GenerateUrl');
27
+ const NavContext = Symbol('NavContext');
28
+ const GetContext = Symbol('NavContext');
29
+ function NavigationMixin(Base) {
30
+ invariant(typeof Base.prototype.dispatchEvent === 'function', messages.INVALID_MIXIN_CMP, [
31
+ Base.toString(),
32
+ ]);
33
+ class Mixin extends Base {
34
+ [GetContext]() {
35
+ /*
36
+ * NavigationMixin is a special snowflake that needs to use the DOM to lookup its parent ContextId,
37
+ * but is not allowed to use the traditional means: @wire(NavigationContext) to do so, because it's
38
+ * part of the navigation API, which must be importable into the priming environment, and thus cannot
39
+ * import anything from LWC. Best solution we have so far is a CustomEvent that allows the module to
40
+ * be imported, but cannot be RAN in the priming environment. This is acceptable because it's generally
41
+ * a component that extends LightningElement that's using the NavigationMixin, rather than any priming code.
42
+ */
43
+ if (!this[NavContext]) {
44
+ this.dispatchEvent(
45
+ // eslint exception reason: this code is safe to be imported into the priming environment, but is not runnable, and not expected to be runnable
46
+ // eslint-disable-next-line no-undef
47
+ new CustomEvent(CONTEXT_ID_BACKDOOR, {
48
+ bubbles: true,
49
+ composed: true,
50
+ detail: {
51
+ callback: (contextId) => {
52
+ this[NavContext] = contextId;
53
+ },
54
+ },
55
+ }));
56
+ if (!this[NavContext]) {
57
+ throw new Error(generateMessage(messages.MISSING_CONTEXT));
58
+ }
59
+ }
60
+ }
61
+ [Navigate](pageRef, replace) {
62
+ this[GetContext]();
63
+ navigate(this[NavContext], pageRef, replace);
64
+ }
65
+ async [GenerateUrl](pageRef) {
66
+ this[GetContext]();
67
+ return generateUrl(this[NavContext], pageRef);
68
+ }
69
+ }
70
+ return Mixin;
71
+ }
72
+ NavigationMixin.Navigate = Navigate;
73
+ NavigationMixin.GenerateUrl = GenerateUrl;
74
+ NavigationMixin.NavContext = NavContext;
75
+ export { NavigationMixin };
76
+ //# sourceMappingURL=navigationMixin.js.map
@@ -1,5 +1,5 @@
1
- export declare type ContextId = () => void;
2
- declare type NavigationContextType = ContextId | undefined;
1
+ export type ContextId = () => void;
2
+ type NavigationContextType = ContextId | undefined;
3
3
  export declare const NavigationContext: import("lwr/contextUtils").ContextualWireAdapter<NavigationContextType, unknown, NavigationContextType>;
4
4
  export {};
5
5
  //# sourceMappingURL=navigationContext.d.ts.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Copyright (c) 2019, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: MIT
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
6
+ */
7
+ import { ContextInfo, generateContextualWireAdapter } from 'lwr/contextUtils';
8
+ const NAVIGATION_CONTEXT = new ContextInfo(undefined);
9
+ export const NavigationContext = generateContextualWireAdapter(NAVIGATION_CONTEXT);
10
+ //# sourceMappingURL=navigationContext.js.map
@@ -0,0 +1,7 @@
1
+ export declare const CONTEXT_ID_BACKDOOR: string;
2
+ export type NavigationContextBackdoorEvent = globalThis.CustomEvent<NavigationContextBackdoorEventPayload>;
3
+ import type { ContextId } from 'lwr/navigation';
4
+ export type NavigationContextBackdoorEventPayload = {
5
+ callback: (contextId: ContextId) => void;
6
+ };
7
+ //# sourceMappingURL=navigationMixinHacks.d.ts.map
@@ -0,0 +1,5 @@
1
+ // This is claimed to be a portable module, but it really isn't. It can be imported, but will not RUN in the portable environment
2
+ import { guid } from 'lwr/routerUtils';
3
+ // A hack to get NavigationMixin working without requiring lwc
4
+ export const CONTEXT_ID_BACKDOOR = `universalcontainergetnavigationcontext${guid()}`;
5
+ //# sourceMappingURL=navigationMixinHacks.js.map
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Creates a simple observable object, which can have any number of observers.
3
+ * @returns {object}
4
+ */
5
+ export function createObservable() {
6
+ // Keep track of the current value and error.
7
+ let currentValue = undefined;
8
+ let currentError = undefined;
9
+ // Observer list with functions to add and remove members safely.
10
+ let observers = [];
11
+ const addObserver = (obs) => {
12
+ observers.push(obs);
13
+ };
14
+ const removeObserver = (obsIndex) => {
15
+ // copy on delete prevents issues when an observer unsubscribes while iterating over them
16
+ observers = [...observers.slice(0, obsIndex), ...observers.slice(obsIndex + 1)];
17
+ };
18
+ // On next, broadcast the value to all observers.
19
+ // Clear out current error.
20
+ const next = (value) => {
21
+ observers
22
+ .filter((obs) => obs !== null)
23
+ .forEach((obs) => obs.next && obs.next(value));
24
+ currentValue = value;
25
+ currentError = undefined;
26
+ };
27
+ // On error, broadcast the error to all observers.
28
+ // Clear out current value.
29
+ const error = (err) => {
30
+ observers
31
+ .filter((obs) => obs !== null)
32
+ .forEach((obs) => obs.error && obs.error(err));
33
+ currentValue = undefined;
34
+ currentError = err;
35
+ };
36
+ // On complete, call complete on all observers.
37
+ // Clear out all observers + current value and error.
38
+ const complete = () => {
39
+ observers
40
+ .filter((obs) => obs !== null)
41
+ .forEach((obs) => obs.complete && obs.complete());
42
+ observers = [];
43
+ currentValue = undefined;
44
+ currentError = undefined;
45
+ };
46
+ // Observable can be subscribed and unsubscribed, by multiple observers.
47
+ // When replay is true, the currentValue will be emitted synchronously.
48
+ const subscribe = (obs, replay = true) => {
49
+ addObserver(obs);
50
+ // Push the current value and error, if they exist.
51
+ if (currentValue && replay) {
52
+ obs.next(currentValue);
53
+ }
54
+ if (currentError) {
55
+ error(currentError);
56
+ }
57
+ // On unsubscribe, the observer is nulled out.
58
+ const obsIndex = observers.length - 1;
59
+ return {
60
+ unsubscribe: () => removeObserver(obsIndex),
61
+ };
62
+ };
63
+ // Return the observation methods + the associated observable.
64
+ return {
65
+ next,
66
+ error,
67
+ complete,
68
+ subscribe,
69
+ };
70
+ }
71
+ //# sourceMappingURL=observable.js.map
@@ -4,6 +4,7 @@ export interface OutletErrorCallback {
4
4
  (error: Error, stack: string): void;
5
5
  }
6
6
  export default class Outlet extends LightningElement {
7
+ static renderMode: string;
7
8
  refocusOff: boolean;
8
9
  outletErrorCallback?: OutletErrorCallback;
9
10
  viewName: string;
@@ -0,0 +1,69 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LightningElement, api, wire } from 'lwc';
8
+ import { CurrentView } from 'lwr/navigation';
9
+ export default class Outlet extends LightningElement {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.refocusOff = false;
13
+ this.viewName = 'default';
14
+ this.viewCtor = undefined;
15
+ this.previousViewCtor = undefined;
16
+ this.hasError = false;
17
+ }
18
+ // Get a reference to the current view
19
+ setView(currentView) {
20
+ this.hasError = false;
21
+ this.viewCtor = currentView;
22
+ this.refocus();
23
+ }
24
+ renderedCallback() {
25
+ if (this.viewCtor !== this.previousViewCtor) {
26
+ this.previousViewCtor = this.viewCtor;
27
+ const viewChangedEvent = new CustomEvent('viewchange', { detail: this.viewCtor });
28
+ this.dispatchEvent(viewChangedEvent);
29
+ }
30
+ }
31
+ errorCallback(e, stack) {
32
+ // when hosted view has unhandled error thrown:
33
+ // - display the error slot
34
+ // - dispatch the "viewchange" event
35
+ // - call the outletErrorCallback()
36
+ this.hasError = true;
37
+ const viewErrorEvent = new CustomEvent('viewerror', { detail: { error: e, stack } });
38
+ this.dispatchEvent(viewErrorEvent);
39
+ if (this.outletErrorCallback) {
40
+ this.outletErrorCallback(e, stack);
41
+ }
42
+ else {
43
+ console.error(e);
44
+ }
45
+ }
46
+ refocus() {
47
+ // If the feature is not turned off, put the browser focus onto the dynamic content.
48
+ // This is done after a route change for accessibility.
49
+ if (!this.refocusOff) {
50
+ const region = this.querySelector(`div[role='region'].outlet`);
51
+ if (region)
52
+ region.focus();
53
+ }
54
+ }
55
+ }
56
+ Outlet.renderMode = 'light';
57
+ __decorate([
58
+ api
59
+ ], Outlet.prototype, "refocusOff", void 0);
60
+ __decorate([
61
+ api
62
+ ], Outlet.prototype, "outletErrorCallback", void 0);
63
+ __decorate([
64
+ api
65
+ ], Outlet.prototype, "viewName", void 0);
66
+ __decorate([
67
+ wire(CurrentView, { viewName: '$viewName' })
68
+ ], Outlet.prototype, "setView", null);
69
+ //# sourceMappingURL=outlet.js.map
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Copyright (c) 2019, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: MIT
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
6
+ */
7
+ import { freeze, getUrlFromPageReference, getPageReferenceFromUrl, matchRouteByUrl, getUrlFromPageReferenceAndRouteDef, parseRoutes, } from 'lwr/routerUtils';
8
+ import { generateMessage, messages } from 'lwr/routerErrors';
9
+ import { createObservable } from 'lwr/observable';
10
+ class RouterImpl {
11
+ /**
12
+ * Create and configure the Router.
13
+ *
14
+ * @param {object} config - The router config object, all properties are optional
15
+ */
16
+ constructor(config) {
17
+ this.deprecatedConfig = {};
18
+ this.routeHandlerId = 0;
19
+ this.compiledRoutes = [];
20
+ this.routeObservable = createObservable();
21
+ this.config = {
22
+ basePath: config.basePath || '',
23
+ caseSensitive: Boolean(config.caseSensitive),
24
+ routes: config.routes || [],
25
+ generateUrl: (address) => getUrlFromPageReference(address, this.compiledRoutes, this.config.basePath),
26
+ parseUrl: (url) => getPageReferenceFromUrl(url, this.compiledRoutes, this.config.basePath),
27
+ };
28
+ const { DEPRECATED_getRouteFromUrl, DEPRECATED_getUrlFromRoute } = config;
29
+ if (DEPRECATED_getRouteFromUrl) {
30
+ this.deprecatedConfig.DEPRECATED_getRouteFromUrl = DEPRECATED_getRouteFromUrl;
31
+ }
32
+ if (DEPRECATED_getUrlFromRoute) {
33
+ this.deprecatedConfig.DEPRECATED_getUrlFromRoute = DEPRECATED_getUrlFromRoute;
34
+ }
35
+ this.compiledRoutes = parseRoutes(this.config);
36
+ }
37
+ /**
38
+ * Convert address to url string.
39
+ *
40
+ * @param address
41
+ */
42
+ generateUrl(address) {
43
+ const { DEPRECATED_getUrlFromRoute: getUrlFromRoute } = this.deprecatedConfig;
44
+ if (getUrlFromRoute) {
45
+ return getUrlFromRoute(address, this.config.generateUrl);
46
+ }
47
+ else {
48
+ return this.config.generateUrl(address);
49
+ }
50
+ }
51
+ /**
52
+ * Convert url string to address.
53
+ *
54
+ * @param url
55
+ */
56
+ parseUrl(url) {
57
+ const { DEPRECATED_getRouteFromUrl: getRouteFromUrl } = this.deprecatedConfig;
58
+ if (getRouteFromUrl) {
59
+ return getRouteFromUrl(url, this.config.parseUrl);
60
+ }
61
+ else {
62
+ return this.config.parseUrl(url);
63
+ }
64
+ }
65
+ /**
66
+ * Match the given url against the internal route definitions and return info
67
+ * on the match.
68
+ *
69
+ * @param address - The address to match
70
+ */
71
+ matchRoute(address) {
72
+ const url = typeof address === 'string' ? address : this.generateUrl(address);
73
+ if (url === null) {
74
+ return null;
75
+ }
76
+ const match = matchRouteByUrl(url, this.compiledRoutes, this.config.basePath);
77
+ const pathMatch = match &&
78
+ getUrlFromPageReferenceAndRouteDef(match.route.pageReference, match.routeDefinition, this.config.basePath);
79
+ if (!match || !pathMatch) {
80
+ return null;
81
+ }
82
+ return {
83
+ pathMatch,
84
+ route: match.route,
85
+ routeDefinition: match.routeDefinition.original,
86
+ };
87
+ }
88
+ /**
89
+ * Given an address, return the associated viewset by calling the route handler.
90
+ *
91
+ * @param address - The address to match to a viewset
92
+ */
93
+ async resolveView(address) {
94
+ return new Promise((resolve, reject) => {
95
+ // get the RoutingMatch: { pathMatch, route, routeDefinition }
96
+ const routingMatch = this.matchRoute(address);
97
+ if (!routingMatch) {
98
+ return reject(generateMessage(messages.NO_ROUTE_MATCH, [JSON.stringify(address)]));
99
+ }
100
+ // retrieve the route handler and use it to get the RouteDestination
101
+ // handler ~= import('my/handlerModule');
102
+ return routingMatch.routeDefinition.handler().then((handlerModule) => {
103
+ // the route handler class is the module's default export
104
+ const routeHandlerClass = handlerModule.default;
105
+ if (!routeHandlerClass) {
106
+ return reject(generateMessage(messages.INVALID_ROUTE_HANDLER, [routingMatch.routeDefinition.id]));
107
+ }
108
+ // instantiate an instance of the route handler class
109
+ // and pass in resolve() as the RouteHandlerCallback
110
+ const routeHandler = new routeHandlerClass(resolve);
111
+ // update() will invoke the resolve callback with the matching RouteDestination/viewset
112
+ if (routeHandler) {
113
+ routeHandler.update(routingMatch.route);
114
+ }
115
+ });
116
+ });
117
+ }
118
+ /**
119
+ * Process the given URL by matching it to an existing route and looking up
120
+ * the associated view
121
+ *
122
+ * @param {object} address
123
+ */
124
+ navigate(address) {
125
+ const routingMatch = this.matchRoute(address);
126
+ if (!routingMatch) {
127
+ throw new Error(generateMessage(messages.MISSING_ROUTE, [JSON.stringify(address)]));
128
+ }
129
+ this.pendingRoute = { ...routingMatch };
130
+ // map the matched route to a view and notify subscribers
131
+ this._mapView(this.pendingRoute);
132
+ }
133
+ /**
134
+ * lightning/navigation
135
+ * Subscribe a callback to the Observable on the current route of this router.
136
+ *
137
+ * @param {function} callback - A callback function invoked when the navigation state changes
138
+ * callback(route, routeDef)
139
+ * @param {boolean} replay - Flag to determine if callback should be called with current route and data immediately
140
+ */
141
+ subscribe(callback, replay) {
142
+ return this.routeObservable.subscribe({
143
+ next: callback,
144
+ error: () => {
145
+ // ignore
146
+ },
147
+ complete: () => {
148
+ // nothing to clean up
149
+ },
150
+ }, Boolean(replay));
151
+ }
152
+ /**
153
+ * Map the given route to a view set that can be emitted to subscribers. After the correct handler
154
+ * is determined (picked from the routers routes in the config), view mapping is delegated to the
155
+ * handler with a callback to finish processing and emit the final result.
156
+ *
157
+ * @param {*} route
158
+ * @param {*} routeInfo
159
+ */
160
+ async _mapView(routingMatch) {
161
+ // set an id in case _mapView is called again.
162
+ const routeHandlerId = Math.random();
163
+ this.routeHandlerId = routeHandlerId;
164
+ const handlerModule = await routingMatch.routeDefinition.handler();
165
+ const routeHandlerClass = handlerModule.default;
166
+ if (!routeHandlerClass) {
167
+ throw new Error(generateMessage(messages.INVALID_ROUTE_HANDLER, [routingMatch.routeDefinition.id]));
168
+ }
169
+ this.routeHandler = new routeHandlerClass((routeDestination) => {
170
+ // If the id in the callback no longer matches the latest id from the router, it indicates _mapView
171
+ // was called again after this handler began loading but before the callback completed.
172
+ this._updateView(routeHandlerId, routeDestination);
173
+ });
174
+ if (this.routeHandler) {
175
+ this.routeHandler.update(routingMatch.route);
176
+ }
177
+ return true;
178
+ }
179
+ /**
180
+ * Set internal state, notify observable with frozen data, and propagate to child router
181
+ *
182
+ * @param {*} viewDestination
183
+ */
184
+ _updateView(viewHandlerId, routeDestination) {
185
+ if (!routeDestination || viewHandlerId !== this.routeHandlerId) {
186
+ // no-op, a status handler stopped the action
187
+ // or this callback does not belong to the most recent view handler.
188
+ return;
189
+ }
190
+ if (!this.pendingRoute) {
191
+ throw new Error('Trying to commit route state without a route');
192
+ }
193
+ const viewset = freeze(routeDestination.viewset);
194
+ this.routeObservable.next({ ...this.pendingRoute, ...routeDestination, viewset });
195
+ }
196
+ }
197
+ // export the function only instead of the class, may give us more flexibility in the future
198
+ export function createRouter(config = {}) {
199
+ return new RouterImpl(config);
200
+ }
201
+ //# sourceMappingURL=router.js.map