@true-engineering/true-react-common-ui-kit 4.0.0-alpha54 → 4.0.0-alpha61

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 (151) hide show
  1. package/README.md +1 -0
  2. package/dist/components/AddButton/AddButton.d.ts +1 -0
  3. package/dist/components/AddButton/AddButton.styles.d.ts +1 -1
  4. package/dist/components/Button/Button.styles.d.ts +1 -1
  5. package/dist/components/Checkbox/Checkbox.styles.d.ts +1 -1
  6. package/dist/components/ControlWrapper/ControlWrapper.d.ts +1 -1
  7. package/dist/components/ControlWrapper/ControlWrapper.styles.d.ts +1 -1
  8. package/dist/components/CssBaseline/CssBaseline.styles.d.ts +1 -1
  9. package/dist/components/DatePicker/components/DatePickerHeader/DatePickerHeader.styles.d.ts +1 -1
  10. package/dist/components/Description/Description.styles.d.ts +1 -1
  11. package/dist/components/FileInput/FileInput.styles.d.ts +1 -1
  12. package/dist/components/FileItem/FileItem.styles.d.ts +1 -1
  13. package/dist/components/FiltersPane/components/FilterInterval/FilterInterval.styles.d.ts +1 -1
  14. package/dist/components/FiltersPane/components/FilterSelect/FilterSelect.styles.d.ts +2 -2
  15. package/dist/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.d.ts +2 -2
  16. package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.d.ts +1 -1
  17. package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.styles.d.ts +1 -1
  18. package/dist/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.styles.d.ts +1 -1
  19. package/dist/components/FiltersPane/types.d.ts +2 -1
  20. package/dist/components/FlexibleTable/FlexibleTable.styles.d.ts +1 -1
  21. package/dist/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.styles.d.ts +1 -1
  22. package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.d.ts +1 -3
  23. package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.styles.d.ts +1 -1
  24. package/dist/components/FloatDocActions/components/DocActions/DocActions.styles.d.ts +1 -1
  25. package/dist/components/IconButton/IconButton.styles.d.ts +1 -1
  26. package/dist/components/List/components/ListItem/ListItem.styles.d.ts +1 -1
  27. package/dist/components/Modal/Modal.styles.d.ts +1 -1
  28. package/dist/components/MoreMenu/MoreMenu.styles.d.ts +1 -1
  29. package/dist/components/MultiSelect/MultiSelect.styles.d.ts +1 -1
  30. package/dist/components/MultiSelect/components/MultiSelectInput/MultiSelectInput.styles.d.ts +1 -1
  31. package/dist/components/MultiSelectList/MultiSelectList.styles.d.ts +1 -1
  32. package/dist/components/NewMoreMenu/NewMoreMenu.styles.d.ts +1 -1
  33. package/dist/components/Notification/Notification.styles.d.ts +1 -1
  34. package/dist/components/PhoneInput/PhoneInput.styles.d.ts +1 -1
  35. package/dist/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.styles.d.ts +1 -1
  36. package/dist/components/RadioButton/RadioButton.styles.d.ts +1 -1
  37. package/dist/components/SearchInput/SearchInput.d.ts +1 -1
  38. package/dist/components/Select/Select.styles.d.ts +3 -3
  39. package/dist/components/Select/components/SelectList/SelectList.styles.d.ts +1 -1
  40. package/dist/components/Selector/Selector.styles.d.ts +1 -1
  41. package/dist/components/Status/Status.styles.d.ts +1 -1
  42. package/dist/components/Switch/Switch.d.ts +3 -2
  43. package/dist/components/Switch/Switch.styles.d.ts +3 -2
  44. package/dist/components/Switch/types.d.ts +3 -0
  45. package/dist/components/TextArea/TextArea.styles.d.ts +1 -1
  46. package/dist/components/TextButton/TextButton.styles.d.ts +1 -1
  47. package/dist/components/TextWithInfo/TextWithInfo.styles.d.ts +1 -1
  48. package/dist/components/TextWithTooltip/TextWithTooltip.d.ts +2 -0
  49. package/dist/components/TextWithTooltip/TextWithTooltip.styles.d.ts +1 -1
  50. package/dist/components/ThemedPreloader/ThemedPreloader.styles.d.ts +1 -1
  51. package/dist/components/ThemedPreloader/components/DotsPreloader/DotsPreloader.styles.d.ts +1 -1
  52. package/dist/components/Toaster/Toaster.styles.d.ts +1 -1
  53. package/dist/components/Tooltip/Tooltip.d.ts +3 -0
  54. package/dist/components/Tooltip/Tooltip.styles.d.ts +2 -1
  55. package/dist/components/Tooltip/types.d.ts +3 -0
  56. package/dist/components/WithMessages/WithMessages.styles.d.ts +1 -1
  57. package/dist/components/WithPopup/WithPopup.styles.d.ts +1 -1
  58. package/dist/components/WithTooltip/WithTooltip.d.ts +2 -0
  59. package/dist/helpers/misc.d.ts +2 -0
  60. package/dist/hooks/index.d.ts +1 -0
  61. package/dist/hooks/use-intersection-ref.d.ts +2 -1
  62. package/dist/hooks/use-resize-ref.d.ts +7 -0
  63. package/dist/hooks/use-tweak-styles.d.ts +3 -2
  64. package/dist/theme/Provider.d.ts +2 -12
  65. package/dist/theme/common.d.ts +34 -4
  66. package/dist/theme/helpers.d.ts +3 -16
  67. package/dist/theme/index.d.ts +0 -2
  68. package/dist/theme/types.d.ts +9 -8
  69. package/dist/true-react-common-ui-kit.js +12132 -10
  70. package/dist/true-react-common-ui-kit.js.map +1 -1
  71. package/dist/true-react-common-ui-kit.umd.cjs +2 -10
  72. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  73. package/dist/types.d.ts +3 -3
  74. package/package.json +1 -3
  75. package/src/components/AccountInfo/AccountInfo.tsx +2 -3
  76. package/src/components/AddButton/AddButton.tsx +3 -5
  77. package/src/components/Button/Button.tsx +76 -77
  78. package/src/components/CloseButton/CloseButton.tsx +2 -4
  79. package/src/components/Colors/Colors.stories.tsx +3 -2
  80. package/src/components/ControlWrapper/ControlWrapper.tsx +2 -2
  81. package/src/components/CssBaseline/CssBaseline.styles.ts +2 -0
  82. package/src/components/CssBaseline/CssBaseline.tsx +2 -3
  83. package/src/components/DateInput/DateInput.tsx +59 -61
  84. package/src/components/DatePicker/DatePicker.tsx +259 -262
  85. package/src/components/Description/Description.tsx +2 -3
  86. package/src/components/FileInput/FileInput.tsx +87 -95
  87. package/src/components/FileItem/FileItem.tsx +2 -4
  88. package/src/components/FiltersPane/FiltersPane.stories.tsx +3 -0
  89. package/src/components/FiltersPane/components/FilterInterval/FilterInterval.tsx +2 -3
  90. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.tsx +6 -3
  91. package/src/components/FiltersPane/components/FilterWrapper/FilterWrapper.tsx +3 -2
  92. package/src/components/FiltersPane/types.ts +2 -0
  93. package/src/components/FlexibleTable/FlexibleTable.styles.ts +1 -0
  94. package/src/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.styles.ts +1 -0
  95. package/src/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.tsx +5 -2
  96. package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.tsx +9 -7
  97. package/src/components/IconButton/IconButton.tsx +44 -48
  98. package/src/components/Input/Input.tsx +26 -24
  99. package/src/components/Input/InputBase.tsx +183 -187
  100. package/src/components/List/List.tsx +2 -3
  101. package/src/components/List/components/ListItem/ListItem.tsx +2 -4
  102. package/src/components/Modal/Modal.tsx +2 -4
  103. package/src/components/MoreMenu/MoreMenu.tsx +2 -4
  104. package/src/components/MultiSelect/MultiSelect.tsx +2 -4
  105. package/src/components/NewMoreMenu/NewMoreMenu.tsx +2 -4
  106. package/src/components/Notification/Notification.tsx +2 -3
  107. package/src/components/NumberInput/NumberInput.tsx +91 -93
  108. package/src/components/PhoneInput/PhoneInput.tsx +2 -3
  109. package/src/components/SearchInput/SearchInput.tsx +20 -19
  110. package/src/components/Select/Select.tsx +1 -1
  111. package/src/components/Selector/Selector.tsx +4 -6
  112. package/src/components/SmartInput/SmartInput.tsx +85 -87
  113. package/src/components/Status/Status.tsx +5 -4
  114. package/src/components/Switch/Switch.styles.ts +21 -13
  115. package/src/components/Switch/Switch.tsx +11 -6
  116. package/src/components/Switch/types.ts +5 -0
  117. package/src/components/TextArea/TextArea.tsx +128 -130
  118. package/src/components/TextButton/TextButton.tsx +68 -69
  119. package/src/components/TextWithInfo/TextWithInfo.tsx +2 -4
  120. package/src/components/TextWithTooltip/TextWithTooltip.tsx +6 -4
  121. package/src/components/ThemedPreloader/ThemedPreloader.tsx +2 -4
  122. package/src/components/Toaster/Toaster.tsx +2 -4
  123. package/src/components/Tooltip/Tooltip.stories.tsx +10 -0
  124. package/src/components/Tooltip/Tooltip.styles.ts +2 -1
  125. package/src/components/Tooltip/Tooltip.tsx +12 -5
  126. package/src/components/Tooltip/types.ts +5 -0
  127. package/src/components/WithMessages/WithMessages.tsx +41 -40
  128. package/src/components/WithTooltip/WithTooltip.tsx +4 -0
  129. package/src/helpers/misc.ts +6 -0
  130. package/src/hooks/index.ts +1 -0
  131. package/src/hooks/use-intersection-ref.ts +24 -6
  132. package/src/hooks/use-latest-ref.ts +6 -2
  133. package/src/hooks/use-resize-ref.ts +35 -0
  134. package/src/hooks/use-tweak-styles.ts +14 -51
  135. package/src/theme/Provider.tsx +4 -21
  136. package/src/theme/common.ts +33 -36
  137. package/src/theme/helpers.ts +50 -42
  138. package/src/theme/index.ts +0 -2
  139. package/src/theme/types.ts +13 -10
  140. package/src/types.ts +3 -3
  141. package/dist/theme/create-themed-styles.d.ts +0 -2
  142. package/dist/theme/true-jss/ThemedStylesManager.d.ts +0 -18
  143. package/dist/theme/true-jss/TweakStylesManager.d.ts +0 -34
  144. package/dist/theme/true-jss/index.d.ts +0 -2
  145. package/dist/theme/true-jss/jss-context.d.ts +0 -9
  146. package/dist/true-react-common-ui-kit.css +0 -756
  147. package/src/theme/create-themed-styles.ts +0 -78
  148. package/src/theme/true-jss/ThemedStylesManager.ts +0 -93
  149. package/src/theme/true-jss/TweakStylesManager.ts +0 -156
  150. package/src/theme/true-jss/index.ts +0 -2
  151. package/src/theme/true-jss/jss-context.tsx +0 -34
