@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
@@ -2,14 +2,13 @@ import themed, { type Theme } from '@dr.pogodin/react-themes';
2
2
 
3
3
  import defaultTheme from './theme.scss';
4
4
 
5
- const validThemeKeys = [
6
- 'bouncing',
7
- 'circle',
8
- 'container',
9
- ] as const;
5
+ type ThemeKeyT =
6
+ | 'bouncing'
7
+ | 'circle'
8
+ | 'container';
10
9
 
11
10
  type PropsT = {
12
- theme: Theme<typeof validThemeKeys>;
11
+ theme: Theme<ThemeKeyT>;
13
12
  };
14
13
 
15
14
  /**
@@ -29,15 +28,4 @@ const Throbber: React.FunctionComponent<PropsT> = ({ theme }) => (
29
28
  </span>
30
29
  );
31
30
 
32
- const ThemedThrobber = themed(
33
- Throbber,
34
- 'Throbber',
35
- validThemeKeys,
36
- defaultTheme,
37
- );
38
-
39
- Throbber.propTypes = {
40
- theme: ThemedThrobber.themeType.isRequired,
41
- };
42
-
43
- export default ThemedThrobber;
31
+ export default themed(Throbber, 'Throbber', defaultTheme);
@@ -16,8 +16,6 @@ import {
16
16
 
17
17
  import { createPortal } from 'react-dom';
18
18
 
19
- import PT from 'prop-types';
20
-
21
19
  import type { Theme } from '@dr.pogodin/react-themes';
22
20
 
23
21
  /* Valid placements of the rendered tooltip. They will be overriden when
@@ -54,14 +52,13 @@ type HeapT = {
54
52
  lastPlacement?: PLACEMENTS | undefined;
55
53
  };
56
54
 
57
- export const validThemeKeys = [
58
- 'appearance',
59
- 'arrow',
60
- 'content',
61
- 'container',
62
- ] as const;
55
+ export type ThemeKeysT =
56
+ | 'appearance'
57
+ | 'arrow'
58
+ | 'content'
59
+ | 'container';
63
60
 
64
- type TooltipThemeT = Theme<typeof validThemeKeys>;
61
+ type TooltipThemeT = Theme<ThemeKeysT>;
65
62
 
66
63
  /**
67
64
  * Creates tooltip components.
@@ -345,9 +342,4 @@ const Tooltip = forwardRef<unknown, {
345
342
  return components ? createPortal(children, components.content) : null;
346
343
  });
347
344
 
348
- Tooltip.propTypes = {
349
- children: PT.node,
350
- theme: PT.shape({}).isRequired,
351
- };
352
-
353
345
  export default Tooltip;
@@ -1,6 +1,5 @@
1
1
  /* global window */
2
2
 
