@tramvai/react 2.70.0 → 2.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/di/context.es.js +5 -0
- package/lib/di/context.js +9 -0
- package/lib/di/hoc.es.js +14 -0
- package/lib/di/hoc.js +22 -0
- package/lib/di/hooks.es.js +33 -0
- package/lib/di/hooks.js +42 -0
- package/lib/error/UniversalErrorBoundary.es.js +48 -0
- package/lib/error/UniversalErrorBoundary.js +52 -0
- package/lib/error/component.es.js +46 -0
- package/lib/error/component.js +48 -0
- package/lib/error/fallback.es.js +21 -0
- package/lib/error/fallback.js +25 -0
- package/lib/error/hoc.es.js +15 -0
- package/lib/error/hoc.js +23 -0
- package/lib/error/tokens.es.js +12 -0
- package/lib/error/tokens.js +18 -0
- package/lib/lazy/lazy.es.js +64 -0
- package/lib/lazy/lazy.js +75 -0
- package/lib/react.es.js +9 -226
- package/lib/react.js +28 -243
- package/package.json +6 -7
package/lib/di/hoc.es.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import hoistStatics from 'hoist-non-react-statics';
|
|
3
|
+
import { useDi } from './hooks.es.js';
|
|
4
|
+
|
|
5
|
+
const withDi = (deps) => (WrappedComponent) => {
|
|
6
|
+
function WrapperWithPropsFromDi(props) {
|
|
7
|
+
const depsInstance = useDi(deps);
|
|
8
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
9
|
+
return jsx(WrappedComponent, { ...props, ...depsInstance });
|
|
10
|
+
}
|
|
11
|
+
return hoistStatics(WrapperWithPropsFromDi, WrappedComponent);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export { withDi };
|
package/lib/di/hoc.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
var hoistStatics = require('hoist-non-react-statics');
|
|
7
|
+
var hooks = require('./hooks.js');
|
|
8
|
+
|
|
9
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
10
|
+
|
|
11
|
+
var hoistStatics__default = /*#__PURE__*/_interopDefaultLegacy(hoistStatics);
|
|
12
|
+
|
|
13
|
+
const withDi = (deps) => (WrappedComponent) => {
|
|
14
|
+
function WrapperWithPropsFromDi(props) {
|
|
15
|
+
const depsInstance = hooks.useDi(deps);
|
|
16
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
17
|
+
return jsxRuntime.jsx(WrappedComponent, { ...props, ...depsInstance });
|
|
18
|
+
}
|
|
19
|
+
return hoistStatics__default["default"](WrapperWithPropsFromDi, WrappedComponent);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
exports.withDi = withDi;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useContext, useMemo } from 'react';
|
|
2
|
+
import mapObj from '@tinkoff/utils/object/map';
|
|
3
|
+
import { DIContext } from './context.es.js';
|
|
4
|
+
|
|
5
|
+
const useDiContainer = () => {
|
|
6
|
+
const di = useContext(DIContext);
|
|
7
|
+
if (!di) {
|
|
8
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
9
|
+
throw new Error(`DI container not found, make sure that the application uses 'DIContext.Provider' from '@tramvai/react'
|
|
10
|
+
(in a tramvai application this is usually done by '@tramvai/module-render', otherwise 'DIContext.Provider' from '@tramvai/react' must be explicitly defined somewhere)
|
|
11
|
+
If the above is correct, make sure that the '@tramvai/react' module is not duplicated in the application dependencies, because then the di versions would be incompatible`);
|
|
12
|
+
}
|
|
13
|
+
throw new Error('DI container not found');
|
|
14
|
+
}
|
|
15
|
+
return di;
|
|
16
|
+
};
|
|
17
|
+
const isTokenObject = (token) => {
|
|
18
|
+
return ('token' in token &&
|
|
19
|
+
(Object.keys(token).length === 1 ||
|
|
20
|
+
typeof token.optional === 'boolean' ||
|
|
21
|
+
typeof token.multi === 'boolean'));
|
|
22
|
+
};
|
|
23
|
+
function useDi(deps) {
|
|
24
|
+
const di = useDiContainer();
|
|
25
|
+
return useMemo(() => {
|
|
26
|
+
if (deps.toString() !== '[object Object]' || isTokenObject(deps)) {
|
|
27
|
+
return di.get(deps);
|
|
28
|
+
}
|
|
29
|
+
return mapObj((dep) => di.get(dep), deps);
|
|
30
|
+
}, [deps, di]);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { useDi, useDiContainer };
|
package/lib/di/hooks.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var react = require('react');
|
|
6
|
+
var mapObj = require('@tinkoff/utils/object/map');
|
|
7
|
+
var context = require('./context.js');
|
|
8
|
+
|
|
9
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
10
|
+
|
|
11
|
+
var mapObj__default = /*#__PURE__*/_interopDefaultLegacy(mapObj);
|
|
12
|
+
|
|
13
|
+
const useDiContainer = () => {
|
|
14
|
+
const di = react.useContext(context.DIContext);
|
|
15
|
+
if (!di) {
|
|
16
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
17
|
+
throw new Error(`DI container not found, make sure that the application uses 'DIContext.Provider' from '@tramvai/react'
|
|
18
|
+
(in a tramvai application this is usually done by '@tramvai/module-render', otherwise 'DIContext.Provider' from '@tramvai/react' must be explicitly defined somewhere)
|
|
19
|
+
If the above is correct, make sure that the '@tramvai/react' module is not duplicated in the application dependencies, because then the di versions would be incompatible`);
|
|
20
|
+
}
|
|
21
|
+
throw new Error('DI container not found');
|
|
22
|
+
}
|
|
23
|
+
return di;
|
|
24
|
+
};
|
|
25
|
+
const isTokenObject = (token) => {
|
|
26
|
+
return ('token' in token &&
|
|
27
|
+
(Object.keys(token).length === 1 ||
|
|
28
|
+
typeof token.optional === 'boolean' ||
|
|
29
|
+
typeof token.multi === 'boolean'));
|
|
30
|
+
};
|
|
31
|
+
function useDi(deps) {
|
|
32
|
+
const di = useDiContainer();
|
|
33
|
+
return react.useMemo(() => {
|
|
34
|
+
if (deps.toString() !== '[object Object]' || isTokenObject(deps)) {
|
|
35
|
+
return di.get(deps);
|
|
36
|
+
}
|
|
37
|
+
return mapObj__default["default"]((dep) => di.get(dep), deps);
|
|
38
|
+
}, [deps, di]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
exports.useDi = useDi;
|
|
42
|
+
exports.useDiContainer = useDiContainer;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Component } from 'react';
|
|
3
|
+
import { FallbackError } from './fallback.es.js';
|
|
4
|
+
|
|
5
|
+
class UniversalErrorBoundary extends Component {
|
|
6
|
+
constructor(props) {
|
|
7
|
+
super(props);
|
|
8
|
+
this.state = {
|
|
9
|
+
error: props.error || null,
|
|
10
|
+
url: props.url,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
// Reference and explanation here - https://github.com/remix-run/remix/blob/main/packages/remix-react/errorBoundaries.tsx#L35
|
|
14
|
+
static getDerivedStateFromProps(props, state) {
|
|
15
|
+
if (props.url !== state.url) {
|
|
16
|
+
return { error: props.error || null, url: props.url };
|
|
17
|
+
}
|
|
18
|
+
return { error: props.error || state.error, url: state.url };
|
|
19
|
+
}
|
|
20
|
+
static getDerivedStateFromError(error) {
|
|
21
|
+
return { error };
|
|
22
|
+
}
|
|
23
|
+
componentDidCatch(error, errorInfo) {
|
|
24
|
+
const { errorHandlers } = this.props;
|
|
25
|
+
if (errorHandlers) {
|
|
26
|
+
errorHandlers.forEach((handler) => {
|
|
27
|
+
handler(error, errorInfo);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
render() {
|
|
32
|
+
const { children, fallback: Fallback, fallbackFromDi } = this.props;
|
|
33
|
+
const { url, error } = this.state;
|
|
34
|
+
if (!error) {
|
|
35
|
+
return children;
|
|
36
|
+
}
|
|
37
|
+
if (Fallback) {
|
|
38
|
+
return jsx(Fallback, { url: url, error: error });
|
|
39
|
+
}
|
|
40
|
+
if (fallbackFromDi) {
|
|
41
|
+
return fallbackFromDi;
|
|
42
|
+
}
|
|
43
|
+
return jsx(FallbackError, {});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
UniversalErrorBoundary.displayName = 'UniversalErrorBoundary';
|
|
47
|
+
|
|
48
|
+
export { UniversalErrorBoundary };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
var react = require('react');
|
|
7
|
+
var fallback = require('./fallback.js');
|
|
8
|
+
|
|
9
|
+
class UniversalErrorBoundary extends react.Component {
|
|
10
|
+
constructor(props) {
|
|
11
|
+
super(props);
|
|
12
|
+
this.state = {
|
|
13
|
+
error: props.error || null,
|
|
14
|
+
url: props.url,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
// Reference and explanation here - https://github.com/remix-run/remix/blob/main/packages/remix-react/errorBoundaries.tsx#L35
|
|
18
|
+
static getDerivedStateFromProps(props, state) {
|
|
19
|
+
if (props.url !== state.url) {
|
|
20
|
+
return { error: props.error || null, url: props.url };
|
|
21
|
+
}
|
|
22
|
+
return { error: props.error || state.error, url: state.url };
|
|
23
|
+
}
|
|
24
|
+
static getDerivedStateFromError(error) {
|
|
25
|
+
return { error };
|
|
26
|
+
}
|
|
27
|
+
componentDidCatch(error, errorInfo) {
|
|
28
|
+
const { errorHandlers } = this.props;
|
|
29
|
+
if (errorHandlers) {
|
|
30
|
+
errorHandlers.forEach((handler) => {
|
|
31
|
+
handler(error, errorInfo);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
render() {
|
|
36
|
+
const { children, fallback: Fallback, fallbackFromDi } = this.props;
|
|
37
|
+
const { url, error } = this.state;
|
|
38
|
+
if (!error) {
|
|
39
|
+
return children;
|
|
40
|
+
}
|
|
41
|
+
if (Fallback) {
|
|
42
|
+
return jsxRuntime.jsx(Fallback, { url: url, error: error });
|
|
43
|
+
}
|
|
44
|
+
if (fallbackFromDi) {
|
|
45
|
+
return fallbackFromDi;
|
|
46
|
+
}
|
|
47
|
+
return jsxRuntime.jsx(fallback.FallbackError, {});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
UniversalErrorBoundary.displayName = 'UniversalErrorBoundary';
|
|
51
|
+
|
|
52
|
+
exports.UniversalErrorBoundary = UniversalErrorBoundary;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { __decorate } from 'tslib';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { Component } from 'react';
|
|
4
|
+
import { withDi } from '../di/hoc.es.js';
|
|
5
|
+
import { FallbackError } from './fallback.es.js';
|
|
6
|
+
import { ERROR_BOUNDARY_TOKEN, ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN } from './tokens.es.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Use UniversalErrorBoundary component
|
|
10
|
+
*/
|
|
11
|
+
let ErrorBoundary = class ErrorBoundary extends Component {
|
|
12
|
+
constructor(props) {
|
|
13
|
+
super(props);
|
|
14
|
+
this.state = {
|
|
15
|
+
hasError: false,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
static getDerivedStateFromError() {
|
|
19
|
+
return { hasError: true };
|
|
20
|
+
}
|
|
21
|
+
componentDidCatch(error, errorInfo) {
|
|
22
|
+
const { errorHandlers } = this.props;
|
|
23
|
+
if (errorHandlers) {
|
|
24
|
+
errorHandlers.forEach((handler) => {
|
|
25
|
+
handler(error, errorInfo);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
render() {
|
|
30
|
+
const { children, fallbackComponent, fallbackComponentFromDi } = this.props;
|
|
31
|
+
const { hasError } = this.state;
|
|
32
|
+
if (!hasError) {
|
|
33
|
+
return children;
|
|
34
|
+
}
|
|
35
|
+
return fallbackComponent || fallbackComponentFromDi || jsx(FallbackError, {});
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
ErrorBoundary.displayName = 'ErrorBoundary';
|
|
39
|
+
ErrorBoundary = __decorate([
|
|
40
|
+
withDi({
|
|
41
|
+
errorHandlers: { token: ERROR_BOUNDARY_TOKEN, optional: true },
|
|
42
|
+
fallbackComponentFromDi: { token: ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN, optional: true },
|
|
43
|
+
})
|
|
44
|
+
], ErrorBoundary);
|
|
45
|
+
|
|
46
|
+
export { ErrorBoundary };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tslib = require('tslib');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
var react = require('react');
|
|
8
|
+
var hoc = require('../di/hoc.js');
|
|
9
|
+
var fallback = require('./fallback.js');
|
|
10
|
+
var tokens = require('./tokens.js');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated Use UniversalErrorBoundary component
|
|
14
|
+
*/
|
|
15
|
+
exports.ErrorBoundary = class ErrorBoundary extends react.Component {
|
|
16
|
+
constructor(props) {
|
|
17
|
+
super(props);
|
|
18
|
+
this.state = {
|
|
19
|
+
hasError: false,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
static getDerivedStateFromError() {
|
|
23
|
+
return { hasError: true };
|
|
24
|
+
}
|
|
25
|
+
componentDidCatch(error, errorInfo) {
|
|
26
|
+
const { errorHandlers } = this.props;
|
|
27
|
+
if (errorHandlers) {
|
|
28
|
+
errorHandlers.forEach((handler) => {
|
|
29
|
+
handler(error, errorInfo);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
render() {
|
|
34
|
+
const { children, fallbackComponent, fallbackComponentFromDi } = this.props;
|
|
35
|
+
const { hasError } = this.state;
|
|
36
|
+
if (!hasError) {
|
|
37
|
+
return children;
|
|
38
|
+
}
|
|
39
|
+
return fallbackComponent || fallbackComponentFromDi || jsxRuntime.jsx(fallback.FallbackError, {});
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
exports.ErrorBoundary.displayName = 'ErrorBoundary';
|
|
43
|
+
exports.ErrorBoundary = tslib.__decorate([
|
|
44
|
+
hoc.withDi({
|
|
45
|
+
errorHandlers: { token: tokens.ERROR_BOUNDARY_TOKEN, optional: true },
|
|
46
|
+
fallbackComponentFromDi: { token: tokens.ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN, optional: true },
|
|
47
|
+
})
|
|
48
|
+
], exports.ErrorBoundary);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
const FallbackError = () => {
|
|
4
|
+
return (jsxs("div", { children: [jsx("div", { style: {
|
|
5
|
+
textAlign: 'center',
|
|
6
|
+
marginBottom: 11,
|
|
7
|
+
paddingTop: 26,
|
|
8
|
+
fontSize: 30,
|
|
9
|
+
lineHeight: '36px',
|
|
10
|
+
fontWeight: 200,
|
|
11
|
+
}, children: "An error occurred :(" }), jsxs("div", { style: {
|
|
12
|
+
textAlign: 'center',
|
|
13
|
+
marginBottom: 17,
|
|
14
|
+
color: '#9299a2',
|
|
15
|
+
fontSize: 20,
|
|
16
|
+
lineHeight: '24px',
|
|
17
|
+
}, children: ["Try", ' ', jsx("a", { href: "", onClick: () => window.location.reload(), children: "reloading the page" })] })] }));
|
|
18
|
+
};
|
|
19
|
+
FallbackError.displayName = 'FallbackError';
|
|
20
|
+
|
|
21
|
+
export { FallbackError };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
const FallbackError = () => {
|
|
8
|
+
return (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("div", { style: {
|
|
9
|
+
textAlign: 'center',
|
|
10
|
+
marginBottom: 11,
|
|
11
|
+
paddingTop: 26,
|
|
12
|
+
fontSize: 30,
|
|
13
|
+
lineHeight: '36px',
|
|
14
|
+
fontWeight: 200,
|
|
15
|
+
}, children: "An error occurred :(" }), jsxRuntime.jsxs("div", { style: {
|
|
16
|
+
textAlign: 'center',
|
|
17
|
+
marginBottom: 17,
|
|
18
|
+
color: '#9299a2',
|
|
19
|
+
fontSize: 20,
|
|
20
|
+
lineHeight: '24px',
|
|
21
|
+
}, children: ["Try", ' ', jsxRuntime.jsx("a", { href: "", onClick: () => window.location.reload(), children: "reloading the page" })] })] }));
|
|
22
|
+
};
|
|
23
|
+
FallbackError.displayName = 'FallbackError';
|
|
24
|
+
|
|
25
|
+
exports.FallbackError = FallbackError;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import hoistStatics from 'hoist-non-react-statics';
|
|
3
|
+
import { ErrorBoundary } from './component.es.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated Use UniversalErrorBoundary component
|
|
7
|
+
*/
|
|
8
|
+
const withError = ({ fallbackComponent } = {}) => (WrappedComponent) => {
|
|
9
|
+
function WrapperWithError(props) {
|
|
10
|
+
return (jsx(ErrorBoundary, { fallbackComponent: fallbackComponent, children: jsx(WrappedComponent, { ...props }) }));
|
|
11
|
+
}
|
|
12
|
+
return hoistStatics(WrapperWithError, WrappedComponent);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { withError };
|
package/lib/error/hoc.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
var hoistStatics = require('hoist-non-react-statics');
|
|
7
|
+
var component = require('./component.js');
|
|
8
|
+
|
|
9
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
10
|
+
|
|
11
|
+
var hoistStatics__default = /*#__PURE__*/_interopDefaultLegacy(hoistStatics);
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @deprecated Use UniversalErrorBoundary component
|
|
15
|
+
*/
|
|
16
|
+
const withError = ({ fallbackComponent } = {}) => (WrappedComponent) => {
|
|
17
|
+
function WrapperWithError(props) {
|
|
18
|
+
return (jsxRuntime.jsx(component.ErrorBoundary, { fallbackComponent: fallbackComponent, children: jsxRuntime.jsx(WrappedComponent, { ...props }) }));
|
|
19
|
+
}
|
|
20
|
+
return hoistStatics__default["default"](WrapperWithError, WrappedComponent);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
exports.withError = withError;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createToken } from '@tinkoff/dippy';
|
|
2
|
+
|
|
3
|
+
const ERROR_BOUNDARY_TOKEN = createToken('reactErrorBoundaryHandlers', {
|
|
4
|
+
multi: true,
|
|
5
|
+
});
|
|
6
|
+
const ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN = createToken('rootErrorBoundaryComponent');
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated
|
|
9
|
+
*/
|
|
10
|
+
const ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN = createToken('errorBoundaryFallbackComponent');
|
|
11
|
+
|
|
12
|
+
export { ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN, ERROR_BOUNDARY_TOKEN, ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var dippy = require('@tinkoff/dippy');
|
|
6
|
+
|
|
7
|
+
const ERROR_BOUNDARY_TOKEN = dippy.createToken('reactErrorBoundaryHandlers', {
|
|
8
|
+
multi: true,
|
|
9
|
+
});
|
|
10
|
+
const ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN = dippy.createToken('rootErrorBoundaryComponent');
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated
|
|
13
|
+
*/
|
|
14
|
+
const ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN = dippy.createToken('errorBoundaryFallbackComponent');
|
|
15
|
+
|
|
16
|
+
exports.ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN = ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN;
|
|
17
|
+
exports.ERROR_BOUNDARY_TOKEN = ERROR_BOUNDARY_TOKEN;
|
|
18
|
+
exports.ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN = ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import hoistStatics from 'hoist-non-react-statics';
|
|
2
|
+
import loadable from '@loadable/component';
|
|
3
|
+
|
|
4
|
+
const resolveLazyComponent = async (componentOrLoader) => {
|
|
5
|
+
if (!componentOrLoader) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
if ('load' in componentOrLoader && typeof componentOrLoader.load === 'function') {
|
|
9
|
+
const mod = await componentOrLoader.load();
|
|
10
|
+
let component;
|
|
11
|
+
if (mod.__esModule) {
|
|
12
|
+
component = mod.default;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
component = mod.default || mod;
|
|
16
|
+
}
|
|
17
|
+
// manually hoist static properties from preloaded component to loadable wrapper,
|
|
18
|
+
// this open access to current page component static properties outside before rendering
|
|
19
|
+
hoistStatics(componentOrLoader, component);
|
|
20
|
+
return component;
|
|
21
|
+
}
|
|
22
|
+
return componentOrLoader;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* @private Only for internal usage!
|
|
26
|
+
* The method is intended to make it possible to wait for retries to synchronously load unsuccessful CSS assets
|
|
27
|
+
*/
|
|
28
|
+
const __lazyErrorHandler = (error, load) => {
|
|
29
|
+
// This error from `mini-css-extract-plugin` fired, when a file loading initiated by this plugin failed.
|
|
30
|
+
// By default, this error will cancel the loading of the component via `loadable`.
|
|
31
|
+
// Now, we can add `__lazyErrorHandler` to catch block of any dynamic import,
|
|
32
|
+
// and if failed assets was loaded again, `loadable` will not fail
|
|
33
|
+
if ((error === null || error === void 0 ? void 0 : error.code) === 'CSS_CHUNK_LOAD_FAILED') {
|
|
34
|
+
const failedLinkUrl = error.request;
|
|
35
|
+
// `mini-css-extract-plugin` instantly removes failed link tags,
|
|
36
|
+
// so we can expect only link tag from our recovery mechanism
|
|
37
|
+
const fallbackLinkTag = document.querySelector(`link[href="${failedLinkUrl}"]`) ||
|
|
38
|
+
document.querySelector(`link[data-href="${failedLinkUrl}"]`);
|
|
39
|
+
if (fallbackLinkTag) {
|
|
40
|
+
return load();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
throw error;
|
|
44
|
+
};
|
|
45
|
+
const lazy = (load, options = {}) => {
|
|
46
|
+
if (process.env.NODE_ENV === 'development') {
|
|
47
|
+
if (!('requireAsync' in load)) {
|
|
48
|
+
console.error(`Lazy import was not processed by lazy-component babel plugin.
|
|
49
|
+
Check lazy helper usage, expected signature is "lazy(() => import('./path/to/component'))",
|
|
50
|
+
the first argument should be transformed into a special object, but the current value is
|
|
51
|
+
"${load.toString()}"`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// @ts-expect-error
|
|
55
|
+
const originalImportAsync = load.importAsync;
|
|
56
|
+
// @ts-expect-error
|
|
57
|
+
// eslint-disable-next-line no-param-reassign
|
|
58
|
+
load.importAsync = () => originalImportAsync().catch((e) => __lazyErrorHandler(e, originalImportAsync));
|
|
59
|
+
return loadable(load, {
|
|
60
|
+
fallback: options.loading,
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export { __lazyErrorHandler, lazy, resolveLazyComponent };
|
package/lib/lazy/lazy.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var hoistStatics = require('hoist-non-react-statics');
|
|
6
|
+
var loadable = require('@loadable/component');
|
|
7
|
+
|
|
8
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
9
|
+
|
|
10
|
+
var hoistStatics__default = /*#__PURE__*/_interopDefaultLegacy(hoistStatics);
|
|
11
|
+
var loadable__default = /*#__PURE__*/_interopDefaultLegacy(loadable);
|
|
12
|
+
|
|
13
|
+
const resolveLazyComponent = async (componentOrLoader) => {
|
|
14
|
+
if (!componentOrLoader) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if ('load' in componentOrLoader && typeof componentOrLoader.load === 'function') {
|
|
18
|
+
const mod = await componentOrLoader.load();
|
|
19
|
+
let component;
|
|
20
|
+
if (mod.__esModule) {
|
|
21
|
+
component = mod.default;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
component = mod.default || mod;
|
|
25
|
+
}
|
|
26
|
+
// manually hoist static properties from preloaded component to loadable wrapper,
|
|
27
|
+
// this open access to current page component static properties outside before rendering
|
|
28
|
+
hoistStatics__default["default"](componentOrLoader, component);
|
|
29
|
+
return component;
|
|
30
|
+
}
|
|
31
|
+
return componentOrLoader;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* @private Only for internal usage!
|
|
35
|
+
* The method is intended to make it possible to wait for retries to synchronously load unsuccessful CSS assets
|
|
36
|
+
*/
|
|
37
|
+
const __lazyErrorHandler = (error, load) => {
|
|
38
|
+
// This error from `mini-css-extract-plugin` fired, when a file loading initiated by this plugin failed.
|
|
39
|
+
// By default, this error will cancel the loading of the component via `loadable`.
|
|
40
|
+
// Now, we can add `__lazyErrorHandler` to catch block of any dynamic import,
|
|
41
|
+
// and if failed assets was loaded again, `loadable` will not fail
|
|
42
|
+
if ((error === null || error === void 0 ? void 0 : error.code) === 'CSS_CHUNK_LOAD_FAILED') {
|
|
43
|
+
const failedLinkUrl = error.request;
|
|
44
|
+
// `mini-css-extract-plugin` instantly removes failed link tags,
|
|
45
|
+
// so we can expect only link tag from our recovery mechanism
|
|
46
|
+
const fallbackLinkTag = document.querySelector(`link[href="${failedLinkUrl}"]`) ||
|
|
47
|
+
document.querySelector(`link[data-href="${failedLinkUrl}"]`);
|
|
48
|
+
if (fallbackLinkTag) {
|
|
49
|
+
return load();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
throw error;
|
|
53
|
+
};
|
|
54
|
+
const lazy = (load, options = {}) => {
|
|
55
|
+
if (process.env.NODE_ENV === 'development') {
|
|
56
|
+
if (!('requireAsync' in load)) {
|
|
57
|
+
console.error(`Lazy import was not processed by lazy-component babel plugin.
|
|
58
|
+
Check lazy helper usage, expected signature is "lazy(() => import('./path/to/component'))",
|
|
59
|
+
the first argument should be transformed into a special object, but the current value is
|
|
60
|
+
"${load.toString()}"`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// @ts-expect-error
|
|
64
|
+
const originalImportAsync = load.importAsync;
|
|
65
|
+
// @ts-expect-error
|
|
66
|
+
// eslint-disable-next-line no-param-reassign
|
|
67
|
+
load.importAsync = () => originalImportAsync().catch((e) => __lazyErrorHandler(e, originalImportAsync));
|
|
68
|
+
return loadable__default["default"](load, {
|
|
69
|
+
fallback: options.loading,
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
exports.__lazyErrorHandler = __lazyErrorHandler;
|
|
74
|
+
exports.lazy = lazy;
|
|
75
|
+
exports.resolveLazyComponent = resolveLazyComponent;
|
package/lib/react.es.js
CHANGED
|
@@ -1,226 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const useDiContainer = () => {
|
|
12
|
-
const di = useContext(DIContext);
|
|
13
|
-
if (!di) {
|
|
14
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
15
|
-
throw new Error(`DI container not found, make sure that the application uses 'DIContext.Provider' from '@tramvai/react'
|
|
16
|
-
(in a tramvai application this is usually done by '@tramvai/module-render', otherwise 'DIContext.Provider' from '@tramvai/react' must be explicitly defined somewhere)
|
|
17
|
-
If the above is correct, make sure that the '@tramvai/react' module is not duplicated in the application dependencies, because then the di versions would be incompatible`);
|
|
18
|
-
}
|
|
19
|
-
throw new Error('DI container not found');
|
|
20
|
-
}
|
|
21
|
-
return di;
|
|
22
|
-
};
|
|
23
|
-
const isTokenObject = (token) => {
|
|
24
|
-
return ('token' in token &&
|
|
25
|
-
(Object.keys(token).length === 1 ||
|
|
26
|
-
typeof token.optional === 'boolean' ||
|
|
27
|
-
typeof token.multi === 'boolean'));
|
|
28
|
-
};
|
|
29
|
-
function useDi(deps) {
|
|
30
|
-
const di = useDiContainer();
|
|
31
|
-
return useMemo(() => {
|
|
32
|
-
if (deps.toString() !== '[object Object]' || isTokenObject(deps)) {
|
|
33
|
-
return di.get(deps);
|
|
34
|
-
}
|
|
35
|
-
return mapObj((dep) => di.get(dep), deps);
|
|
36
|
-
}, [deps, di]);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const withDi = (deps) => (WrappedComponent) => {
|
|
40
|
-
function WrapperWithPropsFromDi(props) {
|
|
41
|
-
const depsInstance = useDi(deps);
|
|
42
|
-
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
43
|
-
return jsx(WrappedComponent, { ...props, ...depsInstance });
|
|
44
|
-
}
|
|
45
|
-
return hoistStatics(WrapperWithPropsFromDi, WrappedComponent);
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const FallbackError = () => {
|
|
49
|
-
return (jsxs("div", { children: [jsx("div", { style: {
|
|
50
|
-
textAlign: 'center',
|
|
51
|
-
marginBottom: 11,
|
|
52
|
-
paddingTop: 26,
|
|
53
|
-
fontSize: 30,
|
|
54
|
-
lineHeight: '36px',
|
|
55
|
-
fontWeight: 200,
|
|
56
|
-
}, children: "An error occurred :(" }), jsxs("div", { style: {
|
|
57
|
-
textAlign: 'center',
|
|
58
|
-
marginBottom: 17,
|
|
59
|
-
color: '#9299a2',
|
|
60
|
-
fontSize: 20,
|
|
61
|
-
lineHeight: '24px',
|
|
62
|
-
}, children: ["Try", ' ', jsx("a", { href: "", onClick: () => window.location.reload(), children: "reloading the page" })] })] }));
|
|
63
|
-
};
|
|
64
|
-
FallbackError.displayName = 'FallbackError';
|
|
65
|
-
|
|
66
|
-
class UniversalErrorBoundary extends Component {
|
|
67
|
-
constructor(props) {
|
|
68
|
-
super(props);
|
|
69
|
-
this.state = {
|
|
70
|
-
error: props.error || null,
|
|
71
|
-
url: props.url,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
// Reference and explanation here - https://github.com/remix-run/remix/blob/main/packages/remix-react/errorBoundaries.tsx#L35
|
|
75
|
-
static getDerivedStateFromProps(props, state) {
|
|
76
|
-
if (props.url !== state.url) {
|
|
77
|
-
return { error: props.error || null, url: props.url };
|
|
78
|
-
}
|
|
79
|
-
return { error: props.error || state.error, url: state.url };
|
|
80
|
-
}
|
|
81
|
-
static getDerivedStateFromError(error) {
|
|
82
|
-
return { error };
|
|
83
|
-
}
|
|
84
|
-
componentDidCatch(error, errorInfo) {
|
|
85
|
-
const { errorHandlers } = this.props;
|
|
86
|
-
if (errorHandlers) {
|
|
87
|
-
errorHandlers.forEach((handler) => {
|
|
88
|
-
handler(error, errorInfo);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
render() {
|
|
93
|
-
const { children, fallback: Fallback, fallbackFromDi } = this.props;
|
|
94
|
-
const { url, error } = this.state;
|
|
95
|
-
if (!error) {
|
|
96
|
-
return children;
|
|
97
|
-
}
|
|
98
|
-
if (Fallback) {
|
|
99
|
-
return jsx(Fallback, { url: url, error: error });
|
|
100
|
-
}
|
|
101
|
-
if (fallbackFromDi) {
|
|
102
|
-
return fallbackFromDi;
|
|
103
|
-
}
|
|
104
|
-
return jsx(FallbackError, {});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
UniversalErrorBoundary.displayName = 'UniversalErrorBoundary';
|
|
108
|
-
|
|
109
|
-
const ERROR_BOUNDARY_TOKEN = createToken('reactErrorBoundaryHandlers', {
|
|
110
|
-
multi: true,
|
|
111
|
-
});
|
|
112
|
-
const ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN = createToken('rootErrorBoundaryComponent');
|
|
113
|
-
/**
|
|
114
|
-
* @deprecated
|
|
115
|
-
*/
|
|
116
|
-
const ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN = createToken('errorBoundaryFallbackComponent');
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* @deprecated Use UniversalErrorBoundary component
|
|
120
|
-
*/
|
|
121
|
-
let ErrorBoundary = class ErrorBoundary extends Component {
|
|
122
|
-
constructor(props) {
|
|
123
|
-
super(props);
|
|
124
|
-
this.state = {
|
|
125
|
-
hasError: false,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
static getDerivedStateFromError() {
|
|
129
|
-
return { hasError: true };
|
|
130
|
-
}
|
|
131
|
-
componentDidCatch(error, errorInfo) {
|
|
132
|
-
const { errorHandlers } = this.props;
|
|
133
|
-
if (errorHandlers) {
|
|
134
|
-
errorHandlers.forEach((handler) => {
|
|
135
|
-
handler(error, errorInfo);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
render() {
|
|
140
|
-
const { children, fallbackComponent, fallbackComponentFromDi } = this.props;
|
|
141
|
-
const { hasError } = this.state;
|
|
142
|
-
if (!hasError) {
|
|
143
|
-
return children;
|
|
144
|
-
}
|
|
145
|
-
return fallbackComponent || fallbackComponentFromDi || jsx(FallbackError, {});
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
ErrorBoundary.displayName = 'ErrorBoundary';
|
|
149
|
-
ErrorBoundary = __decorate([
|
|
150
|
-
withDi({
|
|
151
|
-
errorHandlers: { token: ERROR_BOUNDARY_TOKEN, optional: true },
|
|
152
|
-
fallbackComponentFromDi: { token: ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN, optional: true },
|
|
153
|
-
})
|
|
154
|
-
], ErrorBoundary);
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* @deprecated Use UniversalErrorBoundary component
|
|
158
|
-
*/
|
|
159
|
-
const withError = ({ fallbackComponent } = {}) => (WrappedComponent) => {
|
|
160
|
-
function WrapperWithError(props) {
|
|
161
|
-
return (jsx(ErrorBoundary, { fallbackComponent: fallbackComponent, children: jsx(WrappedComponent, { ...props }) }));
|
|
162
|
-
}
|
|
163
|
-
return hoistStatics(WrapperWithError, WrappedComponent);
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
const resolveLazyComponent = async (componentOrLoader) => {
|
|
167
|
-
if (!componentOrLoader) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
if ('load' in componentOrLoader && typeof componentOrLoader.load === 'function') {
|
|
171
|
-
const mod = await componentOrLoader.load();
|
|
172
|
-
let component;
|
|
173
|
-
if (mod.__esModule) {
|
|
174
|
-
component = mod.default;
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
component = mod.default || mod;
|
|
178
|
-
}
|
|
179
|
-
// manually hoist static properties from preloaded component to loadable wrapper,
|
|
180
|
-
// this open access to current page component static properties outside before rendering
|
|
181
|
-
hoistStatics(componentOrLoader, component);
|
|
182
|
-
return component;
|
|
183
|
-
}
|
|
184
|
-
return componentOrLoader;
|
|
185
|
-
};
|
|
186
|
-
/**
|
|
187
|
-
* @private Only for internal usage!
|
|
188
|
-
* The method is intended to make it possible to wait for retries to synchronously load unsuccessful CSS assets
|
|
189
|
-
*/
|
|
190
|
-
const __lazyErrorHandler = (error, load) => {
|
|
191
|
-
// This error from `mini-css-extract-plugin` fired, when a file loading initiated by this plugin failed.
|
|
192
|
-
// By default, this error will cancel the loading of the component via `loadable`.
|
|
193
|
-
// Now, we can add `__lazyErrorHandler` to catch block of any dynamic import,
|
|
194
|
-
// and if failed assets was loaded again, `loadable` will not fail
|
|
195
|
-
if ((error === null || error === void 0 ? void 0 : error.code) === 'CSS_CHUNK_LOAD_FAILED') {
|
|
196
|
-
const failedLinkUrl = error.request;
|
|
197
|
-
// `mini-css-extract-plugin` instantly removes failed link tags,
|
|
198
|
-
// so we can expect only link tag from our recovery mechanism
|
|
199
|
-
const fallbackLinkTag = document.querySelector(`link[href="${failedLinkUrl}"]`) ||
|
|
200
|
-
document.querySelector(`link[data-href="${failedLinkUrl}"]`);
|
|
201
|
-
if (fallbackLinkTag) {
|
|
202
|
-
return load();
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
throw error;
|
|
206
|
-
};
|
|
207
|
-
const lazy = (load, options = {}) => {
|
|
208
|
-
if (process.env.NODE_ENV === 'development') {
|
|
209
|
-
if (!('requireAsync' in load)) {
|
|
210
|
-
console.error(`Lazy import was not processed by lazy-component babel plugin.
|
|
211
|
-
Check lazy helper usage, expected signature is "lazy(() => import('./path/to/component'))",
|
|
212
|
-
the first argument should be transformed into a special object, but the current value is
|
|
213
|
-
"${load.toString()}"`);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
// @ts-expect-error
|
|
217
|
-
const originalImportAsync = load.importAsync;
|
|
218
|
-
// @ts-expect-error
|
|
219
|
-
// eslint-disable-next-line no-param-reassign
|
|
220
|
-
load.importAsync = () => originalImportAsync().catch((e) => __lazyErrorHandler(e, originalImportAsync));
|
|
221
|
-
return loadable(load, {
|
|
222
|
-
fallback: options.loading,
|
|
223
|
-
});
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
export { DIContext, ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN, ERROR_BOUNDARY_TOKEN, ErrorBoundary, FallbackError, ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN, UniversalErrorBoundary, __lazyErrorHandler, lazy, resolveLazyComponent, useDi, useDiContainer, withDi, withError };
|
|
1
|
+
export { DIContext } from './di/context.es.js';
|
|
2
|
+
export { withDi } from './di/hoc.es.js';
|
|
3
|
+
export { useDi, useDiContainer } from './di/hooks.es.js';
|
|
4
|
+
export { UniversalErrorBoundary } from './error/UniversalErrorBoundary.es.js';
|
|
5
|
+
export { ErrorBoundary } from './error/component.es.js';
|
|
6
|
+
export { FallbackError } from './error/fallback.es.js';
|
|
7
|
+
export { withError } from './error/hoc.es.js';
|
|
8
|
+
export { ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN, ERROR_BOUNDARY_TOKEN, ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN } from './error/tokens.es.js';
|
|
9
|
+
export { __lazyErrorHandler, lazy, resolveLazyComponent } from './lazy/lazy.es.js';
|
package/lib/react.js
CHANGED
|
@@ -2,247 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
throw new Error(`DI container not found, make sure that the application uses 'DIContext.Provider' from '@tramvai/react'
|
|
26
|
-
(in a tramvai application this is usually done by '@tramvai/module-render', otherwise 'DIContext.Provider' from '@tramvai/react' must be explicitly defined somewhere)
|
|
27
|
-
If the above is correct, make sure that the '@tramvai/react' module is not duplicated in the application dependencies, because then the di versions would be incompatible`);
|
|
28
|
-
}
|
|
29
|
-
throw new Error('DI container not found');
|
|
30
|
-
}
|
|
31
|
-
return di;
|
|
32
|
-
};
|
|
33
|
-
const isTokenObject = (token) => {
|
|
34
|
-
return ('token' in token &&
|
|
35
|
-
(Object.keys(token).length === 1 ||
|
|
36
|
-
typeof token.optional === 'boolean' ||
|
|
37
|
-
typeof token.multi === 'boolean'));
|
|
38
|
-
};
|
|
39
|
-
function useDi(deps) {
|
|
40
|
-
const di = useDiContainer();
|
|
41
|
-
return react.useMemo(() => {
|
|
42
|
-
if (deps.toString() !== '[object Object]' || isTokenObject(deps)) {
|
|
43
|
-
return di.get(deps);
|
|
44
|
-
}
|
|
45
|
-
return mapObj__default["default"]((dep) => di.get(dep), deps);
|
|
46
|
-
}, [deps, di]);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const withDi = (deps) => (WrappedComponent) => {
|
|
50
|
-
function WrapperWithPropsFromDi(props) {
|
|
51
|
-
const depsInstance = useDi(deps);
|
|
52
|
-
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
53
|
-
return jsxRuntime.jsx(WrappedComponent, { ...props, ...depsInstance });
|
|
54
|
-
}
|
|
55
|
-
return hoistStatics__default["default"](WrapperWithPropsFromDi, WrappedComponent);
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const FallbackError = () => {
|
|
59
|
-
return (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("div", { style: {
|
|
60
|
-
textAlign: 'center',
|
|
61
|
-
marginBottom: 11,
|
|
62
|
-
paddingTop: 26,
|
|
63
|
-
fontSize: 30,
|
|
64
|
-
lineHeight: '36px',
|
|
65
|
-
fontWeight: 200,
|
|
66
|
-
}, children: "An error occurred :(" }), jsxRuntime.jsxs("div", { style: {
|
|
67
|
-
textAlign: 'center',
|
|
68
|
-
marginBottom: 17,
|
|
69
|
-
color: '#9299a2',
|
|
70
|
-
fontSize: 20,
|
|
71
|
-
lineHeight: '24px',
|
|
72
|
-
}, children: ["Try", ' ', jsxRuntime.jsx("a", { href: "", onClick: () => window.location.reload(), children: "reloading the page" })] })] }));
|
|
73
|
-
};
|
|
74
|
-
FallbackError.displayName = 'FallbackError';
|
|
75
|
-
|
|
76
|
-
class UniversalErrorBoundary extends react.Component {
|
|
77
|
-
constructor(props) {
|
|
78
|
-
super(props);
|
|
79
|
-
this.state = {
|
|
80
|
-
error: props.error || null,
|
|
81
|
-
url: props.url,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
// Reference and explanation here - https://github.com/remix-run/remix/blob/main/packages/remix-react/errorBoundaries.tsx#L35
|
|
85
|
-
static getDerivedStateFromProps(props, state) {
|
|
86
|
-
if (props.url !== state.url) {
|
|
87
|
-
return { error: props.error || null, url: props.url };
|
|
88
|
-
}
|
|
89
|
-
return { error: props.error || state.error, url: state.url };
|
|
90
|
-
}
|
|
91
|
-
static getDerivedStateFromError(error) {
|
|
92
|
-
return { error };
|
|
93
|
-
}
|
|
94
|
-
componentDidCatch(error, errorInfo) {
|
|
95
|
-
const { errorHandlers } = this.props;
|
|
96
|
-
if (errorHandlers) {
|
|
97
|
-
errorHandlers.forEach((handler) => {
|
|
98
|
-
handler(error, errorInfo);
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
render() {
|
|
103
|
-
const { children, fallback: Fallback, fallbackFromDi } = this.props;
|
|
104
|
-
const { url, error } = this.state;
|
|
105
|
-
if (!error) {
|
|
106
|
-
return children;
|
|
107
|
-
}
|
|
108
|
-
if (Fallback) {
|
|
109
|
-
return jsxRuntime.jsx(Fallback, { url: url, error: error });
|
|
110
|
-
}
|
|
111
|
-
if (fallbackFromDi) {
|
|
112
|
-
return fallbackFromDi;
|
|
113
|
-
}
|
|
114
|
-
return jsxRuntime.jsx(FallbackError, {});
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
UniversalErrorBoundary.displayName = 'UniversalErrorBoundary';
|
|
118
|
-
|
|
119
|
-
const ERROR_BOUNDARY_TOKEN = dippy.createToken('reactErrorBoundaryHandlers', {
|
|
120
|
-
multi: true,
|
|
5
|
+
var context = require('./di/context.js');
|
|
6
|
+
var hoc = require('./di/hoc.js');
|
|
7
|
+
var hooks = require('./di/hooks.js');
|
|
8
|
+
var UniversalErrorBoundary = require('./error/UniversalErrorBoundary.js');
|
|
9
|
+
var component = require('./error/component.js');
|
|
10
|
+
var fallback = require('./error/fallback.js');
|
|
11
|
+
var hoc$1 = require('./error/hoc.js');
|
|
12
|
+
var tokens = require('./error/tokens.js');
|
|
13
|
+
var lazy = require('./lazy/lazy.js');
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
exports.DIContext = context.DIContext;
|
|
18
|
+
exports.withDi = hoc.withDi;
|
|
19
|
+
exports.useDi = hooks.useDi;
|
|
20
|
+
exports.useDiContainer = hooks.useDiContainer;
|
|
21
|
+
exports.UniversalErrorBoundary = UniversalErrorBoundary.UniversalErrorBoundary;
|
|
22
|
+
Object.defineProperty(exports, 'ErrorBoundary', {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: function () { return component.ErrorBoundary; }
|
|
121
25
|
});
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
*/
|
|
131
|
-
exports.ErrorBoundary = class ErrorBoundary extends react.Component {
|
|
132
|
-
constructor(props) {
|
|
133
|
-
super(props);
|
|
134
|
-
this.state = {
|
|
135
|
-
hasError: false,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
static getDerivedStateFromError() {
|
|
139
|
-
return { hasError: true };
|
|
140
|
-
}
|
|
141
|
-
componentDidCatch(error, errorInfo) {
|
|
142
|
-
const { errorHandlers } = this.props;
|
|
143
|
-
if (errorHandlers) {
|
|
144
|
-
errorHandlers.forEach((handler) => {
|
|
145
|
-
handler(error, errorInfo);
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
render() {
|
|
150
|
-
const { children, fallbackComponent, fallbackComponentFromDi } = this.props;
|
|
151
|
-
const { hasError } = this.state;
|
|
152
|
-
if (!hasError) {
|
|
153
|
-
return children;
|
|
154
|
-
}
|
|
155
|
-
return fallbackComponent || fallbackComponentFromDi || jsxRuntime.jsx(FallbackError, {});
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
exports.ErrorBoundary.displayName = 'ErrorBoundary';
|
|
159
|
-
exports.ErrorBoundary = tslib.__decorate([
|
|
160
|
-
withDi({
|
|
161
|
-
errorHandlers: { token: ERROR_BOUNDARY_TOKEN, optional: true },
|
|
162
|
-
fallbackComponentFromDi: { token: ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN, optional: true },
|
|
163
|
-
})
|
|
164
|
-
], exports.ErrorBoundary);
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* @deprecated Use UniversalErrorBoundary component
|
|
168
|
-
*/
|
|
169
|
-
const withError = ({ fallbackComponent } = {}) => (WrappedComponent) => {
|
|
170
|
-
function WrapperWithError(props) {
|
|
171
|
-
return (jsxRuntime.jsx(exports.ErrorBoundary, { fallbackComponent: fallbackComponent, children: jsxRuntime.jsx(WrappedComponent, { ...props }) }));
|
|
172
|
-
}
|
|
173
|
-
return hoistStatics__default["default"](WrapperWithError, WrappedComponent);
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
const resolveLazyComponent = async (componentOrLoader) => {
|
|
177
|
-
if (!componentOrLoader) {
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
if ('load' in componentOrLoader && typeof componentOrLoader.load === 'function') {
|
|
181
|
-
const mod = await componentOrLoader.load();
|
|
182
|
-
let component;
|
|
183
|
-
if (mod.__esModule) {
|
|
184
|
-
component = mod.default;
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
component = mod.default || mod;
|
|
188
|
-
}
|
|
189
|
-
// manually hoist static properties from preloaded component to loadable wrapper,
|
|
190
|
-
// this open access to current page component static properties outside before rendering
|
|
191
|
-
hoistStatics__default["default"](componentOrLoader, component);
|
|
192
|
-
return component;
|
|
193
|
-
}
|
|
194
|
-
return componentOrLoader;
|
|
195
|
-
};
|
|
196
|
-
/**
|
|
197
|
-
* @private Only for internal usage!
|
|
198
|
-
* The method is intended to make it possible to wait for retries to synchronously load unsuccessful CSS assets
|
|
199
|
-
*/
|
|
200
|
-
const __lazyErrorHandler = (error, load) => {
|
|
201
|
-
// This error from `mini-css-extract-plugin` fired, when a file loading initiated by this plugin failed.
|
|
202
|
-
// By default, this error will cancel the loading of the component via `loadable`.
|
|
203
|
-
// Now, we can add `__lazyErrorHandler` to catch block of any dynamic import,
|
|
204
|
-
// and if failed assets was loaded again, `loadable` will not fail
|
|
205
|
-
if ((error === null || error === void 0 ? void 0 : error.code) === 'CSS_CHUNK_LOAD_FAILED') {
|
|
206
|
-
const failedLinkUrl = error.request;
|
|
207
|
-
// `mini-css-extract-plugin` instantly removes failed link tags,
|
|
208
|
-
// so we can expect only link tag from our recovery mechanism
|
|
209
|
-
const fallbackLinkTag = document.querySelector(`link[href="${failedLinkUrl}"]`) ||
|
|
210
|
-
document.querySelector(`link[data-href="${failedLinkUrl}"]`);
|
|
211
|
-
if (fallbackLinkTag) {
|
|
212
|
-
return load();
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
throw error;
|
|
216
|
-
};
|
|
217
|
-
const lazy = (load, options = {}) => {
|
|
218
|
-
if (process.env.NODE_ENV === 'development') {
|
|
219
|
-
if (!('requireAsync' in load)) {
|
|
220
|
-
console.error(`Lazy import was not processed by lazy-component babel plugin.
|
|
221
|
-
Check lazy helper usage, expected signature is "lazy(() => import('./path/to/component'))",
|
|
222
|
-
the first argument should be transformed into a special object, but the current value is
|
|
223
|
-
"${load.toString()}"`);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
// @ts-expect-error
|
|
227
|
-
const originalImportAsync = load.importAsync;
|
|
228
|
-
// @ts-expect-error
|
|
229
|
-
// eslint-disable-next-line no-param-reassign
|
|
230
|
-
load.importAsync = () => originalImportAsync().catch((e) => __lazyErrorHandler(e, originalImportAsync));
|
|
231
|
-
return loadable__default["default"](load, {
|
|
232
|
-
fallback: options.loading,
|
|
233
|
-
});
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
exports.DIContext = DIContext;
|
|
237
|
-
exports.ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN = ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN;
|
|
238
|
-
exports.ERROR_BOUNDARY_TOKEN = ERROR_BOUNDARY_TOKEN;
|
|
239
|
-
exports.FallbackError = FallbackError;
|
|
240
|
-
exports.ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN = ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN;
|
|
241
|
-
exports.UniversalErrorBoundary = UniversalErrorBoundary;
|
|
242
|
-
exports.__lazyErrorHandler = __lazyErrorHandler;
|
|
243
|
-
exports.lazy = lazy;
|
|
244
|
-
exports.resolveLazyComponent = resolveLazyComponent;
|
|
245
|
-
exports.useDi = useDi;
|
|
246
|
-
exports.useDiContainer = useDiContainer;
|
|
247
|
-
exports.withDi = withDi;
|
|
248
|
-
exports.withError = withError;
|
|
26
|
+
exports.FallbackError = fallback.FallbackError;
|
|
27
|
+
exports.withError = hoc$1.withError;
|
|
28
|
+
exports.ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN = tokens.ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN;
|
|
29
|
+
exports.ERROR_BOUNDARY_TOKEN = tokens.ERROR_BOUNDARY_TOKEN;
|
|
30
|
+
exports.ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN = tokens.ROOT_ERROR_BOUNDARY_COMPONENT_TOKEN;
|
|
31
|
+
exports.__lazyErrorHandler = lazy.__lazyErrorHandler;
|
|
32
|
+
exports.lazy = lazy.lazy;
|
|
33
|
+
exports.resolveLazyComponent = lazy.resolveLazyComponent;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tramvai/react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.72.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/react.js",
|
|
6
6
|
"typings": "lib/react.d.ts",
|
|
@@ -13,20 +13,19 @@
|
|
|
13
13
|
"url": "git@github.com:Tinkoff/tramvai.git"
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
|
-
"build": "tramvai-build --
|
|
17
|
-
"watch": "tsc -w"
|
|
18
|
-
"build-for-publish": "true"
|
|
16
|
+
"build": "tramvai-build --forPublish --preserveModules",
|
|
17
|
+
"watch": "tsc -w"
|
|
19
18
|
},
|
|
20
19
|
"dependencies": {
|
|
21
20
|
"@loadable/component": "^5.15.2",
|
|
22
21
|
"@types/loadable__component": "^5.13.4",
|
|
23
|
-
"@tramvai/types-actions-state-context": "2.
|
|
22
|
+
"@tramvai/types-actions-state-context": "2.72.0",
|
|
24
23
|
"hoist-non-react-statics": "^3.3.0"
|
|
25
24
|
},
|
|
26
25
|
"peerDependencies": {
|
|
27
|
-
"@tinkoff/dippy": "0.8.
|
|
26
|
+
"@tinkoff/dippy": "0.8.13",
|
|
28
27
|
"@tinkoff/utils": "^2.1.2",
|
|
29
|
-
"@tinkoff/url": "0.8.
|
|
28
|
+
"@tinkoff/url": "0.8.5",
|
|
30
29
|
"react": ">=16.14.0",
|
|
31
30
|
"react-dom": ">=16.14.0",
|
|
32
31
|
"tslib": "^2.4.0"
|