@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
@@ -1,11 +1,15 @@
1
1
  import React from 'react';
2
2
  import styled from 'styled-components';
3
3
  import { StyledTag } from '.';
4
- import { TSizes } from '../../constants/sizes';
4
+ import { GAP_FROM_SIZE, TSizes } from '../../constants/sizes';
5
+ import { IWithReqoreMinimal, IWithReqoreSize } from '../../types/global';
5
6
 
6
- export interface IReqoreTagGroup extends React.HTMLAttributes<HTMLDivElement> {
7
+ export interface IReqoreTagGroup
8
+ extends React.HTMLAttributes<HTMLDivElement>,
9
+ IWithReqoreSize,
10
+ IWithReqoreMinimal {
7
11
  children: any;
8
- size?: TSizes;
12
+ gapSize?: TSizes;
9
13
  columns?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
10
14
  hasBottomMargin?: boolean;
11
15
  }
@@ -15,7 +19,7 @@ const StyledTagGroup = styled.div`
15
19
 
16
20
  ${StyledTag} {
17
21
  &:not(:last-child) {
18
- margin-right: 5px;
22
+ margin-right: ${({ gapSize }: IReqoreTagGroup) => `${GAP_FROM_SIZE[gapSize]}px`};
19
23
  }
20
24
 
21
25
  margin-bottom: ${({ hasBottomMargin }) => (hasBottomMargin ? '5px' : '0px')};
@@ -25,6 +29,8 @@ const StyledTagGroup = styled.div`
25
29
  const ReqoreTagGroup = ({
26
30
  children,
27
31
  size,
32
+ gapSize = 'normal',
33
+ minimal,
28
34
  className,
29
35
  columns,
30
36
  hasBottomMargin = true,
@@ -32,6 +38,7 @@ const ReqoreTagGroup = ({
32
38
  }: IReqoreTagGroup) => (
33
39
  <StyledTagGroup
34
40
  {...rest}
41
+ gapSize={gapSize}
35
42
  hasBottomMargin={hasBottomMargin}
36
43
  className={`${className || ''} reqore-tag-group`}
37
44
  >
@@ -40,6 +47,10 @@ const ReqoreTagGroup = ({
40
47
  ? React.cloneElement(child, {
41
48
  size: child.props?.size || size,
42
49
  width: columns ? `calc(${100 / columns}% - 5px)` : child.props.width,
50
+ minimal:
51
+ child.props?.minimal || child.props?.minimal === false
52
+ ? child.props.minimal
53
+ : minimal,
43
54
  })
44
55
  : null
45
56
  )}
@@ -265,7 +265,7 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
265
265
  <StyledTagKeyWrapper
266
266
  size={size}
267
267
  className='reqore-tag-key-content'
268
- onClick={onClick}
268
+ onClick={rest.disabled ? undefined : onClick}
269
269
  wrap={wrap}
270
270
  hasWidth={!!width}
271
271
  hasKey={!!labelKey}
@@ -282,13 +282,13 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
282
282
  <StyledTagContentWrapper
283
283
  size={size}
284
284
  className='reqore-tag-content'
285
- onClick={onClick}
285
+ onClick={rest.disabled ? undefined : onClick}
286
286
  wrap={wrap}
287
287
  hasWidth={!!width}
288
288
  hasKey={!!labelKey}
289
289
  >
290
290
  {label || label === 0 ? (
291
- <StyledTagContent size={size} onClick={onClick} wrap={wrap} hasWidth={!!width}>
291
+ <StyledTagContent size={size} wrap={wrap} hasWidth={!!width}>
292
292
  {label}
293
293
  </StyledTagContent>
294
294
  ) : null}
@@ -302,8 +302,8 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
302
302
  </StyledTagContentWrapper>
303
303
  ) : null}
304
304
  {_size(actions)
305
- ? actions.map((action) => (
306
- <>
305
+ ? actions.map((action, index) => (
306
+ <React.Fragment key={index}>
307
307
  <ReqorePopover
308
308
  component={StyledButtonWrapper}
309
309
  componentProps={{
@@ -316,13 +316,13 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
316
316
  {...(action.tooltip
317
317
  ? typeof action.tooltip === 'string'
318
318
  ? { tooltip: action.tooltip }
319
- : action.tooltip || {}
319
+ : action.tooltip
320
320
  : {})}
321
321
  noWrapper
322
322
  >
323
323
  <ReqoreIcon icon={action.icon} size={size} />
324
324
  </ReqorePopover>
325
- </>
325
+ </React.Fragment>
326
326
  ))
327
327
  : null}
328
328
  {onRemoveClick && !rest.disabled ? (
@@ -106,9 +106,9 @@ export const ReqoreTree = ({
106
106
  <ReqoreControlGroup size={size}>
107
107
  <ReqoreButton
108
108
  className='reqore-tree-toggle'
109
- icon={isObject ? (isExpandable ? 'ArrowDownSFill' : 'ArrowRightSFill') : undefined}
110
- intent={isObject && isExpandable ? 'info' : undefined}
111
- onClick={isObject ? () => handleItemClick(stateKey, isExpandable) : undefined}
109
+ icon={isExpandable ? 'ArrowDownSFill' : 'ArrowRightSFill'}
110
+ intent={isExpandable ? 'info' : undefined}
111
+ onClick={() => handleItemClick(stateKey, isExpandable)}
112
112
  flat
113
113
  >
114
114
  {displayKey}
@@ -107,6 +107,14 @@ export const RADIUS_FROM_SIZE = {
107
107
  huge: 9,
108
108
  };
109
109
 
110
+ export const GAP_FROM_SIZE = {
111
+ tiny: 1,
112
+ small: 3,
113
+ normal: 5,
114
+ big: 18,
115
+ huge: 30,
116
+ };
117
+
110
118
  export const ICON_FROM_HEADER_SIZE = {
111
119
  1: 23,
112
120
  2: 20,
@@ -3,6 +3,7 @@ import React, { MutableRefObject, useCallback, useEffect, useState } from 'react
3
3
  import Popover from '../components/InternalPopover';
4
4
  import PopoverContext from '../context/PopoverContext';
5
5
  import { IPopoverOptions } from '../hooks/usePopover';
6
+ import { useReqore } from '../hooks/useReqore';
6
7
 
7
8
  export interface IReqorePopoverProviderProps {
8
9
  children: any;
@@ -16,6 +17,7 @@ export interface IPopoverData extends IPopoverOptions {
16
17
 
17
18
  const PopoverProvider: React.FC<IReqorePopoverProviderProps> = ({ children, uiScale }) => {
18
19
  const [popovers, setPopovers] = useState<IPopoverData[]>([]);
20
+ const { closePopoversOnEscPress } = useReqore();
19
21
 
20
22
  const handleClick = useCallback(
21
23
  (event: MouseEvent) => {
@@ -27,8 +29,6 @@ const PopoverProvider: React.FC<IReqorePopoverProviderProps> = ({ children, uiSc
27
29
  !popperRef.current.contains(event.target) &&
28
30
  !targetElement?.contains(event.target as Node))
29
31
  ) {
30
- targetElement.style.position = 'initial';
31
- targetElement.style.zIndex = 'initial';
32
32
  removePopover(id);
33
33
  }
34
34
  });
@@ -36,21 +36,52 @@ const PopoverProvider: React.FC<IReqorePopoverProviderProps> = ({ children, uiSc
36
36
  [popovers]
37
37
  );
38
38
 
39
+ // Close last popover when ESC is pressed
40
+ const handleKeyDown = useCallback(
41
+ (event: KeyboardEvent) => {
42
+ if (event.key === 'Escape') {
43
+ const lastPopover = popovers[popovers.length - 1];
44
+
45
+ if (lastPopover) {
46
+ removePopover(lastPopover.id);
47
+ }
48
+ }
49
+ },
50
+ [popovers]
51
+ );
52
+
39
53
  const removePopover = (id: string) => {
40
- setPopovers((cur: IPopoverData[]) => [...cur].filter((p) => p.id !== id));
54
+ // Get the popover
55
+ const popover = popovers.find((p) => p.id === id);
56
+
57
+ if (popover) {
58
+ // Remove the blur
59
+ if (popover.blur > 0) {
60
+ popover.targetElement.style.position = 'initial';
61
+ popover.targetElement.style.zIndex = 'initial';
62
+ }
63
+ // Remove the popover
64
+ setPopovers((cur: IPopoverData[]) => [...cur].filter((p) => p.id !== id));
65
+ }
41
66
  };
42
67
 
43
68
  useEffect(() => {
44
69
  document.addEventListener('click', handleClick);
45
70
 
71
+ if (closePopoversOnEscPress) {
72
+ document.addEventListener('keydown', handleKeyDown);
73
+ }
74
+
46
75
  return () => {
47
76
  document.removeEventListener('click', handleClick);
77
+ document.removeEventListener('keydown', handleKeyDown);
48
78
  };
49
79
  }, [popovers]);
50
80
 
51
81
  useEffect(() => {
52
82
  if (!size(popovers)) {
53
83
  document.removeEventListener('click', handleClick);
84
+ document.removeEventListener('keydown', handleKeyDown);
54
85
  }
55
86
  }, [popovers]);
56
87
 
@@ -72,6 +103,7 @@ const PopoverProvider: React.FC<IReqorePopoverProviderProps> = ({ children, uiSc
72
103
  }, [])
73
104
  );
74
105
  },
106
+ isPopoverOpen: (popoverId: string) => !!popovers.find((p) => p.id === popoverId),
75
107
  removePopover,
76
108
  popovers,
77
109
  }}
@@ -47,7 +47,7 @@ export interface IReqoreConfirmationModal {
47
47
  intent?: TReqoreIntent;
48
48
  }
49
49
 
50
- const ReqoreProvider: React.FC<IReqoreNotifications> = ({ children, options }) => {
50
+ const ReqoreProvider: React.FC<IReqoreNotifications> = ({ children, options = {} }) => {
51
51
  const [notifications, setNotifications] = useState<IReqoreNotificationData[] | null>([]);
52
52
  const [confirmationModal, setConfirmationModal] = useState<IReqoreConfirmationModal>({});
53
53
  const latestZIndex = useRef<number>(9000);
@@ -121,17 +121,19 @@ const ReqoreProvider: React.FC<IReqoreNotifications> = ({ children, options }) =
121
121
  isTablet,
122
122
  isMobileOrTablet,
123
123
  getAndIncreaseZIndex,
124
- animations: options?.animations || { buttons: true, dialogs: true },
124
+ animations: options.animations || { buttons: true, dialogs: true },
125
+ closePopoversOnEscPress:
126
+ 'closePopoversOnEscPress' in options ? options.closePopoversOnEscPress : true,
125
127
  }}
126
128
  >
127
129
  {size(notifications) > 0 ? (
128
- <ReqoreNotificationsWrapper position={options?.notificationsPosition}>
130
+ <ReqoreNotificationsWrapper position={options.notificationsPosition}>
129
131
  {notifications.map((notification) => (
130
132
  <ReqoreNotification
131
133
  {...notification}
132
134
  key={notification.id}
133
135
  onClick={
134
- notification?.onClick
136
+ notification.onClick
135
137
  ? () => void notification.onClick(notification.id)
136
138
  : undefined
137
139
  }
@@ -18,6 +18,7 @@ export interface IReqoreOptions {
18
18
  buttons?: boolean;
19
19
  dialogs?: boolean;
20
20
  };
21
+ closePopoversOnEscPress?: boolean;
21
22
  }
22
23
  export interface IReqoreUIProviderProps {
23
24
  children?: any;
@@ -5,6 +5,7 @@ export default createContext<{
5
5
  addPopover?: (popoverData: IPopoverData) => void;
6
6
  removePopover?: (popoverId: string) => void;
7
7
  updatePopover?: (popoverId: string, popoverData: Partial<IPopoverData>) => void;
8
+ isPopoverOpen?: (popoverId: string) => boolean;
8
9
  popovers?: IPopoverData[];
9
10
  uiScale?: number;
10
11
  }>({});
@@ -12,6 +12,7 @@ export interface IReqoreContext {
12
12
  readonly isMobileOrTablet?: boolean;
13
13
  readonly getAndIncreaseZIndex?: () => number;
14
14
  readonly animations?: IReqoreOptions['animations'];
15
+ readonly closePopoversOnEscPress?: boolean;
15
16
  }
16
17
 
17
18
  export default createContext<IReqoreContext>({
@@ -23,4 +24,5 @@ export default createContext<IReqoreContext>({
23
24
  buttons: true,
24
25
  dialogs: true,
25
26
  },
27
+ closePopoversOnEscPress: true,
26
28
  });
@@ -1,5 +1,5 @@
1
- import { cloneDeep, merge } from 'lodash';
2
- import { darken, lighten, readableColor } from 'polished';
1
+ import { cloneDeep, merge, reduce } from 'lodash';
2
+ import { darken, getLuminance, lighten, mix, readableColor } from 'polished';
3
3
  import { TReqoreEffectColor, TReqoreEffectColorList, TReqoreHexColor } from '../components/Effect';
4
4
  import { Colors } from '../constants/colors';
5
5
  import { DEFAULT_INTENTS, IReqoreTheme, TReqoreIntent } from '../constants/theme';
@@ -46,9 +46,7 @@ export const percentToHexAlpha = (p: number) => {
46
46
  };
47
47
 
48
48
  export const shouldDarken = (mainColor: TReqoreHexColor): boolean => {
49
- const contrast = getColorByBgColor(mainColor);
50
-
51
- return contrast === '#000000';
49
+ return getLuminance(mainColor) > 0.2;
52
50
  };
53
51
 
54
52
  export const getMainColor: (theme: IReqoreTheme, component: string) => TReqoreHexColor = (
@@ -126,14 +124,14 @@ export const mergeThemes = (element: string, theme: IReqoreTheme, customTheme: a
126
124
  return clonedTheme;
127
125
  }
128
126
 
129
- if (element === 'main' && customTheme) {
127
+ if (element === 'main') {
130
128
  merge(clonedTheme, {
131
129
  main: customTheme.main,
132
130
  originalMain: clonedTheme.main,
133
131
  text: customTheme.text,
134
132
  });
135
133
  } else {
136
- merge(clonedTheme, { [element]: customTheme || {}, text: customTheme.text });
134
+ merge(clonedTheme, { [element]: customTheme, text: customTheme.text });
137
135
  }
138
136
 
139
137
  return clonedTheme;
@@ -191,3 +189,51 @@ export const getColorFromMaybeString = (
191
189
 
192
190
  return _color;
193
191
  };
192
+
193
+ export const createEffectGradient = (
194
+ theme: IReqoreTheme,
195
+ colors: Record<number, TReqoreEffectColor>,
196
+ lighten: number = 0,
197
+ minimal?: boolean
198
+ ): string => {
199
+ return reduce(
200
+ colors,
201
+ (colorsString, color, percentage) => {
202
+ return `${colorsString}, ${
203
+ minimal ? theme.main : changeLightness(getColorFromMaybeString(theme, color), lighten)
204
+ } ${percentage}%`;
205
+ },
206
+ ''
207
+ );
208
+ };
209
+
210
+ export const getNthGradientColor = (
211
+ theme: IReqoreTheme,
212
+ colors?: Record<number, TReqoreEffectColor>,
213
+ nth: number = 1
214
+ ): TReqoreHexColor | undefined => {
215
+ if (colors) {
216
+ return getColorFromMaybeString(theme, Object.values(colors)[nth - 1]);
217
+ }
218
+
219
+ return undefined;
220
+ };
221
+
222
+ export const getGradientMix = (
223
+ theme: IReqoreTheme,
224
+ colors: Record<number, TReqoreEffectColor>,
225
+ fallback?: TReqoreHexColor
226
+ ): TReqoreHexColor | undefined => {
227
+ if (colors && Object.keys(colors).length === 2) {
228
+ const gradientColor1: TReqoreHexColor = getNthGradientColor(theme, colors);
229
+ const gradientColor2: TReqoreHexColor = getNthGradientColor(theme, colors, 2);
230
+
231
+ return mix(
232
+ 0.5,
233
+ gradientColor1 === '#00000000' ? theme.main : gradientColor1,
234
+ gradientColor2 === '#00000000' ? theme.main : gradientColor2
235
+ ) as TReqoreHexColor;
236
+ }
237
+
238
+ return fallback;
239
+ };
@@ -2,7 +2,15 @@ import { Placement } from '@popperjs/core';
2
2
  import { MutableRefObject, useContext, useEffect, useMemo, useRef } from 'react';
3
3
  import { useUnmount, useUpdateEffect } from 'react-use';
4
4
  import shortid from 'shortid';
5
+ import { IPopoverData } from '../containers/PopoverProvider';
5
6
  import PopoverContext from '../context/PopoverContext';
7
+ import {
8
+ IReqoreIntent,
9
+ IWithReqoreEffect,
10
+ IWithReqoreFlat,
11
+ IWithReqoreMinimal,
12
+ } from '../types/global';
13
+ import { IReqoreIconName } from '../types/icons';
6
14
 
7
15
  const startEvents = {
8
16
  hover: 'mouseenter',
@@ -18,7 +26,18 @@ const endEvents = {
18
26
  focus: null,
19
27
  };
20
28
 
21
- export interface IPopover {
29
+ export interface IPopoverControls {
30
+ open: () => void;
31
+ close: () => void;
32
+ isOpen: () => boolean;
33
+ id: string;
34
+ }
35
+
36
+ export interface IPopover
37
+ extends IReqoreIntent,
38
+ IWithReqoreMinimal,
39
+ IWithReqoreEffect,
40
+ IWithReqoreFlat {
22
41
  content?: JSX.Element | string | undefined;
23
42
  handler?: 'hover' | 'click' | 'focus' | 'hoverStay';
24
43
  placement?: Placement;
@@ -30,13 +49,16 @@ export interface IPopover {
30
49
  closeOnAnyClick?: boolean;
31
50
  delay?: number;
32
51
  blur?: number;
33
- opaque?: boolean;
52
+ transparent?: boolean;
34
53
  maxWidth?: string;
35
54
  maxHeight?: string;
55
+ icon?: IReqoreIconName;
56
+ title?: string;
36
57
  }
37
58
 
38
59
  export interface IPopoverOptions extends IPopover {
39
60
  targetElement?: HTMLElement;
61
+ passPopoverData?: (data: IPopoverControls) => void;
40
62
  }
41
63
 
42
64
  const usePopover = ({
@@ -51,14 +73,15 @@ const usePopover = ({
51
73
  openOnMount = false,
52
74
  delay,
53
75
  ...rest
54
- }: IPopoverOptions) => {
55
- const { addPopover, removePopover, updatePopover, popovers } = useContext(PopoverContext);
76
+ }: IPopoverOptions): IPopoverControls => {
77
+ const { addPopover, removePopover, updatePopover, popovers, isPopoverOpen } =
78
+ useContext(PopoverContext);
56
79
  const { current }: MutableRefObject<string> = useRef(shortid.generate());
57
80
  let { current: timeout }: MutableRefObject<any> = useRef(0);
58
81
 
59
82
  const startEvent = startEvents[handler];
60
83
  const endEvent = endEvents[handler];
61
- const currentPopover = useMemo(
84
+ const currentPopover: IPopoverData = useMemo(
62
85
  () => popovers?.find((p) => p.id === current),
63
86
  [popovers, current]
64
87
  );
@@ -84,7 +107,7 @@ const usePopover = ({
84
107
 
85
108
  const _addPopover = () => {
86
109
  if (currentPopover) {
87
- if (handler !== 'hoverStay') {
110
+ if (handler !== 'hoverStay' && handler !== 'focus') {
88
111
  _removePopover?.();
89
112
  }
90
113
  } else if (show) {
@@ -99,11 +122,6 @@ const usePopover = ({
99
122
  };
100
123
 
101
124
  const _removePopover = () => {
102
- if (rest?.blur > 0) {
103
- targetElement.style.position = 'initial';
104
- targetElement.style.zIndex = 'initial';
105
- }
106
-
107
125
  cancelTimeout();
108
126
  removePopover?.(current);
109
127
  };
@@ -175,7 +193,16 @@ const usePopover = ({
175
193
  cancelTimeout();
176
194
  });
177
195
 
178
- return current;
196
+ return {
197
+ id: current,
198
+ open: () => {
199
+ if (!isPopoverOpen(current)) {
200
+ openPopover();
201
+ }
202
+ },
203
+ close: () => _removePopover(),
204
+ isOpen: () => isPopoverOpen(current),
205
+ };
179
206
  };
180
207
 
181
208
  export default usePopover;
@@ -0,0 +1,12 @@
1
+ import { useContext } from 'react';
2
+ import ReqoreContext, { IReqoreContext } from '../context/ReqoreContext';
3
+
4
+ export const useReqore = (): IReqoreContext => {
5
+ const reqore = useContext(ReqoreContext);
6
+
7
+ if (!reqore) {
8
+ throw new Error('Reqore context is not defined');
9
+ }
10
+
11
+ return reqore;
12
+ };
@@ -14,11 +14,16 @@ export interface IReqoreCustomTheme extends Partial<Omit<IReqoreTheme, 'main' |
14
14
  }
15
15
 
16
16
  export const useReqoreTheme = (
17
- element: string,
17
+ element?: string,
18
18
  customTheme: IReqoreCustomTheme = {},
19
19
  intent?: TReqoreIntent
20
20
  ) => {
21
21
  const theme: IReqoreTheme = useContext<IReqoreTheme>(ThemeContext);
22
+
23
+ if (!element) {
24
+ return theme;
25
+ }
26
+
22
27
  let _customTheme: IReqoreCustomTheme = cloneDeep(customTheme);
23
28
 
24
29
  if (_customTheme.main) {
package/src/index.tsx CHANGED
@@ -30,6 +30,7 @@ export { default as ReqoreMenuDivider } from './components/Menu/divider';
30
30
  export { default as ReqoreMenuItem } from './components/Menu/item';
31
31
  export { default as ReqoreMessage } from './components/Message';
32
32
  export { ReqoreModal } from './components/Modal';
33
+ export { ReqoreMultiSelect } from './components/MultiSelect';
33
34
  export { ReqoreFooter, ReqoreHeader } from './components/Navbar';
34
35
  export { default as ReqoreNavbarDivider } from './components/Navbar/divider';
35
36
  export { default as ReqoreNavbarGroup } from './components/Navbar/group';
@@ -58,3 +59,5 @@ export { default as ReqoreUIProvider } from './containers/UIProvider';
58
59
  export { default as ReqoreContext } from './context/ReqoreContext';
59
60
  export { default as ReqoreThemeContext } from './context/ThemeContext';
60
61
  export { default as useLatestZIndex } from './hooks/useLatestZIndex';
62
+ export { useReqore } from './hooks/useReqore';
63
+ export { useReqoreTheme } from './hooks/useTheme';
@@ -0,0 +1,61 @@
1
+ import { TReqoreMultiSelectItem } from '../components/MultiSelect';
2
+
3
+ export const MultiSelectItems: TReqoreMultiSelectItem[] = [
4
+ {
5
+ label: 'Existing item 1',
6
+ value: 'Existing item 1',
7
+ icon: 'SunCloudyLine',
8
+ },
9
+ {
10
+ label: 'Existing item 2',
11
+ value: 'Existing item 2',
12
+ icon: 'BatteryChargeFill',
13
+ },
14
+ {
15
+ label: 'Existing item 3',
16
+ value: 'Existing item 3',
17
+ icon: 'DropboxFill',
18
+ intent: 'info',
19
+ },
20
+ {
21
+ label: 'Existing item 4',
22
+ value: 'Existing item 4',
23
+ icon: 'PagesLine',
24
+ effect: { gradient: { colors: { 0: 'success', 100: 'info:darken:1' } } },
25
+ },
26
+ {
27
+ disabled: true,
28
+ label: 'Disabled item',
29
+ value: 'Disabled item',
30
+ icon: 'StopCircleLine',
31
+ },
32
+ {
33
+ minimal: true,
34
+ label: 'Minimal item',
35
+ value: 'Minimal item',
36
+ icon: 'StopCircleLine',
37
+ },
38
+ {
39
+ divider: true,
40
+ icon: 'CheckDoubleLine',
41
+ },
42
+ {
43
+ value: 'itemWithNoLabel',
44
+ icon: 'TakeawayLine',
45
+ },
46
+ {
47
+ label: 'Other Item 1',
48
+ value: 'Other Item 1',
49
+ icon: 'MapFill',
50
+ },
51
+ {
52
+ label: 'Other Item 2',
53
+ value: 'Other Item 2',
54
+ icon: 'ArrowLeftUpFill',
55
+ },
56
+ {
57
+ label: 'Other Item 3',
58
+ value: 'Other Item 3',
59
+ icon: 'MicLine',
60
+ },
61
+ ];
@@ -32,17 +32,29 @@ const Template: ComponentStory<typeof ReqoreButton> = (buttonProps) => {
32
32
  <ReqoreButton {...buttonProps} active tooltip='hello'>
33
33
  Active
34
34
  </ReqoreButton>
35
+ <ReqoreButton {...buttonProps} minimal flat>
36
+ Minimal
37
+ </ReqoreButton>
38
+ <ReqoreButton {...buttonProps} readOnly onClick={alert}>
39
+ Read only
40
+ </ReqoreButton>
41
+ </ReqoreControlGroup>
42
+ <br />
43
+ <ReqoreControlGroup size={buttonProps.size}>
44
+ <ReqoreButton {...buttonProps} active flat={false} tooltip='hello'>
45
+ Active Not Flat
46
+ </ReqoreButton>
35
47
  <ReqoreButton {...buttonProps} flat={false}>
36
48
  Not Flat
37
49
  </ReqoreButton>
38
- <ReqoreButton {...buttonProps} minimal>
39
- Minimal
50
+ <ReqoreButton {...buttonProps} minimal flat={false}>
51
+ Minimal not flat
40
52
  </ReqoreButton>
41
- <ReqoreButton {...buttonProps} minimal flat>
42
- Minimal flat
53
+ <ReqoreButton {...buttonProps} readOnly onClick={alert} flat={false}>
54
+ Read only not flat
43
55
  </ReqoreButton>
44
- <ReqoreButton {...buttonProps} readOnly onClick={alert}>
45
- Read only
56
+ <ReqoreButton {...buttonProps} disabled flat={false}>
57
+ Disabled not flat
46
58
  </ReqoreButton>
47
59
  </ReqoreControlGroup>
48
60
  <br />
@@ -98,10 +110,10 @@ const Template: ComponentStory<typeof ReqoreButton> = (buttonProps) => {
98
110
  <br />
99
111
  <ReqoreControlGroup>
100
112
  <ReqoreButton {...buttonProps} readOnly badge={10} onClick={alert}>
101
- With Badge
113
+ Read only with badge
102
114
  </ReqoreButton>
103
115
  <ReqoreButton {...buttonProps} minimal badge={20} onClick={alert}>
104
- With Badge
116
+ Minimal with badge
105
117
  </ReqoreButton>
106
118
  <ReqoreButton
107
119
  {...buttonProps}