@qoretechnologies/reqore 0.31.2 → 0.32.2

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 (183) hide show
  1. package/.github/workflows/tests.yml +3 -1
  2. package/__tests__/breadcrumbs.test.tsx +46 -28
  3. package/__tests__/button.test.tsx +18 -0
  4. package/__tests__/checkbox.test.tsx +19 -1
  5. package/__tests__/collection.test.tsx +14 -1
  6. package/__tests__/icon.test.tsx +19 -1
  7. package/__tests__/input.test.tsx +435 -24
  8. package/__tests__/messages.test.tsx +16 -0
  9. package/__tests__/modal.test.tsx +4 -4
  10. package/__tests__/multiselect.test.tsx +8 -10
  11. package/__tests__/notifications.test.tsx +6 -6
  12. package/__tests__/panel.test.tsx +19 -1
  13. package/__tests__/textarea.test.tsx +423 -24
  14. package/__tests__/tree.test.tsx +3 -1
  15. package/dist/components/Breadcrumbs/item.d.ts.map +1 -1
  16. package/dist/components/Breadcrumbs/item.js +6 -2
  17. package/dist/components/Breadcrumbs/item.js.map +1 -1
  18. package/dist/components/Button/index.d.ts.map +1 -1
  19. package/dist/components/Button/index.js +18 -4
  20. package/dist/components/Button/index.js.map +1 -1
  21. package/dist/components/Checkbox/index.d.ts.map +1 -1
  22. package/dist/components/Checkbox/index.js +8 -4
  23. package/dist/components/Checkbox/index.js.map +1 -1
  24. package/dist/components/Collection/index.d.ts +4 -2
  25. package/dist/components/Collection/index.d.ts.map +1 -1
  26. package/dist/components/Collection/index.js +19 -13
  27. package/dist/components/Collection/index.js.map +1 -1
  28. package/dist/components/Collection/item.js +2 -2
  29. package/dist/components/Collection/item.js.map +1 -1
  30. package/dist/components/Comment/index.d.ts +0 -1
  31. package/dist/components/Comment/index.d.ts.map +1 -1
  32. package/dist/components/ControlGroup/index.d.ts.map +1 -1
  33. package/dist/components/ControlGroup/index.js +18 -57
  34. package/dist/components/ControlGroup/index.js.map +1 -1
  35. package/dist/components/Drawer/index.d.ts +1 -1
  36. package/dist/components/Drawer/index.d.ts.map +1 -1
  37. package/dist/components/Drawer/index.js +1 -1
  38. package/dist/components/Drawer/index.js.map +1 -1
  39. package/dist/components/Dropdown/item.d.ts +0 -1
  40. package/dist/components/Dropdown/item.d.ts.map +1 -1
  41. package/dist/components/Icon/index.d.ts +2 -0
  42. package/dist/components/Icon/index.d.ts.map +1 -1
  43. package/dist/components/Icon/index.js +17 -8
  44. package/dist/components/Icon/index.js.map +1 -1
  45. package/dist/components/Input/index.d.ts +4 -0
  46. package/dist/components/Input/index.d.ts.map +1 -1
  47. package/dist/components/Input/index.js +19 -7
  48. package/dist/components/Input/index.js.map +1 -1
  49. package/dist/components/InputClearButton/index.d.ts +1 -1
  50. package/dist/components/InputClearButton/index.d.ts.map +1 -1
  51. package/dist/components/InputClearButton/index.js +18 -8
  52. package/dist/components/InputClearButton/index.js.map +1 -1
  53. package/dist/components/InternalPopover/index.d.ts.map +1 -1
  54. package/dist/components/InternalPopover/index.js +2 -1
  55. package/dist/components/InternalPopover/index.js.map +1 -1
  56. package/dist/components/Menu/item.d.ts +1 -1
  57. package/dist/components/Menu/item.d.ts.map +1 -1
  58. package/dist/components/Menu/item.js +3 -6
  59. package/dist/components/Menu/item.js.map +1 -1
  60. package/dist/components/Message/index.d.ts.map +1 -1
  61. package/dist/components/Message/index.js +6 -2
  62. package/dist/components/Message/index.js.map +1 -1
  63. package/dist/components/Modal/index.d.ts +0 -1
  64. package/dist/components/Modal/index.d.ts.map +1 -1
  65. package/dist/components/Panel/index.d.ts +1 -0
  66. package/dist/components/Panel/index.d.ts.map +1 -1
  67. package/dist/components/Panel/index.js +18 -9
  68. package/dist/components/Panel/index.js.map +1 -1
  69. package/dist/components/Panel/panel.screenshot.d.ts +0 -1
  70. package/dist/components/Panel/panel.screenshot.d.ts.map +1 -1
  71. package/dist/components/Sidebar/item.d.ts +0 -1
  72. package/dist/components/Sidebar/item.d.ts.map +1 -1
  73. package/dist/components/Sidebar/item.js +1 -3
  74. package/dist/components/Sidebar/item.js.map +1 -1
  75. package/dist/components/Spinner/index.d.ts +0 -1
  76. package/dist/components/Spinner/index.d.ts.map +1 -1
  77. package/dist/components/Table/header.d.ts +0 -1
  78. package/dist/components/Table/header.d.ts.map +1 -1
  79. package/dist/components/Tag/index.d.ts.map +1 -1
  80. package/dist/components/Tag/index.js +7 -4
  81. package/dist/components/Tag/index.js.map +1 -1
  82. package/dist/components/Textarea/index.d.ts +2 -0
  83. package/dist/components/Textarea/index.d.ts.map +1 -1
  84. package/dist/components/Textarea/index.js +9 -6
  85. package/dist/components/Textarea/index.js.map +1 -1
  86. package/dist/components/Tree/index.d.ts +0 -1
  87. package/dist/components/Tree/index.d.ts.map +1 -1
  88. package/dist/components/Tree/index.js +2 -4
  89. package/dist/components/Tree/index.js.map +1 -1
  90. package/dist/containers/PopoverProvider.d.ts.map +1 -1
  91. package/dist/containers/PopoverProvider.js +2 -2
  92. package/dist/containers/PopoverProvider.js.map +1 -1
  93. package/dist/containers/ReqoreProvider.d.ts.map +1 -1
  94. package/dist/containers/ReqoreProvider.js +4 -0
  95. package/dist/containers/ReqoreProvider.js.map +1 -1
  96. package/dist/containers/ThemeProvider.d.ts +1 -2
  97. package/dist/containers/ThemeProvider.d.ts.map +1 -1
  98. package/dist/containers/ThemeProvider.js +3 -3
  99. package/dist/containers/ThemeProvider.js.map +1 -1
  100. package/dist/context/PopoverContext.d.ts +1 -2
  101. package/dist/context/PopoverContext.d.ts.map +1 -1
  102. package/dist/context/PopoverContext.js +2 -2
  103. package/dist/context/PopoverContext.js.map +1 -1
  104. package/dist/context/ReqoreContext.d.ts +3 -2
  105. package/dist/context/ReqoreContext.d.ts.map +1 -1
  106. package/dist/context/ReqoreContext.js +5 -3
  107. package/dist/context/ReqoreContext.js.map +1 -1
  108. package/dist/context/ThemeContext.d.ts +1 -2
  109. package/dist/context/ThemeContext.d.ts.map +1 -1
  110. package/dist/context/ThemeContext.js +2 -2
  111. package/dist/context/ThemeContext.js.map +1 -1
  112. package/dist/hooks/useAutoFocus.d.ts +11 -0
  113. package/dist/hooks/useAutoFocus.d.ts.map +1 -0
  114. package/dist/hooks/useAutoFocus.js +80 -0
  115. package/dist/hooks/useAutoFocus.js.map +1 -0
  116. package/dist/hooks/useLatestZIndex.d.ts.map +1 -1
  117. package/dist/hooks/useLatestZIndex.js +3 -2
  118. package/dist/hooks/useLatestZIndex.js.map +1 -1
  119. package/dist/hooks/usePopover.d.ts +0 -1
  120. package/dist/hooks/usePopover.d.ts.map +1 -1
  121. package/dist/hooks/usePopover.js +4 -3
  122. package/dist/hooks/usePopover.js.map +1 -1
  123. package/dist/hooks/useReqore.js +2 -2
  124. package/dist/hooks/useReqore.js.map +1 -1
  125. package/dist/hooks/useReqoreContext.d.ts +3 -0
  126. package/dist/hooks/useReqoreContext.d.ts.map +1 -0
  127. package/dist/hooks/useReqoreContext.js +19 -0
  128. package/dist/hooks/useReqoreContext.js.map +1 -0
  129. package/dist/hooks/useReqoreEffect.js +2 -5
  130. package/dist/hooks/useReqoreEffect.js.map +1 -1
  131. package/dist/hooks/useTheme.d.ts.map +1 -1
  132. package/dist/hooks/useTheme.js +20 -20
  133. package/dist/hooks/useTheme.js.map +1 -1
  134. package/dist/index.d.ts +1 -0
  135. package/dist/index.d.ts.map +1 -1
  136. package/dist/index.js +3 -1
  137. package/dist/index.js.map +1 -1
  138. package/dist/styles.d.ts.map +1 -1
  139. package/dist/styles.js +1 -1
  140. package/dist/styles.js.map +1 -1
  141. package/package.json +20 -16
  142. package/src/components/Breadcrumbs/item.tsx +7 -3
  143. package/src/components/Button/index.tsx +26 -7
  144. package/src/components/Checkbox/index.tsx +9 -5
  145. package/src/components/Collection/index.tsx +33 -11
  146. package/src/components/Collection/item.tsx +3 -3
  147. package/src/components/ControlGroup/index.tsx +26 -87
  148. package/src/components/Drawer/index.tsx +4 -4
  149. package/src/components/Icon/index.tsx +27 -9
  150. package/src/components/Input/index.tsx +35 -4
  151. package/src/components/InputClearButton/index.tsx +41 -17
  152. package/src/components/InternalPopover/index.tsx +2 -1
  153. package/src/components/Menu/item.tsx +6 -9
  154. package/src/components/Message/index.tsx +6 -2
  155. package/src/components/Panel/index.tsx +26 -9
  156. package/src/components/Sidebar/item.tsx +2 -4
  157. package/src/components/Tag/index.tsx +9 -6
  158. package/src/components/Textarea/index.tsx +16 -11
  159. package/src/components/Tree/index.tsx +5 -8
  160. package/src/containers/PopoverProvider.tsx +2 -2
  161. package/src/containers/ReqoreProvider.tsx +5 -1
  162. package/src/containers/ThemeProvider.tsx +3 -13
  163. package/src/context/PopoverContext.tsx +1 -1
  164. package/src/context/ReqoreContext.tsx +4 -1
  165. package/src/context/ThemeContext.tsx +1 -1
  166. package/src/hooks/useAutoFocus.ts +104 -0
  167. package/src/hooks/useLatestZIndex.ts +5 -3
  168. package/src/hooks/usePopover.tsx +4 -3
  169. package/src/hooks/useReqore.ts +1 -1
  170. package/src/hooks/useReqoreContext.ts +16 -0
  171. package/src/hooks/useReqoreEffect.ts +3 -3
  172. package/src/hooks/useTheme.ts +21 -17
  173. package/src/index.tsx +1 -0
  174. package/src/stories/Button/Button.stories.tsx +7 -0
  175. package/src/stories/Collection/Collection.stories.tsx +56 -9
  176. package/src/stories/Drawer/Drawer.stories.tsx +4 -3
  177. package/src/stories/Input/Input.stories.tsx +29 -6
  178. package/src/stories/Modal/Modal.stories.tsx +3 -4
  179. package/src/stories/Notifications/Interactive.stories.tsx +3 -4
  180. package/src/stories/Panel/Panel.stories.tsx +4 -2
  181. package/src/stories/TextArea/TextArea.stories.tsx +1 -0
  182. package/src/styles.ts +0 -1
  183. package/tests.json +1 -1
