@qoretechnologies/reqore 0.28.5 → 0.29.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 (176) hide show
  1. package/.vscode/settings.json +2 -1
  2. package/__tests__/multiselect.test.tsx +361 -0
  3. package/__tests__/popover.test.tsx +35 -8
  4. package/dist/components/Button/index.js +3 -3
  5. package/dist/components/Button/index.js.map +1 -1
  6. package/dist/components/Checkbox/index.d.ts +3 -2
  7. package/dist/components/Checkbox/index.d.ts.map +1 -1
  8. package/dist/components/Checkbox/index.js +28 -24
  9. package/dist/components/Checkbox/index.js.map +1 -1
  10. package/dist/components/Collection/item.js +2 -2
  11. package/dist/components/Collection/item.js.map +1 -1
  12. package/dist/components/ControlGroup/index.d.ts +4 -4
  13. package/dist/components/ControlGroup/index.d.ts.map +1 -1
  14. package/dist/components/ControlGroup/index.js +13 -15
  15. package/dist/components/ControlGroup/index.js.map +1 -1
  16. package/dist/components/Dropdown/index.d.ts +2 -1
  17. package/dist/components/Dropdown/index.d.ts.map +1 -1
  18. package/dist/components/Dropdown/index.js +3 -3
  19. package/dist/components/Dropdown/index.js.map +1 -1
  20. package/dist/components/Dropdown/list.d.ts +6 -3
  21. package/dist/components/Dropdown/list.d.ts.map +1 -1
  22. package/dist/components/Dropdown/list.js +19 -1
  23. package/dist/components/Dropdown/list.js.map +1 -1
  24. package/dist/components/Effect/index.d.ts +3 -1
  25. package/dist/components/Effect/index.d.ts.map +1 -1
  26. package/dist/components/Effect/index.js +24 -19
  27. package/dist/components/Effect/index.js.map +1 -1
  28. package/dist/components/Icon/index.d.ts +12 -2
  29. package/dist/components/Icon/index.d.ts.map +1 -1
  30. package/dist/components/Icon/index.js +35 -4
  31. package/dist/components/Icon/index.js.map +1 -1
  32. package/dist/components/Input/index.js +3 -3
  33. package/dist/components/Input/index.js.map +1 -1
  34. package/dist/components/InputClearButton/index.d.ts.map +1 -1
  35. package/dist/components/InputClearButton/index.js +1 -1
  36. package/dist/components/InputClearButton/index.js.map +1 -1
  37. package/dist/components/InternalPopover/index.d.ts.map +1 -1
  38. package/dist/components/InternalPopover/index.js +31 -37
  39. package/dist/components/InternalPopover/index.js.map +1 -1
  40. package/dist/components/Menu/divider.d.ts +5 -2
  41. package/dist/components/Menu/divider.d.ts.map +1 -1
  42. package/dist/components/Menu/divider.js +41 -8
  43. package/dist/components/Menu/divider.js.map +1 -1
  44. package/dist/components/Menu/index.js +4 -3
  45. package/dist/components/Menu/index.js.map +1 -1
  46. package/dist/components/Message/index.d.ts +3 -2
  47. package/dist/components/Message/index.d.ts.map +1 -1
  48. package/dist/components/Message/index.js.map +1 -1
  49. package/dist/components/MultiSelect/index.d.ts +32 -0
  50. package/dist/components/MultiSelect/index.d.ts.map +1 -0
  51. package/dist/components/MultiSelect/index.js +177 -0
  52. package/dist/components/MultiSelect/index.js.map +1 -0
  53. package/dist/components/Notifications/notification.d.ts +3 -3
  54. package/dist/components/Notifications/notification.d.ts.map +1 -1
  55. package/dist/components/Notifications/notification.js +11 -8
  56. package/dist/components/Notifications/notification.js.map +1 -1
  57. package/dist/components/Panel/index.d.ts +1 -0
  58. package/dist/components/Panel/index.d.ts.map +1 -1
  59. package/dist/components/Panel/index.js +7 -7
  60. package/dist/components/Panel/index.js.map +1 -1
  61. package/dist/components/Popover/index.d.ts +1 -1
  62. package/dist/components/Popover/index.d.ts.map +1 -1
  63. package/dist/components/Popover/index.js +5 -2
  64. package/dist/components/Popover/index.js.map +1 -1
  65. package/dist/components/RadioGroup/index.d.ts +8 -6
  66. package/dist/components/RadioGroup/index.d.ts.map +1 -1
  67. package/dist/components/RadioGroup/index.js +6 -12
  68. package/dist/components/RadioGroup/index.js.map +1 -1
  69. package/dist/components/Table/row.js +2 -2
  70. package/dist/components/Table/row.js.map +1 -1
  71. package/dist/components/Tabs/item.js +1 -1
  72. package/dist/components/Tabs/item.js.map +1 -1
  73. package/dist/components/Tabs/list.d.ts.map +1 -1
  74. package/dist/components/Tabs/list.js +5 -4
  75. package/dist/components/Tabs/list.js.map +1 -1
  76. package/dist/components/Tag/group.d.ts +4 -3
  77. package/dist/components/Tag/group.d.ts.map +1 -1
  78. package/dist/components/Tag/group.js +12 -5
  79. package/dist/components/Tag/group.js.map +1 -1
  80. package/dist/components/Tag/index.js +5 -5
  81. package/dist/components/Tag/index.js.map +1 -1
  82. package/dist/components/Tree/index.js +1 -1
  83. package/dist/components/Tree/index.js.map +1 -1
  84. package/dist/constants/sizes.d.ts +7 -0
  85. package/dist/constants/sizes.d.ts.map +1 -1
  86. package/dist/constants/sizes.js +8 -1
  87. package/dist/constants/sizes.js.map +1 -1
  88. package/dist/containers/PopoverProvider.d.ts.map +1 -1
  89. package/dist/containers/PopoverProvider.js +28 -3
  90. package/dist/containers/PopoverProvider.js.map +1 -1
  91. package/dist/containers/ReqoreProvider.d.ts.map +1 -1
  92. package/dist/containers/ReqoreProvider.js +6 -5
  93. package/dist/containers/ReqoreProvider.js.map +1 -1
  94. package/dist/containers/UIProvider.d.ts +1 -0
  95. package/dist/containers/UIProvider.d.ts.map +1 -1
  96. package/dist/containers/UIProvider.js.map +1 -1
  97. package/dist/context/PopoverContext.d.ts +1 -0
  98. package/dist/context/PopoverContext.d.ts.map +1 -1
  99. package/dist/context/PopoverContext.js.map +1 -1
  100. package/dist/context/ReqoreContext.d.ts +1 -0
  101. package/dist/context/ReqoreContext.d.ts.map +1 -1
  102. package/dist/context/ReqoreContext.js +2 -1
  103. package/dist/context/ReqoreContext.js.map +1 -1
  104. package/dist/helpers/colors.d.ts +3 -0
  105. package/dist/helpers/colors.d.ts.map +1 -1
  106. package/dist/helpers/colors.js +28 -5
  107. package/dist/helpers/colors.js.map +1 -1
  108. package/dist/hooks/usePopover.d.ts +14 -3
  109. package/dist/hooks/usePopover.d.ts.map +1 -1
  110. package/dist/hooks/usePopover.js +12 -7
  111. package/dist/hooks/usePopover.js.map +1 -1
  112. package/dist/hooks/useReqore.d.ts +3 -0
  113. package/dist/hooks/useReqore.d.ts.map +1 -0
  114. package/dist/hooks/useReqore.js +17 -0
  115. package/dist/hooks/useReqore.js.map +1 -0
  116. package/dist/hooks/useTheme.d.ts +1 -1
  117. package/dist/hooks/useTheme.d.ts.map +1 -1
  118. package/dist/hooks/useTheme.js +3 -0
  119. package/dist/hooks/useTheme.js.map +1 -1
  120. package/dist/index.d.ts +3 -0
  121. package/dist/index.d.ts.map +1 -1
  122. package/dist/index.js +8 -2
  123. package/dist/index.js.map +1 -1
  124. package/package.json +1 -1
  125. package/src/components/Button/index.tsx +3 -3
  126. package/src/components/Checkbox/index.tsx +58 -30
  127. package/src/components/Collection/item.tsx +2 -2
  128. package/src/components/ControlGroup/index.tsx +54 -37
  129. package/src/components/Dropdown/index.tsx +7 -2
  130. package/src/components/Dropdown/list.tsx +29 -15
  131. package/src/components/Effect/index.tsx +58 -51
  132. package/src/components/Icon/index.tsx +75 -1
  133. package/src/components/Input/index.tsx +3 -3
  134. package/src/components/InputClearButton/index.tsx +1 -0
  135. package/src/components/InternalPopover/index.tsx +108 -50
  136. package/src/components/Menu/divider.tsx +35 -7
  137. package/src/components/Menu/index.tsx +3 -3
  138. package/src/components/Message/index.tsx +3 -0
  139. package/src/components/MultiSelect/index.tsx +283 -0
  140. package/src/components/Notifications/notification.tsx +23 -13
  141. package/src/components/Panel/index.tsx +14 -8
  142. package/src/components/Popover/index.tsx +8 -3
  143. package/src/components/RadioGroup/index.tsx +36 -27
  144. package/src/components/Table/row.tsx +2 -2
  145. package/src/components/Tabs/item.tsx +1 -1
  146. package/src/components/Tabs/list.tsx +11 -11
  147. package/src/components/Tag/group.tsx +15 -4
  148. package/src/components/Tag/index.tsx +7 -7
  149. package/src/components/Tree/index.tsx +3 -3
  150. package/src/constants/sizes.ts +8 -0
  151. package/src/containers/PopoverProvider.tsx +35 -3
  152. package/src/containers/ReqoreProvider.tsx +6 -4
  153. package/src/containers/UIProvider.tsx +1 -0
  154. package/src/context/PopoverContext.tsx +1 -0
  155. package/src/context/ReqoreContext.tsx +2 -0
  156. package/src/helpers/colors.ts +53 -7
  157. package/src/hooks/usePopover.tsx +39 -12
  158. package/src/hooks/useReqore.ts +12 -0
  159. package/src/hooks/useTheme.ts +6 -1
  160. package/src/index.tsx +3 -0
  161. package/src/mock/multiSelect.ts +61 -0
  162. package/src/stories/Button/Button.stories.tsx +20 -8
  163. package/src/stories/ControlGroup/ControlGroup.stories.tsx +13 -2
  164. package/src/stories/Dropdown/Dropdown.stories.tsx +6 -1
  165. package/src/stories/Icon/Icon.stories.tsx +99 -22
  166. package/src/stories/Input/Input.stories.tsx +25 -0
  167. package/src/stories/Menu/Menu.stories.tsx +3 -2
  168. package/src/stories/Message/Message.stories.tsx +7 -1
  169. package/src/stories/MultiSelect/MultiSelect.stories.tsx +99 -0
  170. package/src/stories/Panel/Panel.stories.tsx +3 -3
  171. package/src/stories/Popover/Popover.stories.tsx +91 -12
  172. package/src/stories/RadioGroup/RadioGroup.stories.tsx +29 -2
  173. package/src/stories/Tabs/Tabs.stories.tsx +23 -3
  174. package/src/stories/Tag/Tag.stories.tsx +12 -3
  175. package/src/stories/utils/args.ts +13 -0
  176. package/tests.json +1 -1
