piral-core 0.15.0-alpha.4036 → 0.15.0-alpha.4041

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 (245) hide show
  1. package/esm/Piral.d.ts +2 -2
  2. package/esm/Piral.js +14 -12
  3. package/esm/Piral.js.map +1 -1
  4. package/esm/PiralContext.d.ts +21 -0
  5. package/esm/PiralContext.js +34 -0
  6. package/esm/PiralContext.js.map +1 -0
  7. package/esm/actions/app.d.ts +1 -2
  8. package/esm/actions/app.js +0 -3
  9. package/esm/actions/app.js.map +1 -1
  10. package/esm/actions/state.js +5 -1
  11. package/esm/actions/state.js.map +1 -1
  12. package/esm/components/ErrorBoundary.js +3 -3
  13. package/esm/components/ErrorBoundary.js.map +1 -1
  14. package/esm/components/PiralGlobals.d.ts +6 -0
  15. package/esm/components/PiralGlobals.js +13 -0
  16. package/esm/components/PiralGlobals.js.map +1 -0
  17. package/esm/components/PiralSuspense.d.ts +2 -0
  18. package/esm/components/PiralSuspense.js +8 -0
  19. package/esm/components/PiralSuspense.js.map +1 -0
  20. package/esm/components/PiralView.d.ts +6 -1
  21. package/esm/components/PiralView.js +12 -24
  22. package/esm/components/PiralView.js.map +1 -1
  23. package/esm/components/ResponsiveLayout.d.ts +2 -1
  24. package/esm/components/ResponsiveLayout.js +5 -12
  25. package/esm/components/ResponsiveLayout.js.map +1 -1
  26. package/esm/components/components.d.ts +13 -6
  27. package/esm/components/components.js +13 -6
  28. package/esm/components/components.js.map +1 -1
  29. package/esm/components/index.d.ts +2 -12
  30. package/esm/components/index.js +2 -12
  31. package/esm/components/index.js.map +1 -1
  32. package/esm/{components → defaults}/DefaultErrorInfo.d.ts +0 -0
  33. package/esm/{components → defaults}/DefaultErrorInfo.js +1 -2
  34. package/esm/defaults/DefaultErrorInfo.js.map +1 -0
  35. package/esm/{components → defaults}/DefaultLayout.d.ts +0 -0
  36. package/esm/{components → defaults}/DefaultLayout.js +0 -0
  37. package/esm/defaults/DefaultLayout.js.map +1 -0
  38. package/esm/{components/DefaultLoader.d.ts → defaults/DefaultLoadingIndicator.d.ts} +0 -0
  39. package/esm/{components/DefaultLoader.js → defaults/DefaultLoadingIndicator.js} +1 -1
  40. package/esm/defaults/DefaultLoadingIndicator.js.map +1 -0
  41. package/esm/{components → defaults}/DefaultRouteSwitch.d.ts +0 -0
  42. package/esm/{components → defaults}/DefaultRouteSwitch.js +0 -0
  43. package/esm/defaults/DefaultRouteSwitch.js.map +1 -0
  44. package/esm/{components → defaults}/DefaultRouter.d.ts +0 -0
  45. package/esm/{components → defaults}/DefaultRouter.js +0 -0
  46. package/esm/defaults/DefaultRouter.js.map +1 -0
  47. package/esm/defaults/index.d.ts +5 -0
  48. package/esm/defaults/index.js +6 -0
  49. package/esm/defaults/index.js.map +1 -0
  50. package/esm/index.d.ts +1 -0
  51. package/esm/index.js +1 -0
  52. package/esm/index.js.map +1 -1
  53. package/esm/{components → setters}/SetComponent.d.ts +0 -0
  54. package/esm/{components → setters}/SetComponent.js +0 -0
  55. package/esm/setters/SetComponent.js.map +1 -0
  56. package/esm/{components → setters}/SetError.d.ts +0 -0
  57. package/esm/{components → setters}/SetError.js +0 -0
  58. package/esm/setters/SetError.js.map +1 -0
  59. package/esm/{components → setters}/SetErrors.d.ts +0 -0
  60. package/esm/{components → setters}/SetErrors.js +0 -0
  61. package/esm/setters/SetErrors.js.map +1 -0
  62. package/esm/{components → setters}/SetLayout.d.ts +0 -0
  63. package/esm/{components → setters}/SetLayout.js +0 -0
  64. package/esm/setters/SetLayout.js.map +1 -0
  65. package/esm/{components → setters}/SetProvider.d.ts +0 -0
  66. package/esm/{components → setters}/SetProvider.js +0 -0
  67. package/esm/setters/SetProvider.js.map +1 -0
  68. package/esm/{components → setters}/SetRedirect.d.ts +0 -0
  69. package/esm/{components → setters}/SetRedirect.js +0 -0
  70. package/esm/setters/SetRedirect.js.map +1 -0
  71. package/esm/{components → setters}/SetRoute.d.ts +0 -0
  72. package/esm/{components → setters}/SetRoute.js +0 -0
  73. package/esm/setters/SetRoute.js.map +1 -0
  74. package/esm/setters/index.d.ts +7 -0
  75. package/esm/setters/index.js +8 -0
  76. package/esm/setters/index.js.map +1 -0
  77. package/esm/state/createGlobalState.js +1 -2
  78. package/esm/state/createGlobalState.js.map +1 -1
  79. package/esm/types/instance.d.ts +7 -2
  80. package/esm/types/state.d.ts +0 -10
  81. package/esm/utils/compare.d.ts +1 -1
  82. package/esm/utils/compare.js +20 -3
  83. package/esm/utils/compare.js.map +1 -1
  84. package/esm/utils/media.js +1 -1
  85. package/esm/utils/media.js.map +1 -1
  86. package/lib/Piral.d.ts +2 -2
  87. package/lib/Piral.js +13 -11
  88. package/lib/Piral.js.map +1 -1
  89. package/lib/PiralContext.d.ts +21 -0
  90. package/lib/PiralContext.js +38 -0
  91. package/lib/PiralContext.js.map +1 -0
  92. package/lib/actions/app.d.ts +1 -2
  93. package/lib/actions/app.js +1 -5
  94. package/lib/actions/app.js.map +1 -1
  95. package/lib/actions/state.js +5 -1
  96. package/lib/actions/state.js.map +1 -1
  97. package/lib/components/ErrorBoundary.js +2 -2
  98. package/lib/components/ErrorBoundary.js.map +1 -1
  99. package/lib/components/PiralGlobals.d.ts +6 -0
  100. package/lib/components/PiralGlobals.js +17 -0
  101. package/lib/components/PiralGlobals.js.map +1 -0
  102. package/lib/components/PiralSuspense.d.ts +2 -0
  103. package/lib/components/PiralSuspense.js +12 -0
  104. package/lib/components/PiralSuspense.js.map +1 -0
  105. package/lib/components/PiralView.d.ts +6 -1
  106. package/lib/components/PiralView.js +11 -23
  107. package/lib/components/PiralView.js.map +1 -1
  108. package/lib/components/ResponsiveLayout.d.ts +2 -1
  109. package/lib/components/ResponsiveLayout.js +3 -10
  110. package/lib/components/ResponsiveLayout.js.map +1 -1
  111. package/lib/components/components.d.ts +13 -6
  112. package/lib/components/components.js +14 -7
  113. package/lib/components/components.js.map +1 -1
  114. package/lib/components/index.d.ts +2 -12
  115. package/lib/components/index.js +2 -12
  116. package/lib/components/index.js.map +1 -1
  117. package/lib/{components → defaults}/DefaultErrorInfo.d.ts +0 -0
  118. package/lib/{components → defaults}/DefaultErrorInfo.js +2 -3
  119. package/lib/defaults/DefaultErrorInfo.js.map +1 -0
  120. package/lib/{components → defaults}/DefaultLayout.d.ts +0 -0
  121. package/lib/{components → defaults}/DefaultLayout.js +0 -0
  122. package/lib/defaults/DefaultLayout.js.map +1 -0
  123. package/lib/{components/DefaultLoader.d.ts → defaults/DefaultLoadingIndicator.d.ts} +0 -0
  124. package/lib/{components/DefaultLoader.js → defaults/DefaultLoadingIndicator.js} +1 -1
  125. package/lib/defaults/DefaultLoadingIndicator.js.map +1 -0
  126. package/lib/{components → defaults}/DefaultRouteSwitch.d.ts +0 -0
  127. package/lib/{components → defaults}/DefaultRouteSwitch.js +0 -0
  128. package/lib/defaults/DefaultRouteSwitch.js.map +1 -0
  129. package/lib/{components → defaults}/DefaultRouter.d.ts +0 -0
  130. package/lib/{components → defaults}/DefaultRouter.js +0 -0
  131. package/lib/defaults/DefaultRouter.js.map +1 -0
  132. package/lib/defaults/index.d.ts +5 -0
  133. package/lib/defaults/index.js +9 -0
  134. package/lib/defaults/index.js.map +1 -0
  135. package/lib/index.d.ts +1 -0
  136. package/lib/index.js +1 -0
  137. package/lib/index.js.map +1 -1
  138. package/lib/{components → setters}/SetComponent.d.ts +0 -0
  139. package/lib/{components → setters}/SetComponent.js +0 -0
  140. package/lib/setters/SetComponent.js.map +1 -0
  141. package/lib/{components → setters}/SetError.d.ts +0 -0
  142. package/lib/{components → setters}/SetError.js +0 -0
  143. package/lib/setters/SetError.js.map +1 -0
  144. package/lib/{components → setters}/SetErrors.d.ts +0 -0
  145. package/lib/{components → setters}/SetErrors.js +0 -0
  146. package/lib/setters/SetErrors.js.map +1 -0
  147. package/lib/{components → setters}/SetLayout.d.ts +0 -0
  148. package/lib/{components → setters}/SetLayout.js +0 -0
  149. package/lib/setters/SetLayout.js.map +1 -0
  150. package/lib/{components → setters}/SetProvider.d.ts +0 -0
  151. package/lib/{components → setters}/SetProvider.js +0 -0
  152. package/lib/setters/SetProvider.js.map +1 -0
  153. package/lib/{components → setters}/SetRedirect.d.ts +0 -0
  154. package/lib/{components → setters}/SetRedirect.js +0 -0
  155. package/lib/setters/SetRedirect.js.map +1 -0
  156. package/lib/{components → setters}/SetRoute.d.ts +0 -0
  157. package/lib/{components → setters}/SetRoute.js +0 -0
  158. package/lib/setters/SetRoute.js.map +1 -0
  159. package/lib/setters/index.d.ts +7 -0
  160. package/lib/setters/index.js +11 -0
  161. package/lib/setters/index.js.map +1 -0
  162. package/lib/state/createGlobalState.js +6 -7
  163. package/lib/state/createGlobalState.js.map +1 -1
  164. package/lib/types/instance.d.ts +7 -2
  165. package/lib/types/state.d.ts +0 -10
  166. package/lib/utils/compare.d.ts +1 -1
  167. package/lib/utils/compare.js +22 -5
  168. package/lib/utils/compare.js.map +1 -1
  169. package/lib/utils/media.js +1 -1
  170. package/lib/utils/media.js.map +1 -1
  171. package/package.json +16 -4
  172. package/src/Piral.test.tsx +3 -3
  173. package/src/Piral.tsx +18 -14
  174. package/src/PiralContext.tsx +39 -0
  175. package/src/actions/app.test.ts +0 -18
  176. package/src/actions/app.ts +0 -8
  177. package/src/actions/state.ts +6 -1
  178. package/src/components/ErrorBoundary.tsx +3 -3
  179. package/src/components/PiralGlobals.tsx +16 -0
  180. package/src/components/PiralRoutes.test.tsx +1 -1
  181. package/src/components/PiralSuspense.tsx +15 -0
  182. package/src/components/PiralView-server.test.tsx +1 -0
  183. package/src/components/PiralView.test.tsx +1 -0
  184. package/src/components/PiralView.tsx +24 -47
  185. package/src/components/ResponsiveLayout.test.tsx +14 -43
  186. package/src/components/ResponsiveLayout.tsx +11 -15
  187. package/src/components/components.tsx +13 -6
  188. package/src/components/index.ts +2 -12
  189. package/src/{components → defaults}/DefaultErrorInfo.test.tsx +0 -0
  190. package/src/{components → defaults}/DefaultErrorInfo.tsx +1 -2
  191. package/src/{components → defaults}/DefaultLayout.test.tsx +0 -0
  192. package/src/{components → defaults}/DefaultLayout.tsx +1 -1
  193. package/src/{components/DefaultLoader.test.tsx → defaults/DefaultLoadingIndicator.test.tsx} +2 -2
  194. package/src/{components/DefaultLoader.tsx → defaults/DefaultLoadingIndicator.tsx} +0 -0
  195. package/src/{components → defaults}/DefaultRouteSwitch.tsx +0 -0
  196. package/src/{components → defaults}/DefaultRouter.tsx +0 -0
  197. package/src/defaults/index.ts +5 -0
  198. package/src/index.tsx +1 -0
  199. package/src/{components → setters}/SetComponent.test.tsx +0 -0
  200. package/src/{components → setters}/SetComponent.tsx +0 -0
  201. package/src/{components → setters}/SetError.test.tsx +0 -0
  202. package/src/{components → setters}/SetError.tsx +0 -0
  203. package/src/{components → setters}/SetErrors.test.tsx +0 -0
  204. package/src/{components → setters}/SetErrors.tsx +0 -0
  205. package/src/{components → setters}/SetLayout.test.tsx +0 -0
  206. package/src/{components → setters}/SetLayout.tsx +0 -0
  207. package/src/{components → setters}/SetProvider.test.tsx +0 -0
  208. package/src/{components → setters}/SetProvider.tsx +0 -0
  209. package/src/{components → setters}/SetRedirect.test.tsx +0 -0
  210. package/src/{components → setters}/SetRedirect.tsx +0 -0
  211. package/src/{components → setters}/SetRoute.test.tsx +0 -0
  212. package/src/{components → setters}/SetRoute.tsx +0 -0
  213. package/src/setters/index.ts +7 -0
  214. package/src/state/createGlobalState.test.ts +1 -10
  215. package/src/state/createGlobalState.ts +2 -3
  216. package/src/types/instance.ts +8 -2
  217. package/src/types/state.ts +0 -10
  218. package/src/utils/compare.test.ts +15 -15
  219. package/src/utils/compare.ts +23 -3
  220. package/src/utils/foreign.test.ts +1 -1
  221. package/src/utils/media.ts +1 -1
  222. package/esm/components/DefaultErrorInfo.js.map +0 -1
  223. package/esm/components/DefaultLayout.js.map +0 -1
  224. package/esm/components/DefaultLoader.js.map +0 -1
  225. package/esm/components/DefaultRouteSwitch.js.map +0 -1
  226. package/esm/components/DefaultRouter.js.map +0 -1
  227. package/esm/components/SetComponent.js.map +0 -1
  228. package/esm/components/SetError.js.map +0 -1
  229. package/esm/components/SetErrors.js.map +0 -1
  230. package/esm/components/SetLayout.js.map +0 -1
  231. package/esm/components/SetProvider.js.map +0 -1
  232. package/esm/components/SetRedirect.js.map +0 -1
  233. package/esm/components/SetRoute.js.map +0 -1
  234. package/lib/components/DefaultErrorInfo.js.map +0 -1
  235. package/lib/components/DefaultLayout.js.map +0 -1
  236. package/lib/components/DefaultLoader.js.map +0 -1
  237. package/lib/components/DefaultRouteSwitch.js.map +0 -1
  238. package/lib/components/DefaultRouter.js.map +0 -1
  239. package/lib/components/SetComponent.js.map +0 -1
  240. package/lib/components/SetError.js.map +0 -1
  241. package/lib/components/SetErrors.js.map +0 -1
  242. package/lib/components/SetLayout.js.map +0 -1
  243. package/lib/components/SetProvider.js.map +0 -1
  244. package/lib/components/SetRedirect.js.map +0 -1
  245. package/lib/components/SetRoute.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "piral-core",