@@ -15,45 +15,46 @@ export interface IWithMessagesProps extends ICommonProps<IWithMessagesStyles> {
15
15
  controlsDirection?: 'horizontal' | 'vertical';
16
16
  }
17
17
 
18
- export const WithMessages = forwardRef<HTMLDivElement, IWithMessagesProps>(
19
- ({ children, infoMessage, errorMessage, controlsDirection, tweakStyles, testId, data }, ref) => {
20
- const classes = useStyles({ theme: tweakStyles });
18
+ export const WithMessages = forwardRef<HTMLDivElement, IWithMessagesProps>(function WithMessages(
19
+ { children, infoMessage, errorMessage, controlsDirection, tweakStyles, testId, data },
20
+ ref,
21
+ ) {
22
+ const classes = useStyles({ theme: tweakStyles });
21
23
 
22
- const shouldShowError = isReactNodeNotEmpty(errorMessage);
23
- const shouldShowInfo = isReactNodeNotEmpty(infoMessage) && !shouldShowError;
24
+ const shouldShowError = isReactNodeNotEmpty(errorMessage);
25
+ const shouldShowInfo = isReactNodeNotEmpty(infoMessage) && !shouldShowError;
24
26
 
25
- return (
26
- <div
27
- ref={ref}
28
- className={classes.withMessages}
29
- data-invalid={shouldShowError ? true : undefined}
30
- {...addDataAttributes(data, testId)}
31
- >
32
- {isReactNodeNotEmpty(children) && (
33
- <div
34
- className={clsx(classes.children, {
35
- [classes.horizontal]: controlsDirection === 'horizontal',
36
- [classes.vertical]: controlsDirection === 'vertical',
37
- })}
38
- >
39
- {children}
40
- </div>
41
- )}
42
- {(shouldShowError || shouldShowInfo) && (
43
- <div className={classes.message}>
44
- {shouldShowError && (
45
- <div className={classes.error} {...addDataTestId(testId, 'error')}>
46
- {errorMessage}
47
- </div>
48
- )}
49
- {shouldShowInfo && (
50
- <div className={classes.info} {...addDataTestId(testId, 'info')}>
51
- {infoMessage}
52
- </div>
53
- )}
54
- </div>
55
- )}
56
- </div>
57
- );
58
- },
59
- );
27
+ return (
28
+ <div
29
+ ref={ref}
30
+ className={classes.withMessages}
31
+ data-invalid={shouldShowError ? true : undefined}
32
+ {...addDataAttributes(data, testId)}
33
+ >
34
+ {isReactNodeNotEmpty(children) && (
35
+ <div
36
+ className={clsx(classes.children, {
37
+ [classes.horizontal]: controlsDirection === 'horizontal',
38
+ [classes.vertical]: controlsDirection === 'vertical',
39
+ })}
40
+ >
41
+ {children}
42
+ </div>
43
+ )}
44
+ {(shouldShowError || shouldShowInfo) && (
45
+ <div className={classes.message}>
46
+ {shouldShowError && (
47
+ <div className={classes.error} {...addDataTestId(testId, 'error')}>
48
+ {errorMessage}
49
+ </div>
50
+ )}
51
+ {shouldShowInfo && (
52
+ <div className={classes.info} {...addDataTestId(testId, 'info')}>
53
+ {infoMessage}
54
+ </div>
55
+ )}
56
+ </div>
57
+ )}
58
+ </div>
59
+ );
60
+ });
@@ -22,6 +22,8 @@ export interface IWithTooltipProps
22
22
  tooltipView?: ITooltipProps['view'];
