@dr.pogodin/react-utils 1.44.10 → 1.46.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.
@@ -1,3 +1,3 @@
1
1
  import { type PropsT, type ValueT } from '../common';
2
- declare const _default: import("@dr.pogodin/react-themes").ThemedComponent<PropsT<React.ReactNode, (value: ValueT) => void>>;
2
+ declare const _default: import("@dr.pogodin/react-themes").ThemedComponent<PropsT<import("react").ReactNode, (value: ValueT) => void>>;
3
3
  export default _default;
@@ -1,6 +1,5 @@
1
1
  type RequireWeakOptionsT = {
2
2
  basePath?: string;
3
- throwOnError?: boolean;
4
3
  };
5
4
  type RequireWeakResT<T> = T extends {
6
5
  default: infer D;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.44.10",
2
+ "version": "1.46.0",
3
3
  "bin": {
4
4
  "react-utils-build": "bin/build.js",
5
5
  "react-utils-setup": "bin/setup.js"
@@ -10,11 +10,11 @@
10
10
  "dependencies": {
11
11
  "@babel/runtime": "^7.28.4",
12
12
  "@dr.pogodin/babel-plugin-react-css-modules": "^6.13.8",
13
- "@dr.pogodin/csurf": "^1.16.5",
13
+ "@dr.pogodin/csurf": "^1.16.6",
14
14
  "@dr.pogodin/js-utils": "^0.1.3",
15
- "@dr.pogodin/react-global-state": "^0.19.4",
15
+ "@dr.pogodin/react-global-state": "^0.20.0",
16
16
  "@dr.pogodin/react-helmet": "^3.0.4",
17
- "@dr.pogodin/react-themes": "^1.9.2",
17
+ "@dr.pogodin/react-themes": "^1.9.3",
18
18
  "@jest/environment": "^30.2.0",
19
19
  "axios": "^1.12.2",
20
20
  "commander": "^14.0.1",
@@ -32,9 +32,9 @@
32
32
  "node-forge": "^1.3.1",
33
33
  "qs": "^6.14.0",
34
34
  "raf": "^3.4.1",
35
- "react": "^19.1.1",
36
- "react-dom": "^19.1.1",
37
- "react-router": "^7.9.3",
35
+ "react": "^19.2.0",
36
+ "react-dom": "^19.2.0",
37
+ "react-router": "^7.9.4",
38
38
  "request-ip": "^3.3.0",
39
39
  "rimraf": "^6.0.0",
40
40
  "serialize-javascript": "^7.0.0",
@@ -55,7 +55,7 @@
55
55
  "@babel/register": "^7.28.3",
56
56
  "@dr.pogodin/babel-plugin-transform-assets": "^1.2.5",
57
57
  "@dr.pogodin/babel-preset-svgr": "^1.9.2",
58
- "@dr.pogodin/eslint-configs": "^0.0.12",
58
+ "@dr.pogodin/eslint-configs": "^0.1.0",
59
59
  "@pmmmwh/react-refresh-webpack-plugin": "^0.6.1",
60
60
  "@standard-schema/spec": "^1.0.0",
61
61
  "@testing-library/dom": "^10.4.1",
@@ -72,25 +72,25 @@
72
72
  "@types/morgan": "^1.9.10",
73
73
  "@types/node-forge": "^1.3.14",
74
74
  "@types/pretty": "^2.0.3",
75
- "@types/react": "^19.1.13",
76
- "@types/react-dom": "^19.1.9",
75
+ "@types/react": "^19.2.2",
76
+ "@types/react-dom": "^19.2.2",
77
77
  "@types/request-ip": "^0.0.41",
78
78
  "@types/serialize-javascript": "^5.0.4",
79
79
  "@types/serve-favicon": "^2.5.7",
80
80
  "@types/supertest": "^6.0.3",
81
81
  "@types/webpack": "^5.28.5",
82
- "@types/webpack-hot-middleware": "^2.25.10",
82
+ "@types/webpack-hot-middleware": "^2.25.11",
83
83
  "autoprefixer": "^10.4.21",
84
84
  "babel-jest": "^30.2.0",
85
85
  "babel-loader": "^10.0.0",
86
86
  "babel-plugin-module-resolver": "^5.0.2",
87
- "core-js": "^3.45.1",
87
+ "core-js": "^3.46.0",
88
88
  "css-loader": "^7.1.2",
89
89
  "css-minimizer-webpack-plugin": "^7.0.2",
90
90
  "identity-obj-proxy": "^3.0.0",
91
91
  "jest": "^30.2.0",
92
92
  "jest-environment-jsdom": "^30.2.0",
93
- "memfs": "^4.48.1",
93
+ "memfs": "^4.49.0",
94
94
  "mini-css-extract-plugin": "^2.9.4",
95
95
  "mockdate": "^3.0.5",
96
96
  "nodelist-foreach-polyfill": "^1.2.0",
@@ -98,12 +98,12 @@
98
98
  "postcss-loader": "^8.2.0",
99
99
  "postcss-scss": "^4.0.9",
100
100
  "pretty": "^2.0.0",
101
- "react-refresh": "^0.17.0",
101
+ "react-refresh": "^0.18.0",
102
102
  "regenerator-runtime": "^0.14.1",
103
103
  "resolve-url-loader": "^5.0.0",
104
104
  "sass": "^1.93.2",
105
105
  "sass-loader": "^16.0.5",
106
- "sitemap": "^8.0.0",
106
+ "sitemap": "^8.0.1",
107
107
  "source-map-loader": "^5.0.0",
108
108
  "stylelint": "^16.25.0",
109
109
  "stylelint-config-standard-scss": "^16.0.0",
@@ -112,7 +112,7 @@
112
112
  "tstyche": "^4.3.0",
113
113
  "typed-scss-modules": "^8.1.1",
114
114
  "typescript": "^5.9.3",
115
- "webpack": "^5.102.0",
115
+ "webpack": "^5.102.1",
116
116
  "webpack-dev-middleware": "^7.4.5",
117
117
  "webpack-hot-middleware": "^2.26.1",
118
118
  "webpack-merge": "^6.0.1",
@@ -5,7 +5,6 @@ import {
5
5
  useEffect,
6
6
  useMemo,
7
7
  useRef,
8
- useState,
9
8
  } from 'react';
10
9
 
11
10
  import ReactDom from 'react-dom';
@@ -54,16 +53,6 @@ const BaseModal: FunctionComponent<PropsT> = ({
54
53
  }) => {
55
54
  const containerRef = useRef<HTMLDivElement | null>(null);
56
55
  const overlayRef = useRef<HTMLDivElement | null>(null);
57
- const [portal, setPortal] = useState<HTMLDivElement>();
58
-
59
- useEffect(() => {
60
- const p = document.createElement('div');
61
- document.body.appendChild(p);
62
- setPortal(p);
63
- return () => {
64
- document.body.removeChild(p);
65
- };
66
- }, []);
67
56
 
68
57
  // Sets up modal cancellation of scrolling, if opted-in.
69
58
  useEffect(() => {
@@ -107,9 +96,9 @@ const BaseModal: FunctionComponent<PropsT> = ({
107
96
  />
108
97
  ), []);
109
98
 
110
- return portal ? ReactDom.createPortal(
99
+ return ReactDom.createPortal(
111
100
  (
112
- <>
101
+ <div>
113
102
  {focusLast}
114
103
  <div
115
104
  aria-label="Cancel"
@@ -176,10 +165,10 @@ const BaseModal: FunctionComponent<PropsT> = ({
176
165
  tabIndex={0}
177
166
  />
178
167
  {focusLast}
179
- </>
168
+ </div>
180
169
  ),
181
- portal,
182
- ) : null;
170
+ document.body,
171
+ );
183
172
  };
184
173
 
185
174
  export default themed(BaseModal, 'Modal', baseTheme);
@@ -8,10 +8,8 @@ import {
8
8
  type FunctionComponent,
9
9
  type ReactNode,
10
10
  type RefObject,
11
- useEffect,
12
11
  useImperativeHandle,
13
12
  useRef,
14
- useState,
15
13
  } from 'react';
16
14
 
17
15
  import { createPortal } from 'react-dom';
@@ -47,42 +45,10 @@ type ComponentsT = {
47
45
  content: HTMLDivElement;
48
46
  };
49
47
 
50
- type HeapT = {
51
- lastElement?: HTMLElement;
52
- lastPageX: number;
53
- lastPageY: number;
54
- lastPlacement?: PLACEMENTS | undefined;
55
- };
56
-
57
48
  export type ThemeKeysT = 'appearance' | 'arrow' | 'content' | 'container';
58
49
 
59
50
  type TooltipThemeT = Theme<ThemeKeysT>;
60
51
 
61
- /**
62
- * Creates tooltip components.
63
- * @ignore
64
- * @param {object} theme Themes to use for tooltip container, arrow,
65
- * and content.
66
- * @return {object} Object with DOM references to the container components:
67
- * container, arrow, content.
68
- */
69
- function createTooltipComponents(theme: TooltipThemeT): ComponentsT {
70
- const arrow = document.createElement('div');
71
- if (theme.arrow) arrow.setAttribute('class', theme.arrow);
72
-
73
- const content = document.createElement('div');
74
- if (theme.content) content.setAttribute('class', theme.content);
75
-
76
- const container = document.createElement('div');
77
- if (theme.container) container.setAttribute('class', theme.container);
78
-
79
- container.appendChild(arrow);
80
- container.appendChild(content);
81
- document.body.appendChild(container);
82
-
83
- return { arrow, container, content };
84
- }
85
-
86
52
  type TooltipRectsT = {
87
53
  arrow: DOMRect;
88
54
  container: DOMRect;
@@ -272,14 +238,9 @@ const Tooltip: FunctionComponent<{
272
238
  // Thus, when we create the <Tooltip> we have to record its target positioning
273
239
  // details, and then apply them when it is created.
274
240
 
275
- const { current: heap } = useRef<HeapT>({
276
- lastElement: undefined,
277
- lastPageX: 0,
278
- lastPageY: 0,
279
- lastPlacement: undefined,
280
- });
281
-
282
- const [components, setComponents] = useState<ComponentsT | null>(null);
241
+ const arrowRef = useRef<HTMLDivElement>(null);
242
+ const containerRef = useRef<HTMLDivElement>(null);
243
+ const contentRef = useRef<HTMLDivElement>(null);
283
244
 
284
245
  const pointTo = (
285
246
  pageX: number,
@@ -287,52 +248,27 @@ const Tooltip: FunctionComponent<{
287
248
  placement: PLACEMENTS,
288
249
  element: HTMLElement,
289
250
  ) => {
290
- heap.lastElement = element;
291
- heap.lastPageX = pageX;
292
- heap.lastPageY = pageY;
293
- heap.lastPlacement = placement;
294
-
295
- if (components) {
296
- setComponentPositions(pageX, pageY, placement, element, components);
251
+ if (!arrowRef.current || !containerRef.current || !contentRef.current) {
252
+ throw Error('Internal error');
297
253
  }
254
+
255
+ setComponentPositions(pageX, pageY, placement, element, {
256
+ arrow: arrowRef.current,
257
+ container: containerRef.current,
258
+ content: contentRef.current,
259
+ });
298
260
  };
299
261
  useImperativeHandle(ref, () => ({ pointTo }));
300
262
 
301
- /* Inits and destroys tooltip components. */
302
- useEffect(() => {
303
- const x = createTooltipComponents(theme);
304
- setComponents(x);
305
- return () => {
306
- document.body.removeChild(x.container);
307
- setComponents(null);
308
- };
309
- }, [theme]);
310
-
311
- useEffect(() => {
312
- if (components) {
313
- setComponentPositions(
314
- heap.lastPageX,
315
- heap.lastPageY,
316
- heap.lastPlacement,
317
- heap.lastElement,
318
- components,
319
- );
320
- }
321
- }, [
322
- components,
323
- // BEWARE: Careful about these dependencies - they are updated when mouse
324
- // is moved over the tool-tipped element, thus potentially may cause
325
- // unnecessary firing of this effect on each mouse event. It does not
326
- // happen now just because the mouse movements themselves are not causing
327
- // the component re-rendering, thus dependencies of this effect are not
328
- // really re-evaluated.
329
- heap.lastPageX,
330
- heap.lastPageY,
331
- heap.lastPlacement,
332
- heap.lastElement,
333
- ]);
334
-
335
- return components ? createPortal(children, components.content) : null;
263
+ return createPortal(
264
+ (
265
+ <div className={theme.container} ref={containerRef}>
266
+ <div className={theme.arrow} ref={arrowRef} />
267
+ <div className={theme.content} ref={contentRef}>{children}</div>
268
+ </div>
269
+ ),
270
+ document.body,
271
+ );
336
272
  };
337
273
 
338
274
  export default Tooltip;
@@ -4,7 +4,6 @@ import { IS_CLIENT_SIDE } from './isomorphy';
4
4
 
5
5
  type RequireWeakOptionsT = {
6
6
  basePath?: string;
7
- throwOnError?: boolean;
8
7
  };
9
8
 
10
9
  type RequireWeakResT<T> = T extends { default: infer D }
@@ -32,46 +31,34 @@ export function requireWeak<T extends object>(
32
31
  let ops: RequireWeakOptionsT;
33
32
  if (typeof basePathOrOptions === 'string') {
34
33
  basePath = basePathOrOptions;
35
- ops = {};
36
34
  } else {
37
35
  ops = basePathOrOptions ?? {};
38
36
  ({ basePath } = ops);
39
37
  }
40
38
 
41
- // TODO: On one hand, this try/catch wrap silencing errors is bad, as it may
42
- // hide legit errors, in a way difficult to notice and understand; but on the
43
- // other hand it fails for some (unclear, but legit?) reasons in some
44
- // environments,
45
- // like during the static code generation for docs. Perhaps, something should
46
- // be implemented differently here.
47
- try {
48
- // eslint-disable-next-line no-eval
49
- const req = eval('require') as (path: string) => unknown;
39
+ // eslint-disable-next-line no-eval
40
+ const req = eval('require') as (path: string) => unknown;
50
41
 
51
- // eslint-disable-next-line @typescript-eslint/unbound-method
52
- const { resolve } = req('path') as typeof PathNS;
42
+ // eslint-disable-next-line @typescript-eslint/unbound-method
43
+ const { resolve } = req('path') as typeof PathNS;
53
44
 
54
- const path = basePath ? resolve(basePath, modulePath) : modulePath;
55
- const module = req(path) as T;
45
+ const path = basePath ? resolve(basePath, modulePath) : modulePath;
46
+ const module = req(path) as T;
56
47
 
57
- if (!('default' in module) || !module.default) return module as RequireWeakResT<T>;
48
+ if (!('default' in module) || !module.default) return module as RequireWeakResT<T>;
58
49
 
59
- const { default: def, ...named } = module;
50
+ const { default: def, ...named } = module;
60
51
 
61
- const res = def as RequireWeakResT<T>;
52
+ const res = def as RequireWeakResT<T>;
62
53
 
63
- Object.entries(named).forEach(([name, value]) => {
64
- const assigned = res[name as keyof RequireWeakResT<T>];
65
- if (assigned) (res[name as keyof RequireWeakResT<T>] as unknown) = value;
66
- else if (assigned !== value) {
67
- throw Error('Conflict between default and named exports');
68
- }
69
- });
70
- return res;
71
- } catch (error) {
72
- if (ops.throwOnError) throw error;
73
- return null;
74
- }
54
+ Object.entries(named).forEach(([name, value]) => {
55
+ const assigned = res[name as keyof RequireWeakResT<T>];
56
+ if (assigned) (res[name as keyof RequireWeakResT<T>] as unknown) = value;
57
+ else if (assigned !== value) {
58
+ throw Error('Conflict between default and named exports');
59
+ }
60
+ });
61
+ return res;
75
62
  }
76
63
 
77
64
  /**