@dr.pogodin/react-utils 1.40.13 → 1.41.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/LICENSE.md +1 -1
- package/build/development/server/renderer.js +2 -0
- package/build/development/server/renderer.js.map +1 -1
- package/build/development/shared/components/Input/index.js +4 -5
- package/build/development/shared/components/Input/index.js.map +1 -1
- package/build/development/shared/components/WithTooltip/Tooltip.js +4 -4
- package/build/development/shared/components/WithTooltip/Tooltip.js.map +1 -1
- package/build/development/shared/components/WithTooltip/index.js +2 -3
- package/build/development/shared/components/WithTooltip/index.js.map +1 -1
- package/build/development/shared/components/selectors/CustomDropdown/Options/index.js +7 -6
- package/build/development/shared/components/selectors/CustomDropdown/Options/index.js.map +1 -1
- package/build/development/shared/utils/splitComponent.js +5 -4
- package/build/development/shared/utils/splitComponent.js.map +1 -1
- package/build/development/shared/utils/time.js +2 -26
- package/build/development/shared/utils/time.js.map +1 -1
- package/build/development/web.bundle.js +7 -7
- package/build/production/server/renderer.js +3 -1
- package/build/production/server/renderer.js.map +1 -1
- package/build/production/shared/components/Input/index.js +2 -3
- package/build/production/shared/components/Input/index.js.map +1 -1
- package/build/production/shared/components/WithTooltip/Tooltip.js +3 -3
- package/build/production/shared/components/WithTooltip/Tooltip.js.map +1 -1
- package/build/production/shared/components/WithTooltip/index.js +2 -3
- package/build/production/shared/components/WithTooltip/index.js.map +1 -1
- package/build/production/shared/components/selectors/CustomDropdown/Options/index.js +2 -2
- package/build/production/shared/components/selectors/CustomDropdown/Options/index.js.map +1 -1
- package/build/production/shared/utils/splitComponent.js +2 -2
- package/build/production/shared/utils/splitComponent.js.map +1 -1
- package/build/production/shared/utils/time.js +2 -24
- package/build/production/shared/utils/time.js.map +1 -1
- package/build/production/style.css.map +1 -1
- package/build/production/web.bundle.js +1 -1
- package/build/production/web.bundle.js.LICENSE.txt +2 -2
- package/build/production/web.bundle.js.map +1 -1
- package/build/types-code/shared/components/Input/index.d.ts +5 -2
- package/build/types-code/shared/components/WithTooltip/Tooltip.d.ts +4 -3
- package/build/types-code/shared/components/selectors/CustomDropdown/Options/index.d.ts +5 -3
- package/build/types-code/shared/utils/splitComponent.d.ts +3 -2
- package/build/types-code/shared/utils/time.d.ts +0 -22
- package/config/babel/node-ssr.js +17 -7
- package/package.json +31 -31
- package/src/server/renderer.tsx +2 -0
- package/src/shared/components/Input/index.tsx +9 -11
- package/src/shared/components/WithTooltip/Tooltip.tsx +6 -5
- package/src/shared/components/WithTooltip/index.tsx +4 -4
- package/src/shared/components/selectors/CustomDropdown/Options/index.tsx +17 -9
- package/src/shared/utils/splitComponent.tsx +9 -7
- package/src/shared/utils/time.ts +4 -28
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import type { RefObject } from 'react';
|
|
1
2
|
import { type Theme } from '@dr.pogodin/react-themes';
|
|
2
3
|
type ThemeKeyT = 'container' | 'input' | 'label';
|
|
3
|
-
|
|
4
|
+
type PropsT = React.InputHTMLAttributes<HTMLInputElement> & {
|
|
4
5
|
label?: React.ReactNode;
|
|
6
|
+
ref?: RefObject<HTMLInputElement>;
|
|
5
7
|
testId?: string;
|
|
6
8
|
theme: Theme<ThemeKeyT>;
|
|
7
|
-
}
|
|
9
|
+
};
|
|
10
|
+
declare const _default: import("@dr.pogodin/react-themes").ThemedComponent<PropsT>;
|
|
8
11
|
export default _default;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* hierarchy, and with sub-components managed without React to achieve the best
|
|
4
4
|
* performance during animation.
|
|
5
5
|
*/
|
|
6
|
-
import { type ReactNode } from 'react';
|
|
6
|
+
import { type FunctionComponent, type ReactNode, type RefObject } from 'react';
|
|
7
7
|
export declare enum PLACEMENTS {
|
|
8
8
|
ABOVE_CURSOR = "ABOVE_CURSOR",
|
|
9
9
|
ABOVE_ELEMENT = "ABOVE_ELEMENT",
|
|
@@ -11,8 +11,9 @@ export declare enum PLACEMENTS {
|
|
|
11
11
|
BELOW_ELEMENT = "BELOW_ELEMENT"
|
|
12
12
|
}
|
|
13
13
|
export type ThemeKeysT = 'appearance' | 'arrow' | 'content' | 'container';
|
|
14
|
-
declare const Tooltip:
|
|
14
|
+
declare const Tooltip: FunctionComponent<{
|
|
15
15
|
children?: ReactNode;
|
|
16
|
+
ref?: RefObject<unknown>;
|
|
16
17
|
theme: any;
|
|
17
|
-
}
|
|
18
|
+
}>;
|
|
18
19
|
export default Tooltip;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type FunctionComponent, type ReactNode, type RefObject } from 'react';
|
|
1
2
|
import { type OptionT, type OptionsT, type ValueT } from '../../common';
|
|
2
3
|
export type ContainerPosT = {
|
|
3
4
|
left: number;
|
|
@@ -11,11 +12,12 @@ export type RefT = {
|
|
|
11
12
|
type PropsT = {
|
|
12
13
|
containerClass: string;
|
|
13
14
|
containerStyle?: ContainerPosT;
|
|
14
|
-
filter?: (item: OptionT<
|
|
15
|
+
filter?: (item: OptionT<ReactNode> | ValueT) => boolean;
|
|
15
16
|
optionClass: string;
|
|
16
|
-
options: Readonly<OptionsT<
|
|
17
|
+
options: Readonly<OptionsT<ReactNode>>;
|
|
17
18
|
onCancel: () => void;
|
|
18
19
|
onChange: (value: ValueT) => void;
|
|
20
|
+
ref?: RefObject<RefT | null>;
|
|
19
21
|
};
|
|
20
|
-
declare const Options:
|
|
22
|
+
declare const Options: FunctionComponent<PropsT>;
|
|
21
23
|
export default Options;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ComponentType, type ReactNode } from 'react';
|
|
1
|
+
import { type ComponentType, type FunctionComponent, type ReactNode, type RefObject } from 'react';
|
|
2
2
|
import { type ChunkGroupsT } from './globalState';
|
|
3
3
|
/**
|
|
4
4
|
* Client-side only! Ensures all CSS stylesheets required for the specified
|
|
@@ -33,9 +33,10 @@ type ComponentOrModule<PropsT> = ComponentType<PropsT> | {
|
|
|
33
33
|
*/
|
|
34
34
|
export default function splitComponent<ComponentPropsT extends {
|
|
35
35
|
children?: ReactNode;
|
|
36
|
+
ref?: RefObject<unknown>;
|
|
36
37
|
}>({ chunkName, getComponent, placeholder, }: {
|
|
37
38
|
chunkName: string;
|
|
38
39
|
getComponent: () => Promise<ComponentOrModule<ComponentPropsT>>;
|
|
39
40
|
placeholder?: ReactNode;
|
|
40
|
-
}):
|
|
41
|
+
}): FunctionComponent<ComponentPropsT>;
|
|
41
42
|
export {};
|
|
@@ -7,18 +7,6 @@ import { timer } from '@dr.pogodin/js-utils';
|
|
|
7
7
|
* then stored in the global state to be reused in all other calls), which
|
|
8
8
|
* is also passed and used in the first client side render, and then updated
|
|
9
9
|
* with a finite precision to avoid infinite re-rendering loops.
|
|
10
|
-
* @param [options] Optional settings.
|
|
11
|
-
* @param [options.globalStatePath="currentTime"] Global state path
|
|
12
|
-
* to keep the current time value.
|
|
13
|
-
* @param [options.precision= 5 * time.SEC_MS] Current time precision.
|
|
14
|
-
* The hook won't update the current time stored in the global state unless it
|
|
15
|
-
* is different from Date.now() result by this number (in milliseconds).
|
|
16
|
-
* Default to 5 seconds.
|
|
17
|
-
* @param [options.autorefresh=false] Set `true` to automatically
|
|
18
|
-
* refresh time stored in the global state with the given `precision` (and
|
|
19
|
-
* thus automatically re-rendering components dependent on this hook, or
|
|
20
|
-
* the global state with the period equal to the `precision`.
|
|
21
|
-
* @return Unix timestamp in milliseconds.
|
|
22
10
|
*/
|
|
23
11
|
export declare function useCurrent({ autorefresh, globalStatePath, precision, }?: {
|
|
24
12
|
autorefresh?: boolean | undefined;
|
|
@@ -33,16 +21,6 @@ export declare function useCurrent({ autorefresh, globalStatePath, precision, }?
|
|
|
33
21
|
* via the global state. Prior to the value being known (in the very first
|
|
34
22
|
* request from the user, when the cookie is still missing), zero value is used
|
|
35
23
|
* as the default value.
|
|
36
|
-
*
|
|
37
|
-
* @param {object} [options] Optional settings.
|
|
38
|
-
* @param {string} [options.cookieName="timezoneOffset"] Optional. The name of
|
|
39
|
-
* cookie to use to store the timezone offset. Defaults "timezoneOffset". Set
|
|
40
|
-
* to a falsy value to forbid using cookies altogether (in that case the hook
|
|
41
|
-
* will always return zero value at the server-side, and in the first render
|
|
42
|
-
* at the client-side).
|
|
43
|
-
* @param {string} [options.timezoneOffset="timezoneOffset"] Optional.
|
|
44
|
-
* The global state path to store the offset. Defaults "timezoneOffset".
|
|
45
|
-
* @return {number} Timezone offset.
|
|
46
24
|
*/
|
|
47
25
|
export declare function useTimezoneOffset({ cookieName, globalStatePath, }?: {
|
|
48
26
|
cookieName?: string | undefined;
|
package/config/babel/node-ssr.js
CHANGED
|
@@ -16,13 +16,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
16
16
|
}) : function(o, v) {
|
|
17
17
|
o["default"] = v;
|
|
18
18
|
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || function (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
};
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
26
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
37
|
exports.default = getConfig;
|
|
28
38
|
const lodash_1 = require("lodash");
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.41.0",
|
|
3
3
|
"bin": {
|
|
4
4
|
"react-utils-build": "bin/build.js",
|
|
5
5
|
"react-utils-setup": "bin/setup.js"
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@babel/runtime": "^7.26.0",
|
|
12
|
-
"@dr.pogodin/babel-plugin-react-css-modules": "^6.13.
|
|
13
|
-
"@dr.pogodin/csurf": "^1.14.
|
|
14
|
-
"@dr.pogodin/js-utils": "^0.0.
|
|
15
|
-
"@dr.pogodin/react-global-state": "^0.
|
|
16
|
-
"@dr.pogodin/react-themes": "^1.
|
|
12
|
+
"@dr.pogodin/babel-plugin-react-css-modules": "^6.13.3",
|
|
13
|
+
"@dr.pogodin/csurf": "^1.14.1",
|
|
14
|
+
"@dr.pogodin/js-utils": "^0.0.13",
|
|
15
|
+
"@dr.pogodin/react-global-state": "^0.18.0",
|
|
16
|
+
"@dr.pogodin/react-themes": "^1.8.0",
|
|
17
17
|
"@jest/environment": "^29.7.0",
|
|
18
|
-
"axios": "^1.7.
|
|
18
|
+
"axios": "^1.7.9",
|
|
19
19
|
"commander": "^12.1.0",
|
|
20
20
|
"compression": "^1.7.5",
|
|
21
21
|
"config": "^3.3.12",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"cookie-parser": "^1.4.7",
|
|
24
24
|
"cross-env": "^7.0.3",
|
|
25
25
|
"dayjs": "^1.11.13",
|
|
26
|
-
"express": "^4.21.
|
|
26
|
+
"express": "^4.21.2",
|
|
27
27
|
"helmet": "^8.0.0",
|
|
28
28
|
"http-status-codes": "^2.3.0",
|
|
29
29
|
"joi": "^17.13.3",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"node-forge": "^1.3.1",
|
|
33
33
|
"qs": "^6.13.1",
|
|
34
34
|
"raf": "^3.4.1",
|
|
35
|
-
"react": "^
|
|
36
|
-
"react-dom": "^
|
|
35
|
+
"react": "^19.0.0",
|
|
36
|
+
"react-dom": "^19.0.0",
|
|
37
37
|
"react-helmet": "^6.1.0",
|
|
38
|
-
"react-router-dom": "^6.28.
|
|
38
|
+
"react-router-dom": "^6.28.1",
|
|
39
39
|
"request-ip": "^3.3.0",
|
|
40
40
|
"rimraf": "^6.0.0",
|
|
41
41
|
"serialize-javascript": "^6.0.2",
|
|
@@ -46,27 +46,27 @@
|
|
|
46
46
|
},
|
|
47
47
|
"description": "Collection of generic ReactJS components and utils",
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@babel/cli": "^7.
|
|
49
|
+
"@babel/cli": "^7.26.4",
|
|
50
50
|
"@babel/core": "^7.26.0",
|
|
51
51
|
"@babel/eslint-parser": "^7.25.9",
|
|
52
52
|
"@babel/eslint-plugin": "^7.25.9",
|
|
53
53
|
"@babel/node": "^7.26.0",
|
|
54
54
|
"@babel/plugin-transform-runtime": "^7.25.9",
|
|
55
55
|
"@babel/preset-env": "^7.26.0",
|
|
56
|
-
"@babel/preset-react": "^7.
|
|
56
|
+
"@babel/preset-react": "^7.26.3",
|
|
57
57
|
"@babel/preset-typescript": "^7.26.0",
|
|
58
58
|
"@babel/register": "^7.25.9",
|
|
59
|
-
"@dr.pogodin/babel-plugin-transform-assets": "^1.2.
|
|
60
|
-
"@dr.pogodin/babel-preset-svgr": "^1.
|
|
59
|
+
"@dr.pogodin/babel-plugin-transform-assets": "^1.2.4",
|
|
60
|
+
"@dr.pogodin/babel-preset-svgr": "^1.9.0",
|
|
61
61
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
|
|
62
62
|
"@testing-library/dom": "^10.4.0",
|
|
63
|
-
"@testing-library/react": "^16.0
|
|
63
|
+
"@testing-library/react": "^16.1.0",
|
|
64
64
|
"@testing-library/user-event": "^14.5.2",
|
|
65
65
|
"@tsconfig/recommended": "^1.0.8",
|
|
66
66
|
"@types/compression": "^1.7.5",
|
|
67
67
|
"@types/config": "^3.3.5",
|
|
68
68
|
"@types/cookie": "^0.6.0",
|
|
69
|
-
"@types/cookie-parser": "^1.4.
|
|
69
|
+
"@types/cookie-parser": "^1.4.8",
|
|
70
70
|
"@types/csurf": "^1.11.5",
|
|
71
71
|
"@types/express": "^4.17.21",
|
|
72
72
|
"@types/jest": "^29.5.14",
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"@types/morgan": "^1.9.9",
|
|
75
75
|
"@types/node-forge": "^1.3.11",
|
|
76
76
|
"@types/pretty": "^2.0.3",
|
|
77
|
-
"@types/react": "^
|
|
78
|
-
"@types/react-dom": "^
|
|
77
|
+
"@types/react": "^19.0.2",
|
|
78
|
+
"@types/react-dom": "^19.0.2",
|
|
79
79
|
"@types/react-helmet": "^6.1.11",
|
|
80
80
|
"@types/request-ip": "^0.0.41",
|
|
81
81
|
"@types/serialize-javascript": "^5.0.4",
|
|
@@ -94,14 +94,14 @@
|
|
|
94
94
|
"eslint-config-airbnb-typescript": "^18.0.0",
|
|
95
95
|
"eslint-import-resolver-babel-module": "^5.3.2",
|
|
96
96
|
"eslint-plugin-import": "^2.31.0",
|
|
97
|
-
"eslint-plugin-jest": "^28.
|
|
97
|
+
"eslint-plugin-jest": "^28.10.0",
|
|
98
98
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
99
|
-
"eslint-plugin-react": "^7.37.
|
|
99
|
+
"eslint-plugin-react": "^7.37.3",
|
|
100
100
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
101
101
|
"identity-obj-proxy": "^3.0.0",
|
|
102
102
|
"jest": "^29.7.0",
|
|
103
103
|
"jest-environment-jsdom": "^29.7.0",
|
|
104
|
-
"memfs": "^4.
|
|
104
|
+
"memfs": "^4.15.1",
|
|
105
105
|
"mini-css-extract-plugin": "^2.9.2",
|
|
106
106
|
"mockdate": "^3.0.5",
|
|
107
107
|
"nodelist-foreach-polyfill": "^1.2.0",
|
|
@@ -109,22 +109,22 @@
|
|
|
109
109
|
"postcss-loader": "^8.1.1",
|
|
110
110
|
"postcss-scss": "^4.0.9",
|
|
111
111
|
"pretty": "^2.0.0",
|
|
112
|
-
"react-refresh": "^0.
|
|
112
|
+
"react-refresh": "^0.16.0",
|
|
113
113
|
"regenerator-runtime": "^0.14.1",
|
|
114
114
|
"resolve-url-loader": "^5.0.0",
|
|
115
|
-
"sass": "^1.
|
|
116
|
-
"sass-loader": "^16.0.
|
|
115
|
+
"sass": "^1.83.0",
|
|
116
|
+
"sass-loader": "^16.0.4",
|
|
117
117
|
"sitemap": "^8.0.0",
|
|
118
118
|
"source-map-loader": "^5.0.0",
|
|
119
|
-
"stylelint": "^16.
|
|
120
|
-
"stylelint-config-standard-scss": "^
|
|
119
|
+
"stylelint": "^16.12.0",
|
|
120
|
+
"stylelint-config-standard-scss": "^14.0.0",
|
|
121
121
|
"supertest": "^7.0.0",
|
|
122
122
|
"tsc-alias": "^1.8.10",
|
|
123
|
-
"tstyche": "^3.
|
|
123
|
+
"tstyche": "^3.2.0",
|
|
124
124
|
"typed-scss-modules": "^8.0.1",
|
|
125
|
-
"typescript": "^5.
|
|
126
|
-
"typescript-eslint": "^8.
|
|
127
|
-
"webpack": "^5.
|
|
125
|
+
"typescript": "^5.7.2",
|
|
126
|
+
"typescript-eslint": "^8.18.2",
|
|
127
|
+
"webpack": "^5.97.1",
|
|
128
128
|
"webpack-dev-middleware": "^7.4.2",
|
|
129
129
|
"webpack-hot-middleware": "^2.26.1",
|
|
130
130
|
"webpack-merge": "^6.0.1",
|
package/src/server/renderer.tsx
CHANGED
|
@@ -437,6 +437,8 @@ export default function factory(
|
|
|
437
437
|
const renderPass = async () => {
|
|
438
438
|
ssrContext.chunks = [];
|
|
439
439
|
return new Promise<PipeableStream>((resolve, reject) => {
|
|
440
|
+
// TODO: pipeableStream has .abort() method,
|
|
441
|
+
// and we should wire it up to the SSR timeout below.
|
|
440
442
|
const pipeableStream = renderToPipeableStream(
|
|
441
443
|
<GlobalStateProvider
|
|
442
444
|
initialState={ssrContext.state}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FunctionComponent, RefObject } from 'react';
|
|
2
2
|
|
|
3
3
|
import themed, { type Theme } from '@dr.pogodin/react-themes';
|
|
4
4
|
|
|
@@ -11,28 +11,26 @@ type ThemeKeyT =
|
|
|
11
11
|
|
|
12
12
|
type PropsT = React.InputHTMLAttributes<HTMLInputElement> & {
|
|
13
13
|
label?: React.ReactNode;
|
|
14
|
+
ref?: RefObject<HTMLInputElement>;
|
|
14
15
|
testId?: string;
|
|
15
16
|
theme: Theme<ThemeKeyT>;
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Themeable input field, based on the standard HTML `<input>` element.
|
|
20
|
-
* @param [props]
|
|
21
21
|
* @param [props.label] Input label.
|
|
22
22
|
* @param [props.theme] _Ad hoc_ theme.
|
|
23
23
|
* @param [props...] [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)
|
|
24
24
|
* @param [props...] Any other properties are passed to the underlying
|
|
25
25
|
* `<input>` element.
|
|
26
26
|
*/
|
|
27
|
-
const Input
|
|
28
|
-
|
|
29
|
-
label,
|
|
30
|
-
testId,
|
|
31
|
-
theme,
|
|
32
|
-
...rest
|
|
33
|
-
}: PropsT,
|
|
27
|
+
const Input: FunctionComponent<PropsT> = ({
|
|
28
|
+
label,
|
|
34
29
|
ref,
|
|
35
|
-
|
|
30
|
+
testId,
|
|
31
|
+
theme,
|
|
32
|
+
...rest
|
|
33
|
+
}) => (
|
|
36
34
|
<span className={theme.container}>
|
|
37
35
|
{ label === undefined ? null : <div className={theme.label}>{label}</div> }
|
|
38
36
|
<input
|
|
@@ -42,6 +40,6 @@ const Input = forwardRef<HTMLInputElement, PropsT>((
|
|
|
42
40
|
{...rest} // eslint-disable-line react/jsx-props-no-spreading
|
|
43
41
|
/>
|
|
44
42
|
</span>
|
|
45
|
-
)
|
|
43
|
+
);
|
|
46
44
|
|
|
47
45
|
export default themed(Input, 'Input', defaultTheme);
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* hierarchy, and with sub-components managed without React to achieve the best
|
|
4
4
|
* performance during animation.
|
|
5
5
|
*/
|
|
6
|
-
/* global document, window */
|
|
7
6
|
|
|
8
7
|
import {
|
|
8
|
+
type FunctionComponent,
|
|
9
9
|
type ReactNode,
|
|
10
|
-
|
|
10
|
+
type RefObject,
|
|
11
11
|
useEffect,
|
|
12
12
|
useImperativeHandle,
|
|
13
13
|
useRef,
|
|
@@ -269,10 +269,11 @@ function setComponentPositions(
|
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
/* The Tooltip component itself. */
|
|
272
|
-
const Tooltip
|
|
272
|
+
const Tooltip: FunctionComponent<{
|
|
273
273
|
children?: ReactNode;
|
|
274
|
+
ref?: RefObject<unknown>;
|
|
274
275
|
theme: any;
|
|
275
|
-
}>(
|
|
276
|
+
}> = ({ children, ref, theme }) => {
|
|
276
277
|
// NOTE: The way it has to be implemented, for clean mounting and unmounting
|
|
277
278
|
// at the client side, the <Tooltip> is fully mounted into DOM in the next
|
|
278
279
|
// rendering cycles, and only then it can be correctly measured and positioned.
|
|
@@ -340,6 +341,6 @@ const Tooltip = forwardRef<unknown, {
|
|
|
340
341
|
]);
|
|
341
342
|
|
|
342
343
|
return components ? createPortal(children, components.content) : null;
|
|
343
|
-
}
|
|
344
|
+
};
|
|
344
345
|
|
|
345
346
|
export default Tooltip;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* global window */
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
+
type FunctionComponent,
|
|
4
5
|
type ReactNode,
|
|
5
6
|
useEffect,
|
|
6
7
|
useRef,
|
|
@@ -49,12 +50,11 @@ type HeapT = {
|
|
|
49
50
|
* **Children:** Children are rendered in the place of `<WithTooltip>`,
|
|
50
51
|
* and when hovered the tooltip is shown. By default the wrapper itself is
|
|
51
52
|
* `<div>` block with `display: inline-block`.
|
|
52
|
-
* @param
|
|
53
|
-
* @param {React.node} props.tip – Anything React is able to render,
|
|
53
|
+
* @param tip – Anything React is able to render,
|
|
54
54
|
* _e.g._ a tooltip text. This will be the tooltip content.
|
|
55
55
|
* @param {WithTooltipTheme} props.theme _Ad hoc_ theme.
|
|
56
56
|
*/
|
|
57
|
-
const Wrapper:
|
|
57
|
+
const Wrapper: FunctionComponent<PropsT> = ({
|
|
58
58
|
children,
|
|
59
59
|
placement = PLACEMENTS.ABOVE_CURSOR,
|
|
60
60
|
tip,
|
|
@@ -66,7 +66,7 @@ const Wrapper: React.FunctionComponent<PropsT> = ({
|
|
|
66
66
|
triggeredByTouch: false,
|
|
67
67
|
timerId: undefined,
|
|
68
68
|
});
|
|
69
|
-
const tooltipRef = useRef<TooltipRefT>();
|
|
69
|
+
const tooltipRef = useRef<TooltipRefT>(null);
|
|
70
70
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
71
71
|
const [showTooltip, setShowTooltip] = useState(false);
|
|
72
72
|
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type FunctionComponent,
|
|
3
|
+
type ReactNode,
|
|
4
|
+
type RefObject,
|
|
5
|
+
useImperativeHandle,
|
|
6
|
+
useRef,
|
|
7
|
+
} from 'react';
|
|
2
8
|
|
|
3
9
|
import { BaseModal } from 'components/Modal';
|
|
4
10
|
|
|
@@ -28,14 +34,15 @@ export type RefT = {
|
|
|
28
34
|
type PropsT = {
|
|
29
35
|
containerClass: string;
|
|
30
36
|
containerStyle?: ContainerPosT;
|
|
31
|
-
filter?: (item: OptionT<
|
|
37
|
+
filter?: (item: OptionT<ReactNode> | ValueT) => boolean;
|
|
32
38
|
optionClass: string;
|
|
33
|
-
options: Readonly<OptionsT<
|
|
39
|
+
options: Readonly<OptionsT<ReactNode>>;
|
|
34
40
|
onCancel: () => void;
|
|
35
41
|
onChange: (value: ValueT) => void;
|
|
42
|
+
ref?: RefObject<RefT | null>;
|
|
36
43
|
};
|
|
37
44
|
|
|
38
|
-
const Options
|
|
45
|
+
const Options: FunctionComponent<PropsT> = ({
|
|
39
46
|
containerClass,
|
|
40
47
|
containerStyle,
|
|
41
48
|
filter,
|
|
@@ -43,7 +50,8 @@ const Options = forwardRef<RefT, PropsT>(({
|
|
|
43
50
|
onChange,
|
|
44
51
|
optionClass,
|
|
45
52
|
options,
|
|
46
|
-
|
|
53
|
+
ref,
|
|
54
|
+
}) => {
|
|
47
55
|
const opsRef = useRef<HTMLDivElement>(null);
|
|
48
56
|
|
|
49
57
|
useImperativeHandle(ref, () => ({
|
|
@@ -51,7 +59,7 @@ const Options = forwardRef<RefT, PropsT>(({
|
|
|
51
59
|
const e = opsRef.current?.parentElement;
|
|
52
60
|
if (!e) return undefined;
|
|
53
61
|
|
|
54
|
-
const rect = opsRef.current
|
|
62
|
+
const rect = opsRef.current!.getBoundingClientRect();
|
|
55
63
|
const style = window.getComputedStyle(e);
|
|
56
64
|
const mBottom = parseFloat(style.marginBottom);
|
|
57
65
|
const mTop = parseFloat(style.marginTop);
|
|
@@ -62,7 +70,7 @@ const Options = forwardRef<RefT, PropsT>(({
|
|
|
62
70
|
},
|
|
63
71
|
}), []);
|
|
64
72
|
|
|
65
|
-
const optionNodes:
|
|
73
|
+
const optionNodes: ReactNode[] = [];
|
|
66
74
|
for (let i = 0; i < options.length; ++i) {
|
|
67
75
|
const option = options[i];
|
|
68
76
|
if (option !== undefined && (!filter || filter(option))) {
|
|
@@ -98,7 +106,7 @@ const Options = forwardRef<RefT, PropsT>(({
|
|
|
98
106
|
// dropdowns during the scrolling (that would need to re-position it in
|
|
99
107
|
// response to the position changes of the root dropdown element).
|
|
100
108
|
cancelOnScrolling
|
|
101
|
-
|
|
109
|
+
style={containerStyle}
|
|
102
110
|
dontDisableScrolling
|
|
103
111
|
onCancel={onCancel}
|
|
104
112
|
theme={{
|
|
@@ -112,6 +120,6 @@ const Options = forwardRef<RefT, PropsT>(({
|
|
|
112
120
|
<div ref={opsRef}>{optionNodes}</div>
|
|
113
121
|
</BaseModal>
|
|
114
122
|
);
|
|
115
|
-
}
|
|
123
|
+
};
|
|
116
124
|
|
|
117
125
|
export default Options;
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
type ComponentType,
|
|
6
|
+
type FunctionComponent,
|
|
6
7
|
type ReactNode,
|
|
7
|
-
|
|
8
|
+
type RefObject,
|
|
8
9
|
lazy,
|
|
9
10
|
Suspense,
|
|
10
11
|
useInsertionEffect,
|
|
@@ -181,7 +182,7 @@ type ComponentOrModule<PropsT> = ComponentType<PropsT> | {
|
|
|
181
182
|
* @return {React.ElementType}
|
|
182
183
|
*/
|
|
183
184
|
export default function splitComponent<
|
|
184
|
-
ComponentPropsT extends { children?: ReactNode },
|
|
185
|
+
ComponentPropsT extends { children?: ReactNode; ref?: RefObject<unknown> },
|
|
185
186
|
>({
|
|
186
187
|
chunkName,
|
|
187
188
|
getComponent,
|
|
@@ -210,10 +211,11 @@ export default function splitComponent<
|
|
|
210
211
|
await bookStyleSheets(chunkName, clientChunkGroups, false);
|
|
211
212
|
}
|
|
212
213
|
|
|
213
|
-
const Wrapper
|
|
214
|
-
|
|
214
|
+
const Wrapper: FunctionComponent<ComponentPropsT> = ({
|
|
215
|
+
children,
|
|
215
216
|
ref,
|
|
216
|
-
|
|
217
|
+
...rest
|
|
218
|
+
}) => {
|
|
217
219
|
// On the server side we'll assert the chunk name here,
|
|
218
220
|
// and also push it to the SSR chunks array.
|
|
219
221
|
if (IS_SERVER_SIDE) {
|
|
@@ -230,11 +232,11 @@ export default function splitComponent<
|
|
|
230
232
|
}, []);
|
|
231
233
|
|
|
232
234
|
return (
|
|
233
|
-
<Component
|
|
235
|
+
<Component {...(rest as unknown as ComponentPropsT)} ref={ref}>
|
|
234
236
|
{children}
|
|
235
237
|
</Component>
|
|
236
238
|
);
|
|
237
|
-
}
|
|
239
|
+
};
|
|
238
240
|
|
|
239
241
|
return { default: Wrapper };
|
|
240
242
|
});
|
package/src/shared/utils/time.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import Cookie from 'cookie';
|
|
1
|
+
import { serialize } from 'cookie';
|
|
4
2
|
import dayjs from 'dayjs';
|
|
5
3
|
import { useEffect } from 'react';
|
|
6
4
|
|
|
@@ -24,18 +22,6 @@ import { getSsrContext } from './globalState';
|
|
|
24
22
|
* then stored in the global state to be reused in all other calls), which
|
|
25
23
|
* is also passed and used in the first client side render, and then updated
|
|
26
24
|
* with a finite precision to avoid infinite re-rendering loops.
|
|
27
|
-
* @param [options] Optional settings.
|
|
28
|
-
* @param [options.globalStatePath="currentTime"] Global state path
|
|
29
|
-
* to keep the current time value.
|
|
30
|
-
* @param [options.precision= 5 * time.SEC_MS] Current time precision.
|
|
31
|
-
* The hook won't update the current time stored in the global state unless it
|
|
32
|
-
* is different from Date.now() result by this number (in milliseconds).
|
|
33
|
-
* Default to 5 seconds.
|
|
34
|
-
* @param [options.autorefresh=false] Set `true` to automatically
|
|
35
|
-
* refresh time stored in the global state with the given `precision` (and
|
|
36
|
-
* thus automatically re-rendering components dependent on this hook, or
|
|
37
|
-
* the global state with the period equal to the `precision`.
|
|
38
|
-
* @return Unix timestamp in milliseconds.
|
|
39
25
|
*/
|
|
40
26
|
// TODO: Should we request the state type as generic parameter, to be able
|
|
41
27
|
// to verify the give globalStatePath is correct?
|
|
@@ -43,7 +29,7 @@ export function useCurrent({
|
|
|
43
29
|
autorefresh = false,
|
|
44
30
|
globalStatePath = 'currentTime',
|
|
45
31
|
precision = 5 * SEC_MS,
|
|
46
|
-
} = {}) {
|
|
32
|
+
} = {}): number {
|
|
47
33
|
const [now, setter] = useGlobalState<ForceT, number>(globalStatePath, Date.now);
|
|
48
34
|
useEffect(() => {
|
|
49
35
|
let timerId: NodeJS.Timeout;
|
|
@@ -70,23 +56,13 @@ export function useCurrent({
|
|
|
70
56
|
* via the global state. Prior to the value being known (in the very first
|
|
71
57
|
* request from the user, when the cookie is still missing), zero value is used
|
|
72
58
|
* as the default value.
|
|
73
|
-
*
|
|
74
|
-
* @param {object} [options] Optional settings.
|
|
75
|
-
* @param {string} [options.cookieName="timezoneOffset"] Optional. The name of
|
|
76
|
-
* cookie to use to store the timezone offset. Defaults "timezoneOffset". Set
|
|
77
|
-
* to a falsy value to forbid using cookies altogether (in that case the hook
|
|
78
|
-
* will always return zero value at the server-side, and in the first render
|
|
79
|
-
* at the client-side).
|
|
80
|
-
* @param {string} [options.timezoneOffset="timezoneOffset"] Optional.
|
|
81
|
-
* The global state path to store the offset. Defaults "timezoneOffset".
|
|
82
|
-
* @return {number} Timezone offset.
|
|
83
59
|
*/
|
|
84
60
|
// TODO: Should we request the state type as generic parameter, to be able
|
|
85
61
|
// to verify the give globalStatePath is correct?
|
|
86
62
|
export function useTimezoneOffset({
|
|
87
63
|
cookieName = 'timezoneOffset',
|
|
88
64
|
globalStatePath = 'timezoneOffset',
|
|
89
|
-
} = {}) {
|
|
65
|
+
} = {}): number {
|
|
90
66
|
const ssrContext = getSsrContext(false);
|
|
91
67
|
const [offset, setOffset] = useGlobalState<ForceT, number>(globalStatePath, () => {
|
|
92
68
|
const value = cookieName && ssrContext?.req?.cookies?.[cookieName];
|
|
@@ -97,7 +73,7 @@ export function useTimezoneOffset({
|
|
|
97
73
|
const value = date.getTimezoneOffset();
|
|
98
74
|
setOffset(value);
|
|
99
75
|
if (cookieName) {
|
|
100
|
-
document.cookie =
|
|
76
|
+
document.cookie = serialize(cookieName, value.toString(), { path: '/' });
|
|
101
77
|
}
|
|
102
78
|
}, [cookieName, setOffset]);
|
|
103
79
|
return offset;
|