@dr.pogodin/react-utils 1.35.3 → 1.36.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.
Files changed (185) hide show
  1. package/LICENSE.md +1 -1
  2. package/bin/build.js +7 -6
  3. package/build/development/client/getInj.js +3 -10
  4. package/build/development/client/getInj.js.map +1 -1
  5. package/build/development/client/index.js +2 -9
  6. package/build/development/client/index.js.map +1 -1
  7. package/build/development/index.js +1 -15
  8. package/build/development/index.js.map +1 -1
  9. package/build/development/server/Cache.js +19 -19
  10. package/build/development/server/Cache.js.map +1 -1
  11. package/build/development/server/renderer.js +7 -4
  12. package/build/development/server/renderer.js.map +1 -1
  13. package/build/development/server/server.js +4 -1
  14. package/build/development/server/server.js.map +1 -1
  15. package/build/development/shared/components/Button/index.js +1 -16
  16. package/build/development/shared/components/Button/index.js.map +1 -1
  17. package/build/development/shared/components/Checkbox/index.js +1 -29
  18. package/build/development/shared/components/Checkbox/index.js.map +1 -1
  19. package/build/development/shared/components/GenericLink/index.js +0 -15
  20. package/build/development/shared/components/GenericLink/index.js.map +1 -1
  21. package/build/development/shared/components/Input/index.js +1 -8
  22. package/build/development/shared/components/Input/index.js.map +1 -1
  23. package/build/development/shared/components/MetaTags.js +0 -12
  24. package/build/development/shared/components/MetaTags.js.map +1 -1
  25. package/build/development/shared/components/Modal/index.js +2 -13
  26. package/build/development/shared/components/Modal/index.js.map +1 -1
  27. package/build/development/shared/components/PageLayout/index.js +1 -10
  28. package/build/development/shared/components/PageLayout/index.js.map +1 -1
  29. package/build/development/shared/components/TextArea/index.js +1 -12
  30. package/build/development/shared/components/TextArea/index.js.map +1 -1
  31. package/build/development/shared/components/Throbber/index.js +1 -6
  32. package/build/development/shared/components/Throbber/index.js.map +1 -1
  33. package/build/development/shared/components/WithTooltip/Tooltip.js +1 -8
  34. package/build/development/shared/components/WithTooltip/Tooltip.js.map +1 -1
  35. package/build/development/shared/components/WithTooltip/index.js +1 -9
  36. package/build/development/shared/components/WithTooltip/index.js.map +1 -1
  37. package/build/development/shared/components/YouTubeVideo/index.js +2 -11
  38. package/build/development/shared/components/YouTubeVideo/index.js.map +1 -1
  39. package/build/development/shared/components/selectors/CustomDropdown/Options/index.js +1 -16
  40. package/build/development/shared/components/selectors/CustomDropdown/Options/index.js.map +1 -1
  41. package/build/development/shared/components/selectors/CustomDropdown/index.js +2 -12
  42. package/build/development/shared/components/selectors/CustomDropdown/index.js.map +1 -1
  43. package/build/development/shared/components/selectors/NativeDropdown/index.js +2 -12
  44. package/build/development/shared/components/selectors/NativeDropdown/index.js.map +1 -1
  45. package/build/development/shared/components/selectors/Switch/index.js +21 -28
  46. package/build/development/shared/components/selectors/Switch/index.js.map +1 -1
  47. package/build/development/shared/components/selectors/common.js +0 -19
  48. package/build/development/shared/components/selectors/common.js.map +1 -1
  49. package/build/development/shared/components/selectors/index.js +0 -13
  50. package/build/development/shared/components/selectors/index.js.map +1 -1
  51. package/build/development/shared/utils/globalState.js.map +1 -1
  52. package/build/development/shared/utils/jest/index.js +4 -2
  53. package/build/development/shared/utils/jest/index.js.map +1 -1
  54. package/build/development/shared/utils/splitComponent.js +21 -28
  55. package/build/development/shared/utils/splitComponent.js.map +1 -1
  56. package/build/development/web.bundle.js +28 -38
  57. package/build/production/client/getInj.js +3 -7
  58. package/build/production/client/getInj.js.map +1 -1
  59. package/build/production/client/index.js +1 -1
  60. package/build/production/client/index.js.map +1 -1
  61. package/build/production/index.js +1 -4
  62. package/build/production/index.js.map +1 -1
  63. package/build/production/server/Cache.js +3 -3
  64. package/build/production/server/Cache.js.map +1 -1
  65. package/build/production/server/renderer.js +2 -2
  66. package/build/production/server/renderer.js.map +1 -1
  67. package/build/production/server/server.js +1 -1
  68. package/build/production/server/server.js.map +1 -1
  69. package/build/production/shared/components/Button/index.js +3 -3
  70. package/build/production/shared/components/Button/index.js.map +1 -1
  71. package/build/production/shared/components/Checkbox/index.js +1 -16
  72. package/build/production/shared/components/Checkbox/index.js.map +1 -1
  73. package/build/production/shared/components/GenericLink/index.js +2 -2
  74. package/build/production/shared/components/GenericLink/index.js.map +1 -1
  75. package/build/production/shared/components/Input/index.js +2 -2
  76. package/build/production/shared/components/Input/index.js.map +1 -1
  77. package/build/production/shared/components/MetaTags.js +2 -2
  78. package/build/production/shared/components/MetaTags.js.map +1 -1
  79. package/build/production/shared/components/Modal/index.js +2 -2
  80. package/build/production/shared/components/Modal/index.js.map +1 -1
  81. package/build/production/shared/components/PageLayout/index.js +2 -2
  82. package/build/production/shared/components/PageLayout/index.js.map +1 -1
  83. package/build/production/shared/components/TextArea/index.js +2 -2
  84. package/build/production/shared/components/TextArea/index.js.map +1 -1
  85. package/build/production/shared/components/Throbber/index.js +2 -2
  86. package/build/production/shared/components/Throbber/index.js.map +1 -1
  87. package/build/production/shared/components/WithTooltip/Tooltip.js +3 -3
  88. package/build/production/shared/components/WithTooltip/Tooltip.js.map +1 -1
  89. package/build/production/shared/components/WithTooltip/index.js +2 -2
  90. package/build/production/shared/components/WithTooltip/index.js.map +1 -1
  91. package/build/production/shared/components/YouTubeVideo/index.js +3 -3
  92. package/build/production/shared/components/YouTubeVideo/index.js.map +1 -1
  93. package/build/production/shared/components/selectors/CustomDropdown/Options/index.js +2 -2
  94. package/build/production/shared/components/selectors/CustomDropdown/Options/index.js.map +1 -1
  95. package/build/production/shared/components/selectors/CustomDropdown/index.js +2 -2
  96. package/build/production/shared/components/selectors/CustomDropdown/index.js.map +1 -1
  97. package/build/production/shared/components/selectors/NativeDropdown/index.js +3 -3
  98. package/build/production/shared/components/selectors/NativeDropdown/index.js.map +1 -1
  99. package/build/production/shared/components/selectors/Switch/index.js +1 -1
  100. package/build/production/shared/components/selectors/Switch/index.js.map +1 -1
  101. package/build/production/shared/components/selectors/common.js +2 -4
  102. package/build/production/shared/components/selectors/common.js.map +1 -1
  103. package/build/production/shared/components/selectors/index.js +1 -1
  104. package/build/production/shared/components/selectors/index.js.map +1 -1
  105. package/build/production/shared/utils/globalState.js.map +1 -1
  106. package/build/production/shared/utils/jest/index.js +1 -1
  107. package/build/production/shared/utils/jest/index.js.map +1 -1
  108. package/build/production/shared/utils/splitComponent.js +10 -12
  109. package/build/production/shared/utils/splitComponent.js.map +1 -1
  110. package/build/production/web.bundle.js +1 -1
  111. package/build/production/web.bundle.js.map +1 -1
  112. package/build/types-code/client/getInj.d.ts +0 -6
  113. package/build/types-code/client/index.d.ts +1 -2
  114. package/build/types-code/index.d.ts +2 -3
  115. package/build/types-code/server/Cache.d.ts +3 -11
  116. package/build/types-code/server/index.d.ts +0 -2
  117. package/build/types-code/server/renderer.d.ts +0 -1
  118. package/build/types-code/server/server.d.ts +0 -1
  119. package/build/types-code/shared/components/Button/index.d.ts +3 -4
  120. package/build/types-code/shared/components/Checkbox/index.d.ts +3 -12
  121. package/build/types-code/shared/components/Input/index.d.ts +4 -5
  122. package/build/types-code/shared/components/Link.d.ts +0 -1
  123. package/build/types-code/shared/components/Modal/index.d.ts +3 -4
  124. package/build/types-code/shared/components/NavLink.d.ts +0 -1
  125. package/build/types-code/shared/components/PageLayout/index.d.ts +4 -4
  126. package/build/types-code/shared/components/TextArea/index.d.ts +4 -5
  127. package/build/types-code/shared/components/Throbber/index.d.ts +4 -4
  128. package/build/types-code/shared/components/WithTooltip/Tooltip.d.ts +1 -1
  129. package/build/types-code/shared/components/WithTooltip/index.d.ts +2 -3
  130. package/build/types-code/shared/components/YouTubeVideo/index.d.ts +3 -4
  131. package/build/types-code/shared/components/selectors/CustomDropdown/Options/index.d.ts +1 -2
  132. package/build/types-code/shared/components/selectors/CustomDropdown/index.d.ts +2 -3
  133. package/build/types-code/shared/components/selectors/NativeDropdown/index.d.ts +2 -2
  134. package/build/types-code/shared/components/selectors/Switch/index.d.ts +4 -5
  135. package/build/types-code/shared/components/selectors/common.d.ts +5 -11
  136. package/build/types-code/shared/components/selectors/index.d.ts +1 -1
  137. package/build/types-code/shared/utils/globalState.d.ts +6 -2
  138. package/build/types-code/shared/utils/jest/index.d.ts +4 -1
  139. package/build/types-code/shared/utils/splitComponent.d.ts +0 -1
  140. package/build/types-code/shared/utils/webpack.d.ts +0 -1
  141. package/config/babel/node-ssr.js +1 -1
  142. package/config/babel/webpack.js +1 -1
  143. package/config/eslint/default.json +1 -0
  144. package/config/eslint/jest.json +1 -0
  145. package/config/eslint/typescript.js +7 -0
  146. package/config/typescript/base.json +9 -0
  147. package/config/webpack/app-base.d.ts +0 -1
  148. package/config/webpack/app-base.js +1 -1
  149. package/config/webpack/app-development.js +1 -1
  150. package/config/webpack/app-production.js +1 -1
  151. package/config/webpack/lib-base.js +1 -2
  152. package/config/webpack/lib-development.js +1 -1
  153. package/config/webpack/lib-production.js +1 -1
  154. package/package.json +28 -27
  155. package/src/client/getInj.ts +3 -9
  156. package/src/client/index.tsx +1 -3
  157. package/src/index.ts +1 -10
  158. package/src/server/Cache.ts +31 -30
  159. package/src/server/renderer.tsx +8 -5
  160. package/src/server/server.ts +6 -1
  161. package/src/shared/components/Button/index.tsx +2 -20
  162. package/src/shared/components/Checkbox/index.tsx +2 -37
  163. package/src/shared/components/GenericLink/index.tsx +0 -15
  164. package/src/shared/components/Input/index.tsx +6 -15
  165. package/src/shared/components/MetaTags.tsx +0 -12
  166. package/src/shared/components/Modal/index.tsx +3 -22
  167. package/src/shared/components/PageLayout/index.tsx +8 -24
  168. package/src/shared/components/TextArea/index.tsx +6 -24
  169. package/src/shared/components/Throbber/index.tsx +6 -18
  170. package/src/shared/components/WithTooltip/Tooltip.tsx +6 -14
  171. package/src/shared/components/WithTooltip/index.tsx +3 -24
  172. package/src/shared/components/YouTubeVideo/index.tsx +3 -20
  173. package/src/shared/components/selectors/CustomDropdown/Options/index.tsx +2 -20
  174. package/src/shared/components/selectors/CustomDropdown/index.tsx +3 -27
  175. package/src/shared/components/selectors/NativeDropdown/index.tsx +3 -27
  176. package/src/shared/components/selectors/Switch/index.tsx +34 -50
  177. package/src/shared/components/selectors/common.ts +13 -45
  178. package/src/shared/components/selectors/index.ts +0 -2
  179. package/src/shared/utils/globalState.ts +6 -0
  180. package/src/shared/utils/jest/index.tsx +13 -2
  181. package/src/shared/utils/splitComponent.tsx +24 -29
  182. package/tsconfig.configs.json +7 -3
  183. package/tsconfig.json +3 -10
  184. package/tsconfig.types.json +1 -7
  185. package/tstyche.config.json +6 -0
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.35.3",
2
+ "version": "1.36.0",
3
3
  "bin": {
4
4
  "react-utils-build": "bin/build.js",
5
5
  "react-utils-setup": "bin/setup.js"
@@ -8,12 +8,12 @@
8
8
  "url": "https://github.com/birdofpreyru/react-utils/issues"
9
9
  },
