@dr.pogodin/react-utils 1.35.5 → 1.36.1

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 (169) hide show
  1. package/LICENSE.md +1 -1
  2. package/build/development/index.js +0 -6
  3. package/build/development/index.js.map +1 -1
  4. package/build/development/server/Cache.js +19 -19
  5. package/build/development/server/Cache.js.map +1 -1
  6. package/build/development/server/renderer.js +7 -4
  7. package/build/development/server/renderer.js.map +1 -1
  8. package/build/development/server/server.js +4 -1
  9. package/build/development/server/server.js.map +1 -1
  10. package/build/development/shared/components/Button/index.js +1 -16
  11. package/build/development/shared/components/Button/index.js.map +1 -1
  12. package/build/development/shared/components/Checkbox/index.js +1 -29
  13. package/build/development/shared/components/Checkbox/index.js.map +1 -1
  14. package/build/development/shared/components/GenericLink/index.js +0 -15
  15. package/build/development/shared/components/GenericLink/index.js.map +1 -1
  16. package/build/development/shared/components/Input/index.js +1 -8
  17. package/build/development/shared/components/Input/index.js.map +1 -1
  18. package/build/development/shared/components/MetaTags.js +0 -12
  19. package/build/development/shared/components/MetaTags.js.map +1 -1
  20. package/build/development/shared/components/Modal/index.js +2 -13
  21. package/build/development/shared/components/Modal/index.js.map +1 -1
  22. package/build/development/shared/components/PageLayout/index.js +1 -10
  23. package/build/development/shared/components/PageLayout/index.js.map +1 -1
  24. package/build/development/shared/components/TextArea/index.js +1 -12
  25. package/build/development/shared/components/TextArea/index.js.map +1 -1
  26. package/build/development/shared/components/Throbber/index.js +1 -6
  27. package/build/development/shared/components/Throbber/index.js.map +1 -1
  28. package/build/development/shared/components/WithTooltip/Tooltip.js +1 -8
  29. package/build/development/shared/components/WithTooltip/Tooltip.js.map +1 -1
  30. package/build/development/shared/components/WithTooltip/index.js +1 -9
  31. package/build/development/shared/components/WithTooltip/index.js.map +1 -1
  32. package/build/development/shared/components/YouTubeVideo/index.js +2 -11
  33. package/build/development/shared/components/YouTubeVideo/index.js.map +1 -1
  34. package/build/development/shared/components/selectors/CustomDropdown/Options/index.js +1 -16
  35. package/build/development/shared/components/selectors/CustomDropdown/Options/index.js.map +1 -1
  36. package/build/development/shared/components/selectors/CustomDropdown/index.js +2 -12
  37. package/build/development/shared/components/selectors/CustomDropdown/index.js.map +1 -1
  38. package/build/development/shared/components/selectors/NativeDropdown/index.js +2 -12
  39. package/build/development/shared/components/selectors/NativeDropdown/index.js.map +1 -1
  40. package/build/development/shared/components/selectors/Switch/index.js +21 -28
  41. package/build/development/shared/components/selectors/Switch/index.js.map +1 -1
  42. package/build/development/shared/components/selectors/common.js +0 -19
  43. package/build/development/shared/components/selectors/common.js.map +1 -1
  44. package/build/development/shared/components/selectors/index.js +0 -13
  45. package/build/development/shared/components/selectors/index.js.map +1 -1
  46. package/build/development/shared/utils/jest/index.js +4 -2
  47. package/build/development/shared/utils/jest/index.js.map +1 -1
  48. package/build/development/shared/utils/splitComponent.js +11 -12
  49. package/build/development/shared/utils/splitComponent.js.map +1 -1
  50. package/build/development/web.bundle.js +26 -36
  51. package/build/production/index.js +1 -1
  52. package/build/production/index.js.map +1 -1
  53. package/build/production/server/Cache.js +3 -3
  54. package/build/production/server/Cache.js.map +1 -1
  55. package/build/production/server/renderer.js +2 -2
  56. package/build/production/server/renderer.js.map +1 -1
  57. package/build/production/server/server.js +1 -1
  58. package/build/production/server/server.js.map +1 -1
  59. package/build/production/shared/components/Button/index.js +3 -3
  60. package/build/production/shared/components/Button/index.js.map +1 -1
  61. package/build/production/shared/components/Checkbox/index.js +1 -16
  62. package/build/production/shared/components/Checkbox/index.js.map +1 -1
  63. package/build/production/shared/components/GenericLink/index.js +2 -2
  64. package/build/production/shared/components/GenericLink/index.js.map +1 -1
  65. package/build/production/shared/components/Input/index.js +2 -2
  66. package/build/production/shared/components/Input/index.js.map +1 -1
  67. package/build/production/shared/components/MetaTags.js +2 -2
  68. package/build/production/shared/components/MetaTags.js.map +1 -1
  69. package/build/production/shared/components/Modal/index.js +2 -2
  70. package/build/production/shared/components/Modal/index.js.map +1 -1
  71. package/build/production/shared/components/PageLayout/index.js +2 -2
  72. package/build/production/shared/components/PageLayout/index.js.map +1 -1
  73. package/build/production/shared/components/TextArea/index.js +2 -2
  74. package/build/production/shared/components/TextArea/index.js.map +1 -1
  75. package/build/production/shared/components/Throbber/index.js +2 -2
  76. package/build/production/shared/components/Throbber/index.js.map +1 -1
  77. package/build/production/shared/components/WithTooltip/Tooltip.js +3 -3
  78. package/build/production/shared/components/WithTooltip/Tooltip.js.map +1 -1
  79. package/build/production/shared/components/WithTooltip/index.js +2 -2
  80. package/build/production/shared/components/WithTooltip/index.js.map +1 -1
  81. package/build/production/shared/components/YouTubeVideo/index.js +3 -3
  82. package/build/production/shared/components/YouTubeVideo/index.js.map +1 -1
  83. package/build/production/shared/components/selectors/CustomDropdown/Options/index.js +2 -2
  84. package/build/production/shared/components/selectors/CustomDropdown/Options/index.js.map +1 -1
  85. package/build/production/shared/components/selectors/CustomDropdown/index.js +2 -2
  86. package/build/production/shared/components/selectors/CustomDropdown/index.js.map +1 -1
  87. package/build/production/shared/components/selectors/NativeDropdown/index.js +3 -3
  88. package/build/production/shared/components/selectors/NativeDropdown/index.js.map +1 -1
  89. package/build/production/shared/components/selectors/Switch/index.js +1 -1
  90. package/build/production/shared/components/selectors/Switch/index.js.map +1 -1
  91. package/build/production/shared/components/selectors/common.js +2 -4
  92. package/build/production/shared/components/selectors/common.js.map +1 -1
  93. package/build/production/shared/components/selectors/index.js +1 -1
  94. package/build/production/shared/components/selectors/index.js.map +1 -1
  95. package/build/production/shared/utils/jest/index.js +1 -1
  96. package/build/production/shared/utils/jest/index.js.map +1 -1
  97. package/build/production/shared/utils/splitComponent.js +5 -5
  98. package/build/production/shared/utils/splitComponent.js.map +1 -1
  99. package/build/production/web.bundle.js +1 -1
  100. package/build/production/web.bundle.js.map +1 -1
  101. package/build/types-code/index.d.ts +1 -2
  102. package/build/types-code/server/Cache.d.ts +3 -11
  103. package/build/types-code/server/index.d.ts +0 -2
  104. package/build/types-code/server/renderer.d.ts +0 -1
  105. package/build/types-code/server/server.d.ts +0 -1
  106. package/build/types-code/shared/components/Button/index.d.ts +3 -4
  107. package/build/types-code/shared/components/Checkbox/index.d.ts +3 -12
  108. package/build/types-code/shared/components/Input/index.d.ts +4 -5
  109. package/build/types-code/shared/components/Link.d.ts +0 -1
  110. package/build/types-code/shared/components/Modal/index.d.ts +3 -4
  111. package/build/types-code/shared/components/NavLink.d.ts +0 -1
  112. package/build/types-code/shared/components/PageLayout/index.d.ts +4 -4
  113. package/build/types-code/shared/components/TextArea/index.d.ts +4 -5
  114. package/build/types-code/shared/components/Throbber/index.d.ts +4 -4
  115. package/build/types-code/shared/components/WithTooltip/Tooltip.d.ts +1 -1
  116. package/build/types-code/shared/components/WithTooltip/index.d.ts +2 -3
  117. package/build/types-code/shared/components/YouTubeVideo/index.d.ts +3 -4
  118. package/build/types-code/shared/components/selectors/CustomDropdown/Options/index.d.ts +1 -2
  119. package/build/types-code/shared/components/selectors/CustomDropdown/index.d.ts +2 -3
  120. package/build/types-code/shared/components/selectors/NativeDropdown/index.d.ts +2 -2
  121. package/build/types-code/shared/components/selectors/Switch/index.d.ts +4 -5
  122. package/build/types-code/shared/components/selectors/common.d.ts +4 -10
  123. package/build/types-code/shared/components/selectors/index.d.ts +1 -1
  124. package/build/types-code/shared/utils/globalState.d.ts +1 -2
  125. package/build/types-code/shared/utils/jest/index.d.ts +4 -1
  126. package/build/types-code/shared/utils/splitComponent.d.ts +0 -1
  127. package/build/types-code/shared/utils/webpack.d.ts +0 -1
  128. package/config/babel/node-ssr.js +1 -1
  129. package/config/babel/webpack.js +1 -1
  130. package/config/eslint/default.json +1 -0
  131. package/config/eslint/jest.json +1 -0
  132. package/config/eslint/typescript.js +7 -0
  133. package/config/typescript/base.json +9 -0
  134. package/config/webpack/app-base.d.ts +0 -1
  135. package/config/webpack/app-base.js +1 -1
  136. package/config/webpack/app-development.js +1 -1
  137. package/config/webpack/app-production.js +1 -1
  138. package/config/webpack/lib-base.js +1 -2
  139. package/config/webpack/lib-development.js +1 -1
  140. package/config/webpack/lib-production.js +1 -1
  141. package/package.json +16 -17
  142. package/src/index.ts +0 -1
  143. package/src/server/Cache.ts +31 -30
  144. package/src/server/renderer.tsx +8 -5
  145. package/src/server/server.ts +6 -1
  146. package/src/shared/components/Button/index.tsx +2 -20
  147. package/src/shared/components/Checkbox/index.tsx +2 -37
  148. package/src/shared/components/GenericLink/index.tsx +0 -15
  149. package/src/shared/components/Input/index.tsx +6 -15
  150. package/src/shared/components/MetaTags.tsx +0 -12
  151. package/src/shared/components/Modal/index.tsx +3 -22
  152. package/src/shared/components/PageLayout/index.tsx +8 -24
  153. package/src/shared/components/TextArea/index.tsx +6 -24
  154. package/src/shared/components/Throbber/index.tsx +6 -18
  155. package/src/shared/components/WithTooltip/Tooltip.tsx +6 -14
  156. package/src/shared/components/WithTooltip/index.tsx +3 -24
  157. package/src/shared/components/YouTubeVideo/index.tsx +3 -20
  158. package/src/shared/components/selectors/CustomDropdown/Options/index.tsx +2 -20
  159. package/src/shared/components/selectors/CustomDropdown/index.tsx +3 -27
  160. package/src/shared/components/selectors/NativeDropdown/index.tsx +3 -27
  161. package/src/shared/components/selectors/Switch/index.tsx +34 -50
  162. package/src/shared/components/selectors/common.ts +12 -44
  163. package/src/shared/components/selectors/index.ts +0 -2
  164. package/src/shared/utils/jest/index.tsx +13 -2
  165. package/src/shared/utils/splitComponent.tsx +14 -11
  166. package/tsconfig.configs.json +7 -3
  167. package/tsconfig.json +3 -10
  168. package/tsconfig.types.json +1 -7
  169. package/tstyche.config.json +6 -0