@@ -0,0 +1,283 @@
1
+ import { size } from 'lodash';
2
+ import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
+ import { useUpdateEffect } from 'react-use';
4
+ import { ReqoreDropdown, ReqoreInput } from '../..';
5
+ import { TSizes } from '../../constants/sizes';
6
+ import { IPopoverControls } from '../../hooks/usePopover';
7
+ import ReqoreControlGroup, { IReqoreControlGroupProps } from '../ControlGroup';
8
+ import { IReqoreDropdownProps } from '../Dropdown';
9
+ import { IReqoreDropdownItem } from '../Dropdown/list';
10
+ import { IReqoreEffect } from '../Effect';
11
+ import { IReqoreInputProps } from '../Input';
12
+ import ReqoreTag, { IReqoreTagProps } from '../Tag';
13
+ import ReqoreTagGroup from '../Tag/group';
14
+
15
+ export type TReqoreMultiSelectItem = Omit<IReqoreDropdownItem, 'color'> &
16
+ Pick<IReqoreTagProps, 'badge'> & { isNew?: boolean };
17
+
18
+ export interface IReqoreMultiSelectProps
19
+ extends Omit<IReqoreControlGroupProps, 'children' | 'vertical' | 'stack'> {
20
+ value?: string[];
21
+ onValueChange?: (value: string[]) => void;
22
+ items?: TReqoreMultiSelectItem[];
23
+ onItemClick?: (item: IReqoreDropdownItem) => void;
24
+ canRemoveItems?: boolean;
25
+ canCreateItems?: boolean;
26
+ selectedItemEffect?: IReqoreEffect;
27
+ selectedItemSize?: TSizes;
28
+ selectorProps?: Omit<IReqoreInputProps, 'value' | 'onValueChange'> & IReqoreDropdownProps;
29
+ openOnMount?: IReqoreDropdownProps['openOnMount'];
30
+ enterKeySelects?: boolean;
31
+ }
32
+
33
+ export interface IReqoreMultiSelectItemProps
34
+ extends Pick<IReqoreMultiSelectProps, 'selectedItemEffect' | 'selectedItemSize'> {
35
+ item: TReqoreMultiSelectItem;
36
+ onClick?: () => void;
37
+ onRemoveClick?: () => void;
38
+ }
39
+
40
+ export const ReqoreMultiSelectItem = memo(
41
+ ({
42
+ item,
43
+ onRemoveClick,
44
+ onClick,
45
+ selectedItemEffect,
46
+ selectedItemSize,
47
+ }: IReqoreMultiSelectItemProps) => {
48
+ if (!item) {
49
+ return null;
50
+ }
51
+
52
+ return (
53
+ <ReqoreTag
54
+ {...item}
55
+ label={item.label || item.value}
56
+ onRemoveClick={onRemoveClick}
57
+ intent={item.intent}
58
+ effect={!item.intent ? item.effect || selectedItemEffect : undefined}
59
+ size={selectedItemSize}
60
+ onClick={onClick}
61
+ />
62
+ );
63
+ }
64
+ );
65
+
66
+ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectProps>(
67
+ (
68
+ {
69
+ value,
70
+ onValueChange,
71
+ onItemClick,
72
+ canRemoveItems,
73
+ canCreateItems,
74
+ items = [],
75
+ selectedItemEffect,
76
+ selectedItemSize,
77
+ selectorProps,
78
+ openOnMount,
79
+ enterKeySelects,
80
+ ...rest
81
+ }: IReqoreMultiSelectProps,
82
+ ref
83
+ ) => {
84
+ const [_value, setValue] = useState<string[]>(value || []);
85
+ const [createdItems, setCreatedItems] = useState<TReqoreMultiSelectItem[]>([]);
86
+ const [query, setQuery] = useState<string>('');
87
+ const popoverData = useRef<IPopoverControls>(undefined);
88
+
89
+ useUpdateEffect(() => {
90
+ onValueChange?.(_value);
91
+ }, [_value]);
92
+
93
+ useEffect(() => {
94
+ setValue(value || []);
95
+ }, [value]);
96
+
97
+ useEffect(() => {
98
+ if (query && !popoverData.current?.isOpen()) {
99
+ popoverData.current?.open();
100
+ }
101
+ }, [query]);
102
+
103
+ useEffect(() => {
104
+ if (enterKeySelects) {
105
+ document.addEventListener('keydown', handleKeyDown);
106
+ }
107
+
108
+ return () => {
109
+ document.removeEventListener('keydown', handleKeyDown);
110
+ };
111
+ });
112
+
113
+ const addRemoveItem = useCallback(
114
+ (item: TReqoreMultiSelectItem): void => {
115
+ if (_value.includes(item.value)) {
116
+ setValue(_value.filter((v) => v !== item.value));
117
+ } else {
118
+ setValue([..._value, item.value]);
119
+ }
120
+ },
121
+ [_value, value]
122
+ );
123
+
124
+ const handleItemSelect = useCallback(
125
+ (item: Partial<TReqoreMultiSelectItem>) => {
126
+ addRemoveItem(item);
127
+
128
+ if (item.isNew) {
129
+ setCreatedItems([
130
+ ...createdItems,
131
+ {
132
+ value: item.value,
133
+ },
134
+ ]);
135
+ }
136
+
137
+ setQuery('');
138
+ },
139
+ [createdItems, _value]
140
+ );
141
+
142
+ /*
143
+ This code creates a list of all items that are available
144
+ for selection in the dropdown. It will include the items
145
+ that are passed in as props, as well as any items that the
146
+ user has created.
147
+ */
148
+ const allItems: TReqoreMultiSelectItem[] = useMemo(() => {
149
+ const customItems: TReqoreMultiSelectItem[] = size(createdItems)
150
+ ? [{ divider: true, label: 'Custom Items' }, ...createdItems]
151
+ : [];
152
+
153
+ let filteredItems: TReqoreMultiSelectItem[] = [...items, ...customItems].filter((item) =>
154
+ query
155
+ ? item.divider
156
+ ? false
157
+ : (item.label || item.value)?.toString().toLowerCase().indexOf(query.toLowerCase()) !==
158
+ -1
159
+ : true
160
+ );
161
+
162
+ // Mark selected items as selected
163
+ filteredItems = filteredItems.map((item: TReqoreMultiSelectItem) => ({
164
+ ...item,
165
+ selected: _value.includes(item.value),
166
+ }));
167
+
168
+ if (query && !size(filteredItems)) {
169
+ filteredItems = [
170
+ { label: 'No existing items found', readOnly: true, minimal: true, icon: 'ForbidLine' },
171
+ ];
172
+ }
173
+
174
+ // If there is a query and there are filtered items
175
+ // and there is no item that exactly matches the query, add it to the list
176
+ if (
177
+ query &&
178
+ !filteredItems.some((item: TReqoreMultiSelectItem) => item.value === query) &&
179
+ canCreateItems
180
+ ) {
181
+ filteredItems = [
182
+ {
183
+ label: `Create new "${query}"`,
184
+ value: query,
185
+ isNew: true,
186
+ icon: 'AddCircleLine',
187
+ minimal: true,
188
+ flat: false,
189
+ effect: {
190
+ gradient: {
191
+ colors: {
192
+ 0: 'success',
193
+ 100: 'success:darken:1',
194
+ },
195
+ },
196
+ },
197
+ },
198
+ { divider: true, label: 'Items matching your query' },
199
+ ...filteredItems,
200
+ ];
201
+ }
202
+
203
+ return filteredItems;
204
+ }, [items, createdItems, query, _value]);
205
+
206
+ const handleKeyDown = useCallback(
207
+ (e: KeyboardEvent) => {
208
+ if (e.key === 'Enter') {
209
+ const item = [...items, ...createdItems].find((item) => item.value === query);
210
+
211
+ if (item) {
212
+ handleItemSelect(item);
213
+ } else if (canCreateItems) {
214
+ handleItemSelect({
215
+ value: query,
216
+ isNew: true,
217
+ });
218
+ }
219
+ }
220
+ },
221
+ [items, createdItems, query, canCreateItems]
222
+ );
223
+
224
+ const getItemByValue = useCallback(
225
+ (value: string): TReqoreMultiSelectItem => {
226
+ return [...items, ...createdItems].find((item) => item.value === value);
227
+ },
228
+ [items, createdItems, _value]
229
+ );
230
+
231
+ return (
232
+ <ReqoreControlGroup vertical fluid {...rest} ref={ref}>
233
+ <ReqoreTagGroup minimal={rest.minimal} size={rest.size}>
234
+ {size(_value) ? (
235
+ _value.map((v) => (
236
+ <ReqoreMultiSelectItem
237
+ key={v}
238
+ item={getItemByValue(v)}
239
+ onRemoveClick={canRemoveItems ? () => addRemoveItem(getItemByValue(v)) : undefined}
240
+ onClick={
241
+ onItemClick
242
+ ? () => {
243
+ onItemClick(getItemByValue(v));
244
+ }
245
+ : undefined
246
+ }
247
+ selectedItemEffect={selectedItemEffect}
248
+ selectedItemSize={selectedItemSize}
249
+ />
250
+ ))
251
+ ) : (
252
+ <ReqoreTag color='transparent' icon='ForbidLine' label='No items selected' />
253
+ )}
254
+ </ReqoreTagGroup>
255
+ <ReqoreControlGroup minimal={rest.minimal} flat={rest.flat} size={rest.size}>
256
+ <ReqoreDropdown<IReqoreInputProps>
257
+ {...selectorProps}
258
+ multiSelect
259
+ handler='focus'
260
+ passPopoverData={(data) => (popoverData.current = data)}
261
+ component={ReqoreInput}
262
+ onClearClick={() => setQuery('')}
263
+ value={query}
264
+ isDefaultOpen={openOnMount}
265
+ onItemSelect={handleItemSelect}
266
+ placeholder={
267
+ canCreateItems ? 'Type to search or create an item...' : 'Type to search...'
268
+ }
269
+ onChange={(e: any) => setQuery(e.target.value)}
270
+ items={
271
+ size(allItems)
272
+ ? allItems
273
+ : canCreateItems
274
+ ? [{ label: 'No items exist', readOnly: true, minimal: true, icon: 'ForbidLine' }]
275
+ : []
276
+ }
277
+ useTargetWidth
278
+ />
279
+ </ReqoreControlGroup>
280
+ </ReqoreControlGroup>
281
+ );
282
+ }
283
+ );
@@ -15,7 +15,7 @@ import { IReqoreTheme, TReqoreIntent } from '../../constants/theme';
15
15
  import ReqoreThemeProvider from '../../containers/ThemeProvider';