3
- "version": "0.15.0-alpha.4036",
3
+ "version": "0.15.0-alpha.4041",
4
4
  "description": "The core library for creating a Piral instance.",
5
5
  "keywords": [
6
6
  "portal",
@@ -11,6 +11,18 @@
11
11
  "core",
12
12
  "functional"
13
13
  ],
14
+ "importmap": {
15
+ "imports": {
16
+ "react": "react",
17
+ "react-dom": "react-dom",
18
+ "react-router": "react-router",
19
+ "react-router-dom": "react-router-dom",
20
+ "history": "history",
21
+ "path-to-regexp": "path-to-regexp",
22
+ "@libre/atom": "@libre/atom",
23
+ "@dbeining/react-atom": "@dbeining/react-atom"
24
+ }
25
+ },
14
26
  "author": "smapiot",
15
27
  "homepage": "https://piral.io",
16
28
  "license": "MIT",
@@ -48,8 +60,8 @@
48
60
  },
49
61
  "dependencies": {
50
62
  "@dbeining/react-atom": "^4.0.0",
51
- "piral-base": "0.15.0-alpha.4036",
52
- "piral-debug-utils": "0.15.0-alpha.4036"
63
+ "piral-base": "0.15.0-alpha.4041",
64
+ "piral-debug-utils": "0.15.0-alpha.4041"
53
65
  },
