@dr.pogodin/react-utils 1.42.0 → 1.43.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/babel.config.js +3 -0
- package/bin/build.js +5 -8
- package/bin/setup.js +2 -1
- package/build/development/client/getInj.js +7 -2
- package/build/development/client/getInj.js.map +1 -1
- package/build/development/client/index.js +1 -2
- package/build/development/client/index.js.map +1 -1
- package/build/development/client/init.js +16 -13
- package/build/development/client/init.js.map +1 -1
- package/build/development/index.js +4 -1
- package/build/development/index.js.map +1 -1
- package/build/development/server/Cache.js +5 -9
- package/build/development/server/Cache.js.map +1 -1
- package/build/development/server/index.js +14 -11
- package/build/development/server/index.js.map +1 -1
- package/build/development/server/renderer.js +36 -40
- package/build/development/server/renderer.js.map +1 -1
- package/build/development/server/server.js +19 -12
- package/build/development/server/server.js.map +1 -1
- package/build/development/server/utils/errors.js.map +1 -1
- package/build/development/shared/components/Button/index.js +2 -3
- package/build/development/shared/components/Button/index.js.map +1 -1
- package/build/development/shared/components/Checkbox/index.js +3 -1
- package/build/development/shared/components/Checkbox/index.js.map +1 -1
- package/build/development/shared/components/GenericLink/index.js +13 -6
- package/build/development/shared/components/GenericLink/index.js.map +1 -1
- package/build/development/shared/components/Input/index.js +5 -1
- package/build/development/shared/components/Input/index.js.map +1 -1
- package/build/development/shared/components/Link.js +5 -6
- package/build/development/shared/components/Link.js.map +1 -1
- package/build/development/shared/components/MetaTags.js +31 -24
- package/build/development/shared/components/MetaTags.js.map +1 -1
- package/build/development/shared/components/Modal/index.js +13 -6
- package/build/development/shared/components/Modal/index.js.map +1 -1
- package/build/development/shared/components/NavLink.js +6 -6
- package/build/development/shared/components/NavLink.js.map +1 -1
- package/build/development/shared/components/TextArea/index.js +6 -3
- package/build/development/shared/components/TextArea/index.js.map +1 -1
- package/build/development/shared/components/WithTooltip/Tooltip.js +35 -39
- package/build/development/shared/components/WithTooltip/Tooltip.js.map +1 -1
- package/build/development/shared/components/WithTooltip/index.js +27 -21
- package/build/development/shared/components/WithTooltip/index.js.map +1 -1
- package/build/development/shared/components/YouTubeVideo/index.js +4 -3
- package/build/development/shared/components/YouTubeVideo/index.js.map +1 -1
- package/build/development/shared/components/selectors/CustomDropdown/Options/index.js +4 -5
- package/build/development/shared/components/selectors/CustomDropdown/Options/index.js.map +1 -1
- package/build/development/shared/components/selectors/CustomDropdown/index.js +7 -9
- package/build/development/shared/components/selectors/CustomDropdown/index.js.map +1 -1
- package/build/development/shared/components/selectors/NativeDropdown/index.js +3 -5
- package/build/development/shared/components/selectors/NativeDropdown/index.js.map +1 -1
- package/build/development/shared/components/selectors/Switch/index.js +21 -20
- package/build/development/shared/components/selectors/Switch/index.js.map +1 -1
- package/build/development/shared/utils/config.js +6 -3
- package/build/development/shared/utils/config.js.map +1 -1
- package/build/development/shared/utils/globalState.js +6 -0
- package/build/development/shared/utils/globalState.js.map +1 -1
- package/build/development/shared/utils/isomorphy/buildInfo.js.map +1 -1
- package/build/development/shared/utils/isomorphy/environment-check.js +6 -1
- package/build/development/shared/utils/isomorphy/environment-check.js.map +1 -1
- package/build/development/shared/utils/isomorphy/index.js +1 -3
- package/build/development/shared/utils/isomorphy/index.js.map +1 -1
- package/build/development/shared/utils/jest/E2eSsrEnv.js +26 -17
- package/build/development/shared/utils/jest/E2eSsrEnv.js.map +1 -1
- package/build/development/shared/utils/jest/global.js +0 -7
- package/build/development/shared/utils/jest/global.js.map +1 -1
- package/build/development/shared/utils/jest/index.js +15 -4
- package/build/development/shared/utils/jest/index.js.map +1 -1
- package/build/development/shared/utils/splitComponent.js +37 -19
- package/build/development/shared/utils/splitComponent.js.map +1 -1
- package/build/development/shared/utils/time.js +3 -3
- package/build/development/shared/utils/time.js.map +1 -1
- package/build/development/shared/utils/webpack.js +11 -11
- package/build/development/shared/utils/webpack.js.map +1 -1
- package/build/development/web.bundle.js +30 -30
- package/build/production/client/getInj.js +4 -2
- package/build/production/client/getInj.js.map +1 -1
- package/build/production/client/index.js +2 -2
- package/build/production/client/index.js.map +1 -1
- package/build/production/client/init.js +4 -2
- package/build/production/client/init.js.map +1 -1
- package/build/production/index.js +2 -1
- package/build/production/index.js.map +1 -1
- package/build/production/server/Cache.js +1 -2
- package/build/production/server/Cache.js.map +1 -1
- package/build/production/server/index.js +9 -5
- package/build/production/server/index.js.map +1 -1
- package/build/production/server/renderer.js +24 -21
- package/build/production/server/renderer.js.map +1 -1
- package/build/production/server/server.js +13 -8
- package/build/production/server/server.js.map +1 -1
- package/build/production/server/utils/errors.js.map +1 -1
- package/build/production/shared/components/Button/index.js +1 -1
- package/build/production/shared/components/Button/index.js.map +1 -1
- package/build/production/shared/components/Checkbox/index.js +1 -1
- package/build/production/shared/components/Checkbox/index.js.map +1 -1
- package/build/production/shared/components/GenericLink/index.js +6 -4
- package/build/production/shared/components/GenericLink/index.js.map +1 -1
- package/build/production/shared/components/Input/index.js +3 -1
- package/build/production/shared/components/Input/index.js.map +1 -1
- package/build/production/shared/components/Link.js +3 -1
- package/build/production/shared/components/Link.js.map +1 -1
- package/build/production/shared/components/MetaTags.js +5 -2
- package/build/production/shared/components/MetaTags.js.map +1 -1
- package/build/production/shared/components/Modal/index.js +6 -2
- package/build/production/shared/components/Modal/index.js.map +1 -1
- package/build/production/shared/components/NavLink.js +4 -1
- package/build/production/shared/components/NavLink.js.map +1 -1
- package/build/production/shared/components/TextArea/index.js +4 -4
- package/build/production/shared/components/TextArea/index.js.map +1 -1
- package/build/production/shared/components/WithTooltip/Tooltip.js +37 -38
- package/build/production/shared/components/WithTooltip/Tooltip.js.map +1 -1
- package/build/production/shared/components/WithTooltip/index.js +4 -4
- package/build/production/shared/components/WithTooltip/index.js.map +1 -1
- package/build/production/shared/components/YouTubeVideo/index.js +3 -2
- package/build/production/shared/components/YouTubeVideo/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/components/selectors/CustomDropdown/index.js +2 -2
- package/build/production/shared/components/selectors/CustomDropdown/index.js.map +1 -1
- package/build/production/shared/components/selectors/NativeDropdown/index.js +2 -2
- package/build/production/shared/components/selectors/NativeDropdown/index.js.map +1 -1
- package/build/production/shared/components/selectors/Switch/index.js +1 -1
- package/build/production/shared/components/selectors/Switch/index.js.map +1 -1
- package/build/production/shared/utils/config.js +6 -4
- package/build/production/shared/utils/config.js.map +1 -1
- package/build/production/shared/utils/globalState.js +4 -1
- package/build/production/shared/utils/globalState.js.map +1 -1
- package/build/production/shared/utils/isomorphy/buildInfo.js.map +1 -1
- package/build/production/shared/utils/isomorphy/environment-check.js +5 -1
- package/build/production/shared/utils/isomorphy/environment-check.js.map +1 -1
- package/build/production/shared/utils/isomorphy/index.js +1 -3
- package/build/production/shared/utils/isomorphy/index.js.map +1 -1
- package/build/production/shared/utils/jest/E2eSsrEnv.js +15 -8
- package/build/production/shared/utils/jest/E2eSsrEnv.js.map +1 -1
- package/build/production/shared/utils/jest/global.js +1 -1
- package/build/production/shared/utils/jest/global.js.map +1 -1
- package/build/production/shared/utils/jest/index.js +13 -5
- package/build/production/shared/utils/jest/index.js.map +1 -1
- package/build/production/shared/utils/splitComponent.js +16 -8
- package/build/production/shared/utils/splitComponent.js.map +1 -1
- package/build/production/shared/utils/time.js +2 -2
- package/build/production/shared/utils/time.js.map +1 -1
- package/build/production/shared/utils/webpack.js +5 -2
- package/build/production/shared/utils/webpack.js.map +1 -1
- package/build/production/web.bundle.js +1 -1
- package/build/production/web.bundle.js.map +1 -1
- package/build/types-code/client/getInj.d.ts +1 -1
- package/build/types-code/client/index.d.ts +2 -2
- package/build/types-code/client/init.d.ts +1 -1
- package/build/types-code/index.d.ts +6 -5
- package/build/types-code/server/Cache.d.ts +1 -2
- package/build/types-code/server/index.d.ts +4 -5
- package/build/types-code/server/renderer.d.ts +8 -10
- package/build/types-code/server/server.d.ts +3 -5
- package/build/types-code/server/utils/errors.d.ts +1 -1
- package/build/types-code/shared/components/Button/index.d.ts +2 -2
- package/build/types-code/shared/components/TextArea/index.d.ts +3 -3
- package/build/types-code/shared/components/WithTooltip/Tooltip.d.ts +7 -1
- package/build/types-code/shared/components/index.d.ts +12 -12
- package/build/types-code/shared/utils/config.d.ts +1 -1
- package/build/types-code/shared/utils/globalState.d.ts +3 -6
- package/build/types-code/shared/utils/isomorphy/index.d.ts +1 -3
- package/build/types-code/shared/utils/jest/E2eSsrEnv.d.ts +1 -1
- package/build/types-code/shared/utils/jest/global.d.ts +4 -4
- package/build/types-code/shared/utils/jest/index.d.ts +2 -2
- package/build/types-code/shared/utils/webpack.d.ts +1 -1
- package/config/babel/node-ssr.d.ts +3 -2
- package/config/babel/node-ssr.js +5 -7
- package/config/babel/webpack.d.ts +3 -11
- package/config/babel/webpack.js +15 -15
- package/config/eslint/default.mjs +32 -0
- package/config/jest/default.js +10 -6
- package/config/jest/resolver.js +2 -0
- package/config/jest/setup.js +2 -2
- package/config/stylelint/default.js +3 -0
- package/config/webpack/app-base.d.ts +0 -6
- package/config/webpack/app-base.js +64 -70
- package/config/webpack/app-development.d.ts +2 -2
- package/config/webpack/app-development.js +8 -12
- package/config/webpack/app-production.js +1 -0
- package/config/webpack/lib-base.js +20 -18
- package/config/webpack/lib-development.js +1 -0
- package/config/webpack/lib-production.js +1 -0
- package/config/workbox/default.js +2 -5
- package/dev-styles.js +1 -0
- package/eslint.config.mjs +13 -0
- package/node-entry.js +7 -2
- package/null.js +1 -0
- package/package.json +17 -25
- package/prod-styles.js +1 -0
- package/src/client/getInj.ts +8 -3
- package/src/client/index.tsx +4 -4
- package/src/client/init.ts +18 -15
- package/src/index.ts +8 -3
- package/src/server/Cache.ts +7 -15
- package/src/server/index.ts +30 -21
- package/src/server/renderer.tsx +76 -66
- package/src/server/server.ts +38 -20
- package/src/server/utils/errors.ts +6 -3
- package/src/shared/components/Button/index.tsx +4 -5
- package/src/shared/components/Checkbox/index.tsx +10 -7
- package/src/shared/components/GenericLink/index.tsx +14 -7
- package/src/shared/components/Input/index.tsx +4 -1
- package/src/shared/components/Link.tsx +9 -5
- package/src/shared/components/MetaTags.tsx +21 -15
- package/src/shared/components/Modal/index.tsx +12 -11
- package/src/shared/components/NavLink.tsx +10 -5
- package/src/shared/components/TextArea/index.tsx +17 -9
- package/src/shared/components/WithTooltip/{Tooltip.tsx → Tooltip.ts} +35 -39
- package/src/shared/components/WithTooltip/index.tsx +36 -30
- package/src/shared/components/YouTubeVideo/index.tsx +10 -6
- package/src/shared/components/selectors/CustomDropdown/Options/index.tsx +5 -6
- package/src/shared/components/selectors/CustomDropdown/index.tsx +10 -14
- package/src/shared/components/selectors/NativeDropdown/index.tsx +5 -7
- package/src/shared/components/selectors/Switch/index.tsx +19 -17
- package/src/shared/utils/config.ts +12 -5
- package/src/shared/utils/globalState.ts +8 -5
- package/src/shared/utils/isomorphy/buildInfo.ts +1 -1
- package/src/shared/utils/isomorphy/environment-check.ts +5 -1
- package/src/shared/utils/isomorphy/index.ts +4 -6
- package/src/shared/utils/jest/E2eSsrEnv.ts +64 -39
- package/src/shared/utils/jest/global.ts +6 -8
- package/src/shared/utils/jest/{index.tsx → index.ts} +25 -12
- package/src/shared/utils/splitComponent.tsx +44 -25
- package/src/shared/utils/time.ts +16 -9
- package/src/shared/utils/webpack.ts +19 -14
- package/webpack.config.ts +36 -10
- package/config/eslint/default.json +0 -30
- package/config/eslint/jest.json +0 -19
- package/config/eslint/typescript.js +0 -46
|
@@ -18,8 +18,10 @@ import { createPortal } from 'react-dom';
|
|
|
18
18
|
|
|
19
19
|
import type { Theme } from '@dr.pogodin/react-themes';
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
*
|
|
21
|
+
/**
|
|
22
|
+
* Valid placements of the rendered tooltip. They will be overriden when
|
|
23
|
+
* necessary to fit the tooltip within the viewport.
|
|
24
|
+
*/
|
|
23
25
|
export enum PLACEMENTS {
|
|
24
26
|
ABOVE_CURSOR = 'ABOVE_CURSOR',
|
|
25
27
|
ABOVE_ELEMENT = 'ABOVE_ELEMENT',
|
|
@@ -82,7 +84,7 @@ function createTooltipComponents(theme: TooltipThemeT): ComponentsT {
|
|
|
82
84
|
container.appendChild(content);
|
|
83
85
|
document.body.appendChild(container);
|
|
84
86
|
|
|
85
|
-
return {
|
|
87
|
+
return { arrow, container, content };
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
type TooltipRectsT = {
|
|
@@ -115,10 +117,10 @@ function calcViewportRect() {
|
|
|
115
117
|
const { scrollX, scrollY } = window;
|
|
116
118
|
const { documentElement: { clientHeight, clientWidth } } = document;
|
|
117
119
|
return {
|
|
120
|
+
bottom: scrollY + clientHeight,
|
|
118
121
|
left: scrollX,
|
|
119
122
|
right: scrollX + clientWidth,
|
|
120
123
|
top: scrollY,
|
|
121
|
-
bottom: scrollY + clientHeight,
|
|
122
124
|
};
|
|
123
125
|
}
|
|
124
126
|
|
|
@@ -157,15 +159,13 @@ function calcPositionAboveXY(
|
|
|
157
159
|
};
|
|
158
160
|
}
|
|
159
161
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
};
|
|
168
|
-
*/
|
|
162
|
+
// const HIT = {
|
|
163
|
+
// NONE: false,
|
|
164
|
+
// LEFT: 'LEFT',
|
|
165
|
+
// RIGHT: 'RIGHT',
|
|
166
|
+
// TOP: 'TOP',
|
|
167
|
+
// BOTTOM: 'BOTTOM',
|
|
168
|
+
// };
|
|
169
169
|
|
|
170
170
|
/**
|
|
171
171
|
* Checks whether
|
|
@@ -174,14 +174,12 @@ const HIT = {
|
|
|
174
174
|
* @param {object} viewportRect
|
|
175
175
|
* @return {HIT}
|
|
176
176
|
*/
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
*/
|
|
177
|
+
// function checkViewportFit(pos, tooltipRects, viewportRect) {
|
|
178
|
+
// const { containerX, containerY } = pos;
|
|
179
|
+
// if (containerX < viewportRect.left + 6) return HIT.LEFT;
|
|
180
|
+
// if (containerX > viewportRect.right - 6) return HIT.RIGHT;
|
|
181
|
+
// return HIT.NONE;
|
|
182
|
+
// }
|
|
185
183
|
|
|
186
184
|
/**
|
|
187
185
|
* Shifts tooltip horizontally to fit into the viewport, while keeping
|
|
@@ -192,23 +190,21 @@ function checkViewportFit(pos, tooltipRects, viewportRect) {
|
|
|
192
190
|
* @param {number} pageXOffset
|
|
193
191
|
* @param {number} pageXWidth
|
|
194
192
|
*/
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
*/
|
|
193
|
+
// function xPageFitCorrection(x, y, pos, pageXOffset, pageXWidth) {
|
|
194
|
+
// if (pos.containerX < pageXOffset + 6) {
|
|
195
|
+
// pos.containerX = pageXOffset + 6;
|
|
196
|
+
// pos.arrowX = Math.max(6, pageX - containerX - arrowRect.width / 2);
|
|
197
|
+
// } else {
|
|
198
|
+
// const maxX = pageXOffset + docRect.width - containerRect.width - 6;
|
|
199
|
+
// if (containerX > maxX) {
|
|
200
|
+
// containerX = maxX;
|
|
201
|
+
// arrowX = Math.min(
|
|
202
|
+
// containerRect.width - 6,
|
|
203
|
+
// pageX - containerX - arrowRect.width / 2,
|
|
204
|
+
// );
|
|
205
|
+
// }
|
|
206
|
+
// }
|
|
207
|
+
// }
|
|
212
208
|
|
|
213
209
|
/**
|
|
214
210
|
* Sets positions of tooltip components to point the tooltip to the specified
|
|
@@ -272,7 +268,7 @@ function setComponentPositions(
|
|
|
272
268
|
const Tooltip: FunctionComponent<{
|
|
273
269
|
children?: ReactNode;
|
|
274
270
|
ref?: RefObject<unknown>;
|
|
275
|
-
theme:
|
|
271
|
+
theme: TooltipThemeT;
|
|
276
272
|
}> = ({ children, ref, theme }) => {
|
|
277
273
|
// NOTE: The way it has to be implemented, for clean mounting and unmounting
|
|
278
274
|
// at the client side, the <Tooltip> is fully mounted into DOM in the next
|
|
@@ -63,34 +63,15 @@ const Wrapper: FunctionComponent<PropsT> = ({
|
|
|
63
63
|
const { current: heap } = useRef<HeapT>({
|
|
64
64
|
lastCursorX: 0,
|
|
65
65
|
lastCursorY: 0,
|
|
66
|
-
triggeredByTouch: false,
|
|
67
66
|
timerId: undefined,
|
|
67
|
+
triggeredByTouch: false,
|
|
68
68
|
});
|
|
69
69
|
const tooltipRef = useRef<TooltipRefT>(null);
|
|
70
70
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
71
71
|
const [showTooltip, setShowTooltip] = useState(false);
|
|
72
72
|
|
|
73
73
|
const updatePortalPosition = (cursorX: number, cursorY: number) => {
|
|
74
|
-
if (
|
|
75
|
-
heap.lastCursorX = cursorX;
|
|
76
|
-
heap.lastCursorY = cursorY;
|
|
77
|
-
|
|
78
|
-
// If tooltip was triggered by a touch, we delay its opening by a bit,
|
|
79
|
-
// to ensure it was not a touch-click - in the case of touch click we
|
|
80
|
-
// want to do the click, rather than show the tooltip, and the delay
|
|
81
|
-
// gives click handler a chance to abort the tooltip openning.
|
|
82
|
-
if (heap.triggeredByTouch) {
|
|
83
|
-
if (!heap.timerId) {
|
|
84
|
-
heap.timerId = setTimeout(() => {
|
|
85
|
-
heap.triggeredByTouch = false;
|
|
86
|
-
heap.timerId = undefined;
|
|
87
|
-
setShowTooltip(true);
|
|
88
|
-
}, 300);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Otherwise we can just open the tooltip right away.
|
|
92
|
-
} else setShowTooltip(true);
|
|
93
|
-
} else {
|
|
74
|
+
if (showTooltip) {
|
|
94
75
|
const wrapperRect = wrapperRef.current!.getBoundingClientRect();
|
|
95
76
|
if (
|
|
96
77
|
cursorX < wrapperRect.left
|
|
@@ -103,10 +84,27 @@ const Wrapper: FunctionComponent<PropsT> = ({
|
|
|
103
84
|
tooltipRef.current.pointTo(
|
|
104
85
|
cursorX + window.scrollX,
|
|
105
86
|
cursorY + window.scrollY,
|
|
106
|
-
placement
|
|
87
|
+
placement,
|
|
107
88
|
wrapperRef.current!,
|
|
108
89
|
);
|
|
109
90
|
}
|
|
91
|
+
} else {
|
|
92
|
+
heap.lastCursorX = cursorX;
|
|
93
|
+
heap.lastCursorY = cursorY;
|
|
94
|
+
|
|
95
|
+
// If tooltip was triggered by a touch, we delay its opening by a bit,
|
|
96
|
+
// to ensure it was not a touch-click - in the case of touch click we
|
|
97
|
+
// want to do the click, rather than show the tooltip, and the delay
|
|
98
|
+
// gives click handler a chance to abort the tooltip openning.
|
|
99
|
+
if (heap.triggeredByTouch) {
|
|
100
|
+
heap.timerId ??= setTimeout(() => {
|
|
101
|
+
heap.triggeredByTouch = false;
|
|
102
|
+
heap.timerId = undefined;
|
|
103
|
+
setShowTooltip(true);
|
|
104
|
+
}, 300);
|
|
105
|
+
|
|
106
|
+
// Otherwise we can just open the tooltip right away.
|
|
107
|
+
} else setShowTooltip(true);
|
|
110
108
|
}
|
|
111
109
|
};
|
|
112
110
|
|
|
@@ -121,14 +119,18 @@ const Wrapper: FunctionComponent<PropsT> = ({
|
|
|
121
119
|
tooltipRef.current.pointTo(
|
|
122
120
|
heap.lastCursorX + window.scrollX,
|
|
123
121
|
heap.lastCursorY + window.scrollY,
|
|
124
|
-
placement
|
|
122
|
+
placement,
|
|
125
123
|
wrapperRef.current!,
|
|
126
124
|
);
|
|
127
125
|
}
|
|
128
126
|
|
|
129
|
-
const listener = () =>
|
|
127
|
+
const listener = () => {
|
|
128
|
+
setShowTooltip(false);
|
|
129
|
+
};
|
|
130
130
|
window.addEventListener('scroll', listener);
|
|
131
|
-
return () =>
|
|
131
|
+
return () => {
|
|
132
|
+
window.removeEventListener('scroll', listener);
|
|
133
|
+
};
|
|
132
134
|
}
|
|
133
135
|
return undefined;
|
|
134
136
|
}, [
|
|
@@ -142,8 +144,6 @@ const Wrapper: FunctionComponent<PropsT> = ({
|
|
|
142
144
|
return (
|
|
143
145
|
<div
|
|
144
146
|
className={theme.wrapper}
|
|
145
|
-
onMouseLeave={() => setShowTooltip(false)}
|
|
146
|
-
onMouseMove={(e) => updatePortalPosition(e.clientX, e.clientY)}
|
|
147
147
|
onClick={() => {
|
|
148
148
|
if (heap.timerId) {
|
|
149
149
|
clearTimeout(heap.timerId);
|
|
@@ -151,6 +151,12 @@ const Wrapper: FunctionComponent<PropsT> = ({
|
|
|
151
151
|
heap.triggeredByTouch = false;
|
|
152
152
|
}
|
|
153
153
|
}}
|
|
154
|
+
onMouseLeave={() => {
|
|
155
|
+
setShowTooltip(false);
|
|
156
|
+
}}
|
|
157
|
+
onMouseMove={(e) => {
|
|
158
|
+
updatePortalPosition(e.clientX, e.clientY);
|
|
159
|
+
}}
|
|
154
160
|
onTouchStart={() => {
|
|
155
161
|
heap.triggeredByTouch = true;
|
|
156
162
|
}}
|
|
@@ -158,9 +164,9 @@ const Wrapper: FunctionComponent<PropsT> = ({
|
|
|
158
164
|
role="presentation"
|
|
159
165
|
>
|
|
160
166
|
{
|
|
161
|
-
showTooltip && tip !== null
|
|
162
|
-
<Tooltip ref={tooltipRef} theme={theme}>{tip}</Tooltip>
|
|
163
|
-
|
|
167
|
+
showTooltip && tip !== null
|
|
168
|
+
? <Tooltip ref={tooltipRef} theme={theme}>{tip}</Tooltip>
|
|
169
|
+
: null
|
|
164
170
|
}
|
|
165
171
|
{children}
|
|
166
172
|
</div>
|
|
@@ -12,7 +12,7 @@ type ComponentThemeT = Theme<'container' | 'video'>;
|
|
|
12
12
|
type PropsT = {
|
|
13
13
|
autoplay?: boolean;
|
|
14
14
|
src: string;
|
|
15
|
-
theme: ComponentThemeT
|
|
15
|
+
theme: ComponentThemeT;
|
|
16
16
|
title?: string;
|
|
17
17
|
};
|
|
18
18
|
|
|
@@ -38,12 +38,12 @@ const YouTubeVideo: React.FunctionComponent<PropsT> = ({
|
|
|
38
38
|
title,
|
|
39
39
|
}) => {
|
|
40
40
|
const srcParts = src.split('?');
|
|
41
|
-
let url = srcParts
|
|
42
|
-
const queryString = srcParts
|
|
41
|
+
let [url] = srcParts;
|
|
42
|
+
const [, queryString] = srcParts;
|
|
43
43
|
const query = queryString ? qs.parse(queryString) : {};
|
|
44
44
|
|
|
45
|
-
const videoId = query.v
|
|
46
|
-
url = `https://www.youtube.com/embed/${videoId}`;
|
|
45
|
+
const videoId = query.v ?? url?.match(/\/([a-zA-Z0-9-_]*)$/)?.[1];
|
|
46
|
+
url = `https://www.youtube.com/embed/${videoId as string}`;
|
|
47
47
|
|
|
48
48
|
delete query.v;
|
|
49
49
|
query.autoplay = autoplay ? '1' : '0';
|
|
@@ -55,7 +55,11 @@ const YouTubeVideo: React.FunctionComponent<PropsT> = ({
|
|
|
55
55
|
return (
|
|
56
56
|
<div className={theme.container}>
|
|
57
57
|
<Throbber theme={throbberTheme} />
|
|
58
|
-
|
|
58
|
+
{/* TODO: I guess, we better add the sanbox, but right now I don't have
|
|
59
|
+
time to carefully explore which restrictions should be lifted to allow
|
|
60
|
+
embed YouTube player to work... sometime later we'll take care of it */
|
|
61
|
+
}
|
|
62
|
+
<iframe // eslint-disable-line react/iframe-missing-sandbox
|
|
59
63
|
allow="autoplay"
|
|
60
64
|
allowFullScreen
|
|
61
65
|
className={theme.video}
|
|
@@ -71,13 +71,13 @@ const Options: FunctionComponent<PropsT> = ({
|
|
|
71
71
|
}), []);
|
|
72
72
|
|
|
73
73
|
const optionNodes: ReactNode[] = [];
|
|
74
|
-
for (
|
|
75
|
-
|
|
76
|
-
if (option !== undefined && (!filter || filter(option))) {
|
|
74
|
+
for (const option of options) {
|
|
75
|
+
if (!filter || filter(option)) {
|
|
77
76
|
const [iValue, iName] = optionValueName(option);
|
|
78
77
|
optionNodes.push(
|
|
79
78
|
<div
|
|
80
79
|
className={optionClass}
|
|
80
|
+
key={iValue}
|
|
81
81
|
onClick={(e) => {
|
|
82
82
|
onChange(iValue);
|
|
83
83
|
e.stopPropagation();
|
|
@@ -88,7 +88,6 @@ const Options: FunctionComponent<PropsT> = ({
|
|
|
88
88
|
e.stopPropagation();
|
|
89
89
|
}
|
|
90
90
|
}}
|
|
91
|
-
key={iValue}
|
|
92
91
|
role="button"
|
|
93
92
|
tabIndex={0}
|
|
94
93
|
>
|
|
@@ -106,14 +105,14 @@ const Options: FunctionComponent<PropsT> = ({
|
|
|
106
105
|
// dropdowns during the scrolling (that would need to re-position it in
|
|
107
106
|
// response to the position changes of the root dropdown element).
|
|
108
107
|
cancelOnScrolling
|
|
109
|
-
style={containerStyle}
|
|
110
108
|
dontDisableScrolling
|
|
111
109
|
onCancel={onCancel}
|
|
110
|
+
style={containerStyle}
|
|
112
111
|
theme={{
|
|
113
112
|
ad: '',
|
|
114
|
-
hoc: '',
|
|
115
113
|
container: containerClass,
|
|
116
114
|
context: '',
|
|
115
|
+
hoc: '',
|
|
117
116
|
overlay: S.overlay,
|
|
118
117
|
}}
|
|
119
118
|
>
|
|
@@ -9,7 +9,7 @@ import defaultTheme from './theme.scss';
|
|
|
9
9
|
import { type PropsT, type ValueT, optionValueName } from '../common';
|
|
10
10
|
|
|
11
11
|
const BaseCustomDropdown: React.FunctionComponent<
|
|
12
|
-
PropsT<React.ReactNode, (value: ValueT) => void>
|
|
12
|
+
PropsT<React.ReactNode, (value: ValueT) => void>
|
|
13
13
|
> = ({
|
|
14
14
|
filter,
|
|
15
15
|
label,
|
|
@@ -18,8 +18,6 @@ PropsT<React.ReactNode, (value: ValueT) => void>
|
|
|
18
18
|
theme,
|
|
19
19
|
value,
|
|
20
20
|
}) => {
|
|
21
|
-
if (!options) throw Error('Internal error');
|
|
22
|
-
|
|
23
21
|
const [active, setActive] = useState(false);
|
|
24
22
|
|
|
25
23
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
@@ -44,8 +42,8 @@ PropsT<React.ReactNode, (value: ValueT) => void>
|
|
|
44
42
|
setUpward(up);
|
|
45
43
|
|
|
46
44
|
const pos = up ? {
|
|
47
|
-
top: anchor.top - opsRect.height - 1,
|
|
48
45
|
left: anchor.left,
|
|
46
|
+
top: anchor.top - opsRect.height - 1,
|
|
49
47
|
width: anchor.width,
|
|
50
48
|
} : {
|
|
51
49
|
left: anchor.left,
|
|
@@ -78,8 +76,8 @@ PropsT<React.ReactNode, (value: ValueT) => void>
|
|
|
78
76
|
// move it above, at least with the current position update via local
|
|
79
77
|
// react state, and not imperatively).
|
|
80
78
|
setOpsPos({
|
|
81
|
-
left: view?.width
|
|
82
|
-
top: view?.height
|
|
79
|
+
left: view?.width ?? 0,
|
|
80
|
+
top: view?.height ?? 0,
|
|
83
81
|
width: rect.width,
|
|
84
82
|
});
|
|
85
83
|
|
|
@@ -87,9 +85,8 @@ PropsT<React.ReactNode, (value: ValueT) => void>
|
|
|
87
85
|
};
|
|
88
86
|
|
|
89
87
|
let selected: React.ReactNode = <>‌</>;
|
|
90
|
-
for (
|
|
91
|
-
|
|
92
|
-
if (option !== undefined && (!filter || filter(option))) {
|
|
88
|
+
for (const option of options) {
|
|
89
|
+
if (!filter || filter(option)) {
|
|
93
90
|
const [iValue, iName] = optionValueName(option);
|
|
94
91
|
if (iValue === value) {
|
|
95
92
|
selected = iName;
|
|
@@ -101,7 +98,7 @@ PropsT<React.ReactNode, (value: ValueT) => void>
|
|
|
101
98
|
let containerClassName = theme.container;
|
|
102
99
|
if (active) containerClassName += ` ${theme.active}`;
|
|
103
100
|
|
|
104
|
-
let opsContainerClass = theme.select
|
|
101
|
+
let opsContainerClass = theme.select ?? '';
|
|
105
102
|
if (upward) {
|
|
106
103
|
containerClassName += ` ${theme.upward}`;
|
|
107
104
|
opsContainerClass += ` ${theme.upward}`;
|
|
@@ -109,9 +106,8 @@ PropsT<React.ReactNode, (value: ValueT) => void>
|
|
|
109
106
|
|
|
110
107
|
return (
|
|
111
108
|
<div className={containerClassName}>
|
|
112
|
-
{label === undefined ? null
|
|
113
|
-
<div className={theme.label}>{label}</div>
|
|
114
|
-
)}
|
|
109
|
+
{label === undefined ? null
|
|
110
|
+
: <div className={theme.label}>{label}</div>}
|
|
115
111
|
<div
|
|
116
112
|
className={theme.dropdown}
|
|
117
113
|
onClick={openList}
|
|
@@ -137,7 +133,7 @@ PropsT<React.ReactNode, (value: ValueT) => void>
|
|
|
137
133
|
setActive(false);
|
|
138
134
|
if (onChange) onChange(newValue);
|
|
139
135
|
}}
|
|
140
|
-
optionClass={theme.option
|
|
136
|
+
optionClass={theme.option ?? ''}
|
|
141
137
|
options={options}
|
|
142
138
|
ref={opsRef}
|
|
143
139
|
/>
|
|
@@ -34,14 +34,11 @@ const Dropdown: React.FunctionComponent<PropsT<string>> = ({
|
|
|
34
34
|
theme,
|
|
35
35
|
value,
|
|
36
36
|
}) => {
|
|
37
|
-
if (!options) throw Error('Internal error');
|
|
38
|
-
|
|
39
37
|
let isValidValue = false;
|
|
40
38
|
const optionElements = [];
|
|
41
39
|
|
|
42
|
-
for (
|
|
43
|
-
|
|
44
|
-
if (option !== undefined && (!filter || filter(option))) {
|
|
40
|
+
for (const option of options) {
|
|
41
|
+
if (!filter || filter(option)) {
|
|
45
42
|
const [iValue, iName] = optionValueName(option);
|
|
46
43
|
isValidValue ||= iValue === value;
|
|
47
44
|
optionElements.push(
|
|
@@ -58,8 +55,8 @@ const Dropdown: React.FunctionComponent<PropsT<string>> = ({
|
|
|
58
55
|
// to show it as disabled.
|
|
59
56
|
const hiddenOption = isValidValue ? null : (
|
|
60
57
|
<option
|
|
61
|
-
disabled
|
|
62
58
|
className={theme.hiddenOption}
|
|
59
|
+
disabled
|
|
63
60
|
key="__reactUtilsHiddenOption"
|
|
64
61
|
value={value}
|
|
65
62
|
>
|
|
@@ -72,7 +69,8 @@ const Dropdown: React.FunctionComponent<PropsT<string>> = ({
|
|
|
72
69
|
|
|
73
70
|
return (
|
|
74
71
|
<div className={theme.container}>
|
|
75
|
-
{ label === undefined
|
|
72
|
+
{ label === undefined
|
|
73
|
+
? null : <div className={theme.label}>{label}</div> }
|
|
76
74
|
<div className={theme.dropdown}>
|
|
77
75
|
<select
|
|
78
76
|
className={selectClassName}
|
|
@@ -33,40 +33,42 @@ const BaseSwitch: React.FunctionComponent<PropsT> = ({
|
|
|
33
33
|
if (!options || !theme.option) throw Error('Internal error');
|
|
34
34
|
|
|
35
35
|
const optionNodes: React.ReactNode[] = [];
|
|
36
|
-
for (
|
|
37
|
-
const
|
|
38
|
-
if (option !== undefined) {
|
|
39
|
-
const [iValue, iName] = optionValueName(option);
|
|
36
|
+
for (const option of options) {
|
|
37
|
+
const [iValue, iName] = optionValueName(option);
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
let className: string = theme.option;
|
|
40
|
+
let onPress: (() => void) | undefined;
|
|
41
|
+
if (iValue === value) className += ` ${theme.selected}`;
|
|
42
|
+
else if (onChange) {
|
|
43
|
+
onPress = () => {
|
|
44
|
+
onChange(iValue);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
optionNodes.push(
|
|
49
|
+
onPress
|
|
50
|
+
? (
|
|
48
51
|
<div
|
|
49
52
|
className={className}
|
|
53
|
+
key={iValue}
|
|
50
54
|
onClick={onPress}
|
|
51
55
|
onKeyDown={(e) => {
|
|
52
|
-
if (
|
|
56
|
+
if (e.key === 'Enter') onPress();
|
|
53
57
|
}}
|
|
54
|
-
key={iValue}
|
|
55
58
|
role="button"
|
|
56
59
|
tabIndex={0}
|
|
57
60
|
>
|
|
58
61
|
{iName}
|
|
59
62
|
</div>
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
);
|
|
64
|
-
}
|
|
63
|
+
)
|
|
64
|
+
: <div className={className} key={iValue}>{iName}</div>,
|
|
65
|
+
);
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
return (
|
|
68
69
|
<div className={theme.container}>
|
|
69
70
|
{label ? <div className={theme.label}>{label}</div> : null}
|
|
71
|
+
|
|
70
72
|
<div className={theme.options}>
|
|
71
73
|
{optionNodes}
|
|
72
74
|
</div>
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
/* global document */
|
|
2
2
|
|
|
3
|
+
import type CookieM from 'cookie';
|
|
4
|
+
|
|
3
5
|
import { IS_CLIENT_SIDE } from './isomorphy/environment-check';
|
|
4
6
|
import { requireWeak } from './webpack';
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
// TODO: The internal type casting is somewhat messed up here,
|
|
9
|
+
// to be corrected later.
|
|
10
|
+
const config: Record<string, unknown> = (
|
|
7
11
|
IS_CLIENT_SIDE
|
|
8
|
-
// eslint-disable-next-line
|
|
9
|
-
? require('client/getInj')
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
|
+
? (require('client/getInj') as {
|
|
14
|
+
default: () => Record<string, unknown>;
|
|
15
|
+
}).default().CONFIG
|
|
10
16
|
: requireWeak('config')
|
|
11
|
-
)
|
|
17
|
+
) as (Record<string, unknown> | undefined) ?? ({} as Record<string, unknown>);
|
|
12
18
|
|
|
13
19
|
// The safeguard for "document" is necessary because in non-Node environments,
|
|
14
20
|
// like React Native, IS_CLIENT_SIDE is "true", however "document" and a bunch
|
|
15
21
|
// of other browser-world features are not available.
|
|
16
22
|
if (IS_CLIENT_SIDE && typeof document !== 'undefined') {
|
|
17
|
-
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
24
|
+
const cookie = require('cookie') as typeof CookieM;
|
|
18
25
|
config.CSRF = cookie.parse(document.cookie).csrfToken;
|
|
19
26
|
}
|
|
20
27
|
|
|
@@ -2,27 +2,30 @@ import type { Request } from 'express';
|
|
|
2
2
|
|
|
3
3
|
import { type SsrContext, withGlobalStateType } from '@dr.pogodin/react-global-state';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
5
|
+
/** Mapping "chunkName" > array of asset paths. */
|
|
6
|
+
export type ChunkGroupsT = Record<string, string[]>;
|
|
8
7
|
|
|
9
8
|
// The type of data object injected by server into generated markup.
|
|
10
9
|
export type InjT = {
|
|
11
10
|
CHUNK_GROUPS?: ChunkGroupsT;
|
|
12
|
-
CONFIG?:
|
|
11
|
+
CONFIG?: Record<string, unknown>;
|
|
13
12
|
ISTATE?: unknown;
|
|
14
13
|
};
|
|
15
14
|
|
|
16
15
|
declare global {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
17
17
|
interface Window {
|
|
18
18
|
REACT_UTILS_INJECTION?: InjT;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
// TODO: Not 100% sure now, whether it indeed can be replaced by type,
|
|
23
|
+
// or do we really need it to be an interface. Keeping the interface for now.
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
22
25
|
export interface SsrContextT<StateT> extends SsrContext<StateT> {
|
|
23
26
|
chunkGroups: ChunkGroupsT;
|
|
24
27
|
chunks: string[];
|
|
25
|
-
req: Request
|
|
28
|
+
req: Request;
|
|
26
29
|
status: number;
|
|
27
30
|
}
|
|
28
31
|
|
|
@@ -31,7 +31,7 @@ if (typeof BUILD_INFO !== 'undefined') buildInfo = BUILD_INFO;
|
|
|
31
31
|
* @param info
|
|
32
32
|
* @param force
|
|
33
33
|
*/
|
|
34
|
-
export function setBuildInfo(info?: BuildInfoT, force = false) {
|
|
34
|
+
export function setBuildInfo(info?: BuildInfoT, force = false): void {
|
|
35
35
|
if (buildInfo !== undefined && !force) {
|
|
36
36
|
throw Error('"Build Info" is already initialized');
|
|
37
37
|
}
|
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
* `true` within client-side environment (browser), `false` at server-side.
|
|
5
5
|
*/
|
|
6
6
|
export const IS_CLIENT_SIDE: boolean = typeof process !== 'object'
|
|
7
|
-
|
|
7
|
+
// NOTE: Because in this case we assume the host environment might be partially
|
|
8
|
+
// polyfilled to emulate some Node interfaces, thus it might have global `process`
|
|
9
|
+
// object, but without `versions` sub-object inside it.
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
11
|
+
|| !process.versions?.node
|
|
8
12
|
|| !!global.REACT_UTILS_FORCE_CLIENT_SIDE;
|
|
9
13
|
|
|
10
14
|
/**
|
|
@@ -12,26 +12,24 @@ function getMode() {
|
|
|
12
12
|
/**
|
|
13
13
|
* Returns `true` if development version of the code is running;
|
|
14
14
|
* `false` otherwise.
|
|
15
|
-
* @return {boolean}
|
|
16
15
|
*/
|
|
17
|
-
export function isDevBuild() {
|
|
16
|
+
export function isDevBuild(): boolean {
|
|
18
17
|
return getMode() === 'development';
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
/**
|
|
22
21
|
* Returns `true` if production build of the code is running;
|
|
23
22
|
* `false` otherwise.
|
|
24
|
-
* @return {boolean}
|
|
25
23
|
*/
|
|
26
|
-
export function isProdBuild() {
|
|
24
|
+
export function isProdBuild(): boolean {
|
|
27
25
|
return getMode() === 'production';
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
/**
|
|
31
29
|
* Returns build timestamp of the front-end JS bundle.
|
|
32
|
-
* @return
|
|
30
|
+
* @return ISO date/time string.
|
|
33
31
|
*/
|
|
34
|
-
export function buildTimestamp() {
|
|
32
|
+
export function buildTimestamp(): string {
|
|
35
33
|
return getBuildInfo().timestamp;
|
|
36
34
|
}
|
|
37
35
|
|