3
- import PT from 'prop-types';
4
3
  import {
5
4
  type ReactNode,
6
5
  useEffect,
@@ -11,19 +10,17 @@ import {
11
10
  import themed, { type Theme } from '@dr.pogodin/react-themes';
12
11
 
13
12
  import Tooltip, {
13
+ type ThemeKeysT as TooltipThemeKeysT,
14
14
  PLACEMENTS,
15
- validThemeKeys as validTooltipThemeKeys,
16
15
  } from './Tooltip';
17
16
 
18
17
  import defaultTheme from './default-theme.scss';
19
18
 
20
- const validThemeKeys = [...validTooltipThemeKeys, 'wrapper'] as const;
21
-
22
19
  type PropsT = {
23
20
  children?: ReactNode;
24
21
  placement?: PLACEMENTS;
25
22
  tip?: ReactNode;
26
- theme: Theme<typeof validThemeKeys>;
23
+ theme: Theme<'wrapper' | TooltipThemeKeysT>;
27
24
  };
28
25
 
29
26
  type TooltipRefT = {
@@ -170,18 +167,7 @@ const Wrapper: React.FunctionComponent<PropsT> = ({
170
167
  );
171
168
  };
172
169
 
173
- const ThemedWrapper = themed(
174
- Wrapper,
175
- 'WithTooltip',
176
- [
177
- 'appearance',
178
- 'arrow',
179
- 'container',
180
- 'content',
181
- 'wrapper',
182
- ],
183
- defaultTheme,
184
- );
170
+ const ThemedWrapper = themed(Wrapper, 'WithTooltip', defaultTheme);
185
171
 
186
172
  type ExportT = typeof ThemedWrapper & {
187
173
  PLACEMENTS: typeof PLACEMENTS;
@@ -191,11 +177,4 @@ const e: ExportT = ThemedWrapper as ExportT;
191
177
 
192
178
  e.PLACEMENTS = PLACEMENTS;
193
179
 
194
- Wrapper.propTypes = {
195
- children: PT.node,
196
- placement: PT.oneOf(Object.values(PLACEMENTS)),
197
- theme: ThemedWrapper.themeType.isRequired,
198
- tip: PT.node,
199
- };
200
-
201
180
  export default e;
@@ -1,4 +1,3 @@
1
- import PT from 'prop-types';
2
1
  import qs from 'qs';
3
2
 
4
3
  import themed, { type Theme } from '@dr.pogodin/react-themes';
@@ -8,9 +7,7 @@ import Throbber from 'components/Throbber';
8
7
  import baseTheme from './base.scss';
9
8
  import throbberTheme from './throbber.scss';
10
9
 
11
- const validThemeKeys = ['container', 'video'] as const;
12
-
13
- type ComponentThemeT = Theme<typeof validThemeKeys>;
10
+ type ComponentThemeT = Theme<'container' | 'video'>;
14
11
 
15
12
  type PropsT = {
16
13
  autoplay?: boolean;
@@ -45,7 +42,7 @@ const YouTubeVideo: React.FunctionComponent<PropsT> = ({
45
42
  const queryString = srcParts[1];
46
43
  const query = queryString ? qs.parse(queryString) : {};
47
44
 
48
- const videoId = query.v || url.match(/\/([a-zA-Z0-9-_]*)$/)?.[1];
45
+ const videoId = query.v || url?.match(/\/([a-zA-Z0-9-_]*)$/)?.[1];
49
46
  url = `https://www.youtube.com/embed/${videoId}`;
50
47
 
51
48
  delete query.v;
@@ -69,18 +66,4 @@ const YouTubeVideo: React.FunctionComponent<PropsT> = ({
69
66
  );
70
67
  };
71
68
 
72
- const ThemedYouTubeVideo = themed(
73
- YouTubeVideo,
74
- 'YouTubeVideo',
75
- validThemeKeys,
76
- baseTheme,
77
- );
78
-
79
- YouTubeVideo.propTypes = {
80
- autoplay: PT.bool,
81
- src: PT.string.isRequired,
82
- theme: ThemedYouTubeVideo.themeType.isRequired,
83
- title: PT.string,
84
- };
85
-
86
- export default ThemedYouTubeVideo;
69
+ export default themed(YouTubeVideo, 'YouTubeVideo', baseTheme);
@@ -1,4 +1,3 @@
1
- import PT from 'prop-types';
2
1
  import { forwardRef, useImperativeHandle, useRef } from 'react';
3
2
 
4
3
  import { BaseModal } from 'components/Modal';
@@ -9,7 +8,6 @@ import {
9
8
  type OptionT,
10
9
  type OptionsT,
11
10
  type ValueT,
12
- optionsValidator,
13
11
  optionValueName,
14
12
  } from '../../common';
15
13
 
@@ -32,7 +30,7 @@ type PropsT = {
32
30
  containerStyle?: ContainerPosT;
33
31
  filter?: (item: OptionT<React.ReactNode> | ValueT) => boolean;
34
32
  optionClass: string;
35
- options: OptionsT<React.ReactNode>;
33
+ options: Readonly<OptionsT<React.ReactNode>>;
36
34
  onCancel: () => void;
37
35
  onChange: (value: ValueT) => void;
38
36
  };
@@ -67,7 +65,7 @@ const Options = forwardRef<RefT, PropsT>(({
67
65
  const optionNodes: React.ReactNode[] = [];
68
66
  for (let i = 0; i < options.length; ++i) {
69
67
  const option = options[i];
70
- if (!filter || filter(option)) {
68
+ if (option !== undefined && (!filter || filter(option))) {
71
69
  const [iValue, iName] = optionValueName(option);
72
70
  optionNodes.push(
73
71
  <div
@@ -116,20 +114,4 @@ const Options = forwardRef<RefT, PropsT>(({
116
114
  );
117
115
  });
118
116
 
119
- Options.propTypes = {
120
- containerClass: PT.string.isRequired,
121
-
122
- containerStyle: PT.shape({
123
- left: PT.number.isRequired,
124
- top: PT.number.isRequired,
125
- width: PT.number.isRequired,
126
- }),
127
-
128
- filter: PT.func,
129
- onCancel: PT.func.isRequired,
130
- onChange: PT.func.isRequired,
131
- optionClass: PT.string.isRequired,
132
- options: optionsValidator.isRequired,
133
- };
134
-
135
117
  export default Options;
@@ -1,4 +1,3 @@
1
- import PT from 'prop-types';
2
1
  import { useEffect, useRef, useState } from 'react';
3
2
 
4
3
  import themed from '@dr.pogodin/react-themes';
@@ -7,14 +6,7 @@ import Options, { type ContainerPosT, type RefT, areEqual } from './Options';
7
6
 
8
7
  import defaultTheme from './theme.scss';
9
8
 
10
- import {
11
- type PropsT,
12
- type ValueT,
13
- optionValidator,
14
- optionValueName,
15
- validThemeKeys,
16
- valueValidator,
17
- } from '../common';
9
+ import { type PropsT, type ValueT, optionValueName } from '../common';
18
10
 
19
11
  const BaseCustomDropdown: React.FunctionComponent<
20
12
  PropsT<React.ReactNode, (value: ValueT) => void>
@@ -97,7 +89,7 @@ PropsT<React.ReactNode, (value: ValueT) => void>
97
89
  let selected: React.ReactNode = <>&zwnj;</>;
98
90
  for (let i = 0; i < options.length; ++i) {
99
91
  const option = options[i];
100
- if (!filter || filter(option)) {
92
+ if (option !== undefined && (!filter || filter(option))) {
101
93
  const [iValue, iName] = optionValueName(option);
102
94
  if (iValue === value) {
103
95
  selected = iName;
@@ -155,20 +147,4 @@ PropsT<React.ReactNode, (value: ValueT) => void>
155
147
  );
156
148
  };
157
149
 
158
- const ThemedCustomDropdown = themed(
159
- BaseCustomDropdown,
160
- 'CustomDropdown',
161
- validThemeKeys,
162
- defaultTheme,
163
- );
164
-
165
- BaseCustomDropdown.propTypes = {
166
- filter: PT.func,
167
- label: PT.node,
168
- onChange: PT.func,
169
- options: PT.arrayOf(optionValidator.isRequired),
170
- theme: ThemedCustomDropdown.themeType.isRequired,
171
- value: valueValidator,
172
- };
173
-
174
- export default ThemedCustomDropdown;
150
+ export default themed(BaseCustomDropdown, 'CustomDropdown', defaultTheme);
@@ -1,18 +1,10 @@
1
1
  // Implements dropdown based on the native HTML <select> element.
2
2
 
3
- import PT from 'prop-types';
4
-
5
3
  import themed from '@dr.pogodin/react-themes';
6
4
 
7
5
  import defaultTheme from './theme.scss';
8
6
 
9
- import {
10
- type PropsT,
11
- optionValueName,
12
- stringOptionsValidator,
13
- validThemeKeys,
14
- valueValidator,
15
- } from '../common';
7
+ import { type PropsT, optionValueName } from '../common';
16
8
 
17
9
  /**
18
10
  * Implements a themeable dropdown list. Internally it is rendered with help of
@@ -48,7 +40,7 @@ const Dropdown: React.FunctionComponent<PropsT<string>> = ({
48
40
 
49
41
  for (let i = 0; i < options.length; ++i) {
50
42
  const option = options[i];
51
- if (!filter || filter(option)) {
43
+ if (option !== undefined && (!filter || filter(option))) {
52
44
  const [iValue, iName] = optionValueName(option);
53
45
  isValidValue ||= iValue === value;
54
46
  optionElements.push(
@@ -92,20 +84,4 @@ const Dropdown: React.FunctionComponent<PropsT<string>> = ({
92
84
  );
93
85
  };
94
86
 
95
- const ThemedDropdown = themed(
96
- Dropdown,
97
- 'Dropdown',
98
- validThemeKeys,
99
- defaultTheme,
100
- );
101
-
102
- Dropdown.propTypes = {
103
- filter: PT.func,
104
- label: PT.node,
105
- onChange: PT.func,
106
- options: stringOptionsValidator,
107
- theme: ThemedDropdown.themeType.isRequired,
108
- value: valueValidator,
109
- };
110
-
111
- export default ThemedDropdown;
87
+ export default themed(Dropdown, 'Dropdown', defaultTheme);
@@ -1,29 +1,25 @@
1
- import PT from 'prop-types';
2
1
  import themed, { type Theme } from '@dr.pogodin/react-themes';
3
2
 
4
3
  import {
5
4
  type OptionsT,
6
5
  type ValueT,
7
- optionsValidator,
8
6
  optionValueName,
9
- valueValidator,
10
7
  } from '../common';
11
8
 
12
9
  import defaultTheme from './theme.scss';
13
10
 
14
- const validThemeKeys = [
15
- 'container',
16
- 'label',
17
- 'option',
18
- 'options',
19
- 'selected',
20
- ] as const;
11
+ type ThemeKeyT =
12
+ | 'container'
13
+ | 'label'
14
+ | 'option'
15
+ | 'options'
16
+ | 'selected';
21
17
 
22
18
  type PropsT = {
23
19
  label?: React.ReactNode;
24
20
  onChange?: (value: ValueT) => void;
25
21
  options?: Readonly<OptionsT<React.ReactNode>>;
26
- theme: Theme<typeof validThemeKeys>;
22
+ theme: Theme<ThemeKeyT>;
27
23
  value?: ValueT;
28
24
  };
29
25
 
@@ -38,31 +34,34 @@ const BaseSwitch: React.FunctionComponent<PropsT> = ({
38
34
 
39
35
  const optionNodes: React.ReactNode[] = [];
40
36
  for (let i = 0; i < options?.length; ++i) {
41
- const [iValue, iName] = optionValueName(options[i]);
37
+ const option = options[i];
38
+ if (option !== undefined) {
39
+ const [iValue, iName] = optionValueName(option);
42
40
 
43
- let className: string = theme.option;
44
- let onPress: (() => void) | undefined;
45
- if (iValue === value) className += ` ${theme.selected}`;
46
- else if (onChange) onPress = () => onChange(iValue);
41
+ let className: string = theme.option;
42
+ let onPress: (() => void) | undefined;
43
+ if (iValue === value) className += ` ${theme.selected}`;
44
+ else if (onChange) onPress = () => onChange(iValue);
47
45
 
48
- optionNodes.push(
49
- onPress ? (
50
- <div
51
- className={className}
52
- onClick={onPress}
53
- onKeyDown={(e) => {
54
- if (onPress && e.key === 'Enter') onPress();
55
- }}
56
- key={iValue}
57
- role="button"
58
- tabIndex={0}
59
- >
60
- {iName}
61
- </div>
62
- ) : (
63
- <div className={className} key={iValue}>{iName}</div>
64
- ),
65
- );
46
+ optionNodes.push(
47
+ onPress ? (
48
+ <div
49
+ className={className}
50
+ onClick={onPress}
51
+ onKeyDown={(e) => {
52
+ if (onPress && e.key === 'Enter') onPress();
53
+ }}
54
+ key={iValue}
55
+ role="button"
56
+ tabIndex={0}
57
+ >
58
+ {iName}
59
+ </div>
60
+ ) : (
61
+ <div className={className} key={iValue}>{iName}</div>
62
+ ),
63
+ );
64
+ }
66
65
  }
67
66
 
68
67
  return (
@@ -75,19 +74,4 @@ const BaseSwitch: React.FunctionComponent<PropsT> = ({
75
74
  );
76
75
  };
77
76
 
78
- const ThemedSwitch = themed(
79
- BaseSwitch,
80
- 'Switch',
81
- validThemeKeys,
82
- defaultTheme,
83
- );
84
-
85
- BaseSwitch.propTypes = {
86
- label: PT.node,
87
- onChange: PT.func,
88
- options: optionsValidator,
89
- theme: ThemedSwitch.themeType.isRequired,
90
- value: valueValidator,
91
- };
92
-
93
- export default ThemedSwitch;
77
+ export default themed(BaseSwitch, 'Switch', defaultTheme);
@@ -1,37 +1,29 @@
1
1
  // The stuff common between different dropdown implementations.
2
2
 
3
- import PT from 'prop-types';
4
-
5
3
  import type { Theme } from '@dr.pogodin/react-themes';
6
4
 
7
- export const validThemeKeys = [
8
- 'active',
9
- 'arrow',
10
- 'container',
11
- 'dropdown',
12
- 'hiddenOption',
13
- 'label',
14
- 'option',
15
- 'select',
5
+ type ThemeKeyT =
6
+ | 'active'
7
+ | 'arrow'
8
+ | 'container'
9
+ | 'dropdown'
10
+ | 'hiddenOption'
11
+ | 'label'
12
+ | 'option'
13
+ | 'select'
16
14
 
17
15
  // TODO: This is only valid for <CustomDropdown>, thus we need to re-factor it
18
16
  // into a separate theme spec for that component.
19
- 'upward',
20
- ] as const;
17
+ | 'upward';
21
18
 
22
19
  export type ValueT = number | string;
23
20
 
24
- export const valueValidator: PT.Requireable<ValueT> = PT.oneOfType([
25
- PT.number.isRequired,
26
- PT.string.isRequired,
27
- ]);
28
-
29
21
  export type OptionT<NameT> = {
30
22
  name?: NameT | null;
31
23
  value: ValueT;
32
24
  };
33
25
 
34
- export type OptionsT<NameT> = Array<OptionT<NameT> | ValueT>;
26
+ export type OptionsT<NameT> = Readonly<Array<OptionT<NameT> | ValueT>>;
35
27
 
36
28
  export type PropsT<
37
29
  NameT,
@@ -40,35 +32,11 @@ export type PropsT<
40
32
  filter?: (item: OptionT<NameT> | ValueT) => boolean;
41
33
  label?: React.ReactNode;
42
34
  onChange?: OnChangeT;
43
- options?: OptionsT<NameT>;
44
- theme: Theme<typeof validThemeKeys>;
35
+ options?: Readonly<OptionsT<NameT>>;
36
+ theme: Theme<ThemeKeyT>;
45
37
  value?: ValueT;
46
38
  };
47
39
 
48
- export const optionValidator:
49
- PT.Requireable<OptionT<React.ReactNode> | ValueT> = PT.oneOfType([
50
- PT.shape({
51
- name: PT.node,
52
- value: valueValidator.isRequired,
53
- }).isRequired,
54
- PT.number.isRequired,
55
- PT.string.isRequired,
56
- ]);
57
-
58
- export const optionsValidator = PT.arrayOf(optionValidator.isRequired);
59
-
60
- export const stringOptionValidator:
61
- PT.Requireable<OptionT<string> | ValueT> = PT.oneOfType([
62
- PT.shape({
63
- name: PT.string,
64
- value: valueValidator.isRequired,
65
- }).isRequired,
66
- PT.number.isRequired,
67
- PT.string.isRequired,
68
- ]);
69
-
70
- export const stringOptionsValidator = PT.arrayOf(stringOptionValidator.isRequired);
71
-
72
40
  function isValue<T>(x: OptionT<T> | ValueT): x is ValueT {
73
41
  const type = typeof x;
74
42
  return type === 'number' || type === 'string';
@@ -5,6 +5,4 @@ export { default as Switch } from './Switch';
5
5
  export {
6
6
  type OptionT,
7
7
  type OptionsT,
8
- optionValidator,
9
- optionsValidator,
10
8
  } from './common';
@@ -13,6 +13,12 @@ export type InjT = {
13
13
  ISTATE?: unknown;
14
14
  };
15
15
 
16
+ declare global {
17
+ interface Window {
18
+ REACT_UTILS_INJECTION?: InjT;
19
+ }
20
+ }
21
+
16
22
  export interface SsrContextT<StateT> extends SsrContext<StateT> {
17
23
  chunkGroups: ChunkGroupsT;
18
24
  chunks: string[];
@@ -100,12 +100,23 @@ export function mount(scene: ReactNode): MountedSceneT {
100
100
  return res;
101
101
  }
102
102
 
103
- export function snapshot(element: React.ReactElement) {
103
+ type SnapshotOptionsT = {
104
+ await?: Promise<void>;
105
+ };
106
+
107
+ export async function snapshot(
108
+ element: React.ReactElement,
109
+ options?: SnapshotOptionsT,
110
+ ) {
104
111
  let res: RenderResult | undefined;
105
- act(() => {
112
+
113
+ const promise = act(() => {
106
114
  res = render(element);
115
+ return options?.await;
107
116
  });
117
+
108
118
  if (res === undefined) throw Error('Render failed');
119
+ if (options?.await) await promise;
109
120
 
110
121
  const nodes = res.asFragment().childNodes;
111
122
  expect(nodes.length > 1 ? [...nodes] : nodes[0]).toMatchSnapshot();