10
10
  "dependencies": {
11
- "@babel/runtime": "^7.24.6",
12
- "@dr.pogodin/babel-plugin-react-css-modules": "^6.13.1",
11
+ "@babel/runtime": "^7.24.7",
12
+ "@dr.pogodin/babel-plugin-react-css-modules": "^6.13.2",
13
13
  "@dr.pogodin/csurf": "^1.13.0",
14
14
  "@dr.pogodin/js-utils": "^0.0.12",
15
15
  "@dr.pogodin/react-global-state": "^0.14.2",
16
- "@dr.pogodin/react-themes": "^1.6.2",
16
+ "@dr.pogodin/react-themes": "^1.7.0",
17
17
  "@jest/environment": "^29.7.0",
18
18
  "axios": "^1.7.2",
19
19
  "commander": "^12.1.0",
@@ -26,11 +26,10 @@
26
26
  "express": "^4.19.2",
27
27
  "helmet": "^7.1.0",
28
28
  "http-status-codes": "^2.3.0",
29
- "joi": "^17.13.1",
29
+ "joi": "^17.13.3",
30
30
  "lodash": "^4.17.21",
31
31
  "morgan": "^1.10.0",
32
32
  "node-forge": "^1.3.1",
33
- "prop-types": "^15.8.1",
34
33
  "qs": "^6.12.1",
35
34
  "raf": "^3.4.1",
36
35
  "react": "^18.3.1",
@@ -42,20 +41,20 @@
42
41
  "serialize-javascript": "^6.0.2",
43
42
  "serve-favicon": "^2.5.0",
44
43
  "source-map-support": "^0.5.21",
45
- "uuid": "^9.0.1",
44
+ "uuid": "^10.0.0",
46
45
  "winston": "^3.13.0"
47
46
  },