@@ -1,12 +1,5 @@
1
1
  import { debounce } from 'lodash';
2
- import React, {
3
- memo,
4
- useCallback,
5
- useEffect,
6
- useMemo,
7
- useRef,
8
- useState,
9
- } from 'react';
2
+ import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
10
3
  import { useMount, useUnmount } from 'react-use';
11
4
  import styled, { css } from 'styled-components';
12
5
  import { ReqoreButton, ReqoreDrawer } from '../..';
@@ -63,16 +56,13 @@ export interface IReqoreControlGroupStyle extends IReqoreControlGroupProps {
63
56
 
64
57
  export const StyledReqoreControlGroup = styled.div<IReqoreControlGroupStyle>`
65
58
  display: flex;
66
- flex: ${({ fluid, fixed }) =>
67
- fixed ? '0 0 auto' : fluid ? undefined : '0 0 auto'};
59
+ flex: ${({ fluid, fixed }) => (fixed ? '0 0 auto' : fluid ? undefined : '0 0 auto')};
68
60
  width: ${({ fluid, fixed }) => (fluid && !fixed ? '100%' : undefined)};
69
- justify-content: ${({ fluid, vertical }) =>
70
- vertical && fluid ? 'stretch' : undefined};
61
+ justify-content: ${({ fluid, vertical }) => (vertical && fluid ? 'stretch' : undefined)};
71
62
  align-items: ${({ vertical, fluid, horizontalAlign }) =>
72
63
  vertical ? (fluid ? 'stretch' : horizontalAlign) : undefined};
73
64
  flex-flow: ${({ vertical }) => (vertical ? 'column' : 'row')};
74
- gap: ${({ gapSize, stack }) =>
75
- !stack ? `${GAP_FROM_SIZE[gapSize]}px` : undefined};
65
+ gap: ${({ gapSize, stack }) => (!stack ? `${GAP_FROM_SIZE[gapSize]}px` : undefined)};
76
66
  flex-wrap: ${({ wrap }) => (wrap ? 'wrap' : 'nowrap')};
77
67
 
78
68
  // If the group has the fill prop,
@@ -95,23 +85,16 @@ export const StyledReqoreControlGroup = styled.div<IReqoreControlGroupStyle>`
95
85
 
96
86
  > * {
97
87
  margin-top: ${({ fill, verticalAlign }) =>
98
- !fill && (verticalAlign === 'flex-end' || verticalAlign === 'center')
99
- ? 'auto'
100
- : undefined};
88
+ !fill && (verticalAlign === 'flex-end' || verticalAlign === 'center') ? 'auto' : undefined};
101
89
  margin-bottom: ${({ fill, verticalAlign }) =>
102
- !fill && (verticalAlign === 'flex-start' || verticalAlign === 'center')
103
- ? 'auto'
104
- : undefined};
105
- margin-right: ${({ horizontalAlign }) =>
106
- horizontalAlign === 'center' ? 'auto' : undefined};
90
+ !fill && (verticalAlign === 'flex-start' || verticalAlign === 'center') ? 'auto' : undefined};
91
+ margin-right: ${({ horizontalAlign }) => (horizontalAlign === 'center' ? 'auto' : undefined)};
107
92
 
