@true-engineering/true-react-common-ui-kit 3.0.5 → 3.1.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 (154) hide show
  1. package/README.md +39 -0
  2. package/dist/components/AccountInfo/AccountInfo.stories.d.ts +8 -0
  3. package/dist/components/AccountInfo/AccountInfo.styles.d.ts +1 -1
  4. package/dist/components/AddButton/AddButton.stories.d.ts +8 -0
  5. package/dist/components/AddButton/AddButton.styles.d.ts +1 -1
  6. package/dist/components/Button/Button.stories.d.ts +6 -0
  7. package/dist/components/Button/Button.styles.d.ts +1 -1
  8. package/dist/components/Button/types.d.ts +2 -2
  9. package/dist/components/Checkbox/Checkbox.stories.d.ts +5 -0
  10. package/dist/components/Checkbox/Checkbox.styles.d.ts +1 -1
  11. package/dist/components/CloseButton/CloseButton.styles.d.ts +1 -1
  12. package/dist/components/Colors/Colors.stories.d.ts +5 -0
  13. package/dist/components/CssBaseline/CssBaseline.d.ts +1 -1
  14. package/dist/components/CssBaseline/CssBaseline.styles.d.ts +1 -1
  15. package/dist/components/DateInput/DateInput.stories.d.ts +8 -0
  16. package/dist/components/DateInput/DateInput.styles.d.ts +1 -1
  17. package/dist/components/DatePicker/DatePicker.d.ts +1 -0
  18. package/dist/components/DatePicker/DatePicker.stories.d.ts +8 -0
  19. package/dist/components/DatePicker/DatePicker.styles.d.ts +1 -1
  20. package/dist/components/DatePicker/components/DatePickerHeader/DatePickerHeader.styles.d.ts +1 -1
  21. package/dist/components/DatePicker/types.d.ts +2 -2
  22. package/dist/components/Description/Description.stories.d.ts +18 -0
  23. package/dist/components/Description/Description.styles.d.ts +1 -1
  24. package/dist/components/FiltersPane/FiltersPane.stories.d.ts +32 -0
  25. package/dist/components/FiltersPane/FiltersPane.styles.d.ts +1 -1
  26. package/dist/components/FiltersPane/components/FilterInterval/FilterInterval.styles.d.ts +1 -1
  27. package/dist/components/FiltersPane/components/FilterMultiSelect/FilterMultiSelect.d.ts +1 -1
  28. package/dist/components/FiltersPane/components/FilterSelect/FilterSelect.styles.d.ts +1 -1
  29. package/dist/components/FiltersPane/components/FilterValueView/FilterValueView.styles.d.ts +1 -1
  30. package/dist/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.d.ts +1 -1
  31. package/dist/components/FiltersPane/components/FilterWithPeriod/FilterWithPeriod.styles.d.ts +1 -1
  32. package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.styles.d.ts +2 -2
  33. package/dist/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.styles.d.ts +1 -1
  34. package/dist/components/FiltersPane/types.d.ts +18 -18
  35. package/dist/components/Flag/Flag.stories.d.ts +14 -0
  36. package/dist/components/Flag/Flag.styles.d.ts +1 -1
  37. package/dist/components/FlexibleTable/FlexibleTable.stories.d.ts +20 -0
  38. package/dist/components/FlexibleTable/FlexibleTable.styles.d.ts +1 -1
  39. package/dist/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.styles.d.ts +1 -1
  40. package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.styles.d.ts +1 -1
  41. package/dist/components/FlexibleTable/types.d.ts +6 -6
  42. package/dist/components/Icon/Icon.stories.d.ts +6 -0
  43. package/dist/components/Icon/Icon.styles.d.ts +1 -1
  44. package/dist/components/Icon/icons-list.d.ts +1 -1
  45. package/dist/components/Icon/types.d.ts +4 -4
  46. package/dist/components/IncrementInput/IncrementInput.stories.d.ts +8 -0
  47. package/dist/components/IncrementInput/IncrementInput.styles.d.ts +1 -1
  48. package/dist/components/Input/Input.stories.d.ts +35 -0
  49. package/dist/components/Input/Input.styles.d.ts +2 -2
  50. package/dist/components/Input/types.d.ts +1 -1
  51. package/dist/components/List/List.stories.d.ts +6 -0
  52. package/dist/components/List/List.styles.d.ts +1 -1
  53. package/dist/components/List/components/ListItem/ListItem.styles.d.ts +1 -1
  54. package/dist/components/Modal/Modal.stories.d.ts +30 -0
  55. package/dist/components/Modal/Modal.styles.d.ts +1 -1
  56. package/dist/components/Modal/types.d.ts +2 -2
  57. package/dist/components/MoreMenu/MoreMenu.stories.d.ts +8 -0
  58. package/dist/components/MoreMenu/MoreMenu.styles.d.ts +1 -1
  59. package/dist/components/MultiSelect/MultiSelect.stories.d.ts +14 -0
  60. package/dist/components/MultiSelect/MultiSelect.styles.d.ts +2 -2
  61. package/dist/components/MultiSelect/components/MultiSelectInput/MultiSelectInput.styles.d.ts +1 -1
  62. package/dist/components/MultiSelect/types.d.ts +1 -1
  63. package/dist/components/MultiSelectList/MultiSelectList.styles.d.ts +1 -1
  64. package/dist/components/MultiSelectList/types.d.ts +1 -1
  65. package/dist/components/Notification/Notification.d.ts +0 -1
  66. package/dist/components/Notification/Notification.stories.d.ts +8 -0
  67. package/dist/components/Notification/Notification.styles.d.ts +1 -1
  68. package/dist/components/Notification/types.d.ts +1 -1
  69. package/dist/components/NumberInput/NumberInput.stories.d.ts +8 -0
  70. package/dist/components/PhoneInput/PhoneInput.stories.d.ts +30 -0
  71. package/dist/components/PhoneInput/PhoneInput.styles.d.ts +1 -1
  72. package/dist/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.stories.d.ts +6 -0
  73. package/dist/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.styles.d.ts +1 -1
  74. package/dist/components/RadioButton/RadioButton.stories.d.ts +8 -0
  75. package/dist/components/RadioButton/RadioButton.styles.d.ts +1 -1
  76. package/dist/components/ScrollIntoViewIfNeeded/ScrollIntoViewIfNeeded.d.ts +2 -2
  77. package/dist/components/SearchInput/SearchInput.d.ts +1 -1
  78. package/dist/components/SearchInput/SearchInput.stories.d.ts +8 -0
  79. package/dist/components/SearchInput/SearchInput.styles.d.ts +1 -1
  80. package/dist/components/Select/MultiSelect.stories.d.ts +17 -0
  81. package/dist/components/Select/Select.stories.d.ts +17 -0
  82. package/dist/components/Select/Select.styles.d.ts +4 -4
  83. package/dist/components/Select/components/SelectList/SelectList.styles.d.ts +1 -1
  84. package/dist/components/Select/types.d.ts +1 -1
  85. package/dist/components/Selector/Selector.d.ts +21 -0
  86. package/dist/components/Selector/Selector.stories.d.ts +8 -0
  87. package/dist/components/Selector/Selector.styles.d.ts +9 -0
  88. package/dist/components/Selector/index.d.ts +2 -0
  89. package/dist/components/Selector/types.d.ts +10 -0
  90. package/dist/components/Skeleton/Skeleton.stories.d.ts +8 -0
  91. package/dist/components/Skeleton/Skeleton.styles.d.ts +1 -1
  92. package/dist/components/SmartInput/SmartInput.stories.d.ts +19 -0
  93. package/dist/components/SmartInput/types.d.ts +1 -1
  94. package/dist/components/Status/Status.d.ts +16 -0
  95. package/dist/components/Status/Status.stories.d.ts +8 -0
  96. package/dist/components/Status/Status.styles.d.ts +3 -0
  97. package/dist/components/Status/constants.d.ts +2 -0
  98. package/dist/components/Status/index.d.ts +2 -0
  99. package/dist/components/Status/types.d.ts +3 -0
  100. package/dist/components/Switch/Switch.stories.d.ts +17 -0
  101. package/dist/components/Switch/Switch.styles.d.ts +1 -1
  102. package/dist/components/TextArea/TextArea.stories.d.ts +18 -0
  103. package/dist/components/TextArea/TextArea.styles.d.ts +1 -1
  104. package/dist/components/TextButton/TextButton.d.ts +30 -0
  105. package/dist/components/TextButton/TextButton.stories.d.ts +6 -0
  106. package/dist/components/TextButton/TextButton.styles.d.ts +7 -0
  107. package/dist/components/TextButton/index.d.ts +3 -0
  108. package/dist/components/TextWithInfo/TextWithInfo.stories.d.ts +13 -0
  109. package/dist/components/TextWithInfo/TextWithInfo.styles.d.ts +1 -1
  110. package/dist/components/TextWithTooltip/TextWithTooltip.stories.d.ts +26 -0
  111. package/dist/components/TextWithTooltip/TextWithTooltip.styles.d.ts +1 -1
  112. package/dist/components/ThemedPreloader/ThemedPreloader.stories.d.ts +18 -0
  113. package/dist/components/ThemedPreloader/ThemedPreloader.styles.d.ts +1 -1
  114. package/dist/components/ThemedPreloader/components/DotsPreloader/DotsPreloader.d.ts +1 -1
  115. package/dist/components/ThemedPreloader/components/DotsPreloader/DotsPreloader.styles.d.ts +1 -1
  116. package/dist/components/ThemedPreloader/components/SvgPreloader/SvgPreloader.styles.d.ts +1 -1
  117. package/dist/components/ThemedPreloader/types.d.ts +1 -1
  118. package/dist/components/Toaster/Toaster.stories.d.ts +6 -0
  119. package/dist/components/Toaster/Toaster.styles.d.ts +1 -1
  120. package/dist/components/Toaster/types.d.ts +1 -1
  121. package/dist/components/Tooltip/Tooltip.stories.d.ts +6 -0
  122. package/dist/components/Tooltip/Tooltip.styles.d.ts +1 -1
  123. package/dist/components/Tooltip/types.d.ts +1 -1
  124. package/dist/components/index.d.ts +7 -4
  125. package/dist/hooks/use-tweak-styles.d.ts +1 -1
  126. package/dist/theme/common.d.ts +37 -2
  127. package/dist/theme/types.d.ts +12 -9
  128. package/dist/true-react-common-ui-kit.js +2286 -1487
  129. package/dist/true-react-common-ui-kit.js.map +1 -1
  130. package/dist/true-react-common-ui-kit.umd.cjs +2285 -1486
  131. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  132. package/package.json +3 -3
  133. package/src/components/Notification/Notification.tsx +0 -2
  134. package/src/components/Selector/Selector.stories.tsx +62 -0
  135. package/src/components/Selector/Selector.styles.ts +164 -0
  136. package/src/components/Selector/Selector.tsx +115 -0
  137. package/src/components/Selector/index.ts +2 -0
  138. package/src/components/Selector/types.ts +12 -0
  139. package/src/components/Status/Status.stories.tsx +73 -0
  140. package/src/components/Status/Status.styles.ts +143 -0
  141. package/src/components/Status/Status.tsx +49 -0
  142. package/src/components/Status/constants.ts +11 -0
  143. package/src/components/Status/index.ts +3 -0
  144. package/src/components/Status/types.ts +5 -0
  145. package/src/components/TextButton/TextButton.stories.tsx +46 -0
  146. package/src/components/TextButton/TextButton.styles.ts +129 -0
  147. package/src/components/TextButton/TextButton.tsx +103 -0
  148. package/src/components/TextButton/index.ts +4 -0
  149. package/src/components/index.ts +7 -4
  150. package/src/theme/common.ts +4 -3
  151. package/src/theme/types.ts +13 -7
  152. package/dist/components/Flag/augment.d.ts +0 -1
  153. package/dist/components/Icon/complexIcons/augment.d.ts +0 -1
  154. package/dist/vite-env.d.ts +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@true-engineering/true-react-common-ui-kit",