16
16
  import { fadeIn } from '../../helpers/animations';
17
17
  import { changeLightness, getNotificationIntent, getReadableColor } from '../../helpers/colors';
18
- import { IWithReqoreEffect, IWithReqoreMinimal } from '../../types/global';
18
+ import { IWithReqoreEffect, IWithReqoreMinimal, IWithReqoreOpaque } from '../../types/global';
19
19
  import { IReqoreIconName } from '../../types/icons';
20
20
  import { StyledEffect } from '../Effect';
21
21
  import { ReqoreHeading } from '../Header';
@@ -23,7 +23,10 @@ import ReqoreIcon from '../Icon';
23
23
 
24
24
  export type IReqoreNotificationType = TReqoreIntent;
25
25
 
26
- export interface IReqoreNotificationProps extends IWithReqoreEffect, IWithReqoreMinimal {
26
+ export interface IReqoreNotificationProps
27
+ extends IWithReqoreEffect,
28
+ IWithReqoreMinimal,
29
+ IWithReqoreOpaque {
27
30
  type?: IReqoreNotificationType;
28
31
  intent?: TReqoreIntent;
29
32
  title?: string;
@@ -38,7 +41,7 @@ export interface IReqoreNotificationProps extends IWithReqoreEffect, IWithReqore
38
41
  size?: TSizes;
39
42
  }
40
43
 
41
- export interface IReqoreNotificationStyle {
44
+ export interface IReqoreNotificationStyle extends IWithReqoreOpaque {
42
45
  theme: IReqoreTheme;
43
46
  type?: IReqoreNotificationType;
44
47
  clickable?: boolean;
@@ -73,12 +76,14 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
73
76
  transition: all 0.2s ease-out;
74
77
 
75
78
  // Do not fade in the component if it's a message
76
- ${({ asMessage }) =>
77
- asMessage
78
- ? undefined
79
- : css`
80
- animation: 0.2s ${fadeIn} ease-in;
81
- `};
79
+ ${({ asMessage }) => {
80
+ if (asMessage) {
81
+ return undefined;
82
+ }
83
+ return css`
84
+ animation: 0.2s ${fadeIn} ease-in;
85
+ `;
86
+ }}
82
87
 
83
88
  &:not(:first-child) {
84
89
  margin-top: ${({ asMessage }) => (asMessage ? undefined : `10px`)};
@@ -93,12 +98,15 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
93
98
  hasShadow,
94
99
  flat,
95
100
  minimal,
101
+ opaque,
96
102
  }: IReqoreNotificationStyle) => css`
97
103
  background-color: ${minimal
98
104
  ? 'transparent'
105
+ : opaque
106
+ ? changeLightness(theme.main, 0.1)
99
107
  : rgba(getNotificationIntent(theme, intent || type), 0.3)};
100
108
  border: ${flat ? 0 : '1px solid'};
101
- border-color: ${getNotificationIntent(theme, intent || type)};
109
+ border-color: ${changeLightness(getNotificationIntent(theme, intent || type), 0.2)};
102
110
 
103
111
  ${hasShadow &&
104
112
  css`
@@ -113,13 +121,13 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
113
121
  display: block;
114
122
  top: 0;
115
123
  height: 3px;
116
- background-color: ${changeLightness(getNotificationIntent(theme, intent || type), 0.1)};
124
+ background-color: ${changeLightness(getNotificationIntent(theme, intent || type), 0.2)};
117
125
  animation-name: ${timeoutAnimation};
118
126
  animation-duration: ${timeout}ms;
119
127
  }
120
128
  `}
121
129
 
122
- color: ${getReadableColor(theme, null, null, true, theme.originalMain)};
130
+ color: ${getReadableColor(theme, null, null, true, !opaque ? theme.originalMain : undefined)};
123
131
 
124
132
  ${clickable &&
125
133
  css`
@@ -129,7 +137,7 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
129
137
  getNotificationIntent(theme, intent || type),
130
138
  minimal ? 0.2 : 0.5
131
139
  )};