54
66
  "peerDependencies": {
55
67
  "react": ">=16.8.0",
@@ -79,5 +91,5 @@
79
91
  "@libre/atom",
80
92
  "@dbeining/react-atom"
81
93
  ],
82
- "gitHead": "5bd5efc3af82380f20e25d821a0de8a88c16a670"
94
+ "gitHead": "3d305d88c72e3e05a44acbf240a38f6ad7b03959"
83
95
  }
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { act } from 'react-dom/test-utils';
3
3
  import { mount, ReactWrapper } from 'enzyme';
4
4
  import { Piral } from './Piral';
5
- import { PiralRouter } from './components';
5
+ import { RegisteredRouter } from './components';
6
6
  import { createInstance } from './createInstance';
7
7
 
8
8
  async function waitForComponentToPaint<P = {}>(wrapper: ReactWrapper<P>, amount = 0) {
@@ -16,13 +16,13 @@ describe('Piral Component', () => {
16
16
  it('renders the Piral instance with default settings', async () => {
17
17
  const node = mount(<Piral />);
18
18
  await waitForComponentToPaint(node);
19
- expect(node.find(PiralRouter).length).toBe(1);
19
+ expect(node.find(RegisteredRouter).length).toBe(1);
20
20
  });
21
21
 
22
22
  it('renders the Piral instance with custom settings', async () => {
23
23
  const instance = createInstance();
24
24
  const node = mount(<Piral instance={instance} />);
25
25
  await waitForComponentToPaint(node);
26
- expect(node.find(PiralRouter).length).toBe(1);
26
+ expect(node.find(RegisteredRouter).length).toBe(1);
27
27
  });
28
28
  });
package/src/Piral.tsx CHANGED
@@ -1,15 +1,23 @@
1
1
  import * as React from 'react';
2
- import { StateContext } from './state';
2
+ import { StaticRouter } from 'react-router';
3
3
  import { createInstance } from './createInstance';
4
- import { PiralView, Mediator, ResponsiveLayout, PortalRenderer } from './components';
5
- import { RootListener } from './RootListener';
4
+ import { PiralView, RegisteredRouter } from './components';
5
+ import { useGlobalState } from './hooks';
6
+ import { PiralContext } from './PiralContext';
6
7
  import type { PiralProps } from './types';
7
8
 
9
+ const FallbackRouter: React.FC = (props) => {
10
+ const publicPath = useGlobalState((s) => s.app.publicPath);
11
+ return <StaticRouter location="/" {...props} basename={publicPath} />;
12
+ };
13
+
14
+ const Router = typeof window === 'undefined' ? FallbackRouter : RegisteredRouter;
15
+
8
16
  /**
9
17
  * Represents the Piral app shell frame. Use this component together
10
18
  * with an existing instance to render the app shell.
11
- * Includes layout and routing handling. Wires the state container
12
- * to the generated views.
19
+ * Includes layout and routing handling. Connects the Piral context
20
+ * and the React router to the generated views.
13
21
  *
14
22
  * @example
15
23
  ```jsx
@@ -21,14 +29,10 @@ const app = (
21
29
  ```
22
30
  */
23
31
  export const Piral: React.FC<PiralProps> = ({ instance = createInstance(), breakpoints, children }) => (
24
- <StateContext.Provider value={instance.context}>
25
- <ResponsiveLayout breakpoints={breakpoints} />
26
- <Mediator options={instance.options} key={instance.id} />
27
- <RootListener />
28
- <PiralView>
29
- <PortalRenderer id="root" />
30
- {children}
31
- </PiralView>
32
- </StateContext.Provider>
32
+ <PiralContext instance={instance}>
33
+ <Router>
34
+ <PiralView breakpoints={breakpoints}>{children}</PiralView>
35
+ </Router>
36
+ </PiralContext>
33
37
  );
34
38
  Piral.displayName = 'Piral';
@@ -0,0 +1,39 @@
1
+ import * as React from 'react';
2
+ import { StateContext } from './state';
3
+ import { createInstance } from './createInstance';
4
+ import { Mediator } from './components';
5
+ import { useGlobalState } from './hooks';
6
+ import { RootListener } from './RootListener';
7
+ import type { PiralContextProps } from './types';
8
+
9
+ const PiralProvider: React.FC = ({ children }) => {
10
+ const Provider = useGlobalState((m) => m.provider || React.Fragment);
11
+ return <Provider>{children}</Provider>;
12
+ };
13
+
14
+ /**
15
+ * Represents the Piral app shell frame. Use this component together
16
+ * with an existing instance to render components from micro frontends
17
+ * in your app.
18
+ * Wires the state container together with the global providers.
19
+ *
20
+ * @example
21
+ ```jsx
22
+ const app = (
23
+ <MyRouter>
24
+ <PiralContext instance={yourPiralInstance}>
25
+ <PiralGlobals />
26
+ <MyAppContent />
27
+ </PiralContext>
28
+ </MyRouter>
29
+ );
30
+ ```
31
+ */
32
+ export const PiralContext: React.FC<PiralContextProps> = ({ instance = createInstance(), children }) => (
33
+ <StateContext.Provider value={instance.context}>
34
+ <Mediator options={instance.options} key={instance.id} />
35
+ <RootListener />
36
+ <PiralProvider>{children}</PiralProvider>
37
+ </StateContext.Provider>
38
+ );
39
+ PiralContext.displayName = 'PiralContext';
@@ -2,7 +2,6 @@ import { createElement } from 'react';
2
2
  import { Atom, deref } from '@dbeining/react-atom';
3
3
  import { createListener, Pilet } from 'piral-base';
4
4
  import {
5
- changeLayout,
6
5
  includeProvider,
7
6
  initialize,
8
7
  injectPilet,
@@ -23,23 +22,6 @@ const pilet: Pilet = {
23
22
  };
24
23
 
25
24
  describe('App Actions Module', () => {
26
- it('changeLayout changes the current layout', () => {
27
- const state = Atom.of({
28
- foo: 5,
29
- app: {
30
- layout: 'tablet',
31
- },
32
- });
33
- const ctx = createActions(state, createListener({}));
34
- changeLayout(ctx, 'mobile');
35
- expect(deref(state)).toEqual({
36
- foo: 5,
37
- app: {
38
- layout: 'mobile',
39
- },
40
- });
41
- });
42
-
43
25
  it('initialize initializes state data', () => {
44
26
  const state = Atom.of({
45
27
  app: {},
@@ -3,7 +3,6 @@ import { RouteComponentProps } from 'react-router';
3
3
  import { runPilet } from 'piral-base';
4
4
  import { withKey, replaceOrAddItem, removeNested, withProvider, withRoute, noop } from '../utils';
5
5
  import {
6
- LayoutType,
7
6
  ComponentsState,
8
7
  ErrorComponentsState,
9
8
  BaseRegistration,
@@ -13,13 +12,6 @@ import {
13
12
  PiletEntry,
14
13
  } from '../types';
15
14
 
16
- export function changeLayout(ctx: GlobalStateContext, current: LayoutType) {
17
- ctx.dispatch((state) => ({
18
- ...state,
19
- app: withKey(state.app, 'layout', current),
20
- }));
21
- }
22
-
23
15
  export function initialize(ctx: GlobalStateContext, loading: boolean, error: Error | undefined, modules: Array<Pilet>) {
24
16
  ctx.dispatch((state) => ({
25
17
  ...state,
@@ -1,8 +1,13 @@
1
1
  import { swap, deref } from '@dbeining/react-atom';
2
+ import { isSame } from '../utils';
2
3
  import { GlobalState, GlobalStateContext } from '../types';
3
4
 
5
+ function onlyChangedState(oldState: GlobalState, newState: GlobalState) {
6
+ return isSame(oldState, newState) ? oldState : newState;
7
+ }
8
+
4
9
  export function dispatch(ctx: GlobalStateContext, update: (state: GlobalState) => GlobalState) {
5
- swap(ctx.state, update);
10
+ swap(ctx.state, oldState => onlyChangedState(oldState, update(oldState)));
6
11
  }
7
12
 
8
13
  export function readState<S>(ctx: GlobalStateContext, read: (state: GlobalState) => S) {
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { PiralError, PiralLoadingIndicator } from './components';
2
+ import { RegisteredErrorInfo, RegisteredLoadingIndicator } from './components';
3
3
  import { Errors, PiletApi } from '../types';
4
4
 
5
5
  export interface ErrorBoundaryProps {
@@ -45,9 +45,9 @@ export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoun
45
45
 
46
46
  if (error) {
47
47
  const pilet = piral.meta.name;
48
- return <PiralError type={errorType} error={error} pilet={pilet} {...rest} />;
48
+ return <RegisteredErrorInfo type={errorType} error={error} pilet={pilet} {...rest} />;
49
49
  }
50
50
 
51
- return <React.Suspense fallback={<PiralLoadingIndicator />}>{children}</React.Suspense>;
51
+ return <React.Suspense fallback={<RegisteredLoadingIndicator />}>{children}</React.Suspense>;
52
52
  }
53
53
  }
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ import { PortalRenderer } from './PortalRenderer';
3
+ import { RegisteredDebug } from './components';
4
+
5
+ /**
6
+ * Integrates the global portal renderer and the debug utilities
7
+ * (if registered).
8
+ */
9
+ export const PiralGlobals: React.FC = () => {
10
+ return (
11
+ <>
12
+ <PortalRenderer id="root" />
13
+ <RegisteredDebug />
14
+ </>
15
+ );
16
+ };
@@ -2,8 +2,8 @@ import * as React from 'react';
2
2
  import * as hooks from '../hooks';
3
3
  import { MemoryRouter } from 'react-router';
4
4
  import { mount } from 'enzyme';
5
- import { DefaultRouteSwitch } from './DefaultRouteSwitch';
6
5
  import { PiralRoutes } from './PiralRoutes';
6
+ import { DefaultRouteSwitch } from '../defaults';
7
7
 
8
8
  const mountWithRouter = (node, url = '/') =>
9
9
  mount(
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ import { RegisteredErrorInfo, RegisteredLoadingIndicator } from './components';
3
+ import { useGlobalState } from '../hooks';
4
+
5
+ export const PiralSuspense: React.FC = ({ children }) => {
6
+ const { error, loading } = useGlobalState((m) => m.app);
7
+
8
+ return error ? (
9
+ <RegisteredErrorInfo type="loading" error={error} />
10
+ ) : loading ? (
11
+ <RegisteredLoadingIndicator />
12
+ ) : (
13
+ <>{children}</>
14
+ );
15
+ };
@@ -41,6 +41,7 @@ const state = {
41
41
  pages: {},
42
42
  extensions: {},
43
43
  },
44
+ portals: {},
44
45
  routes: {},
45
46
  provider: undefined,
46
47
  };
@@ -33,6 +33,7 @@ const state = {
33
33
  Router: StubRouter,
34
34
  Layout: StubLayout,
35
35
  },
36
+ portals: {},
36
37
  registry: {
37
38
  pages: {},
38
39
  extensions: {},
@@ -1,60 +1,37 @@
1
1
  import * as React from 'react';
2
- import { RouteComponentProps, StaticRouter } from 'react-router';
2
+ import { RouteComponentProps } from 'react-router';
3
+ import { PiralGlobals } from './PiralGlobals';
3
4
  import { PiralRoutes } from './PiralRoutes';
4
- import {
5
- PiralError,
6
- PiralRouter,
7
- PiralLoadingIndicator,
8
- PiralRouteSwitch,
9
- PiralLayout,
10
- PiralDebug,
11
- } from './components';
12
- import { useGlobalState } from '../hooks';
5
+ import { PiralSuspense } from './PiralSuspense';
6
+ import { ResponsiveLayout } from './ResponsiveLayout';
7
+ import { RegisteredErrorInfo, RegisteredRouteSwitch, RegisteredLayout } from './components';
8
+ import { LayoutBreakpoints } from '../types';
13
9
 
14
- const NotFound: React.FC<RouteComponentProps> = (props) => <PiralError type="not_found" {...props} />;
15
-
16
- const PiralContent: React.FC = () => {
17
- const { error, loading, layout } = useGlobalState((m) => m.app);
18
-
19
- return error ? (
20
- <PiralError type="loading" error={error} />
21
- ) : loading ? (
22
- <PiralLoadingIndicator />
23
- ) : (
24
- <PiralLayout currentLayout={layout}>
25
- <PiralRoutes NotFound={NotFound} RouteSwitch={PiralRouteSwitch} />
26
- </PiralLayout>
27
- );
28
- };
29
-
30
- const FallbackRouter: React.FC = (props) => {
31
- const publicPath = useGlobalState((s) => s.app.publicPath);
32
- return <StaticRouter location="/" {...props} basename={publicPath} />;
33
- };
34
-
35
- const Router = typeof window === 'undefined' ? FallbackRouter : PiralRouter;
36
-
37
- const PiralProvider: React.FC = ({ children }) => {
38
- const provider = useGlobalState((m) => m.provider) || React.Fragment;
39
- return React.createElement(provider, undefined, children);
40
- };
10
+ const NotFound: React.FC<RouteComponentProps> = (props) => <RegisteredErrorInfo type="not_found" {...props} />;
41
11
 
42
12
  /**
43
13
  * The props for the PiralView component.
44
14
  */
45
- export interface PiralViewProps { }
15
+ export interface PiralViewProps {
16
+ /**
17
+ * The custom breakpoints for the different layout modi.
18
+ */
19
+ breakpoints?: LayoutBreakpoints;
20
+ }
46
21
 
47
22
  /**
48
23
  * The component responsible for the generic view of the application.
49
- * This includes the global providers, the used Router, the current content and some convenience.
24
+ * This includes the used the current content and some convenience.
50
25
  */
51
- export const PiralView: React.FC<PiralViewProps> = ({ children }) => (
52
- <PiralProvider>
53
- <Router>
54
- <PiralContent />
55
- {children}
56
- <PiralDebug />
57
- </Router>
58
- </PiralProvider>
26
+ export const PiralView: React.FC<PiralViewProps> = ({ breakpoints, children }) => (
27
+ <>
28
+ <PiralGlobals />
29
+ <PiralSuspense>
30
+ <ResponsiveLayout breakpoints={breakpoints} Layout={RegisteredLayout}>
31
+ <PiralRoutes NotFound={NotFound} RouteSwitch={RegisteredRouteSwitch} />
32
+ </ResponsiveLayout>
33
+ </PiralSuspense>
34
+ {children}
35
+ </>
59
36
  );
60
37
  PiralView.displayName = 'PiralView';
@@ -6,25 +6,15 @@ import { defaultBreakpoints } from '../utils';
6
6
 
7
7
  jest.mock('../hooks');
8
8
 
9
- (hooks as any).useGlobalState = (select: any) =>
10
- select({
11
- app: {
12
- layout: 'desktop',
13
- },
14
- });
15
-
16
- const StubComponent: React.FC = () => <div />;
17
- StubComponent.displayName = 'StubComponent';
18
-
19
9
  describe('Responsive Module', () => {
20
10
  it('always renders the given children', () => {
21
- const changeTo = jest.fn();
22
- (hooks as any).useGlobalStateContext = () => ({
23
- changeLayout: changeTo,
24
- });
25
11
  (hooks as any).useMedia = () => 'desktop';
12
+ const Layout: React.FC = jest.fn().mockImplementation(({ children }) => <div>{children}</div>);
13
+ Layout.displayName = 'Layout';
14
+ const StubComponent: React.FC = () => <div />;
15
+ StubComponent.displayName = 'StubComponent';
26
16
  const node = mount(
27
- <ResponsiveLayout breakpoints={defaultBreakpoints}>
17
+ <ResponsiveLayout Layout={Layout} breakpoints={defaultBreakpoints}>
28
18
  <StubComponent />)
29
19
  </ResponsiveLayout>,
30
20
  );
@@ -32,42 +22,23 @@ describe('Responsive Module', () => {
32
22
  });
33
23
 
34
24
  it('does not call changeTo when nothing changed', () => {
35
- const changeTo = jest.fn();
36
- (hooks as any).useGlobalStateContext = () => ({
37
- changeLayout: changeTo,
38
- });
39
- (hooks as any).useMedia = () => 'desktop';
40
- mount(<ResponsiveLayout breakpoints={defaultBreakpoints} />);
41
- expect(changeTo).not.toHaveBeenCalled();
42
- });
43
-
44
- it('does not call changeTo when nothing changed', () => {
45
- const changeTo = jest.fn();
46
- (hooks as any).useGlobalStateContext = () => ({
47
- changeLayout: changeTo,
48
- });
49
25
  (hooks as any).useMedia = () => 'desktop';
50
- mount(<ResponsiveLayout breakpoints={defaultBreakpoints} />);
51
- expect(changeTo).not.toHaveBeenCalled();
26
+ const Layout = jest.fn().mockImplementation(({ children }) => <div>{children}</div>);
27
+ mount(<ResponsiveLayout Layout={Layout} breakpoints={defaultBreakpoints} />);
28
+ expect(Layout).toHaveBeenCalledWith({ currentLayout: 'desktop' }, {});
52
29
  });
53
30
 
54
31
  it('does calls changeTo when someething changed (desktop -> tablet)', () => {
55
- const changeTo = jest.fn();
56
- (hooks as any).useGlobalStateContext = () => ({
57
- changeLayout: changeTo,
58
- });
59
32
  (hooks as any).useMedia = () => 'tablet';
60
- mount(<ResponsiveLayout breakpoints={defaultBreakpoints} />);
61
- expect(changeTo).toHaveBeenCalledWith('tablet');
33
+ const Layout = jest.fn().mockImplementation(({ children }) => <div>{children}</div>);
34
+ mount(<ResponsiveLayout Layout={Layout} breakpoints={defaultBreakpoints} />);
35
+ expect(Layout).toHaveBeenCalledWith({ currentLayout: 'tablet' }, {});
62
36
  });
63
37
 
64
38
  it('does calls changeTo when someething changed (desktop -> mobile)', () => {
65
- const changeTo = jest.fn();
66
- (hooks as any).useGlobalStateContext = () => ({
67
- changeLayout: changeTo,
68
- });
69
39
  (hooks as any).useMedia = () => 'mobile';
70
- mount(<ResponsiveLayout breakpoints={defaultBreakpoints} />);
71
- expect(changeTo).toHaveBeenCalledWith('mobile');
40
+ const Layout = jest.fn().mockImplementation(({ children }) => <div>{children}</div>);
41
+ mount(<ResponsiveLayout Layout={Layout} breakpoints={defaultBreakpoints} />);
42
+ expect(Layout).toHaveBeenCalledWith({ currentLayout: 'mobile' }, {});
72
43
  });
73
44
  });
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
- import { useMedia, useGlobalState, useGlobalStateContext } from '../hooks';
3
- import { defaultLayouts, defaultRender, defaultBreakpoints } from '../utils';
4
- import { LayoutBreakpoints } from '../types';
2
+ import { useMedia } from '../hooks';
3
+ import { defaultLayouts, defaultBreakpoints } from '../utils';
4
+ import { LayoutBreakpoints, LayoutProps } from '../types';
5
5
 
6
6
  /**
7
7
  * The props for the ResponsiveLayout component.
@@ -11,22 +11,18 @@ export interface ResponsiveLayoutProps {
11
11
  * The individual breakpoints to be used for the different layouts.
12
12
  */
13
13
  breakpoints?: LayoutBreakpoints;
14
+ Layout: React.ComponentType<LayoutProps>;
14
15
  }
15
16
 
16
17
  /**
17
18
  * The component capable of identifying and switching the currently used layout.
18
19
  */
19
- export const ResponsiveLayout: React.FC<ResponsiveLayoutProps> = ({ breakpoints = defaultBreakpoints, children }) => {
20
- const current = useGlobalState((m) => m.app.layout) || 'desktop';
21
- const { changeLayout } = useGlobalStateContext();
22
- const selected = useMedia(breakpoints, defaultLayouts, current);
23
-
24
- React.useEffect(() => {
25
- if (selected !== current) {
26
- changeLayout(selected);
27
- }
28
- }, [selected]);
29
-
30
- return defaultRender(children);
20
+ export const ResponsiveLayout: React.FC<ResponsiveLayoutProps> = ({
21
+ breakpoints = defaultBreakpoints,
22
+ Layout,
23
+ children,
24
+ }) => {
25
+ const selected = useMedia(breakpoints, defaultLayouts, 'desktop');
26
+ return <Layout currentLayout={selected}>{children}</Layout>;
31
27
  };
32
28
  ResponsiveLayout.displayName = 'ResponsiveLayout';
@@ -2,6 +2,13 @@ import * as React from 'react';
2
2
  import { useGlobalState } from '../hooks';
3
3
  import { ComponentsState } from '../types';
4
4
 
5
+ /**
6
+ * Gets a registered layout component by its name.
7
+ * This will always return a valid component. If nothing is found
8
+ * then the returned component will just return null.
9
+ * @param name The name of the registered layout component.
10
+ * @returns The registered layout component or an empty stub component.
11
+ */
5
12
  export function getPiralComponent<TKey extends keyof ComponentsState>(name: TKey): ComponentsState[TKey] {
6
13
  return (props) => {
7
14
  const Component = useGlobalState((s) => s.components[name]);
@@ -14,34 +21,34 @@ export function getPiralComponent<TKey extends keyof ComponentsState>(name: TKey
14
21
  * Gets the currently registered ErrorInfo component.
15
22
  * By default the DefaultErrorInfo component is used.
16
23
  */
17
- export const PiralError = getPiralComponent('ErrorInfo');
24
+ export const RegisteredErrorInfo = getPiralComponent('ErrorInfo');
18
25
 
19
26
  /**
20
27
  * Gets the currently registered LoadingIndicator component.
21
28
  * By default only Loading is rendered.
22
29
  */
23
- export const PiralLoadingIndicator = getPiralComponent('LoadingIndicator');
30
+ export const RegisteredLoadingIndicator = getPiralComponent('LoadingIndicator');
24
31
 
25
32
  /**
26
33
  * Gets the currently registered Router component.
27
34
  * By default the BrowserRouter is used.
28
35
  */
29
- export const PiralRouter = getPiralComponent('Router');
36
+ export const RegisteredRouter = getPiralComponent('Router');
30
37
 
31
38
  /**
32
39
  * Gets the currently registered Route Switch component.
33
40
  * By default the DefaultRouteSwitch component is used.
34
41
  */
35
- export const PiralRouteSwitch = getPiralComponent('RouteSwitch');
42
+ export const RegisteredRouteSwitch = getPiralComponent('RouteSwitch');
36
43
 
37
44
  /**
38
45
  * Gets the currently registered Layout component.
39
46
  * By default the children are rendered.
40
47
  */
41
- export const PiralLayout = getPiralComponent('Layout');
48
+ export const RegisteredLayout = getPiralComponent('Layout');
42
49
 
43
50
  /**
44
51
  * Gets the currently registered Debug component.
45
52
  * By default nothing is used.
46
53
  */
47
- export const PiralDebug = getPiralComponent('Debug');
54
+ export const RegisteredDebug = getPiralComponent('Debug');
@@ -1,22 +1,12 @@
1
1
  export * from './components';
2
- export * from './DefaultErrorInfo';
3
- export * from './DefaultLayout';
4
- export * from './DefaultLoader';
5
- export * from './DefaultRouter';
6
- export * from './DefaultRouteSwitch';
7
2
  export * from './ErrorBoundary';
8
3
  export * from './ExtensionSlot';
9
4
  export * from './Mediator';
5
+ export * from './PiralGlobals';
10
6
  export * from './PiralRoutes';
7
+ export * from './PiralSuspense';
11
8
  export * from './PiralView';
12
9
  export * from './PortalRenderer';
13
10
  export * from './ResponsiveLayout';
14
- export * from './SetComponent';
15
- export * from './SetError';
16
- export * from './SetErrors';
17
- export * from './SetLayout';
18
- export * from './SetProvider';
19
- export * from './SetRedirect';
20
- export * from './SetRoute';
21
11
  export * from './SwitchErrorInfo';
22
12
  export * from './wrapComponent';
@@ -1,6 +1,5 @@
1
1
  import * as React from 'react';
2
- import { ExtensionSlot } from './ExtensionSlot';
3
- import { SwitchErrorInfo } from './SwitchErrorInfo';
2
+ import { ExtensionSlot, SwitchErrorInfo } from '../components';
4
3
  import { ErrorInfoProps } from '../types';
5
4
 
6
5
  /**
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
- import { LayoutProps } from '../types';
3
2
  import { defaultRender } from '../utils';
3
+ import { LayoutProps } from '../types';
4
4
 
5
5
  /**
6
6
  * The default layout only rendering the provided children.
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
- import { DefaultLoadingIndicator } from './DefaultLoader';
2
+ import { DefaultLoadingIndicator } from './DefaultLoadingIndicator';
3
3
  import { mount } from 'enzyme';
4
4
 
5
- describe('Default Loader Component', () => {
5
+ describe('Default Loading Indicator Component', () => {
6
6
  it('renders correctly', () => {
7
7
  const node = mount(<DefaultLoadingIndicator />);
8
8
  expect(node.find('div').length).toBe(1);
File without changes
@@ -0,0 +1,5 @@
1
+ export * from './DefaultErrorInfo';
2
+ export * from './DefaultLayout';
3
+ export * from './DefaultLoadingIndicator';
4
+ export * from './DefaultRouter';
5
+ export * from './DefaultRouteSwitch';