@@ -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,31 +1,23 @@
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;
@@ -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';
@@ -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();
@@ -1,8 +1,6 @@
1
1
  /* eslint-disable react/jsx-props-no-spreading */
2
2
  /* global document */
3
3
 
4
- import PT from 'prop-types';
5
-
6
4
  import {
7
5
  type ComponentType,
8
6
  type ReactNode,
@@ -88,7 +86,7 @@ function getLoadedStyleSheets(): Set<string> {
88
86
  const res = new Set<string>();
89
87
  const { styleSheets } = document;
90
88
  for (let i = 0; i < styleSheets.length; ++i) {
91
- const { href } = styleSheets[i];
89
+ const href = styleSheets[i]?.href;
92
90
  if (href) res.add(href);
93
91
  }
94
92
  return res;
@@ -118,11 +116,13 @@ export function bookStyleSheets(
118
116
  ): Promise<void> {
119
117
  const promises = [];
120
118
  const assets = chunkGroups[chunkName];
119
+ if (!assets) return Promise.resolve();
120
+
121
121
  const loadedSheets = getLoadedStyleSheets();
122
122
 
123
123
  for (let i = 0; i < assets.length; ++i) {
124
124
  const asset = assets[i];
125
- if (asset.endsWith('.css')) {
125
+ if (asset?.endsWith('.css')) {
126
126
  const promise = bookStyleSheet(asset, loadedSheets, refCount);
127
127
  if (promise) promises.push(promise);
128
128
  }
@@ -145,12 +145,19 @@ export function freeStyleSheets(
145
145
  chunkGroups: ChunkGroupsT,
146
146
  ) {
147
147
  const assets = chunkGroups[chunkName];
148
+ if (!assets) return;
149
+
148
150
  for (let i = 0; i < assets.length; ++i) {
149
151
  const asset = assets[i];
150
- if (asset.endsWith('.css')) {
152
+ if (asset?.endsWith('.css')) {
151
153
  const path = `${getPublicPath()}/${asset}`;
152
- if (--refCounts[path] <= 0) {
153
- document.head.querySelector(`link[href="${path}"]`)!.remove();
154
+
155
+ const pathRefCount = refCounts[path];
156
+ if (pathRefCount) {
157
+ if (pathRefCount <= 1) {
158
+ document.head.querySelector(`link[href="${path}"]`)!.remove();
159
+ delete refCounts[path];
160
+ } else refCounts[path] = pathRefCount - 1;
154
161
  }
155
162
  }
156
163
  }
@@ -243,9 +250,5 @@ export default function splitComponent<
243
250
  </Suspense>
244
251
  );
245
252
 
246
- CodeSplit.propTypes = {
247
- children: PT.node,
248
- } as PT.WeakValidationMap<ComponentPropsT>;
249
-
250
253
  return CodeSplit;
251
254
  }
@@ -1,18 +1,22 @@
1
1
  // TS configuration for configs pre-building from TS sources.
2
2
 
3
3
  {
4
- "extends": "@tsconfig/recommended",
4
+ "extends": "./config/typescript/base.json",
5
5
  "include": [
6
6
  "config-ts-src",
7
7
  ],
8
8
  "compilerOptions": {
9
9
  "declaration": true,
10
- "jsx": "react-jsx",
11
10
  "rootDir": "config-ts-src",
12
11
  "outDir": "config",
13
12
  "paths": {
14
13
  "*": ["./src/shared/*", "./src/*", "./*"]
15
14
  },
16
- "strict": true
15
+
16
+ // TODO: Overriding the base config as configs are compiled into CommonJS
17
+ // modules, and this flag leads to the following error in that case, if set:
18
+ // ESM syntax is not allowed in a CommonJS module when 'verbatimModuleSyntax' is enabled.
19
+ // Perhaps, there is a better workaround?
20
+ "verbatimModuleSyntax": false
17
21
  }
18
22
  }
package/tsconfig.json CHANGED
@@ -1,13 +1,11 @@
1
1
  // TS config for ESLint, editor plugins, and other tools that look-up and use
2
2
  // the default tsconfig.json file.
3
3
  {
4
- // Note: Full relative paths, as some tools don't support Node module
5
- // resolution mechanics.
6
- "extends": "./node_modules/@tsconfig/recommended/tsconfig.json",
4
+ // Relative path, as some tools relying on this config do not support Node's
5
+ // module resolution mechanics.
6
+ "extends": "./config/typescript/base.json",
7
7
 
8
8
  "compilerOptions": {
9
- "jsx": "react-jsx",
10
-
11
9
  // BEWARE: Different settings are likely to transform dynamic import()
12
10
  // statements in the code, thus breaking Webpack's code splitting.
13
11
  // See: https://davidea.st/articles/webpack-typescript-code-split-wont-work
@@ -18,10 +16,5 @@
18
16
  "*": ["./src/shared/*", "./src/*", "./*"]
19
17
  },
20
18
  "rootDirs": [".", "build/types-scss"],
21
- "strict": true,
22
-
23
- // This ensures TypeScript does not remove unused imports, which may cause
24
- // troubles when we rely on some side-effects from imported modules.
25
- "verbatimModuleSyntax": true,
26
19
  }
27
20
  }
@@ -1,7 +1,7 @@
1
1
  // TS config for ESLint, editor plugins, and other tools that look-up and use
2
2
  // the default tsconfig.json file.
3
3
  {
4
- "extends": "@tsconfig/recommended",
4
+ "extends": "./config/typescript/base.json",
5
5
 
6
6
  // Keep these in case any mocks / tests are declared within "src" code tree.
7
7
  "exclude": [
@@ -16,7 +16,6 @@
16
16
  "compilerOptions": {
17
17
  "declaration": true,
18
18
  "emitDeclarationOnly": true,
19
- "jsx": "react-jsx",
20
19
 
21
20
  // BEWARE: Different settings are likely to transform dynamic import()
22
21
  // statements in the code, thus breaking Webpack's code splitting.
@@ -42,10 +41,5 @@
42
41
  "utils/*": ["./src/shared/utils/*"],
43
42
  },
44
43
  "rootDirs": [".", "build/types-scss"],
45
- "strict": true,
46
-
47
- // This ensures TypeScript does not remove unused imports, which may cause
48
- // troubles when we rely on some side-effects from imported modules.
49
- "verbatimModuleSyntax": true,
50
44
  },
51
45
  }
@@ -0,0 +1,6 @@
1
+ {
2
+ "testFileMatch": [
3
+ "__tests__/**/*.ts",
4
+ "__tests__/**/*.tsx"
5
+ ]
6
+ }