3
- "version": "3.0.5",
3
+ "version": "3.1.0",
4
4
  "description": "True Engineering React UI Kit with theming support",
5
5
  "author": "True Engineering (https://trueengineering.ru)",
6
6
  "keywords": [
@@ -82,13 +82,13 @@
82
82
  "@vitejs/plugin-react": "3.0.0",
83
83
  "eslint": "8.36.0",
84
84
  "eslint-config-prettier": "8.7.0",
85
- "eslint-plugin-react": "7.32.2",
86
85
  "eslint-plugin-import": "2.29.0",
86
+ "eslint-plugin-react": "7.32.2",
87
87
  "prettier": "2.8.3",
88
88
  "rollup-plugin-swc3": "0.3.0",
89
89
  "typescript": "4.9.3",
90
90
  "unplugin-swc": "1.3.2",
91
91
  "vite": "4.0.0",
92
- "vite-plugin-dts": "1.7.1"
92
+ "vite-plugin-dts": "3.7.3"
93
93
  }
94
94
  }
@@ -71,5 +71,3 @@ export const Notification: FC<INotificationProps> = ({
71
71
  </div>
72
72
  );
73
73
  };
74
-
75
- export default Notification;
@@ -0,0 +1,62 @@
1
+ import { useState } from 'react';
2
+ import { ComponentStory } from '@storybook/react';
3
+ import { Status } from '../Status';
4
+ import { Selector } from './Selector';
5
+ import { ISelectorOption } from './types';
6
+
7
+ const options: Array<ISelectorOption<string>> = [
8
+ {
9
+ label: 'Label 1',
10
+ value: '1',
11
+ icon: 'eye',
12
+ },
13
+ {
14
+ label: 'My label 2',
15
+ value: '2',
16
+ },
17
+ {
18
+ label: (
19
+ <>
20
+ This is Label 3{' '}
21
+ <Status size="xs" color="teal">
22
+ P
23
+ </Status>
24
+ </>
25
+ ),
26
+ value: '3',
27
+ },
28
+ {
29
+ label: 'This is disabled',
30
+ value: '4',
31
+ isDisabled: true,
32
+ },
33
+ ];
34
+
35
+ export default {
36
+ title: 'Selector',
37
+ component: Selector,
38
+ };
39
+
40
+ const Template: ComponentStory<typeof Selector> = (args) => {
41
+ const [value, setValue] = useState(options[0].value);
42
+ return <Selector {...args} value={value} options={options} onChange={setValue} />;
43
+ };
44
+
45
+ export const Default = Template.bind({});
46
+
47
+ Default.args = {
48
+ size: 'l',
49
+ iconPosition: 'left',
50
+ hasSameOptionsWidth: true,
51
+ isDisabled: false,
52
+ isInvalid: false,
53
+ isRequired: false,
54
+ };
55
+
56
+ Default.argTypes = {};
57
+
58
+ Default.parameters = {
59
+ controls: {
60
+ exclude: ['options', 'value', 'testId', 'onChange'],
61
+ },
62
+ };
@@ -0,0 +1,164 @@
1
+ import { CSSProperties } from 'react';
2
+ import { isNotEmpty } from '@true-engineering/true-react-platform-helpers';
3
+ import { colors, dimensions, ITweakStyles, createThemedStyles } from '../../theme';
4
+
5
+ const SELECTOR_TOTAL_GAP = 4;
6
+ const SELECTOR_BORDER_WIDTH = 1;
7
+ export const SELECTOR_GAP = SELECTOR_TOTAL_GAP - SELECTOR_BORDER_WIDTH;
8
+
9
+ export const getSelectorLineStyle = (activeElementData?: {
10
+ clientWidth: number;
11
+ offsetLeft: number;
12
+ }): CSSProperties | undefined =>
13
+ isNotEmpty(activeElementData)
14
+ ? {
15
+ width: activeElementData.clientWidth - SELECTOR_GAP * 2,
16
+ transform: `translateX(${activeElementData.offsetLeft}px)`,
17
+ }
18
+ : undefined;
19
+
20
+ export const useStyles = createThemedStyles('Selector', {
21
+ root: {
22
+ display: 'flex',
23
+ alignItems: 'center',
24
+ listStyle: 'none',
25
+ position: 'relative',
26
+ },
27
+
28
+ disabled: {
29
+ cursor: 'default',
30
+
31
+ '& $optionText': {
32
+ color: colors.FONT_LABEL,
33
+ },
34
+ },
35
+
36
+ required: {
37
+ '&::before': {
38
+ top: '50%',
39
+ left: -12,
40
+ width: 6,
41
+ height: 6,
42
+ content: '""',
43
+ position: 'absolute',
44
+ transform: 'translate(0, -50%)',
45
+ borderRadius: '50%',
46
+ backgroundColor: colors.ORANGE_FOCUS,
47
+ },
48
+ },
49
+
50
+ invalid: {},
51
+
52
+ optionWrapper: {
53
+ height: '100%',
54
+ },
55
+
56
+ option: {
57
+ display: 'flex',
58
+ alignItems: 'center',
59
+ justifyContent: 'center',
60
+ appearance: 'none',
61
+ borderRadius: 0,
62
+ padding: 0,
63
+ border: 'none',
64
+ cursor: 'pointer',
65
+ width: '100%',
66
+ },
67
+
68
+ active: {
69
+ cursor: 'default',
70
+ },
71
+
72
+ optionIcon: {
73
+ width: 20,
74
+ height: 20,
75
+ },
76
+
77
+ optionText: {},
78
+
79
+ iconFromRight: {
80
+ '& $option': {
81
+ flexDirection: 'row-reverse',
82
+ },
83
+ },
84
+
85
+ s: {},
86
+
87
+ m: {},
88
+
89
+ l: {},
90
+
91
+ line: {},
92
+
93
+ selector: {
94
+ display: 'grid',
95
+ gridAutoFlow: 'column',
96
+ gridAutoColumns: '1fr',
97
+ borderRadius: dimensions.BORDER_RADIUS_SMALL,
98
+ backgroundColor: colors.BORDER_LIGHT,
99
+ width: 'fit-content',
100
+ position: 'relative',
101
+ border: ['solid', SELECTOR_BORDER_WIDTH, 'transparent'],
102
+
103
+ '& $line': {
104
+ content: '""',
105
+ position: 'absolute',
106
+ left: SELECTOR_GAP,
107
+ height: `calc(100% - ${SELECTOR_GAP * 2}px)`,
108
+ backgroundColor: colors.CLASSIC_WHITE,
109
+ borderRadius: dimensions.BORDER_RADIUS_SMALL,
110
+ transition: '0.25s ease-in-out',
111
+ transitionProperty: 'transform, width',
112
+ },
113
+
114
+ '&$invalid': {
115
+ borderColor: colors.RED_WARNING,
116
+ },
117
+
118
+ '& $option': {
119
+ gap: 6,
120
+ position: 'relative',
121
+ zIndex: 1,
122
+ height: '100%',
123
+ color: colors.FONT_MEDIUM,
124
+ fontSize: 16,
125
+ transition: 'color 0.25s ease-in-out',
126
+ background: 'none',
127
+
128
+ '&$s': {
129
+ padding: [4, 8],
130
+ fontSize: 10,
131
+ lineHeight: '14px',
132
+ },
133
+
134
+ '&$m': {
135
+ padding: [14, 18],
136
+ },
137
+
138
+ '&$l': {
139
+ padding: [16, 24],
140
+ },
141
+
142
+ '&:hover, &:focus': {
143
+ color: colors.FONT_MAIN,
144
+ },
145
+
146
+ '&$active': {
147
+ color: colors.FONT_MAIN,
148
+ },
149
+ },
150
+ },
151
+
152
+ autoWidth: {
153
+ '&$selector': {
154
+ gridAutoColumns: 'auto',
155
+
156
+ '& $line': {
157
+ width: 'unset',
158
+ transform: 'unset',
159
+ },
160
+ },
161
+ },
162
+ });
163
+
164
+ export type ISelectorStyles = ITweakStyles<typeof useStyles>;
@@ -0,0 +1,115 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+ import clsx from 'clsx';
3
+ import {
4
+ addDataTestId,
5
+ getTestId,
6
+ hasDuplicates,
7
+ isNotEmpty,
8
+ isReactNodeNotEmpty,
9
+ } from '@true-engineering/true-react-platform-helpers';
10
+ import { addDataAttributes } from '../../helpers';
11
+ import { ICommonProps } from '../../types';
12
+ import { renderIcon } from '../Icon';
13
+ import { ISelectorOption, ISelectorValue } from './types';
14
+ import { getSelectorLineStyle, useStyles, ISelectorStyles } from './Selector.styles';
15
+
16
+ export interface ISelectorProps<V extends ISelectorValue> extends ICommonProps<ISelectorStyles> {
17
+ options: Array<ISelectorOption<V>>;
18
+ value?: V;
19
+ /** @default false */
20
+ isDisabled?: boolean;
21
+ /** @default false */
22
+ isRequired?: boolean;
23
+ /** @default false */
24
+ isInvalid?: boolean;
25
+ /** @default true */
26
+ hasSameOptionsWidth?: boolean;
27
+ /** @default 'left' */
28
+ iconPosition?: 'left' | 'right';
29
+ /** @default 'l' */
30
+ size?: 's' | 'm' | 'l';
31
+ onChange: (value: V) => void;
32
+ }
33
+
34
+ export function Selector<V extends ISelectorValue>({
35
+ options,
36
+ value,
37
+ isDisabled = false,
38
+ isRequired = false,
39
+ isInvalid = false,
40
+ hasSameOptionsWidth = true,
41
+ iconPosition = 'left',
42
+ size = 'l',
43
+ testId,
44
+ data,
45
+ tweakStyles,
46
+ onChange,
47
+ }: ISelectorProps<V>): JSX.Element {
48
+ const classes = useStyles({ theme: tweakStyles });
49
+ const optionsValues = options.map((opt) => opt.value);
50
+
51
+ const [elementsData, setElementsData] = useState<HTMLElement[]>([]);
52
+ const listRef = useRef<HTMLDivElement>(null);
53
+
54
+ if (hasDuplicates(optionsValues)) {
55
+ // eslint-disable-next-line no-console
56
+ console.error('Selector: Значения options.value должны быть уникальными');
57
+ }
58
+
59
+ useEffect(() => {
60
+ const listEl = listRef.current;
61
+ if (listEl === null) {
62
+ return;
63
+ }
64
+
65
+ setElementsData([...listEl.querySelectorAll<HTMLElement>(`.${classes.optionWrapper}`)]);
66
+ }, [options, size]);
67
+
68
+ const activeElementData = isNotEmpty(value)
69
+ ? elementsData[optionsValues.indexOf(value)]
70
+ : undefined;
71
+
72
+ return (
73
+ <div
74
+ className={clsx(classes.root, classes.selector, {
75
+ [classes.iconFromRight]: iconPosition === 'right',
76
+ [classes.invalid]: isInvalid,
77
+ [classes.required]: isRequired,
78
+ [classes.autoWidth]: hasSameOptionsWidth,
79
+ })}
80
+ ref={listRef}
81
+ {...addDataTestId(testId)}
82
+ {...addDataAttributes(data)}
83
+ >
84
+ {isNotEmpty(activeElementData) && (
85
+ <div className={classes.line} style={getSelectorLineStyle(activeElementData)} />
86
+ )}
87
+
88
+ {options.map((option) => {
89
+ const optionId = option.value.toString();
90
+ const isDisabledOption = option.isDisabled ?? isDisabled;
91
+ const isActiveOption = option.value === value;
92
+
93
+ return (
94
+ <div key={optionId} className={classes.optionWrapper} {...addDataTestId(testId)}>
95
+ <button
96
+ type="button"
97
+ className={clsx(classes.option, classes[size], {
98
+ [classes.active]: isActiveOption,
99
+ [classes.disabled]: isDisabledOption,
100
+ })}
101
+ disabled={isDisabledOption}
102
+ onClick={!isDisabledOption ? () => onChange(option.value) : undefined}
103
+ {...addDataTestId(getTestId(testId, optionId))}
104
+ >
105
+ {isReactNodeNotEmpty(option.icon) && (
106
+ <div className={classes.optionIcon}>{renderIcon(option.icon)}</div>
107
+ )}
108
+ <div className={classes.optionText}>{option.label}</div>
109
+ </button>
110
+ </div>
111
+ );
112
+ })}
113
+ </div>
114
+ );
115
+ }
@@ -0,0 +1,2 @@
1
+ export * from './Selector';
2
+ export type { ISelectorStyles } from './Selector.styles';
@@ -0,0 +1,12 @@
1
+ import { ReactNode } from 'react';
2
+ import { IIcon } from '../Icon';
3
+
4
+ export type ISelectorValue = string | number | boolean;
5
+
6
+ export interface ISelectorOption<V> {
7
+ label: ReactNode;
8
+ icon?: IIcon;
9
+ value: V;
10
+ /** @default false */
11
+ isDisabled?: boolean;
12
+ }
@@ -0,0 +1,73 @@
1
+ import { Status } from '.';
2
+ import { ComponentStory } from '@storybook/react';
3
+ import { IIconType, iconsList } from '../Icon';
4
+ import { complexIcons } from '../Icon/complexIcons';
5
+ import { STATUS_COLORS, STATUS_SIZES } from './constants';
6
+ import { IStatusStyles } from './Status.styles';
7
+
8
+ export default {
9
+ title: 'Status',
10
+ component: Status,
11
+ };
12
+
13
+ const iconTypes = [
14
+ undefined,
15
+ ...Object.keys(iconsList),
16
+ ...Object.keys(complexIcons),
17
+ ] as IIconType[];
18
+
19
+ const customTweakStyles: IStatusStyles = {
20
+ custom: {
21
+ '--status-color': '#793472',
22
+ '--status-background': '#F2B9ED',
23
+ },
24
+ };
25
+
26
+ const Template: ComponentStory<typeof Status> = (args) => (
27
+ <div
28
+ style={{
29
+ display: 'grid',
30
+ gridTemplateRows: `repeat(${STATUS_SIZES.length + 1}, 1fr)`,
31
+ gridTemplateColumns: `repeat(${STATUS_COLORS.length + 1}, 1fr)`,
32
+ gap: 20,
33
+ }}
34
+ >
35
+ <div key={0} style={{ display: 'contents' }}>
36
+ <div />
37
+ {STATUS_COLORS.map((color, j) => (
38
+ <div key={j + 1}>{color}</div>
39
+ ))}
40
+ </div>
41
+
42
+ {STATUS_SIZES.map((size, i) => (
43
+ <div key={i + 1} style={{ display: 'contents' }}>
44
+ <div>{size}</div>
45
+ {STATUS_COLORS.map((color, j) => (
46
+ <div key={j + 1}>
47
+ <Status {...args} size={size} color={color} tweakStyles={customTweakStyles} />
48
+ </div>
49
+ ))}
50
+ </div>
51
+ ))}
52
+ </div>
53
+ );
54
+
55
+ export const Default = Template.bind({});
56
+
57
+ Default.args = {
58
+ children: 'Status',
59
+ badge: '+ Badge',
60
+ icon: 'balloon',
61
+ iconPosition: 'left',
62
+ };
63
+
64
+ Default.argTypes = {
65
+ icon: { options: iconTypes, control: 'select' },
66
+ iconPosition: { options: ['left', 'right'], control: 'inline-radio' },
67
+ };
68
+
69
+ Default.parameters = {
70
+ controls: {
71
+ exclude: ['size', 'color', 'tweakStyles', 'testId', 'data'],
72
+ },
73
+ };
@@ -0,0 +1,143 @@
1
+ import { rgba } from '../../helpers';
2
+ import { colors, createThemedStyles, ITweakStyles } from '../../theme';
3
+
4
+ export const useStyles = createThemedStyles('Status', {
5
+ root: {
6
+ display: 'inline-flex',
7
+ verticalAlign: 'middle',
8
+ color: 'var(--status-color)',
9
+ backgroundColor: 'var(--status-background)',
10
+ width: 'max-content',
11
+ alignItems: 'center',
12
+
13
+ '& > *': {
14
+ flexShrink: 0,
15
+ },
16
+ },
17
+
18
+ icon: {
19
+ '& > div': {
20
+ display: 'inline-block',
21
+ },
22
+ },
23
+
24
+ iconLeft: {
25
+ order: -1,
26
+ },
27
+
28
+ text: {},
29
+
30
+ badge: {
31
+ color: colors.CLASSIC_WHITE,
32
+ backgroundColor: 'var(--status-color)',
33
+ },
34
+
35
+ xs: {
36
+ padding: [2, 4],
37
+ gap: 4,
38
+ borderRadius: 2,
39
+
40
+ fontSize: 12,
41
+ lineHeight: '16px',
42
+ letterSpacing: 0.24,
43
+ fontWeight: 'bold',
44
+
45
+ '& $icon': {
46
+ width: 16,
47
+ height: 16,
48
+ },
49
+
50
+ '& $badge': {
51
+ padding: [0, 2],
52
+ marginRight: -1,
53
+ borderRadius: 4,
54
+ },
55
+ },
56
+
57
+ s: {
58
+ padding: [3, 8, 5, 8],
59
+ gap: 4,
60
+ borderRadius: 6,
61
+
62
+ fontSize: 13,
63
+ lineHeight: '16px',
64
+ letterSpacing: 0.2,
65
+ fontWeight: 'bold',
66
+
67
+ '& $text': {},
68
+
69
+ '& $icon': {
70
+ width: 16,
71
+ height: 16,
72
+ },
73
+
74
+ '& $badge': {
75
+ padding: [0, 4, 2, 4],
76
+ margin: [0, -4, -2, 0],
77
+ borderRadius: 4,
78
+ },
79
+ },
80
+
81
+ m: {
82
+ padding: [7, 12],
83
+ gap: 4,
84
+ borderRadius: 6,
85
+
86
+ fontSize: 15,
87
+ lineHeight: '18px',
88
+ letterSpacing: 0.15,
89
+ fontWeight: 'bold',
90
+
91
+ '& $text': {},
92
+
93
+ '& $icon': {
94
+ width: 18,
95
+ height: 18,
96
+ },
97
+
98
+ '& $badge': {
99
+ padding: [2, 4],
100
+ margin: [-2, -7, -2, 0],
101
+ borderRadius: 4,
102
+ },
103
+ },
104
+
105
+ green: {
106
+ '--status-background': rgba('#D4E3AC', 0.4),
107
+ '--status-color': '#769E19',
108
+ },
109
+
110
+ blue: {
111
+ '--status-background': '#EBF1FF',
112
+ '--status-color': '#577EDC',
113
+ },
114
+
115
+ grey: {
116
+ '--status-background': '#ECEFF5',
117
+ '--status-color': '#7A869A',
118
+ },
119
+
120
+ orange: {
121
+ '--status-background': rgba('#FCD3A9', 0.4),
122
+ '--status-color': '#E5741C',
123
+ },
124
+
125
+ red: {
126
+ '--status-background': rgba('#F7949A', 0.25),
127
+ '--status-color': '#F14D56',
128
+ },
129
+
130
+ teal: {
131
+ '--status-background': rgba('#8CE3EA', 0.4),
132
+ '--status-color': '#0092A6',
133
+ },
134
+
135
+ violet: {
136
+ '--status-background': rgba('#BEABE0', 0.4),
137
+ '--status-color': '#7450B2',
138
+ },
139
+
140
+ custom: {},
141
+ });
142
+
143
+ export type IStatusStyles = ITweakStyles<typeof useStyles>;
@@ -0,0 +1,49 @@
1
+ import { FC, ReactNode } from 'react';
2
+ import clsx from 'clsx';
3
+ import { addDataTestId, isReactNodeNotEmpty } from '@true-engineering/true-react-platform-helpers';
4
+ import { addDataAttributes } from '../../helpers';
5
+ import { ICommonProps } from '../../types';
6
+ import { IIcon, renderIcon } from '../Icon';
7
+ import { IStatusColor, IStatusSize } from './types';
8
+ import { useStyles, IStatusStyles } from './Status.styles';
9
+
10
+ export interface IStatusProps extends ICommonProps<IStatusStyles> {
11
+ children: ReactNode;
12
+ color: IStatusColor;
13
+ icon?: IIcon;
14
+ /** @default 's' */
15
+ size?: IStatusSize;
16
+ /** @default 'right' */
17
+ iconPosition?: 'left' | 'right';
18
+ badge?: ReactNode;
19
+ }
20
+
21
+ export const Status: FC<IStatusProps> = ({
22
+ children,
23
+ color,
24
+ size = 's',
25
+ icon,
26
+ iconPosition = 'right',
27
+ badge,
28
+ tweakStyles,
29
+ testId,
30
+ data,
31
+ }) => {
32
+ const classes = useStyles({ theme: tweakStyles });
33
+
34
+ return (
35
+ <span
36
+ className={clsx(classes.root, classes[size], classes[color])}
37
+ {...addDataTestId(testId)}
38
+ {...addDataAttributes(data)}
39
+ >
40
+ {isReactNodeNotEmpty(children) && <span className={classes.text}>{children}</span>}
41
+ {isReactNodeNotEmpty(icon) && (
42
+ <span className={clsx(classes.icon, iconPosition === 'left' && classes.iconLeft)}>
43
+ {renderIcon(icon)}
44
+ </span>
45
+ )}
46
+ {isReactNodeNotEmpty(badge) && <span className={classes.badge}>{badge}</span>}
47
+ </span>
48
+ );
49
+ };
@@ -0,0 +1,11 @@
1
+ export const STATUS_COLORS = [
2
+ 'green',
3
+ 'teal',
4
+ 'blue',
5
+ 'grey',
6
+ 'orange',
7
+ 'red',
8
+ 'violet',
9
+ 'custom',
10
+ ] as const;
11
+ export const STATUS_SIZES = ['xs', 's', 'm'] as const;
@@ -0,0 +1,3 @@
1
+ export * from './Status';
2
+
3
+ export type { IStatusStyles } from './Status.styles';
@@ -0,0 +1,5 @@
1
+ import { STATUS_COLORS, STATUS_SIZES } from './constants';
2
+
3
+ export type IStatusColor = (typeof STATUS_COLORS)[number];
4
+
5
+ export type IStatusSize = (typeof STATUS_SIZES)[number];