132
- border-color: ${changeLightness(getNotificationIntent(theme, intent || type), 0.1)};
140
+ border-color: ${changeLightness(getNotificationIntent(theme, intent || type), 0.25)};
133
141
  }
134
142
  `}
135
143
  `}
@@ -218,6 +226,7 @@ const ReqoreNotification = forwardRef<HTMLDivElement, IReqoreNotificationProps>(
218
226
  onFinish,
219
227
  flat,
220
228
  minimal,
229
+ opaque,
221
230
  size = 'normal',
222
231
  },
223
232
  ref: any
@@ -273,6 +282,7 @@ const ReqoreNotification = forwardRef<HTMLDivElement, IReqoreNotificationProps>(
273
282
  ref={ref}
274
283
  style={styles}
275
284
  size={size}
285
+ opaque={opaque}
276
286
  >
277
287
  {type || intent || icon ? (
278
288
  <StyledIconWrapper type={type || intent} size={size}>
@@ -1,6 +1,6 @@
1
1
  import { size } from 'lodash';
2
2
  import { darken, rgba } from 'polished';
3
- import { ReactElement, forwardRef, useCallback, useMemo, useState } from 'react';
3
+ import { forwardRef, ReactElement, useCallback, useMemo, useState } from 'react';
4
4
  import { useUpdateEffect } from 'react-use';
5
5
  import styled, { css } from 'styled-components';
6
6
  import {
@@ -86,6 +86,7 @@ export interface IReqorePanelProps
86
86
  contentSize?: TSizes;
87
87
  contentEffect?: IReqoreEffect;
88
88
  headerEffect?: IReqoreEffect;
89
+ transparent?: boolean;
89
90
  }
90
91
 
91
92
  export interface IStyledPanel extends IReqorePanelProps {
@@ -133,7 +134,7 @@ export const StyledPanel = styled(StyledEffect)<IStyledPanel>`
133
134
  : `${rgba(
134
135
  changeLightness(
135
136
  intent ? theme.intents[intent] : getMainBackgroundColor(theme),
136
- 0.3
137
+ 0.25
137
138
  ),
138
139
  opacity
139
140
  )}`};
@@ -322,7 +323,9 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
322
323
  (actionOrActions: IReqorePanelAction | IReqorePanelAction[], index: number) => {
323
324
  if (Array.isArray(actionOrActions)) {
324
325
  return (
325
- <ReqoreControlGroup stack>{actionOrActions.map(renderActions)}</ReqoreControlGroup>
326
+ <ReqoreControlGroup key={index} stack>
327
+ {actionOrActions.map(renderActions)}
328
+ </ReqoreControlGroup>
326
329
  );
327
330
  }
328
331
 
@@ -417,6 +420,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
417
420
  return newContentEffect;
418
421
  }, [intent, theme, contentEffect, interactive]);
419
422
 
423
+ const opacity = rest.transparent ? 0 : rest.opacity;
424
+
420
425
  return (
421
426
  <StyledPanel
422
427
  {...rest}
@@ -430,6 +435,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
430
435
  interactive={interactive}
431
436
  theme={theme}
432
437
  effect={transformedContentEffect}
438
+ opacity={opacity}
433
439
  >
434
440
  {hasTitleBar && (
435
441
  <StyledPanelTitle
@@ -440,8 +446,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
440
446
  onClick={handleCollapseClick}
441
447
  theme={theme}
442
448
  contentSize={contentSize}
443
- opacity={rest.opacity ?? (minimal ? 0 : 1)}
444
- noHorizontalPadding={rest.opacity === 0}
449
+ opacity={opacity ?? (minimal ? 0 : 1)}
450
+ noHorizontalPadding={opacity === 0}
445
451
  >
446
452
  <StyledPanelTitleHeader>
447
453
  {icon && (
@@ -509,7 +515,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
509
515
  padded={padded}
510
516
  minimal={minimal}
511
517
  contentSize={contentSize}
512
- noHorizontalPadding={rest.opacity === 0}
518
+ noHorizontalPadding={opacity === 0}
513
519
  >
514
520
  {children}
515
521
  </StyledPanelContent>
@@ -519,8 +525,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
519
525
  flat={flat}
520
526
  className='reqore-panel-bottom-actions'
521
527
  theme={theme}
522
- opacity={rest.opacity ?? (minimal ? 0 : 1)}
523
- noHorizontalPadding={rest.opacity === 0}
528
+ opacity={opacity ?? (minimal ? 0 : 1)}
529
+ noHorizontalPadding={opacity === 0}
524
530
  >
525
531
  <ReqoreControlGroup>{leftBottomActions.map(renderActions)}</ReqoreControlGroup>
526
532
  <ReqoreControlGroup>{rightBottomActions.map(renderActions)}</ReqoreControlGroup>
@@ -1,6 +1,6 @@
1
- import React, { memo, useState } from 'react';
1
+ import React, { memo, useEffect, useState } from 'react';
2
2
  import styled from 'styled-components';
3
- import usePopover, { IPopoverOptions } from '../../hooks/usePopover';
3
+ import usePopover, { IPopoverControls, IPopoverOptions } from '../../hooks/usePopover';
4
4
  import { IReqoreComponent } from '../../types/global';
5
5
 
6
6
  export interface IReqorePopoverProps extends IReqoreComponent, IPopoverOptions {
@@ -26,13 +26,18 @@ const Popover = memo(
26
26
  noWrapper,
27
27
  wrapperTag = 'span',
28
28
  wrapperStyle = {},
29
+ passPopoverData,
29
30
  _insidePopover,
30
31
  _popoverId,
31
32
  ...rest
32
33
  }: IReqorePopoverProps) => {
33
34
  const [ref, setRef] = useState(undefined);
34
35
 
35
- usePopover({ targetElement: ref, ...rest });
36
+ const popoverData: IPopoverControls = usePopover({ targetElement: ref, ...rest });
37
+
38
+ useEffect(() => {
39
+ passPopoverData?.(popoverData);
40
+ }, [popoverData]);
36
41
 
37
42
  if (isReqoreComponent || noWrapper) {
38
43
  return (
@@ -1,15 +1,18 @@
1
- import React from "react";
2
- import styled from "styled-components";
3
- import { ReqoreCheckbox } from "../..";
4
- import { TSizes } from "../../constants/sizes";
5
- import { IReqoreCheckboxProps } from "../Checkbox";
1
+ import React from 'react';
2
+ import { ReqoreCheckbox, ReqoreControlGroup } from '../..';
3
+ import { TSizes } from '../../constants/sizes';
4
+ import { IReqoreCheckboxProps } from '../Checkbox';
5
+ import { IReqoreControlGroupProps } from '../ControlGroup';
6
+ import ReqoreMenuDivider from '../Menu/divider';
6
7
 
7
8
  export interface IReqoreRadioGroupItem extends IReqoreCheckboxProps {
8
- value: string;
9
+ value?: string;
10
+ divider?: boolean;
9
11
  }
10
12
 
11
13
  export interface IReqoreRadioGroupProps
12
- extends React.HTMLAttributes<HTMLDivElement> {
14
+ extends Omit<IReqoreControlGroupProps, 'children'>,
15
+ Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
13
16
  items: IReqoreRadioGroupItem[];
14
17
  selected?: string;
15
18
  onSelectClick?: (value: string) => void;
@@ -18,11 +21,6 @@ export interface IReqoreRadioGroupProps
18
21
  asSwitch?: boolean;
19
22
  }
20
23
 
21
- const StyledRadioGroup = styled.div`
22
- display: flex;
23
- flex-flow: column;
24
- `;
25
-
26
24
  const ReqoreRadioGroup = ({
27
25
  items = [],
28
26
  selected,
@@ -30,23 +28,34 @@ const ReqoreRadioGroup = ({
30
28
  size,
31
29
  disabled,
32
30
  asSwitch,
31
+ vertical = true,
33
32
  ...rest
34
33
  }: IReqoreRadioGroupProps) => (
35
- <StyledRadioGroup {...rest}>
36
- {items.map(({ value, ...itemRest }) => (
37
- <ReqoreCheckbox
38
- asSwitch={asSwitch}
39
- {...itemRest}
40
- key={value}
41
- checked={value === selected}
42
- size={size || itemRest.size}
43
- disabled={disabled || itemRest.disabled}
44
- onClick={() => {
45
- onSelectClick(value);
46
- }}
47
- />
48
- ))}
49
- </StyledRadioGroup>
34
+ <ReqoreControlGroup {...rest} vertical={vertical}>
35
+ {items.map(({ value, divider, ...itemRest }) =>
36
+ divider ? (
37
+ <ReqoreMenuDivider
38
+ {...itemRest}
39
+ size={size || itemRest.size}
40
+ effect={{ ...itemRest.effect, textAlign: 'left' }}
41
+ margin='left'
42
+ label={vertical ? itemRest.label : undefined}
43
+ />
44
+ ) : (
45
+ <ReqoreCheckbox
46
+ asSwitch={asSwitch}
47
+ {...itemRest}
48
+ key={value}
49
+ checked={value === selected}
50
+ size={size || itemRest.size}
51
+ disabled={disabled || itemRest.disabled}
52
+ onClick={() => {
53
+ onSelectClick(value);
54
+ }}
55
+ />
56
+ )
57
+ )}
58
+ </ReqoreControlGroup>
50
59
  );
51
60
 
52
61
  export default ReqoreRadioGroup;
@@ -277,10 +277,10 @@ const ReqoreTableRow = ({
277
277
  onClick: (e: React.MouseEvent<HTMLDivElement>) => {
278
278
  if (onCellClick) {
279
279
  e.stopPropagation();
280
- onCellClick?.(data[index]);
280
+ onCellClick(data[index]);
281
281
  } else if (onRowClick) {
282
282
  e.stopPropagation();
283
- onRowClick?.(data[index]);
283
+ onRowClick(data[index]);
284
284
  } else if (selectable && data[index]._selectId) {
285
285
  // Otherwise select the row if selectable
286
286
  onSelectClick(data[index]._selectId);
@@ -35,7 +35,7 @@ export const StyledTabListItem = styled.div<IReqoreTabListItemStyle>`
35
35
  position: relative;
36
36
  align-items: center;
37
37
  width: ${vertical ? `100%` : undefined};
38
- padding: ${vertical ? `${TABS_PADDING_TO_PX[size!]}px` : `${TABS_PADDING_TO_PX[size!]}px`};
38
+ padding: ${`${TABS_PADDING_TO_PX[size!]}px`};
39
39
  padding-bottom: ${!vertical && 0};
40
40
  padding-right: ${vertical && 0};
41
41
 
@@ -13,9 +13,14 @@ import {
13
13
  } from '../../constants/sizes';
14
14
  import { IReqoreBreadcrumbsTheme, IReqoreCustomTheme, IReqoreTheme } from '../../constants/theme';
15
15
  import ReqoreThemeProvider from '../../containers/ThemeProvider';
16
- import { changeLightness } from '../../helpers/colors';
16
+ import {
17
+ changeLightness,
18
+ getColorFromMaybeString,
19
+ getNthGradientColor,
20
+ } from '../../helpers/colors';
17
21
  import { calculateStringSizeInPixels } from '../../helpers/utils';
18
22
  import { useReqoreTheme } from '../../hooks/useTheme';
23
+ import { TReqoreHexColor } from '../Effect';
19
24
  import ReqoreMenu from '../Menu';
20
25
  import ReqoreMenuItem, { IReqoreMenuItemProps } from '../Menu/item';
21
26
  import { StyledPopover } from '../Popover';
@@ -159,23 +164,18 @@ const ReqoreTabsList = ({
159
164
  intent,
160
165
  ...rest
161
166
  }: IReqoreTabsListProps) => {
162
- const [ref, { width, height }] = useMeasure();
167
+ const [ref, { width }] = useMeasure();
163
168
  const theme = useReqoreTheme('main', customTheme, intent);
164
169
  const activeTabData = tabs.find((tab) => tab.id === activeTab);
165
- const currentTabColor =
170
+ const currentTabColor: TReqoreHexColor =
166
171
  activeTabIntent || activeTabData?.intent
167
172
  ? theme.intents[activeTabIntent || activeTabData.intent]
168
- : activeTabData?.customTheme?.main || theme.main;
173
+ : getNthGradientColor(theme, activeTabData?.effect?.gradient?.colors) ||
174
+ getColorFromMaybeString(theme, activeTabData?.customTheme?.main || theme.main);
169
175
 
170
176
  const transformedItems = vertical
171
177
  ? tabs
172
- : getTransformedItems(
173
- tabs,
174
- vertical ? height : _testWidth || width,
175
- vertical ? 'height' : 'width',
176
- activeTab,
177
- size
178
- );
178
+ : getTransformedItems(tabs, _testWidth || width, 'width', activeTab, size);
179
179
 
180
180
  return (
181
181
  <ReqoreThemeProvider theme={theme}>