48
47
  "description": "Collection of generic ReactJS components and utils",
49
48
  "devDependencies": {
50
- "@babel/cli": "^7.24.6",
51
- "@babel/core": "^7.24.6",
52
- "@babel/eslint-parser": "^7.24.6",
53
- "@babel/eslint-plugin": "^7.24.6",
54
- "@babel/node": "^7.24.6",
55
- "@babel/plugin-transform-runtime": "^7.24.6",
56
- "@babel/preset-env": "^7.24.6",
57
- "@babel/preset-react": "^7.24.6",
58
- "@babel/preset-typescript": "^7.24.6",
49
+ "@babel/cli": "^7.24.7",
50
+ "@babel/core": "^7.24.7",
51
+ "@babel/eslint-parser": "^7.24.7",
52
+ "@babel/eslint-plugin": "^7.24.7",
53
+ "@babel/node": "^7.24.7",
54
+ "@babel/plugin-transform-runtime": "^7.24.7",
55
+ "@babel/preset-env": "^7.24.7",
56
+ "@babel/preset-react": "^7.24.7",
57
+ "@babel/preset-typescript": "^7.24.7",
59
58
  "@babel/register": "^7.24.6",
60
59
  "@dr.pogodin/babel-plugin-transform-assets": "^1.2.2",
61
60
  "@dr.pogodin/babel-preset-svgr": "^1.8.0",
@@ -71,7 +70,7 @@
71
70
  "@types/csurf": "^1.11.5",
72
71
  "@types/express": "^4.17.21",
73
72
  "@types/jest": "^29.5.12",
74
- "@types/lodash": "^4.17.4",
73
+ "@types/lodash": "^4.17.5",
75
74
  "@types/morgan": "^1.9.9",
76
75
  "@types/node-forge": "^1.3.11",
77
76
  "@types/pretty": "^2.0.3",
@@ -82,7 +81,7 @@
82
81
  "@types/serialize-javascript": "^5.0.4",
83
82
  "@types/serve-favicon": "^2.5.7",
84
83
  "@types/supertest": "^6.0.2",
85
- "@types/uuid": "^9.0.8",
84
+ "@types/uuid": "^10.0.0",
86
85
  "@types/webpack": "^5.28.5",
87
86
  "autoprefixer": "^10.4.19",
88
87
  "babel-jest": "^29.7.0",
@@ -96,14 +95,14 @@
96
95
  "eslint-config-airbnb-typescript": "^18.0.0",
97
96
  "eslint-import-resolver-babel-module": "^5.3.2",
98
97
  "eslint-plugin-import": "^2.29.1",
99
- "eslint-plugin-jest": "^28.5.0",
100
- "eslint-plugin-jsx-a11y": "^6.8.0",
101
- "eslint-plugin-react": "^7.34.2",
98
+ "eslint-plugin-jest": "^28.6.0",
99
+ "eslint-plugin-jsx-a11y": "^6.9.0",
100
+ "eslint-plugin-react": "^7.34.3",
102
101
  "eslint-plugin-react-hooks": "^4.6.2",
103
102
  "identity-obj-proxy": "^3.0.0",
104
103
  "jest": "^29.7.0",
105
104
  "jest-environment-jsdom": "^29.7.0",
106
- "memfs": "^4.9.2",
105
+ "memfs": "^4.9.3",
107
106
  "mini-css-extract-plugin": "^2.9.0",
108
107
  "mockdate": "^3.0.5",
109
108
  "nodelist-foreach-polyfill": "^1.2.0",
@@ -114,17 +113,18 @@
114
113
  "react-refresh": "^0.14.2",
115
114
  "regenerator-runtime": "^0.14.1",
116
115
  "resolve-url-loader": "^5.0.0",
117
- "sass": "^1.77.4",
116
+ "sass": "^1.77.6",
118
117
  "sass-loader": "^14.2.1",
119
118
  "sitemap": "^8.0.0",
120
119
  "stylelint": "^16.6.1",
121
120
  "stylelint-config-standard-scss": "^13.1.0",
122
121
  "supertest": "^7.0.0",
123
122
  "tsc-alias": "^1.8.10",
123
+ "tstyche": "^2.0.0",
124
124
  "typed-scss-modules": "^8.0.1",
125
- "typescript": "^5.4.5",
126
- "typescript-eslint": "^7.12.0",
127
- "webpack": "^5.91.0",
125
+ "typescript": "^5.5.2",
126
+ "typescript-eslint": "^7.13.1",
127
+ "webpack": "^5.92.1",
128
128
  "webpack-dev-middleware": "^7.2.1",
129
129
  "webpack-hot-middleware": "^2.26.1",
130
130
  "webpack-merge": "^5.10.0",
@@ -200,7 +200,8 @@
200
200
  "jest:2": "NODE_CONFIG_ENV=test jest --no-cache -w 1 --config config/jest/default.js --shard=2/4",
201
201
  "jest:3": "NODE_CONFIG_ENV=test jest --no-cache -w 1 --config config/jest/default.js --shard=3/4",
202
202
  "jest:4": "NODE_CONFIG_ENV=test jest --no-cache -w 1 --config config/jest/default.js --shard=4/4",
203
- "jest": "npm run jest:1 && npm run jest:2 && npm run jest:3 && npm run jest:4",
203
+ "jest:types": "tstyche",
204
+ "jest": "npm run jest:types && npm run jest:1 && npm run jest:2 && npm run jest:3 && npm run jest:4",
204
205
  "lint": "npm run lint:code && npm run lint:scss",
205
206
  "lint:code": "eslint --ext .js,.jsx,.ts,.tsx .",
206
207
  "lint:scss": "stylelint -- **/*.{css,scss}",
@@ -31,6 +31,9 @@ if (metaElement) {
31
31
 
32
32
  data = forge.util.decodeUtf8(d.output.data);
33
33
  inj = eval(`(${data})`); // eslint-disable-line no-eval
34
+ } else if (typeof window !== 'undefined' && window.REACT_UTILS_INJECTION) {
35
+ inj = window.REACT_UTILS_INJECTION;
36
+ delete window.REACT_UTILS_INJECTION;
34
37
  } else {
35
38
  // Otherwise, a bunch of dependent stuff will easily fail in non-standard
36
39
  // environments, where no client-side initialization is performed. Like tests,
@@ -41,12 +44,3 @@ if (metaElement) {
41
44
  export default function getInj(): InjT {
42
45
  return inj;
43
46
  }
44
-
45
- /**
46
- * Allows to set a custom injection object instance,
47
- * for server-less scenarios, for example, where it is not auto-injected
48
- * into generated pages from the server side.
49
- */
50
- export function setInj(value: InjT) {
51
- inj = value;
52
- }
@@ -8,15 +8,13 @@ import { GlobalStateProvider } from '@dr.pogodin/react-global-state';
8
8
  import { createRoot, hydrateRoot } from 'react-dom/client';
9
9
  import { BrowserRouter } from 'react-router-dom';
10
10
 
11
- import getInj, { setInj } from './getInj';
11
+ import getInj from './getInj';
12
12
 
13
13
  type OptionsT = {
14
14
  dontHydrate?: boolean;
15
15
  initialState?: any;
16
16
  };
17
17
 
18
- export { setInj };
19
-
20
18
  /**
21
19
  * Prepares and launches the app at client side.
22
20
  * @param Application Root application component
package/src/index.ts CHANGED
@@ -6,18 +6,9 @@ import type ServerT from './server';
6
6
 
7
7
  const server = webpack.requireWeak('./server', __dirname) as (typeof ServerT) | null;
8
8
 
9
- // TODO: Should be done in a cleaner way, but technically it is fine
10
- // for this scenario.
11
- // eslint-disable-next-line import/no-mutable-exports
12
- let client = server ? undefined : require('./client');
13
-
14
- if (client) {
15
- client.default.setInj = client.setInj;
16
- client = client.default;
17
- }
9
+ const client = server ? undefined : require('./client').default;
18
10
 
19
11
  export { default as api } from 'axios';
20
- export * as PT from 'prop-types';
21
12
 
22
13
  export {
23
14
  type AsyncCollectionLoaderT,
@@ -1,25 +1,21 @@
1
+ type CachedItemT<DatumT> = {
2
+ data: DatumT;
3
+ size: number;
4
+ timestamp: number;
5
+ };
6
+
1
7
  /**
2
8
  * Implements the static cache.
3
9
  */
4
10
  export default class Cache<DatumT> {
5
- private: {
6
- items: {
7
- [key: string]: {
8
- data: DatumT;
9
- size: number;
10
- timestamp: number;
11
- }
12
- };
13
- maxSize: number;
14
- size: number;
15
- };
11
+ private items: Record<string, CachedItemT<DatumT>> = {};
12
+
13
+ private maxSize: number;
14
+
15
+ private size = 0;
16
16
 
17
17
  constructor(maxSize: number) {
18
- this.private = {
19
- items: {},
20
- maxSize,
21
- size: 0,
22
- };
18
+ this.maxSize = maxSize;
23
19
  }
24
20
 
25
21
  /**
@@ -37,7 +33,7 @@ export default class Cache<DatumT> {
37
33
  key: string;
38
34
  maxage?: number;
39
35
  }): DatumT | null {
40
- const item = this.private.items[key];
36
+ const item = this.items[key];
41
37
  return item && Date.now() - item.timestamp < maxage ? item.data : null;
42
38
  }
43
39
 
@@ -49,19 +45,24 @@ export default class Cache<DatumT> {
49
45
  * @param size Byte size of the item.
50
46
  */
51
47
  add(data: DatumT, key: string, size: number) {
52
- const p = this.private;
53
- const old = p.items[key];
54
- if (old) p.size -= old.size;
55
- p.items[key] = { data, size, timestamp: Date.now() };
56
- p.size += size;
57
- if (p.size > p.maxSize) {
58
- const items = Object.entries(p.items);
59
- items.sort((a, b) => a[1].timestamp - b[1].timestamp);
60
- for (let i = 0; i < items.length; ++i) {
61
- const [itemKey, item] = items[i];
62
- delete p.items[itemKey];
63
- p.size -= item.size;
64
- if (p.size < p.maxSize / 2) break;
48
+ const cached = this.items[key];
49
+ if (cached) this.size -= cached.size;
50
+
51
+ this.items[key] = { data, size, timestamp: Date.now() };
52
+ this.size += size;
53
+
54
+ if (this.size > this.maxSize) {
55
+ const entries = Object.entries(this.items);
56
+ entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
57
+
58
+ for (let i = 0; i < entries.length; ++i) {
59
+ const entry = entries[i];
60
+ if (entry) {
61
+ const [itemKey, item] = entry;
62
+ delete this.items[itemKey];
63
+ this.size -= item.size;
64
+ if (this.size < this.maxSize / 2) break;
65
+ }
65
66
  }
66
67
  }
67
68
  }
@@ -159,10 +159,13 @@ export function isBrotliAcceptable(req: Request) {
159
159
  if (acceptable) {
160
160
  const ops = acceptable.split(',');
161
161
  for (let i = 0; i < ops.length; ++i) {
162
- const [type, priority] = ops[i].trim().split(';q=');
163
- if ((type === '*' || type === 'br')
164
- && (!priority || parseFloat(priority) > 0)) {
165
- return true;
162
+ const op = ops[i];
163
+ if (op) {
164
+ const [type, priority] = op.trim().split(';q=');
165
+ if ((type === '*' || type === 'br')
166
+ && (!priority || parseFloat(priority) > 0)) {
167
+ return true;
168
+ }
166
169
  }
167
170
  }
168
171
  }
@@ -193,7 +196,7 @@ function groupExtraScripts(scripts: Array<string | ScriptT> = []) {
193
196
  const script = scripts[i];
194
197
  if (isString(script)) {
195
198
  if (script) res[SCRIPT_LOCATIONS.DEFAULT] += script;
196
- } else if (script.code) {
199
+ } else if (script?.code) {
197
200
  if (res[script.location] !== undefined) {
198
201
  res[script.location] += script.code;
199
202
  } else throw Error(`Invalid location "${script.location}"`);
@@ -71,7 +71,12 @@ defaultCspSettings.directives['frame-src'] = [
71
71
  // out of box.
72
72
  'https://*.youtube.com',
73
73
  ];
74
- defaultCspSettings.directives['script-src'].push("'unsafe-eval'");
74
+
75
+ {
76
+ const directives = defaultCspSettings.directives['script-src'];
77
+ if (directives) directives.push("'unsafe-eval'");
78
+ else defaultCspSettings.directives['script-src'] = ["'unsafe-eval'"];
79
+ }
75
80
 
76
81
  // No need for automatic re-writes via Content Security Policy settings:
77
82
  // the forefront Apache or Nginx server is supposed to take care of this
@@ -1,6 +1,5 @@
1
1
  // The <Button> component implements a standard button / button-like link.
2
2
 
3
- import PT from 'prop-types';
4
3
  import { type ReactNode } from 'react';
5
4
 
6
5
  import Link from 'components/Link';
@@ -9,8 +8,6 @@ import themed, { type Theme } from '@dr.pogodin/react-themes';
9
8
 
10
9
  import defaultTheme from './style.scss';
11
10
 
12
- const validThemeKeys = ['active', 'button', 'disabled'] as const;
13
-
14
11
  type PropsT = {
15
12
  active?: boolean;
16
13
  children?: ReactNode;
@@ -20,7 +17,7 @@ type PropsT = {
20
17
  onMouseDown?: React.MouseEventHandler;
21
18
  openNewTab?: boolean;
22
19
  replace?: boolean;
23
- theme: Theme<typeof validThemeKeys>;
20
+ theme: Theme<'active' | 'button' | 'disabled'>;
24
21
  // TODO: It needs a more precise typing of the object option.
25
22
  to?: object | string;
26
23
  };
@@ -87,19 +84,4 @@ export const BaseButton: React.FunctionComponent<PropsT> = ({
87
84
  * @prop {string} [button] to the root element of any button.
88
85
  * @prop {string} [disabled] to the root element of disabled button.
89
86
  */
90
- const ThemedButton = themed(BaseButton, 'Button', validThemeKeys, defaultTheme);
91
-
92
- BaseButton.propTypes = {
93
- active: PT.bool,
94
- children: PT.node,
95
- disabled: PT.bool,
96
- enforceA: PT.bool,
97
- onClick: PT.func,
98
- onMouseDown: PT.func,
99
- openNewTab: PT.bool,
100
- replace: PT.bool,
101
- theme: ThemedButton.themeType.isRequired,
102
- to: PT.oneOfType([PT.object, PT.string]),
103
- };
104
-
105
- export default ThemedButton;
87
+ export default themed(BaseButton, 'Button', defaultTheme);
@@ -1,16 +1,12 @@
1
- import PT from 'prop-types';
2
-
3
1
  import themed, { type Theme } from '@dr.pogodin/react-themes';
4
2
 
5
3
  import defaultTheme from './theme.scss';
6
4
 
7
- const validThemeKeys = ['checkbox', 'container', 'label'] as const;
8
-
9
5
  type PropT = {
10
6
  checked?: boolean;
11
7
  label?: React.ReactNode;
12
8
  onChange?: React.ChangeEventHandler<HTMLInputElement>;
13
- theme: Theme<typeof validThemeKeys>;
9
+ theme: Theme<'checkbox' | 'container' | 'label'>;
14
10
  };
15
11
 
16
12
  const Checkbox: React.FunctionComponent<PropT> = ({
@@ -31,35 +27,4 @@ const Checkbox: React.FunctionComponent<PropT> = ({
31
27
  </div>
32
28
  );
33
29
 
34
- /**
35
- * Checkbox component theme: a map of
36
- * CSS classes to append to its elements:
37
- * @prop [checkbox] to the underlying checkbox `<input>` element.
38
- * @prop [container] to the root checkbox element.
39
- * @prop [label] to the checkbox label element.
40
- */
41
- const ThemedCheckbox = themed(
42
- Checkbox,
43
- 'Checkbox',
44
- validThemeKeys,
45
- defaultTheme,
46
- );
47
-
48
- /**
49
- * The `<Checkbox>` component implements themeable checkboxes.
50
- * @param [props] Component properties.
51
- * @param [props.checked] Checkbox value.
52
- * @param [props.label] Checkbox label.
53
- * @param [props.onChange] State change handler.
54
- * @param [props.theme] _Ad hoc_ theme.
55
- * @param [props....]
56
- * [Other properties of themeable components](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties).
57
- */
58
- Checkbox.propTypes = {
59
- checked: PT.bool,
60
- label: PT.node,
61
- onChange: PT.func,
62
- theme: ThemedCheckbox.themeType.isRequired,
63
- };
64
-
65
- export default ThemedCheckbox;
30
+ export default themed(Checkbox, 'Checkbox', defaultTheme);
@@ -1,6 +1,5 @@
1
1
  /* global window */
2
2
 
3
- import PT from 'prop-types';
4
3
  import { type ReactNode } from 'react';
5
4
 
6
5
  import { type Link, type NavLink } from 'react-router-dom';
@@ -127,18 +126,4 @@ const GenericLink: React.FunctionComponent<PropsT> = ({
127
126
  );
128
127
  };
129
128
 
130
- GenericLink.propTypes = {
131
- children: PT.node,
132
- className: PT.string,
133
- disabled: PT.bool,
134
- enforceA: PT.bool,
135
- keepScrollPosition: PT.bool,
136
- onClick: PT.func,
137
- onMouseDown: PT.func,
138
- openNewTab: PT.bool,
139
- replace: PT.bool,
140
- routerLinkType: PT.elementType.isRequired,
141
- to: PT.oneOfType([PT.object, PT.string]),
142
- };
143
-
144
129
  export default GenericLink;
@@ -1,19 +1,17 @@
1
- import PT from 'prop-types';
2
1
  import { forwardRef } from 'react';
3
2
 
4
3
  import themed, { type Theme } from '@dr.pogodin/react-themes';
5
4
 
6
5
  import defaultTheme from './theme.scss';
7
6
 
8
- const validThemeKeys = [
9
- 'container',
10
- 'input',
11
- 'label',
12
- ] as const;
7
+ type ThemeKeyT =
8
+ | 'container'
9
+ | 'input'
10
+ | 'label';
13
11
 
14
12
  type PropsT = React.InputHTMLAttributes<HTMLInputElement> & {
15
13
  label?: React.ReactNode;
16
- theme: Theme<typeof validThemeKeys>;
14
+ theme: Theme<ThemeKeyT>;
17
15
  };
18
16
 
19
17
  /**
@@ -43,11 +41,4 @@ const Input = forwardRef<HTMLInputElement, PropsT>((
43
41
  </span>
44
42
  ));
45
43
 
46
- const ThemedInput = themed(Input, 'Input', validThemeKeys, defaultTheme);
47
-
48
- Input.propTypes = {
49
- label: PT.node,
50
- theme: ThemedInput.themeType.isRequired,
51
- };
52
-
53
- export default ThemedInput;
44
+ export default themed(Input, 'Input', defaultTheme);
@@ -1,4 +1,3 @@
1
- import PT from 'prop-types';
2
1
  import { type ReactNode, createContext, useMemo } from 'react';
3
2
  import { Helmet } from 'react-helmet';
4
3
 
@@ -147,15 +146,4 @@ const MetaTags: React.FunctionComponent<PropsT> & {
147
146
 
148
147
  MetaTags.Context = Context;
149
148
 
150
- MetaTags.propTypes = {
151
- children: PT.node,
152
- description: PT.string.isRequired,
153
- image: PT.string,
154
- siteName: PT.string,
155
- socialDescription: PT.string,
156
- socialTitle: PT.string,
157
- title: PT.string.isRequired,
158
- url: PT.string,
159
- };
160
-
161
149
  export default MetaTags;
@@ -9,21 +9,18 @@ import {
9
9
  } from 'react';
10
10
 
11
11
  import ReactDom from 'react-dom';
12
- import PT from 'prop-types';
13
12
  import themed, { type Theme } from '@dr.pogodin/react-themes';
14
13
 
15
14
  import baseTheme from './base-theme.scss';
16
15
  import S from './styles.scss';
17
16
 
18
- const validThemeKeys = ['container', 'overlay'] as const;
19
-
20
17
  type PropsT = {
21
18
  cancelOnScrolling?: boolean;
22
19
  children?: ReactNode;
23
20
  containerStyle?: React.CSSProperties;
24
21
  dontDisableScrolling?: boolean;
25
22
  onCancel?: () => void;
26
- theme: Theme<typeof validThemeKeys>;
23
+ theme: Theme<'container' | 'overlay'>;
27
24
  };
28
25
 
29
26
  /**
@@ -89,7 +86,7 @@ const BaseModal: React.FunctionComponent<PropsT> = ({
89
86
  onFocus={() => {
90
87
  const elems = containerRef.current?.querySelectorAll('*') as NodeListOf<HTMLElement>;
91
88
  for (let i = elems.length - 1; i >= 0; --i) {
92
- elems[i].focus();
89
+ elems[i]?.focus();
93
90
  if (document.activeElement === elems[i]) return;
94
91
  }
95
92
  overlayRef.current?.focus();
@@ -169,23 +166,7 @@ const BaseModal: React.FunctionComponent<PropsT> = ({
169
166
  ) : null;
170
167
  };
171
168
 
172
- const ThemedModal = themed(
173
- BaseModal,
174
- 'Modal',
175
- validThemeKeys,
176
- baseTheme,
177
- );
178
-
179
- BaseModal.propTypes = {
180
- cancelOnScrolling: PT.bool,
181
- children: PT.node,
182
- containerStyle: PT.shape({}),
183
- dontDisableScrolling: PT.bool,
184
- onCancel: PT.func,
185
- theme: ThemedModal.themeType.isRequired,
186
- };
187
-
188
- export default ThemedModal;
169
+ export default themed(BaseModal, 'Modal', baseTheme);
189
170
 
190
171
  /* Non-themed version of the Modal. */
191
172
  export { BaseModal };
@@ -1,23 +1,21 @@
1
- import PT from 'prop-types';
2
1
  import type { ReactNode } from 'react';
3
2
 
4
3
  import themed, { type Theme } from '@dr.pogodin/react-themes';
5
4
 
6
5
  import baseTheme from './base-theme.scss';
7
6
 
8
- const validThemeKeys = [
9
- 'container',
10
- 'leftSidePanel',
11
- 'mainPanel',
12
- 'rightSidePanel',
13
- 'sidePanel',
14
- ] as const;
7
+ type ThemeKeyT =
8
+ | 'container'
9
+ | 'leftSidePanel'
10
+ | 'mainPanel'
11
+ | 'rightSidePanel'
12
+ | 'sidePanel';
15
13
 
16
14
  type PropsT = {
17
15
  children?: ReactNode;
18
16
  leftSidePanelContent?: ReactNode;
19
17
  rightSidePanelContent?: ReactNode;
20
- theme: Theme<typeof validThemeKeys>;
18
+ theme: Theme<ThemeKeyT>;
21
19
  };
22
20
 
23
21
  /**
@@ -54,18 +52,4 @@ const PageLayout: React.FunctionComponent<PropsT> = ({
54
52
  </div>
55
53
  );
56
54
 
57
- const ThemedPageLayout = themed(
58
- PageLayout,
59
- 'PageLayout',
60
- validThemeKeys,
61
- baseTheme,
62
- );
63
-
64
- PageLayout.propTypes = {
65
- children: PT.node,
66
- leftSidePanelContent: PT.node,
67
- rightSidePanelContent: PT.node,
68
- theme: ThemedPageLayout.themeType.isRequired,
69
- };
70
-
71
- export default ThemedPageLayout;
55
+ export default themed(PageLayout, 'PageLayout', baseTheme);
@@ -1,22 +1,20 @@
1
1
  import { useEffect, useRef, useState } from 'react';
2
- import PT from 'prop-types';
3
2
 
4
3
  import themed, { type Theme } from '@dr.pogodin/react-themes';
5
4
 
6
5
  import defaultTheme from './style.scss';
7
6
 
8
- const validThemeKeys = [
9
- 'container',
10
- 'hidden',
11
- 'textarea',
12
- ] as const;
7
+ type ThemeKeyT =
8
+ | 'container'
9
+ | 'hidden'
10
+ | 'textarea';
13
11
 
14
12
  type Props = {
15
13
  disabled?: boolean;
16
14
  onChange?: React.ChangeEventHandler<HTMLTextAreaElement>;
17
15
  onKeyDown?: React.KeyboardEventHandler<HTMLTextAreaElement>;
18
16
  placeholder?: string;
19
- theme: Theme<typeof validThemeKeys>;
17
+ theme: Theme<ThemeKeyT>;
20
18
  value?: string;
21
19
  };
22
20
 
@@ -85,20 +83,4 @@ const TextArea: React.FunctionComponent<Props> = ({
85
83
  );
86
84
  };
87
85
 
88
- const ThemedTextArea = themed(
89
- TextArea,
90
- 'TextArea',
91
- validThemeKeys,
92
- defaultTheme,
93
- );
94
-
95
- TextArea.propTypes = {
96
- disabled: PT.bool,
97
- onChange: PT.func,
98
- onKeyDown: PT.func,
99
- placeholder: PT.string,
100
- theme: ThemedTextArea.themeType.isRequired,
101
- value: PT.string,
102
- };
103
-
104
- export default ThemedTextArea;
86
+ export default themed(TextArea, 'TextArea', defaultTheme);