108
93
  ${({ vertical }) =>
109
94
  vertical &&
110
95
  css`
111
96
  margin-left: ${({ horizontalAlign }) =>
112
- horizontalAlign === 'flex-end' || horizontalAlign === 'center'
113
- ? 'auto'
114
- : undefined};
97
+ horizontalAlign === 'flex-end' || horizontalAlign === 'center' ? 'auto' : undefined};
115
98
  `}
116
99
  }
117
100
 
@@ -120,9 +103,7 @@ export const StyledReqoreControlGroup = styled.div<IReqoreControlGroupStyle>`
120
103
  css`
121
104
  > *:first-child {
122
105
  margin-left: ${({ horizontalAlign }) =>
123
- horizontalAlign === 'flex-end' || horizontalAlign === 'center'
124
- ? 'auto'
125
- : undefined};
106
+ horizontalAlign === 'flex-end' || horizontalAlign === 'center' ? 'auto' : undefined};
126
107
  }
127
108
  `}
128
109
 
@@ -168,12 +149,9 @@ const ReqoreControlGroup = memo(
168
149
  const isStack = stack || isInsideStackGroup;
169
150
  const isVertical = vertical || isInsideVerticalGroup;
170
151
 
171
- const [overflowingChildren, setOverflowingChildren] = useState<
172
- number | undefined
173
- >(0);
152
+ const [overflowingChildren, setOverflowingChildren] = useState<number | undefined>(0);
174
153
  const [lastReSize, setLastReSize] = useState<number>(0);
175
- const [isOverflownDialogOpen, setIsOverflownDialogOpen] =
176
- useState<boolean>(false);
154
+ const [isOverflownDialogOpen, setIsOverflownDialogOpen] = useState<boolean>(false);
177
155
  const observer = useRef<ResizeObserver | null>(null);
178
156
  const ref = useRef<HTMLDivElement>(null);
179
157
 
@@ -232,10 +210,7 @@ const ReqoreControlGroup = memo(
232
210
 
233
211
  useEffect(() => {
234
212
  // Is the control group still overflowing?
235
- if (
236
- (overflowingChildren || overflowingChildren === 0) &&
237
- checkIfOverflowing()
238
- ) {
213
+ if ((overflowingChildren || overflowingChildren === 0) && checkIfOverflowing()) {
239
214
  setOverflowingChildren(overflowingChildren + 1);
240
215
  }
241
216
 
@@ -258,33 +233,22 @@ const ReqoreControlGroup = memo(
258
233
  const getIsLastInFirstGroup = (index: number): boolean => {
259
234
  return !isInsideStackGroup
260
235
  ? index === 0
261
- : isFirstGroup &&
262
- (isLast || isLast !== false) &&
263
- index === realChildCount - 1;
236
+ : isFirstGroup && (isLast || isLast !== false) && index === realChildCount - 1;
264
237
  };
265
238
  const getIsFirstInLastGroup = (index: number): boolean => {
266
239
  return !isInsideStackGroup
267
240
  ? index === realChildCount - 1
268
- : isLastGroup &&
269
- (isFirst || isFirst !== false) &&
270
- childId === 1 &&
271
- index === 0;
241
+ : isLastGroup && (isFirst || isFirst !== false) && childId === 1 && index === 0;
272
242
  };
273
243
  const getIsLastInLastGroup = (index: number): boolean => {
274
244
  return !isInsideStackGroup
275
245
  ? index === realChildCount - 1
276
- : isLastGroup &&
277
- (isLast || isLast !== false) &&
278
- index === realChildCount - 1;
246
+ : isLastGroup && (isLast || isLast !== false) && index === realChildCount - 1;
279
247
  };
280
248
 
281
249
  const getBorderTopLeftRadius = (index: number): number | undefined => {
282
250
  const _isFirstGroup =
283
- !isInsideStackGroup || childrenCount === 1
284
- ? true
285
- : isChild
286
- ? isFirstGroup
287
- : index === 0;
251
+ !isInsideStackGroup || childrenCount === 1 ? true : isChild ? isFirstGroup : index === 0;
288
252
 
289
253
  // If this is the first item
290
254
  if (_isFirstGroup && getIsFirst(index)) {
@@ -324,11 +288,7 @@ const ReqoreControlGroup = memo(
324
288
  // If this group is not vertical we need to style the very first item
325
289
  if (!isVertical || !isStack) {
326
290
  const _isFirstGroup =
327
- !isInsideStackGroup || childrenCount === 1
328
- ? true
329
- : isChild
330
- ? isFirstGroup
331
- : index === 0;
291
+ !isInsideStackGroup || childrenCount === 1 ? true : isChild ? isFirstGroup : index === 0;
332
292
 
333
293
  if (_isFirstGroup && getIsFirst(index)) {
334
294
  return RADIUS_FROM_SIZE[size];
@@ -369,38 +329,23 @@ const ReqoreControlGroup = memo(
369
329
  return React.Children.map(children, (child) => {
370
330
  if (child && React.isValidElement(child)) {
371
331
  if (child.type === React.Fragment) {
372
- // just compare to `React.Fragment`
373
332
  return cloneThroughFragments(child.props.children);
374
333
  }
375
334
 
376
335
  let newProps = {
377
336
  ...child.props,
378
- key: index,
337
+ key: child.props.reactKey || child.props.key || index,
379
338
  minimal:
380
339
  child.props?.minimal || child.props?.minimal === false
381
340
  ? child.props.minimal
382
341
  : minimal,
383
342
  size: child.props?.size || size,
384
- flat:
385
- child.props?.flat || child.props?.flat === false
386
- ? child.props.flat
387
- : flat,
388
- fluid:
389
- child.props?.fluid || child.props?.fluid === false
390
- ? child.props.fluid
391
- : fluid,
392
- fixed:
393
- child.props?.fixed || child.props?.fixed === false
394
- ? child.props.fixed
395
- : fixed,
396
- fill:
397
- child.props?.fill || child.props?.fill === false
398
- ? child.props.fill
399
- : fill,
343
+ flat: child.props?.flat || child.props?.flat === false ? child.props.flat : flat,
344
+ fluid: child.props?.fluid || child.props?.fluid === false ? child.props.fluid : fluid,
345
+ fixed: child.props?.fixed || child.props?.fixed === false ? child.props.fixed : fixed,
346
+ fill: child.props?.fill || child.props?.fill === false ? child.props.fill : fill,
400
347
  stack:
401
- child.props?.stack || child.props?.stack === false
402
- ? child.props.stack
403
- : isStack,
348
+ child.props?.stack || child.props?.stack === false ? child.props.stack : isStack,
404
349
  intent: child.props?.intent || intent,
405
350
  customTheme: child.props?.customTheme || customTheme,
406
351
  };
@@ -428,9 +373,7 @@ const ReqoreControlGroup = memo(
428
373
  childId: index + 1,
429
374
 
430
375
  isFirstGroup: isChild ? isFirstGroup : index === 0,
431
- isLastGroup: isChild
432
- ? isLastGroup
433
- : index === realChildCount - 1,
376
+ isLastGroup: isChild ? isLastGroup : index === realChildCount - 1,
434
377
  };
435
378
  }
436
379
 
@@ -469,9 +412,7 @@ const ReqoreControlGroup = memo(
469
412
  // Get the overflown children
470
413
  const overflownChildren = useMemo(
471
414
  () =>
472
- overflowingChildren
473
- ? React.Children.toArray(children).slice(0, overflowingChildren)
474
- : [],
415
+ overflowingChildren ? React.Children.toArray(children).slice(0, overflowingChildren) : [],
475
416
  [children, overflowingChildren]
476
417
  );
477
418
 
@@ -485,9 +426,7 @@ const ReqoreControlGroup = memo(
485
426
  icon='MenuLine'
486
427
  customTheme={customTheme}
487
428
  tooltip={{
488
- content: `Show ${React.Children.count(
489
- overflownChildren
490
- )} hidden items`,
429
+ content: `Show ${React.Children.count(overflownChildren)} hidden items`,
491
430
  }}
492
431
  fixed
493
432
  active={isOverflownDialogOpen}
@@ -1,10 +1,10 @@
1
1
  import { animated, useTransition } from '@react-spring/web';
2
2
  import { rgba } from 'polished';
3
3
  import { Resizable } from 're-resizable';
4
- import { useContext, useEffect, useMemo, useState } from 'react';
4
+ import { useEffect, useMemo, useState } from 'react';
5
5
  import { createPortal } from 'react-dom';
6
6
  import styled, { css } from 'styled-components';
7
- import { ReqoreContext } from '../..';
7
+ import { useReqoreProperty } from '../..';
8
8
  import { SPRING_CONFIG, SPRING_CONFIG_NO_ANIMATIONS } from '../../constants/animations';
9
9
  import { IReqoreTheme } from '../../constants/theme';
10
10
  import ReqoreThemeProvider from '../../containers/ThemeProvider';
@@ -147,7 +147,7 @@ const getSpringConfig = (isModal?: boolean, position?: TPosition, floating?: boo
147
147
  leave: { opacity: 0, [position]: '-80px' },
148
148
  };
149
149
 
150
- export const ReqoreDrawer = ({
150
+ export const ReqoreDrawer: React.FC<IReqoreDrawerProps> = ({
151
151
  children,
152
152
  isOpen,
153
153
  isHidden,
@@ -173,7 +173,7 @@ export const ReqoreDrawer = ({
173
173
  actions = [],
174
174
  ...rest
175
175
  }: IReqoreDrawerProps) => {
176
- const { animations } = useContext(ReqoreContext);
176
+ const animations = useReqoreProperty('animations');
177
177
  const theme = useReqoreTheme('main', customTheme, intent);
178
178
  const layout = useMemo(
179
179
  () =>
@@ -1,9 +1,9 @@
1
- import React, { forwardRef, memo, useContext } from 'react';
1
+ import React, { forwardRef, memo } from 'react';
2
2
  import { IconContext } from 'react-icons';
3
3
  import { IconBaseProps, IconType } from 'react-icons/lib';
4
4
  import * as RemixIcons from 'react-icons/ri';
5
5
  import styled, { css, keyframes } from 'styled-components';
6
- import { ReqoreThemeContext } from '../..';
6
+ import { useReqoreTheme } from '../..';
7
7
  import { ICON_FROM_SIZE, PADDING_FROM_SIZE, TSizes } from '../../constants/sizes';
8
8
  import { getColorFromMaybeString } from '../../helpers/colors';
9
9
  import { isStringSize } from '../../helpers/utils';
@@ -21,6 +21,8 @@ export interface IReqoreIconProps
21
21
  icon?: IReqoreIconName;
22
22
  color?: TReqoreEffectColor;
23
23
  size?: TSizes | string;
24
+ wrapperSize?: TSizes | string;
25
+ wrapperElement?: any;
24
26
  iconProps?: IconBaseProps;
25
27
  margin?: 'right' | 'left' | 'both';
26
28
  image?: string;
@@ -38,8 +40,10 @@ const SpinKeyframes = keyframes`
38
40
  `;
39
41
 
40
42
  export const StyledIconWrapper = styled(StyledEffect)<{ margin: 'right' | 'left' | 'both' }>`