23
23
  /** @default 'info' */
24
24
  tooltipType?: ITooltipProps['type'];
25
+ /** @default 'undefined' */
26
+ tooltipSize?: ITooltipProps['size'];
25
27
  }
26
28
 
27
29
  export const WithTooltip: FC<IWithTooltipProps> = ({
@@ -31,6 +33,7 @@ export const WithTooltip: FC<IWithTooltipProps> = ({
31
33
  tooltipText,
32
34
  tooltipView = 'tooltip',
33
35
  tooltipType = 'info',
36
+ tooltipSize,
34
37
  isDisabled = false,
35
38
  popupData,
36
39
  tweakStyles,
@@ -64,6 +67,7 @@ export const WithTooltip: FC<IWithTooltipProps> = ({
64
67
  view={tooltipView}
65
68
  type={tooltipType}
66
69
  text={tooltipText}
70
+ size={tooltipSize}
67
71
  tweakStyles={tweakTooltipStyles}
68
72
  testId={getTestId(restProps.testId, 'tooltip')}
69
73
  />
@@ -1,3 +1,4 @@
1
+ import { ComponentType, memo } from 'react';
1
2
  import {
2
3
  isNotEmpty,
3
4
  isString,
@@ -160,3 +161,8 @@ export const addDataAttributes = (data: IDataAttributes = {}): IDataAttributes =
160
161
 
161
162
  export const excludeStorybookParams = (params: string[]): RegExp =>
162
163
  new RegExp(`^(on.*|${['tweakStyles', 'data', ...params].join('|')})$`);
164
+
165
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
166
+ export const genericMemo = memo as <T extends ComponentType<any>>(
167
+ ...args: Parameters<typeof memo<T>>
168
+ ) => T;
@@ -1,6 +1,7 @@
1
1
  export * from './use-did-mount-effect';
2
2
  export * from './use-dropdown';
3
3
  export * from './use-intersection-ref';
4
+ export * from './use-resize-ref';
4
5
  export * from './use-is-mounted';
5
6
  export * from './use-latest-ref';
6
7
  export * from './use-merge';
@@ -1,4 +1,4 @@
1
- import { RefCallback, useMemo } from 'react';
1
+ import { RefCallback, useEffect, useMemo } from 'react';
2
2
  import { isNotEmpty } from '@true-engineering/true-react-platform-helpers';
3
3
  import { useLatestRef } from './use-latest-ref';
4
4
 
@@ -7,12 +7,16 @@ export interface IInsertionRefOptions {
7
7
  isDisabled?: boolean;
8
8
  onIntersection?: VoidFunction;
9
9
  onIntersectionEnd?: VoidFunction;
10
+ observerOptions?: IntersectionObserverInit;
10
11
  }
11
12
 
12
- export const useIntersectionRef = (options?: IInsertionRefOptions): RefCallback<Element> => {
13
+ export const useIntersectionRef = ({
14
+ observerOptions,
15
+ ...options
16
+ }: IInsertionRefOptions): RefCallback<Element> => {
13
17
  const optionsRef = useLatestRef(options);
14
18
 
15
- return useMemo(() => {
19
+ const { ref, disconnect } = useMemo(() => {
16
20
  const observer = new IntersectionObserver(([{ isIntersecting }]) => {
17
21
  const { current } = optionsRef;
18
22
  if (current?.isDisabled) {
@@ -23,8 +27,22 @@ export const useIntersectionRef = (options?: IInsertionRefOptions): RefCallback<
23
27
  } else {
24
28
  current?.onIntersectionEnd?.();
25
29
  }
26
- });
30
+ }, observerOptions);
27
31
 
28
- return (node) => (isNotEmpty(node) ? observer.observe(node) : observer.disconnect());
29
- }, [optionsRef]);
32
+ const observerRef: RefCallback<Element> = (node) => {
33
+ observer.disconnect();
34
+ if (isNotEmpty(node)) {
35
+ observer.observe(node);
36
+ }
37
+ };
38
+
39
+ return {
40
+ ref: observerRef,
41
+ disconnect: () => observer.disconnect(),
42
+ };
43
+ }, [optionsRef, observerOptions]);
44
+
45
+ useEffect(() => disconnect, [disconnect]);
46
+
47
+ return ref;
30
48
  };
@@ -1,7 +1,11 @@
1
- import { MutableRefObject, useRef } from 'react';
1
+ import { MutableRefObject, useLayoutEffect, useRef } from 'react';
2
2
 
3
3
  export const useLatestRef = <T>(value: T): MutableRefObject<T> => {
4
4
  const ref = useRef(value);
5
- ref.current = value;
5
+
6
+ useLayoutEffect(() => {
7
+ ref.current = value;
8
+ });
9
+
6
10
  return ref;
7
11
  };
@@ -0,0 +1,35 @@
1
+ import { RefCallback, useMemo, useEffect } from 'react';
2
+ import { isNotEmpty } from '@true-engineering/true-react-platform-helpers';
3
+ import { useLatestRef } from './use-latest-ref';
4
+
5
+ export interface IResizeRefOptions {
6
+ /** @default false */
7
+ isDisabled?: boolean;
8
+ onChange: (entry: ResizeObserverEntry) => void;
9
+ }
10
+
11
+ export const useResizeRef = (options: IResizeRefOptions): RefCallback<Element> => {
12
+ const optionsRef = useLatestRef(options);
13
+
14
+ const { ref, disconnect } = useMemo(() => {
15
+ const observer = new ResizeObserver(([entry]) => {
16
+ const { current } = optionsRef;
17
+ if (!current.isDisabled) {
18
+ current?.onChange(entry);
19
+ }
20
+ });
21
+
22
+ const observerRef: RefCallback<Element> = (node) => {
23
+ observer.disconnect();
24
+ if (isNotEmpty(node)) {
25
+ observer.observe(node);
26
+ }
27
+ };
28
+
29
+ return { ref: observerRef, disconnect: () => observer.disconnect() };
30
+ }, [optionsRef]);
31
+
32
+ useEffect(() => disconnect, [disconnect]);
33
+
34
+ return ref;
35
+ };
@@ -1,18 +1,6 @@
1
- import { useContext, useMemo } from 'react';
2
- import {
3
- isArrayNotEmpty,
4
- isNotEmpty,
5
- mergeStyles,
6
- } from '@true-engineering/true-react-platform-helpers';
7
- import {
8
- areStylesThemed,
9
- themedStyles,
10
- IComponentName,
11
- IMaybeArray,
12
- useTheme,
13
- JssContext,
14
- IMixedStyles,
15
- } from '../theme';
1
+ import { useMemo } from 'react';
2
+ import { IMaybeArray } from '@true-engineering/true-react-platform-helpers';
3
+ import { IComponentName, IMixedStyles, useThemeComponentStyles } from '../theme';
16
4
  import { mixStyles } from './use-mixed-styles';
17
5
 
18
6
  // TODO: Можно усилить типы
@@ -37,43 +25,18 @@ export const useTweakStyles = <StyleSheet, ClassName extends keyof StyleSheet &
37
25
  */
38
26
  className: ClassName;
39
27
  /**
40
- * Название компонента который вызывает useTweakStyles. (В данном примере 'Select')
28
+ * Название компонента который вызывает useTweakStyles
41
29
  */
42
30
  currentComponentName?: IComponentName;
43
31
  }): Array<NonNullable<StyleSheet[ClassName]>> => {
44
- const theme = useTheme();
45
- const isMergeDisabled = isNotEmpty(useContext(JssContext).tweakStylesArch);
46
-
47
- return useMemo(() => {
48
- const themeStyles = isNotEmpty(currentComponentName)
49
- ? (theme.components?.[currentComponentName] as StyleSheet)
50
- : undefined;
51
-
52
- const resultStyles = mixStyles(
53
- innerStyles,
54
- mixStyles(themeStyles, tweakStyles).map((style) => style[className]),
55
- );
56
-
57
- if (isMergeDisabled || resultStyles.length < 2) {
58
- return resultStyles;
59
- }
60
-
61
- const [maybeInnerStyles, maybeThemeStyles, ...rest] = resultStyles;
62
-
63
- if (
64
- maybeThemeStyles !== themeStyles?.[className] || // Если нет themeStyles или innerStyles
65
- isArrayNotEmpty(rest) // Или есть tweakStyles
66
- ) {
67
- // Мёржим как есть
68
- return [mergeStyles(maybeInnerStyles, maybeThemeStyles, ...rest)];
69
- }
70
-
71
- // Иначе мёржим themeStyles в innerStyles
72
- if (!areStylesThemed(maybeInnerStyles)) {
73
- themedStyles(maybeInnerStyles, maybeThemeStyles);
74
- }
75
-
76
- // И возвращаем только innerStyles
77
- return [maybeInnerStyles];
78
- }, [innerStyles, className, currentComponentName, tweakStyles, theme, isMergeDisabled]);
32
+ const themeStyles = useThemeComponentStyles<StyleSheet>(currentComponentName);
33
+
34
+ return useMemo(
35
+ () =>
36
+ mixStyles(
37
+ innerStyles,
38
+ mixStyles(themeStyles, tweakStyles).map((style) => style[className]),
39
+ ),
40
+ [innerStyles, className, themeStyles, tweakStyles],
41
+ );
79
42
  };
@@ -1,26 +1,9 @@
1
- import { createContext, FC, ReactNode, useContext, useMemo } from 'react';
1
+ import { createContext, useContext } from 'react';
2
2
  import { common } from './common';
3
3
  import type { IUiKitTheme } from './types';
4
4
 
5
- export interface IThemedProviderProps {
6
- theme: IUiKitTheme;
7
- children: ReactNode;
8
- }
5
+ export const ThemeContext = createContext<IUiKitTheme>(common);
9
6
 
10
- let globalTheme: IUiKitTheme;
7
+ export const ThemeProvider = ThemeContext.Provider;
11
8
 
12
- export const getTheme = (): IUiKitTheme => globalTheme;
13
-
14
- interface ThemeContextValue {
15
- theme: IUiKitTheme;
16
- }
17
-
18
- export const ThemeContext = createContext<ThemeContextValue>({ theme: common });
19
-
20
- export const ThemeProvider: FC<IThemedProviderProps> = ({ theme, children }) => {
21
- globalTheme = theme;
22
- const value: ThemeContextValue = useMemo(() => ({ theme }), [theme]);
23
- return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
24
- };
25
-
26
- export const useTheme = (): IUiKitTheme => useContext(ThemeContext).theme;
9
+ export const useTheme = (): IUiKitTheme => useContext(ThemeContext);
@@ -1,4 +1,3 @@
1
- import { Styles } from 'react-jss';
2
1
  import { IUiKitHelpers, IUiKitTheme } from './types';
3
2
 
4
3
  export const colors = {
@@ -49,41 +48,40 @@ export const dimensions = {
49
48
  } as const;
50
49
 
51
50
  export const helpers = {
52
- withAngle: (angleSize = 6, position: 'left' | 'right' = 'left', distance = 100): Styles =>
53
- ({
54
- display: 'inline-block',
55
- position: 'relative',
56
- marginTop: angleSize * 2 - 1,
57
- boxShadow: '0 8px 20px 0 rgba(0, 0, 0, 0.04)',
58
- border: ['solid', 1, colors.BORDER_MAIN],
59
- borderRadius: dimensions.BORDER_RADIUS_EXTRA_SMALL,
60
-
61
- '&:before': {
62
- content: '""',
63
- position: 'absolute',
64
- top: -angleSize,
65
- left: position === 'left' && distance,
66
- right: position === 'right' && distance,
67
- width: 0,
68
- height: 0,
69
- borderLeft: [angleSize, 'solid', 'transparent'],
70
- borderRight: [angleSize, 'solid', 'transparent'],
71
- borderBottom: [angleSize, 'solid', colors.BORDER_MAIN],
72
- },
51
+ withAngle: (angleSize = 6, position: 'left' | 'right' = 'left', distance = 100) => ({
52
+ display: 'inline-block',
53
+ position: 'relative',
54
+ marginTop: angleSize * 2 - 1,
55
+ boxShadow: '0 8px 20px 0 rgba(0, 0, 0, 0.04)',
56
+ border: ['solid', 1, colors.BORDER_MAIN],
57
+ borderRadius: dimensions.BORDER_RADIUS_EXTRA_SMALL,
58
+
59
+ '&:before': {
60
+ content: '""',
61
+ position: 'absolute',
62
+ top: -angleSize,
63
+ left: position === 'left' && distance,
64
+ right: position === 'right' && distance,
65
+ width: 0,
66
+ height: 0,
67
+ borderLeft: [angleSize, 'solid', 'transparent'],
68
+ borderRight: [angleSize, 'solid', 'transparent'],
69
+ borderBottom: [angleSize, 'solid', colors.BORDER_MAIN],
70
+ },
73
71
 
74
- '&:after': {
75
- content: '""',
76
- position: 'absolute',
77
- top: -angleSize + 1,
78
- left: position === 'left' && distance + 1,
79
- right: position === 'right' && distance + 1,
80
- width: 0,
81
- height: 0,
82
- borderLeft: [angleSize - 1, 'solid', 'transparent'],
83
- borderRight: [angleSize - 1, 'solid', 'transparent'],
84
- borderBottom: [angleSize - 1, 'solid', colors.CLASSIC_WHITE],
85
- },
86
- } as unknown as Styles),
72
+ '&:after': {
73
+ content: '""',
74
+ position: 'absolute',
75
+ top: -angleSize + 1,
76
+ left: position === 'left' && distance + 1,
77
+ right: position === 'right' && distance + 1,
78
+ width: 0,
79
+ height: 0,
80
+ borderLeft: [angleSize - 1, 'solid', 'transparent'],
81
+ borderRight: [angleSize - 1, 'solid', 'transparent'],
82
+ borderBottom: [angleSize - 1, 'solid', colors.CLASSIC_WHITE],
83
+ },
84
+ }),
87
85
 
88
86
  withScrollBar: {
89
87
  boxSizing: 'border-box',
@@ -135,7 +133,6 @@ const SLIDE_UP_POSITION_END = 0;
135
133
 
136
134
  export const animations = {
137
135
  defaultTransition: '0.25s ease-in-out',
138
- // Если понадобится, сюда можно пробросить параметры через useTheme props
139
136
  slideUp: {
140
137
  'slide-up-enter': {
141
138
  opacity: 0,
@@ -1,30 +1,28 @@
1
- import { merge } from 'lodash-es';
1
+ import { useMemo } from 'react';
2
+ import { createUseStyles } from 'react-jss';
2
3
  import {
3
4
  isArrayNotEmpty,
4
5
  isNotEmpty,
6
+ isString,
5
7
  mergeStyles,
6
8
  } from '@true-engineering/true-react-platform-helpers';
7
- import { IMaybeArray } from './types';
9
+ import { mixStyles } from '../hooks/use-mixed-styles';
10
+ import { useTheme } from './Provider';
11
+ import { IComponentName, IStyles, IUseStyles } from './types';
8
12
 
9
- const EMPTY_STYLES = {};
13
+ export const useThemeComponentStyles = <T>(
14
+ componentName?: IComponentName,
15
+ ): Partial<T> | undefined => {
16
+ const { components } = useTheme();
17
+ return isNotEmpty(componentName) ? (components?.[componentName] as never) : undefined;
18
+ };
10
19
 
11
- export const isTweakStyle = (key: string): boolean => key.startsWith('tweak');
20
+ const isTweakStyle = (key: string): boolean => key.startsWith('tweak');
12
21
 
13
- export const isStylesNotEmpty = <T>(tweakStyles?: T): tweakStyles is NonNullable<T> =>
22
+ const areStylesNotEmpty = <T>(tweakStyles?: T): tweakStyles is NonNullable<T> =>
14
23
  isNotEmpty(tweakStyles) && !Object.keys(tweakStyles).every(isTweakStyle);
15
24
 
16
- export const cleanStyles = <T>(tweakStyles?: T): T =>
17
- isStylesNotEmpty(tweakStyles) ? tweakStyles : (EMPTY_STYLES as T);
18
-
19
- export const mergeTweakStyles = <T>(tweakStyles?: IMaybeArray<T>): T | undefined => {
20
- if (!Array.isArray(tweakStyles)) {
21
- return tweakStyles;
22
- }
23
- const [first, ...rest] = tweakStyles;
24
- return isArrayNotEmpty(rest) ? mergeStyles(first, ...rest) : first;
25
- };
26
-
27
- export const checkStyles = (componentName: string, styles: Record<string, unknown>): void => {
25
+ const checkStyles = (styles: IStyles<string>, componentName = 'LocalComponent'): void => {
28
26
  const invalidClasses = Object.keys(styles).filter(isTweakStyle);
29
27
 
30
28
  if (isArrayNotEmpty(invalidClasses)) {
@@ -34,23 +32,8 @@ export const checkStyles = (componentName: string, styles: Record<string, unknow
34
32
  }
35
33
  };
36
34
 
37
- export const areStylesThemed = (styles: Record<string, unknown>): boolean =>
38
- // eslint-disable-next-line no-underscore-dangle
39
- styles.__themed === true;
40
-
41
- /**
42
- * Подмешивает стили из темы. Мутирует, добавляя специально поле,
43
- * по которому можно определить была ли уже произведена мутация ранее,
44
- * тем самым сохраняя ссылку на объект и позволяя этим кэшировать JSS стили
45
- */
46
- export const themedStyles = <T>(styles: T, themeComponentStyles: T): T => {
47
- merge(styles, themeComponentStyles); // mutation !!!!
48
- Object.defineProperty(styles, '__themed', { value: true });
49
- return styles;
50
- };
51
-
52
- type TweakStylesCache = (styles: object[], prev?: object[]) => object | undefined;
53
- export const getTweakStylesCache = (): TweakStylesCache => {
35
+ type TweakStylesCache = (styles: object[], idx?: number) => object | undefined;
36
+ const getTweakStylesCache = (): TweakStylesCache => {
54
37
  let mergedStyles: object | undefined;
55
38
  const cache = new WeakMap<object, TweakStylesCache>();
56
39
 
@@ -59,20 +42,45 @@ export const getTweakStylesCache = (): TweakStylesCache => {
59
42
  cache.set(next, getTweakStylesCache());
60
43
  }
61
44
 
62
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
63
- return cache.get(next)!;
45
+ return cache.get(next)!; // eslint-disable-line @typescript-eslint/no-non-null-assertion
64
46
  };
65
47
 
66
- return (styles, prev = []) => {
67
- const [next, ...rest] = styles;
48
+ return (styles, idx = 0) => {
49
+ const next = styles.at(idx);
68
50
  if (isNotEmpty(next)) {
69
- return getNext(next)(rest, prev.concat(next));
51
+ return getNext(next)(styles, idx + 1);
70
52
  }
71
53
 
72
- if (isNotEmpty(mergedStyles)) {
73
- return mergedStyles;
54
+ if (!isNotEmpty(mergedStyles)) {
55
+ const [first, ...rest] = styles;
56
+ mergedStyles = isArrayNotEmpty(rest) ? mergeStyles(first, ...rest) : first;
74
57
  }
75
58
 
76
- return (mergedStyles = mergeTweakStyles(prev));
59
+ return mergedStyles;
60
+ };
61
+ };
62
+
63
+ const tweakStylesCache = getTweakStylesCache();
64
+ const useStyles = createUseStyles<string>((tweakStyles) => tweakStyles as never);
65
+
66
+ export const createThemedStyles: <C extends string>(
67
+ ...args: [IStyles<C>] | [IComponentName, IStyles<C>]
68
+ ) => IUseStyles<C> = (first, second?) => {
69
+ const componentName = isString(first) ? first : undefined;
70
+ const styles = second! ?? first; // eslint-disable-line @typescript-eslint/no-non-null-assertion
71
+
72
+ if (process.env.NODE_ENV !== 'production') {
73
+ checkStyles(styles, componentName);
74
+ }
75
+
76
+ return ({ theme, tweakStyles = theme }) => {
77
+ const themeStyles = useThemeComponentStyles<typeof styles>(componentName);
78
+
79
+ const data = useMemo(() => {
80
+ const resultStyles = mixStyles(styles, themeStyles, tweakStyles).filter(areStylesNotEmpty);
81
+ return { theme: tweakStylesCache(resultStyles) };
82
+ }, [themeStyles, tweakStyles]);
83
+
84
+ return useStyles(data);
77
85
  };
78
86
  };
@@ -1,6 +1,4 @@
1
1
  export * from './Provider';
2
- export * from './true-jss';
3
2
  export * from './common';
4
3
  export * from './types';
5
4
  export * from './helpers';
6
- export * from './create-themed-styles';
@@ -1,5 +1,5 @@
1
- import { Styles } from 'react-jss';
2
- import { Classes, JssValue } from 'jss';
1
+ import type { Classes, JssStyle, JssValue, Styles } from 'jss';
2
+ import type { IMaybeArray } from '@true-engineering/true-react-platform-helpers';
3
3
  import type {
4
4
  IAccountInfoStyles,
5
5
  IAddButtonStyles,
@@ -67,19 +67,22 @@ import type {
67
67
  IWithTooltipStyles,
68
68
  } from '../components';
69
69
 
70
- export type IStyles<C extends string, P = unknown> = Styles<C, P, Partial<Styles<C, P>>>;
70
+ export type IStyles<C extends string> = Styles<C>;
71
+
72
+ export type IStyle = JssStyle;
71
73
 
72
- export type IMaybeArray<T> = T[] | T;
73
74
  export type IMixedStyles<T> = IMaybeArray<T | boolean | undefined>;
74
- export type IUseStyles<C extends string, P = unknown> = (
75
- data?: P & { theme?: IMaybeArray<Partial<Styles<C, P>>> },
76
- ) => Classes<C>;
75
+
76
+ export type IUseStyles<C extends string> = (data: {
77
+ theme?: IMaybeArray<Partial<IStyles<C>>>;
78
+ tweakStyles?: IMaybeArray<Partial<IStyles<C>>>;
79
+ }) => Classes<C>;
77
80
 
78
81
  export type ITweakStyles<
79
82
  StyleCreator,
80
83
  ChildTweakStyles = unknown,
81
- > = StyleCreator extends IUseStyles<infer C, infer P>
82
- ? Partial<Styles<C, P>> & Partial<ChildTweakStyles>
84
+ > = StyleCreator extends IUseStyles<infer C>
85
+ ? Partial<IStyles<C>> & Partial<ChildTweakStyles>
83
86
  : never;
84
87
 
85
88
  export interface IComponentStyles {
@@ -149,7 +152,7 @@ export interface IComponentStyles {
149
152
  export type IComponentName = keyof IComponentStyles;
150
153
 
151
154
  export type IUiKitAnimations = Record<string, any>;
152
- export type IUiKitHelpers = Record<string, Styles | (() => Styles)>;
155
+ export type IUiKitHelpers = Record<string, IStyle | (() => IStyle)>;
153
156
 
154
157
  export interface IUiKitTheme {
155
158
  components?: Partial<IComponentStyles>;
package/src/types.ts CHANGED
@@ -8,8 +8,8 @@ import type {
8
8
  ReactNode,
9
9
  } from 'react';
10
10
  import type { Modifier, Placement } from 'react-overlays/usePopper';
11
- import type { JssStyle } from 'jss';
12
- import type { IMaybeArray } from './theme';
11
+ import type { IMaybeArray } from '@true-engineering/true-react-platform-helpers';
12
+ import { IStyle } from './theme';
13
13
 
14
14
  export interface ITestIdProps {
15
15
  testId?: string;
@@ -66,7 +66,7 @@ export type IRenderNode<T> = ReactNode | ((props: T) => ReactNode);
66
66
 
67
67
  export type IExtendableProps<T extends string | readonly string[]> = Record<
68
68
  T extends ReadonlyArray<infer P> ? P : T,
69
- JssStyle
69
+ IStyle
70
70
  >;
71
71
 
72
72
  export type IDefaultExtendableProps = IExtendableProps<'custom'>;
@@ -1,2 +0,0 @@
1
- import { IComponentName, IStyles, IUseStyles } from './types';
2
- export declare function createThemedStyles<C extends string>(...args: [IStyles<C>] | [IComponentName, IStyles<C>]): IUseStyles<C>;
@@ -1,18 +0,0 @@
1
- import { Classes } from 'jss';
2
- import { IStyles } from '../types';
3
- import { IPartialStyle } from './TweakStylesManager';
4
- import { IJssContext } from './jss-context';
5
- interface IThemedStylesManagerOptions<C extends string> {
6
- styles: IStyles<C>;
7
- name: string;
8
- }
9
- export declare class ThemedStylesManager<C extends string> {
10
- #private;
11
- constructor({ styles, name }: IThemedStylesManagerOptions<C>);
12
- getClasses(theme: object | undefined, tweak: IPartialStyle[], jssContext: IJssContext): Classes<C>;
13
- manageTweak(theme: object | undefined, tweak: IPartialStyle[]): VoidFunction | undefined;
14
- manage(theme?: object): VoidFunction | undefined;
15
- private unmanage;
16
- private getOrCreate;
17
- }
18
- export {};