41
- display: inline-block;
43
+ display: inline-flex;
42
44
  flex: 0 0 auto;
45
+ justify-content: center;
46
+ align-items: center;
43
47
  vertical-align: text-bottom;
44
48
  transition: all 0.2s ease-out;
45
49
  overflow: hidden;
@@ -78,6 +82,8 @@ const ReqoreIcon = memo(
78
82
  {
79
83
  icon,
80
84
  size = 'normal',
85
+ wrapperSize,
86
+ wrapperElement,
81
87
  className,
82
88
  color,
83
89
  margin,
@@ -91,24 +97,31 @@ const ReqoreIcon = memo(
91
97
  ref
92
98
  ) => {
93
99
  const { targetRef } = useCombinedRefs(ref);
94
- const theme = useContext(ReqoreThemeContext);
100
+ const [iconRef, setIconRef] = React.useState<HTMLSpanElement>(undefined);
101
+ const theme = useReqoreTheme();
95
102
  const Icon: IconType = RemixIcons[`Ri${icon}`];
96
103
  const finalColor: string | undefined = intent
97
104
  ? theme.intents[intent]
98
105
  : getColorFromMaybeString(theme, color);
99
106
  const finalSize: string = isStringSize(size) ? ICON_FROM_SIZE[size] : size;
107
+ const finalWrapperSize: string = wrapperSize
108
+ ? isStringSize(wrapperSize)
109
+ ? ICON_FROM_SIZE[wrapperSize]
110
+ : wrapperSize
111
+ : finalSize;
100
112
 
101
- useTooltip(targetRef.current, tooltip);
113
+ useTooltip(iconRef, tooltip);
102
114
 
103
115
  if (image) {
104
116
  return (
105
117
  <StyledIconWrapper
106
118
  {...rest}
119
+ as={wrapperElement}
107
120
  ref={targetRef}
108
121
  size={size}
109
122
  margin={margin}
110
123
  className={`${className || ''} reqore-icon`}
111
- style={{ ...style, width: finalSize, height: finalSize }}
124
+ style={{ width: finalWrapperSize, height: finalWrapperSize, ...style }}
112
125
  >
113
126
  <img src={image} alt='' />
114
127
  </StyledIconWrapper>
@@ -119,11 +132,12 @@ const ReqoreIcon = memo(
119
132
  return (
120
133
  <StyledIconWrapper
121
134
  {...rest}
135
+ as={wrapperElement}
122
136
  ref={targetRef}
123
137
  size={size}
124
138
  margin={margin}
125
139
  className={`${className || ''} reqore-icon`}
126
- style={{ ...style, width: finalSize, height: finalSize }}
140
+ style={{ width: finalWrapperSize, height: finalWrapperSize, ...style }}
127
141
  />
128
142
  );
129
143
  }
@@ -131,10 +145,14 @@ const ReqoreIcon = memo(
131
145
  return (
132
146
  <StyledIconWrapper
133
147
  {...rest}
134
- ref={targetRef}
148
+ as={wrapperElement}
149
+ ref={(ref) => {
150
+ targetRef.current = ref;
151
+ setIconRef(ref);
152
+ }}
135
153
  margin={margin}
136
154
  size={size}
137
- style={{ ...style, width: finalSize, height: finalSize }}
155
+ style={{ width: finalWrapperSize, height: finalWrapperSize, ...style }}
138
156
  className={`${className || ''} reqore-icon`}
139
157
  >
140
158
  <IconContext.Provider
@@ -1,5 +1,5 @@
1
1
  import { rgba } from 'polished';
2
- import React, { forwardRef } from 'react';
2
+ import React, { forwardRef, useState } from 'react';
3
3
  import styled, { css } from 'styled-components';
4
4
  import {
5
5
  PADDING_FROM_SIZE,
@@ -10,6 +10,7 @@ import {
10
10
  } from '../../constants/sizes';
11
11
  import { IReqoreTheme } from '../../constants/theme';
12
12
  import { changeLightness, getReadableColor } from '../../helpers/colors';
13
+ import { IReqoreAutoFocusRules, useAutoFocus } from '../../hooks/useAutoFocus';
13
14
  import { useCombinedRefs } from '../../hooks/useCombinedRefs';
14
15
  import { useReqoreTheme } from '../../hooks/useTheme';
15
16
  import { useTooltip } from '../../hooks/useTooltip';
@@ -44,11 +45,14 @@ export interface IReqoreInputProps
44
45
  onClearClick?: () => void;
45
46
  maxLength?: number;
46
47
  icon?: IReqoreIconName;
48
+ rightIcon?: IReqoreIconName;
47
49
  flat?: boolean;
48
50
  rounded?: boolean;
49
51
  type?: 'text' | 'password' | 'email' | 'number' | 'tel' | 'url';
50
52
  wrapperStyle?: React.CSSProperties;
51
53
  iconColor?: TReqoreEffectColor;
54
+ rightIconColor?: TReqoreEffectColor;
55
+ focusRules?: IReqoreAutoFocusRules;
52
56
  }
53
57
 
54
58
  export interface IReqoreInputStyle extends IReqoreInputProps {
@@ -76,6 +80,8 @@ const StyledIconWrapper = styled.div<IReqoreInputStyle>`
76
80
  position: absolute;
77
81
  height: ${({ _size }) => SIZE_TO_PX[_size]}px;
78
82
  width: ${({ _size }) => SIZE_TO_PX[_size]}px;
83
+ right: ${({ position }) => (position === 'right' ? 0 : undefined)};
84
+ top: 0;
79
85
  display: flex;
80
86
  justify-content: center;
81
87
  align-items: center;
@@ -87,7 +93,18 @@ export const StyledInput = styled(StyledEffect)<IReqoreInputStyle>`
87
93
  flex: 1;
88
94
  margin: 0;
89
95
  padding: ${({ _size }) => PADDING_FROM_SIZE[_size] / 2}px 7px;
90
- padding-right: ${({ clearable, _size }) => (clearable ? SIZE_TO_PX[_size] : 7)}px;
96
+ padding-right: ${({ clearable, hasRightIcon, _size }) => {
97
+ let padding = 7;
98
+
99
+ if (clearable || hasRightIcon) {
100
+ padding = 0;
101
+ padding += clearable ? SIZE_TO_PX[_size] : 0;
102
+ padding += hasRightIcon ? SIZE_TO_PX[_size] : 0;
103
+ }
104
+
105
+ return padding;
106
+ }}px;
107
+
91
108
  padding-left: ${({ hasIcon, _size }) => (hasIcon ? SIZE_TO_PX[_size] : 7)}px;
92
109
  font-size: ${({ _size }) => TEXT_FROM_SIZE[_size]}px;
93
110
  transition: all 0.2s ease-out;
@@ -154,7 +171,9 @@ const ReqoreInput = forwardRef<HTMLDivElement, IReqoreInputProps>(
154
171
  className,
155
172
  onClearClick,
156
173
  icon,
174
+ rightIcon,
157
175
  iconColor,
176
+ rightIconColor,
158
177
  flat,
159
178
  rounded = true,
160
179
  minimal,
@@ -163,14 +182,17 @@ const ReqoreInput = forwardRef<HTMLDivElement, IReqoreInputProps>(
163
182
  customTheme,
164
183
  intent,
165
184
  wrapperStyle,
185
+ focusRules,
166
186
  ...rest
167
187
  }: IReqoreInputProps,
168
188
  ref
169
189
  ) => {
170
190
  const { targetRef } = useCombinedRefs(ref);
191
+ const [inputRef, setInputRef] = useState<HTMLInputElement>(null);
171
192
  const theme = useReqoreTheme('main', customTheme, intent);
172
193
 
173
- useTooltip(targetRef.current, tooltip);
194
+ useTooltip(inputRef, tooltip);
195
+ useAutoFocus(inputRef, readOnly || rest.disabled ? undefined : focusRules, rest.onChange);
174
196
 
175
197
  return (
176
198
  <StyledInputWrapper
@@ -199,23 +221,32 @@ const ReqoreInput = forwardRef<HTMLDivElement, IReqoreInputProps>(
199
221
  interactive: !rest?.disabled && !readOnly,
200
222
  ...rest?.effect,
201
223
  }}
224
+ onChange={!readOnly && !rest?.disabled ? rest?.onChange : undefined}
202
225
  as='input'
226
+ ref={(ref) => setInputRef(ref)}
203
227
  theme={theme}
204
228
  _size={size}
205
229
  minimal={minimal}
206
230
  flat={flat}
207
231
  rounded={rounded}
208
232
  hasIcon={!!icon}
209
- clearable={!rest?.disabled && !!(onClearClick && rest?.onChange)}
233
+ hasRightIcon={!!rightIcon}
234
+ clearable={!rest?.disabled && !readOnly && !!(onClearClick && rest?.onChange)}
210
235
  className={`${className || ''} reqore-control reqore-input`}
211
236
  readOnly={readOnly}
212
237
  />
213
238
  <ReqoreInputClearButton
214
239
  enabled={!readOnly && !rest?.disabled && !!(onClearClick && rest?.onChange)}
215
240
  onClick={onClearClick}
241
+ hasRightIcon={!!rightIcon}
216
242
  size={size}
217
243
  show={rest?.value && rest.value !== '' ? true : false}
218
244
  />
245
+ {rightIcon && (
246
+ <StyledIconWrapper _size={size} position='right'>
247
+ <ReqoreIcon size={size} icon={rightIcon} color={rightIconColor} />
248
+ </StyledIconWrapper>
249
+ )}
219
250
  </StyledInputWrapper>
220
251
  );
221
252
  }
@@ -1,16 +1,28 @@
1
+ import { animated, useTransition } from '@react-spring/web';
1
2
  import styled from 'styled-components';
2
- import ReqoreButton, { IReqoreButtonProps } from '../Button';
3
+ import { SPRING_CONFIG } from '../../constants/animations';
4
+ import { SIZE_TO_PX } from '../../constants/sizes';
5
+ import { IReqoreButtonProps } from '../Button';
6
+ import ReqoreIcon from '../Icon';
3
7
 
4
8
  export interface IReqoreInputClearButtonProps extends IReqoreButtonProps {
5
9
  show: boolean;
6
10
  enabled: boolean;
11
+ hasRightIcon?: boolean;
7
12
  }
8
13
 
9
- export const StyledInputClearButton = styled(ReqoreButton)<{ show?: boolean }>`
14
+ export const StyledInputClearButton = styled(ReqoreIcon)<{ show?: boolean }>`
10
15
  position: absolute;
11
- right: ${({ show }) => (show ? 0 : -40)}px;
16
+ right: ${({ size, hasRightIcon }) => (hasRightIcon ? SIZE_TO_PX[size] : 0)}px;
12
17
  top: 0;
13
- opacity: ${({ show }) => (show ? 0.2 : 0)};
18
+ justify-content: center;
19
+ align-items: center;
20
+ transition: all 0.1s ease-out;
21
+ cursor: pointer;
22
+
23
+ &:hover {
24
+ opacity: 1 !important;
25
+ }
14
26
  `;
15
27
 
16
28
  const ReqoreInputClearButton = ({
@@ -18,18 +30,30 @@ const ReqoreInputClearButton = ({
18
30
  enabled,
19
31
  size = 'normal',
20
32
  ...rest
21
- }: IReqoreInputClearButtonProps) =>
22
- enabled ? (
23
- <StyledInputClearButton
24
- {...rest}
25
- className='reqore-clear-input-button'
26
- icon='CloseLine'
27
- minimal
28
- flat
29
- tabIndex={show ? 1 : -1}
30
- size={size}
31
- show={show}
32
- />
33
- ) : null;
33
+ }: IReqoreInputClearButtonProps) => {
34
+ const transitions = useTransition(show && enabled, {
35
+ from: { opacity: 0, filter: 'blur(10px)' },
36
+ enter: { opacity: 0.5, filter: 'blur(0px)' },
37
+ leave: { opacity: 0, filter: 'blur(10px)' },
38
+ config: SPRING_CONFIG,
39
+ });
40
+
41
+ return transitions((styles, item) =>
42
+ item ? (
43
+ <StyledInputClearButton
44
+ {...rest}
45
+ className='reqore-clear-input-button'
46
+ icon='CloseLine'
47
+ wrapperElement={animated.span}
48
+ size={size}
49
+ wrapperSize={SIZE_TO_PX[size]}
50
+ show={show}
51
+ style={{
52
+ opacity: styles.opacity,
53
+ }}
54
+ />
55
+ ) : null
56
+ );
57
+ };
34
58
 
35
59
  export default ReqoreInputClearButton;
@@ -1,9 +1,10 @@
1
1
  import { cloneDeep, isString } from 'lodash';
2
2
  import { rgba } from 'polished';
3
- import React, { memo, MutableRefObject, useContext, useEffect, useRef, useState } from 'react';
3
+ import React, { MutableRefObject, memo, useEffect, useRef, useState } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
5
  import { usePopper } from 'react-popper';
6
6
  import styled, { css } from 'styled-components';
7
+ import { useContext } from 'use-context-selector';
7
8
  import { RADIUS_FROM_SIZE } from '../../constants/sizes';
8
9
  import { IReqoreTheme } from '../../constants/theme';
9
10
  import { IPopoverData } from '../../containers/PopoverProvider';
@@ -1,9 +1,8 @@
1
- import React, { forwardRef, useContext } from 'react';
1
+ import React, { forwardRef } from 'react';
2
+ import { useContext } from 'use-context-selector';
2
3
  import { ReqoreButton, ReqoreControlGroup } from '../..';
3
4
  import { IReqoreTheme, TReqoreIntent } from '../../constants/theme';
4
5
  import PopoverContext from '../../context/PopoverContext';
5
- import { useCombinedRefs } from '../../hooks/useCombinedRefs';
6
- import { useTooltip } from '../../hooks/useTooltip';
7
6
  import { IReqoreComponent } from '../../types/global';
8
7
  import { IReqoreButtonProps } from '../Button';
9
8
 
@@ -33,7 +32,7 @@ export interface IReqoreMenuItemRightIconStyle {
33
32
  intent?: TReqoreIntent;
34
33
  }
35
34
 
36
- const ReqoreMenuItem = forwardRef<HTMLDivElement, IReqoreMenuItemProps>(
35
+ const ReqoreMenuItem = forwardRef<HTMLButtonElement, IReqoreMenuItemProps>(
37
36
  (
38
37
  {
39
38
  children,
@@ -53,10 +52,9 @@ const ReqoreMenuItem = forwardRef<HTMLDivElement, IReqoreMenuItemProps>(
53
52
  flat = true,
54
53
  ...rest
55
54
  }: IReqoreMenuItemProps,
56
- ref: any
55
+ ref
57
56
  ) => {
58
57
  const { removePopover } = useContext(PopoverContext);
59
- const { targetRef } = useCombinedRefs(ref);
60
58
 
61
59
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
62
60
  event.persist();
@@ -81,8 +79,6 @@ const ReqoreMenuItem = forwardRef<HTMLDivElement, IReqoreMenuItemProps>(
81
79
  }
82
80
  };
83
81
 
84
- useTooltip(targetRef.current, tooltip);
85
-
86
82
  return (
87
83
  <ReqoreControlGroup stack={!!onRightIconClick} fluid>
88
84
  <ReqoreButton
@@ -94,11 +90,12 @@ const ReqoreMenuItem = forwardRef<HTMLDivElement, IReqoreMenuItemProps>(
94
90
  fluid
95
91
  onClick={handleClick}
96
92
  active={selected}
97
- ref={targetRef}
93
+ ref={ref}
98
94
  disabled={disabled}
99
95
  intent={intent}
100
96
  icon={icon}
101
97
  rightIcon={onRightIconClick ? undefined : rightIcon}
98
+ tooltip={tooltip}
102
99
  >
103
100
  {label || children}
104
101
  </ReqoreButton>
@@ -87,8 +87,9 @@ const ReqoreMessage = memo(
87
87
  const [internalTimeout, setInternalTimeout] = useState<NodeJS.Timeout | null>(null);
88
88
  const theme = useReqoreTheme('main', customTheme, intent);
89
89
  const { targetRef } = useCombinedRefs(ref);
90
+ const [itemRef, setItemRef] = useState<HTMLDivElement>(undefined);
90
91
 
91
- useTooltip(targetRef.current, tooltip);
92
+ useTooltip(itemRef, tooltip);
92
93
 
93
94
  useMount(() => {
94
95
  if (duration) {
@@ -142,7 +143,10 @@ const ReqoreMessage = memo(
142
143
  fluid={fluid}
143
144
  fixed={fixed}
144
145
  className={`${rest?.className || ''} reqore-message`}
145
- ref={targetRef}
146
+ ref={(ref) => {
147
+ targetRef.current = ref;
148
+ setItemRef(ref);
149
+ }}
146
150
  size={size}
147
151
  theme={theme}
148
152
  >