@qoretechnologies/reqore 0.34.3 → 0.34.5

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 (69) hide show
  1. package/__tests__/button.test.tsx +30 -1
  2. package/__tests__/collection.test.tsx +30 -0
  3. package/__tests__/drawer.test.tsx +1 -1
  4. package/__tests__/dropdown.test.tsx +5 -2
  5. package/__tests__/heading.test.tsx +58 -0
  6. package/__tests__/hooks/useReqorePaging.test.tsx +16 -0
  7. package/__tests__/pagination.test.tsx +104 -3
  8. package/__tests__/panel.test.tsx +23 -2
  9. package/__tests__/stories/Collection.stories.tsx +0 -0
  10. package/dist/components/Button/index.d.ts +3 -1
  11. package/dist/components/Button/index.d.ts.map +1 -1
  12. package/dist/components/Button/index.js +9 -7
  13. package/dist/components/Button/index.js.map +1 -1
  14. package/dist/components/Collection/index.d.ts.map +1 -1
  15. package/dist/components/Collection/index.js +1 -1
  16. package/dist/components/Collection/index.js.map +1 -1
  17. package/dist/components/ControlGroup/index.d.ts.map +1 -1
  18. package/dist/components/ControlGroup/index.js +4 -4
  19. package/dist/components/ControlGroup/index.js.map +1 -1
  20. package/dist/components/Drawer/index.d.ts.map +1 -1
  21. package/dist/components/Drawer/index.js +3 -10
  22. package/dist/components/Drawer/index.js.map +1 -1
  23. package/dist/components/Dropdown/index.d.ts.map +1 -1
  24. package/dist/components/Dropdown/index.js +5 -1
  25. package/dist/components/Dropdown/index.js.map +1 -1
  26. package/dist/components/Header/index.d.ts +3 -3
  27. package/dist/components/Header/index.d.ts.map +1 -1
  28. package/dist/components/Header/index.js +5 -2
  29. package/dist/components/Header/index.js.map +1 -1
  30. package/dist/components/Paging/index.d.ts +2 -1
  31. package/dist/components/Paging/index.d.ts.map +1 -1
  32. package/dist/components/Paging/index.js +31 -1
  33. package/dist/components/Paging/index.js.map +1 -1
  34. package/dist/components/Panel/NonResponsiveActions.d.ts +18 -0
  35. package/dist/components/Panel/NonResponsiveActions.d.ts.map +1 -0
  36. package/dist/components/Panel/NonResponsiveActions.js +47 -0
  37. package/dist/components/Panel/NonResponsiveActions.js.map +1 -0
  38. package/dist/components/Panel/index.d.ts +5 -1
  39. package/dist/components/Panel/index.d.ts.map +1 -1
  40. package/dist/components/Panel/index.js +36 -20
  41. package/dist/components/Panel/index.js.map +1 -1
  42. package/dist/components/Tag/group.js +4 -1
  43. package/dist/components/Tag/group.js.map +1 -1
  44. package/dist/containers/Paging.d.ts +2 -1
  45. package/dist/containers/Paging.d.ts.map +1 -1
  46. package/dist/containers/Paging.js.map +1 -1
  47. package/dist/hooks/usePaging.d.ts +5 -0
  48. package/dist/hooks/usePaging.d.ts.map +1 -1
  49. package/dist/hooks/usePaging.js +7 -1
  50. package/dist/hooks/usePaging.js.map +1 -1
  51. package/package.json +1 -1
  52. package/src/components/Button/index.tsx +19 -14
  53. package/src/components/Collection/index.tsx +1 -0
  54. package/src/components/ControlGroup/index.tsx +3 -2
  55. package/src/components/Drawer/index.tsx +4 -10
  56. package/src/components/Dropdown/index.tsx +28 -15
  57. package/src/components/Header/index.tsx +9 -3
  58. package/src/components/Paging/index.tsx +37 -1
  59. package/src/components/Panel/NonResponsiveActions.tsx +79 -0
  60. package/src/components/Panel/index.tsx +129 -76
  61. package/src/components/Tag/group.tsx +1 -1
  62. package/src/containers/Paging.tsx +7 -3
  63. package/src/hooks/usePaging.ts +14 -0
  64. package/src/stories/Drawer/Drawer.stories.tsx +6 -1
  65. package/src/stories/Dropdown/Dropdown.stories.tsx +1 -0
  66. package/src/stories/Header/Header.stories.tsx +6 -8
  67. package/src/stories/Paging/Paging.stories.tsx +17 -1
  68. package/src/stories/Panel/Panel.stories.tsx +13 -3
  69. package/tests.json +1 -1
@@ -328,7 +328,7 @@ const ReqoreControlGroup = memo(
328
328
 
329
329
  const cloneThroughFragments = useCallback(
330
330
  (children: React.ReactNode): React.ReactNode => {
331
- return React.Children.map(children, (child) => {
331
+ return React.Children.map(children, (child, _index) => {
332
332
  if (child && React.isValidElement(child)) {
333
333
  if (child.type === React.Fragment) {
334
334
  return cloneThroughFragments(child.props.children);
@@ -336,6 +336,7 @@ const ReqoreControlGroup = memo(
336
336
 
337
337
  let newProps = {
338
338
  ...child.props,
339
+ key: child.props.reactKey || child.props.key || child.key || _index,
339
340
  minimal:
340
341
  child.props?.minimal || child.props?.minimal === false
341
342
  ? child.props.minimal
@@ -429,13 +430,13 @@ const ReqoreControlGroup = memo(
429
430
  tooltip={{
430
431
  content: `Show ${React.Children.count(overflownChildren)} hidden items`,
431
432
  }}
432
- fixed
433
433
  active={isOverflownDialogOpen}
434
434
  onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
435
435
  e.stopPropagation();
436
436
  setIsOverflownDialogOpen(!isOverflownDialogOpen);
437
437
  }}
438
438
  flat
439
+ fixed
439
440
  />,
440
441
  ]
441
442
  : children,
@@ -218,16 +218,6 @@ export const ReqoreDrawer: React.FC<IReqoreDrawerProps> = ({
218
218
  });
219
219
  }
220
220
 
221
- /* Adding a close button to the drawer. */
222
- if (onClose) {
223
- builtActions.push({
224
- responsive: false,
225
- icon: 'CloseLine',
226
- onClick: onClose,
227
- className: 'reqore-drawer-close-button',
228
- });
229
- }
230
-
231
221
  return builtActions;
232
222
  }, [hidable, position, onClose]);
233
223
 
@@ -370,6 +360,10 @@ export const ReqoreDrawer: React.FC<IReqoreDrawerProps> = ({
370
360
  intent={intent}
371
361
  rounded={floating || _isModal ? true : false}
372
362
  flat={flat}
363
+ onClose={onClose}
364
+ closeButtonProps={{
365
+ className: 'reqore-drawer-close-button',
366
+ }}
373
367
  className={`reqore-drawer`}
374
368
  style={{
375
369
  width: '100%',
@@ -7,7 +7,11 @@ import { IReqoreIconName } from '../../types/icons';
7
7
  import ReqoreButton, { IReqoreButtonProps } from '../Button';
8
8
  import { IReqoreInputProps } from '../Input';
9
9
  import { IReqorePanelProps } from '../Panel';
10
- import ReqoreDropdownList, { IReqoreDropdownItem, TDropdownItemOnClick } from './list';
10
+ import ReqoreDropdownList, {
11
+ IReqoreDropdownItem,
12
+ IReqoreDropdownListProps,
13
+ TDropdownItemOnClick,
14
+ } from './list';
11
15
 
12
16
  export interface IReqoreDropdownProps extends Partial<Omit<IPopoverOptions, 'openOnMount'>> {
13
17
  items?: IReqoreDropdownItem[];
@@ -32,6 +36,17 @@ export interface IReqoreDropdownProps extends Partial<Omit<IPopoverOptions, 'ope
32
36
  paging?: TReqorePaginationType<IReqoreDropdownItem>;
33
37
  }
34
38
 
39
+ const ReqoreDropdownListWrapper = ({
40
+ wrapperProps,
41
+ ...rest
42
+ }: IReqoreDropdownListProps & { wrapperProps?: IReqoreDropdownProps['wrapperProps'] }) => {
43
+ return (
44
+ <ReqorePanel flat size='small' {...wrapperProps}>
45
+ <ReqoreDropdownList {...rest} />
46
+ </ReqorePanel>
47
+ );
48
+ };
49
+
35
50
  function ReqoreDropdown<T extends unknown = IReqoreButtonProps>({
36
51
  items,
37
52
  component,
@@ -84,20 +99,18 @@ function ReqoreDropdown<T extends unknown = IReqoreButtonProps>({
84
99
 
85
100
  const popoverContent = useMemo(() => {
86
101
  return size(items) ? (
87
- <ReqorePanel flat size='small' {...wrapperProps}>
88
- <ReqoreDropdownList
89
- multiSelect={multiSelect}
90
- listStyle={listStyle}
91
- width={useTargetWidth ? '100%' : listWidth}
92
- height={listHeight}
93
- items={items}
94
- filterable={filterable}
95
- onItemSelect={onItemSelect}
96
- inputProps={inputProps}
97
- scrollToSelected={scrollToSelected}
98
- paging={paging}
99
- />
100
- </ReqorePanel>
102
+ <ReqoreDropdownListWrapper
103
+ multiSelect={multiSelect}
104
+ listStyle={listStyle}
105
+ width={useTargetWidth ? '100%' : listWidth}
106
+ height={listHeight}
107
+ items={items}
108
+ filterable={filterable}
109
+ onItemSelect={onItemSelect}
110
+ inputProps={inputProps}
111
+ scrollToSelected={scrollToSelected}
112
+ paging={paging}
113
+ />
101
114
  ) : undefined;
102
115
  }, [items]);
103
116
 
@@ -1,14 +1,16 @@
1
- import { memo, useMemo } from 'react';
1
+ import { memo, useMemo, useState } from 'react';
2
2
  import styled from 'styled-components';
3
3
  import { HEADER_SIZE_TO_NUMBER, TSizes } from '../../constants/sizes';
4
4
  import { IReqoreTheme, TReqoreIntent } from '../../constants/theme';
5
5
  import { isStringSize } from '../../helpers/utils';
6
6
  import { useReqoreTheme } from '../../hooks/useTheme';
7
- import { IWithReqoreEffect } from '../../types/global';
7
+ import { useTooltip } from '../../hooks/useTooltip';
8
+ import { IWithReqoreEffect, IWithReqoreTooltip } from '../../types/global';
8
9
  import { StyledTextEffect } from '../Effect';
9
10
 
10
11
  export interface IReqoreHeadingProps
11
12
  extends IWithReqoreEffect,
13
+ IWithReqoreTooltip,
12
14
  React.HTMLAttributes<HTMLHeadingElement> {
13
15
  intent?: TReqoreIntent;
14
16
  size?: 1 | 2 | 3 | 4 | 5 | 6 | TSizes;
@@ -45,18 +47,22 @@ export const StyledHeader = styled(StyledTextEffect)`
45
47
  `;
46
48
 
47
49
  export const ReqoreHeading = memo(
48
- ({ size, children, customTheme, intent, className, ...rest }: IReqoreHeadingProps) => {
50
+ ({ size, children, customTheme, intent, className, tooltip, ...rest }: IReqoreHeadingProps) => {
51
+ const [ref, setRef] = useState<HTMLHeadingElement>(undefined);
49
52
  const theme = useReqoreTheme('main', customTheme, intent);
50
53
  const _size: number = isStringSize(size) ? HEADER_SIZE_TO_NUMBER[size] : size;
51
54
  const HTMLheaderElement = useMemo(() => {
52
55
  return `h${_size}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
53
56
  }, [_size]);
54
57
 
58
+ useTooltip(ref, tooltip);
59
+
55
60
  return (
56
61
  <StyledHeader
57
62
  as={HTMLheaderElement}
58
63
  theme={theme}
59
64
  intent={intent}
65
+ ref={setRef}
60
66
  {...rest}
61
67
  _size={_size}
62
68
  className={`${className || ''} reqore-heading`}
@@ -1,4 +1,5 @@
1
- import { memo, useRef, useState } from 'react';
1
+ import { debounce } from 'lodash';
2
+ import { memo, useEffect, useRef, useState } from 'react';
2
3
  import { useUnmount, useUpdateEffect } from 'react-use';
3
4
  import styled from 'styled-components';
4
5
  import { ReqoreDropdown } from '../..';
@@ -27,6 +28,7 @@ export interface IReqorePaginationComponentProps
27
28
  showLabels?: boolean;
28
29
  scrollOnLoadMore?: boolean;
29
30
  autoLoadMore?: boolean;
31
+ changePageOnScroll?: 'vertical' | 'horizontal';
30
32
  scrollContainer?: HTMLElement;
31
33
  scrollToTopOnPageChange?: boolean;
32
34
  }
@@ -79,6 +81,7 @@ function Pagination<T>({
79
81
  renderControls,
80
82
  scrollContainer,
81
83
  scrollToTopOnPageChange = true,
84
+ changePageOnScroll,
82
85
  ...rest
83
86
  }: IReqorePaginationProps<T>) {
84
87
  const [loadMoreRef, setLoadMoreRef] = useState<HTMLButtonElement>(undefined);
@@ -119,6 +122,39 @@ function Pagination<T>({
119
122
  }
120
123
  }, [currentPage, scrollContainer, scrollToTopOnPageChange, infinite]);
121
124
 
125
+ // Switch pages when user scrolls and holds the Shift key
126
+ useEffect(() => {
127
+ const handleScroll = debounce((e: WheelEvent) => {
128
+ const deltaKey = changePageOnScroll === 'vertical' ? 'deltaY' : 'deltaX';
129
+ // Only change pages when user holds the shift key
130
+ // aka horizontal scroll
131
+ if (
132
+ changePageOnScroll === 'vertical' ||
133
+ (changePageOnScroll === 'horizontal' && e.shiftKey)
134
+ ) {
135
+ // Do not horizontal scroll
136
+ e.preventDefault();
137
+ // If the user scrolls to the right, go to the next page
138
+ if (e[deltaKey] > 20) {
139
+ next();
140
+ // If the user scrolls to the left, go to the previous page
141
+ } else if (e[deltaKey] < -20) {
142
+ back();
143
+ }
144
+ }
145
+ }, 30);
146
+
147
+ if (scrollContainer && changePageOnScroll) {
148
+ scrollContainer.addEventListener('wheel', handleScroll);
149
+ }
150
+
151
+ return () => {
152
+ if (scrollContainer) {
153
+ scrollContainer.removeEventListener('wheel', handleScroll);
154
+ }
155
+ };
156
+ }, [currentPage, scrollContainer, changePageOnScroll]);
157
+
122
158
  useUpdateEffect(() => {
123
159
  if (loadMoreRef && autoLoadMore) {
124
160
  observer.current = new IntersectionObserver(
@@ -0,0 +1,79 @@
1
+ import { size } from 'lodash';
2
+ import { memo } from 'react';
3
+ import { IReqorePanelProps } from '.';
4
+ import { ReqoreButton } from '../..';
5
+ import { IWithReqoreCustomTheme } from '../../types/global';
6
+ import ReqoreControlGroup, { IReqoreControlGroupProps } from '../ControlGroup';
7
+
8
+ export interface IReqorePanelNonResponsiveActionsProps
9
+ extends IWithReqoreCustomTheme,
10
+ Omit<IReqoreControlGroupProps, 'children'> {
11
+ onCollapseClick?: () => void;
12
+ onCloseClick?: () => void;
13
+ hasResponsiveActions?: boolean;
14
+ isCollapsed?: boolean;
15
+ showControlButtons?: boolean;
16
+ show?: boolean;
17
+ children?: IReqoreControlGroupProps['children'] | undefined;
18
+ closeButtonProps?: IReqorePanelProps['closeButtonProps'];
19
+ collapseButtonProps?: IReqorePanelProps['collapseButtonProps'];
20
+ isSmall: boolean;
21
+ }
22
+
23
+ export const ReqorePanelNonResponsiveActions = memo(
24
+ ({
25
+ onCollapseClick,
26
+ onCloseClick,
27
+ hasResponsiveActions,
28
+ isCollapsed,
29
+ customTheme,
30
+ children,
31
+ showControlButtons,
32
+ show,
33
+ collapseButtonProps,
34
+ closeButtonProps,
35
+ isSmall,
36
+ ...rest
37
+ }: IReqorePanelNonResponsiveActionsProps) => {
38
+ if (!show || (!size(children) && !showControlButtons)) {
39
+ return null;
40
+ }
41
+
42
+ return (
43
+ <ReqoreControlGroup
44
+ fixed={isSmall ? false : hasResponsiveActions}
45
+ fluid={isSmall ? true : !hasResponsiveActions}
46
+ horizontalAlign='flex-end'
47
+ {...rest}
48
+ >
49
+ {children}
50
+ {!!onCollapseClick && showControlButtons ? (
51
+ <ReqoreButton
52
+ customTheme={customTheme}
53
+ icon={isCollapsed ? 'ArrowDownSLine' : 'ArrowUpSLine'}
54
+ onClick={(e) => {
55
+ e.stopPropagation();
56
+ onCollapseClick();
57
+ }}
58
+ tooltip={isCollapsed ? 'Expand' : 'Collapse'}
59
+ fixed
60
+ {...collapseButtonProps}
61
+ />
62
+ ) : null}
63
+ {!!onCloseClick && showControlButtons ? (
64
+ <ReqoreButton
65
+ fixed
66
+ customTheme={customTheme}
67
+ icon='CloseLine'
68
+ onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
69
+ e.stopPropagation();
70
+ onCloseClick();
71
+ }}
72
+ tooltip='Close'
73
+ {...closeButtonProps}
74
+ />
75
+ ) : null}
76
+ </ReqoreControlGroup>
77
+ );
78
+ }
79
+ );
@@ -1,7 +1,7 @@
1
1
  import { size } from 'lodash';
2
2
  import { darken, rgba } from 'polished';
3
3
  import { ReactElement, forwardRef, useCallback, useMemo, useState } from 'react';
4
- import { useUpdateEffect } from 'react-use';
4
+ import { useMeasure, useUpdateEffect } from 'react-use';
5
5
  import styled, { css } from 'styled-components';
6
6
  import {
7
7
  GAP_FROM_SIZE,
@@ -41,8 +41,9 @@ import ReqoreControlGroup from '../ControlGroup';
41
41
  import ReqoreDropdown from '../Dropdown';
42
42
  import { IReqoreDropdownItem } from '../Dropdown/list';
43
43
  import { IReqoreEffect, StyledEffect, TReqoreEffectColor } from '../Effect';
44
- import { ReqoreHeading } from '../Header';
44
+ import { ReqoreHeading, StyledHeader } from '../Header';
45
45
  import ReqoreIcon, { IReqoreIconProps, StyledIconWrapper } from '../Icon';
46
+ import { ReqorePanelNonResponsiveActions } from './NonResponsiveActions';
46
47
 
47
48
  export interface IReqorePanelAction extends IReqoreButtonProps, IWithReqoreTooltip, IReqoreIntent {
48
49
  label?: string | number;
@@ -83,7 +84,11 @@ export interface IReqorePanelProps
83
84
  badge?: TReqoreBadge | TReqoreBadge[];
84
85
  collapsible?: boolean;
85
86
  isCollapsed?: boolean;
87
+ collapseButtonProps?: IReqoreButtonProps;
88
+
86
89
  onClose?: () => void;
90
+ closeButtonProps?: IReqoreButtonProps;
91
+
87
92
  rounded?: boolean;
88
93
  actions?: TReqorePanelActions;
89
94
  bottomActions?: TReqorePanelBottomActions;
@@ -104,6 +109,8 @@ export interface IReqorePanelProps
104
109
  responsiveActions?: boolean;
105
110
  responsiveTitle?: boolean;
106
111
  getContentRef?: (ref: HTMLDivElement) => any;
112
+
113
+ headerProps?: React.HTMLAttributes<unknown>;
107
114
  }
108
115
 
109
116
  export interface IStyledPanel extends IReqorePanelProps {
@@ -111,6 +118,40 @@ export interface IStyledPanel extends IReqorePanelProps {
111
118
  noHorizontalPadding?: boolean;
112
119
  }
113
120
 
121
+ export const StyledPanelTitleHeader = styled.div`
122
+ display: flex;
123
+ justify-content: flex-start;
124
+ align-items: center;
125
+ flex: 1 1 auto;
126
+ width: 100%;
127
+ overflow: hidden;
128
+ `;
129
+
130
+ export const StyledPanelTitleHeaderContent = styled.div`
131
+ display: flex;
132
+ justify-content: flex-start;
133
+ align-items: center;
134
+ flex: 0 1 auto;
135
+ overflow: hidden;
136
+ min-width: ${({ iconSize, hasLabel, hasIcon }) => {
137
+ let width = 0;
138
+
139
+ if (hasIcon) {
140
+ width += iconSize;
141
+ }
142
+
143
+ if (hasLabel) {
144
+ width += 50;
145
+ }
146
+
147
+ return width;
148
+ }}px;
149
+
150
+ ${StyledHeader} {
151
+ min-width: 50px;
152
+ }
153
+ `;
154
+
114
155
  export const StyledPanel = styled(StyledEffect)<IStyledPanel>`
115
156
  background-color: ${({ theme, opacity = 1 }: IStyledPanel) =>
116
157
  rgba(changeDarkness(getMainBackgroundColor(theme), 0.03), opacity)};
@@ -139,7 +180,7 @@ export const StyledPanel = styled(StyledEffect)<IStyledPanel>`
139
180
  cursor: pointer;
140
181
 
141
182
  &:hover {
142
- ${StyledPanelTitle} > div > ${StyledIconWrapper} {
183
+ ${StyledPanelTitle} ${StyledPanelTitleHeaderContent} > ${StyledIconWrapper} {
143
184
  transform: scale(${ACTIVE_ICON_SCALE});
144
185
  }
145
186
 
@@ -206,7 +247,7 @@ export const StyledPanelTitle = styled.div<IStyledPanel>`
206
247
  flex: 0 0 auto;
207
248
  gap: ${GAP_FROM_SIZE.normal}px;
208
249
 
209
- > div > ${StyledIconWrapper} {
250
+ ${StyledPanelTitleHeaderContent} > ${StyledIconWrapper} {
210
251
  transform: scale(${INACTIVE_ICON_SCALE});
211
252
  }
212
253
 
@@ -215,7 +256,7 @@ export const StyledPanelTitle = styled.div<IStyledPanel>`
215
256
  css`
216
257
  cursor: pointer;
217
258
  &:hover {
218
- > div > ${StyledIconWrapper} {
259
+ ${StyledPanelTitleHeaderContent} > ${StyledIconWrapper} {
219
260
  transform: scale(${ACTIVE_ICON_SCALE});
220
261
  }
221
262
 
@@ -255,23 +296,15 @@ export const StyledPanelContent = styled.div<IStyledPanel>`
255
296
  font-size: ${({ size }) => TEXT_FROM_SIZE[size]}px;
256
297
  `;
257
298
 
258
- export const StyledPanelTitleHeader = styled.div`
259
- display: flex;
260
- justify-content: flex-start;
261
- align-items: center;
262
- flex: 1 1 auto;
263
- width: 100%;
264
- overflow: hidden;
265
- min-width: 100px;
266
- `;
267
-
268
299
  export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
269
300
  (
270
301
  {
271
302
  children,
272
303
  label,
304
+ collapseButtonProps = {},
273
305
  collapsible,
274
306
  onClose,
307
+ closeButtonProps = {},
275
308
  rounded = true,
276
309
  actions = [],
277
310
  bottomActions = [],
@@ -300,6 +333,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
300
333
  responsiveTitle = true,
301
334
  size: panelSize = 'normal',
302
335
  getContentRef,
336
+ headerProps = {},
303
337
  ...rest
304
338
  }: IReqorePanelProps,
305
339
  ref
@@ -315,6 +349,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
315
349
  const isMobile = useReqoreProperty('isMobile');
316
350
  const { targetRef } = useCombinedRefs(ref);
317
351
  const [itemRef, setItemRef] = useState<HTMLDivElement>(undefined);
352
+ const [measureRef, { width }] = useMeasure();
318
353
 
319
354
  useTooltip(itemRef, tooltip);
320
355
 
@@ -340,6 +375,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
340
375
  [label, icon, badge]
341
376
  );
342
377
 
378
+ const isSmall = useMemo(() => width < 480 && process.env.NODE_ENV !== 'test', [width]);
379
+
343
380
  // If collapsible is true, toggle the isCollapsed state
344
381
  // If the isCollapsed state is true, the component is expanded
345
382
  // If the isCollapsed state is false, the component is collapsed
@@ -465,8 +502,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
465
502
  <CustomElement
466
503
  fixed
467
504
  {...props}
468
- key={props.key || index}
469
- reactKey={props.key || index}
505
+ // key={props.key || index}
506
+ // reactKey={props.key || index}
470
507
  customTheme={props.customTheme || theme}
471
508
  onClick={(e: React.MouseEvent<any>) => {
472
509
  e.stopPropagation();
@@ -557,51 +594,80 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
557
594
  opacity={opacity ?? (minimal ? 0 : 1)}
558
595
  noHorizontalPadding={noHorizontalPadding}
559
596
  responsive={responsiveTitle}
560
- isMobile={isMobile}
597
+ isMobile={isMobile || isSmall}
598
+ ref={measureRef}
561
599
  >
562
600
  {hasTitleHeader && (
563
601
  <StyledPanelTitleHeader>
564
- {icon || iconImage ? (
565
- <ReqoreIcon
566
- size={`${
567
- ICON_FROM_HEADER_SIZE[headerSize || HEADER_SIZE_TO_NUMBER[panelSize]]
568
- }px`}
569
- icon={icon}
570
- image={iconImage}
571
- margin='right'
572
- color={iconColor}
573
- {...iconProps}
574
- />
575
- ) : null}
576
- {typeof label === 'string' ? (
577
- <ReqoreHeading
578
- size={headerSize || panelSize}
579
- customTheme={theme}
580
- effect={{
581
- noWrap: true,
582
- ...headerEffect,
583
- }}
602
+ {icon || iconImage || label ? (
603
+ <StyledPanelTitleHeaderContent
604
+ size={panelSize}
605
+ {...headerProps}
606
+ hasLabel={!!label}
607
+ hasIcon={!!icon || !!iconImage}
608
+ iconSize={ICON_FROM_HEADER_SIZE[headerSize || HEADER_SIZE_TO_NUMBER[panelSize]]}
584
609
  >
585
- {label}
586
- </ReqoreHeading>
587
- ) : (
588
- label
589
- )}
610
+ {icon || iconImage ? (
611
+ <ReqoreIcon
612
+ size={`${
613
+ ICON_FROM_HEADER_SIZE[headerSize || HEADER_SIZE_TO_NUMBER[panelSize]]
614
+ }px`}
615
+ icon={icon}
616
+ image={iconImage}
617
+ margin='right'
618
+ color={iconColor}
619
+ tooltip={{
620
+ content: label,
621
+ }}
622
+ {...iconProps}
623
+ />
624
+ ) : null}
625
+ {typeof label === 'string' ? (
626
+ <ReqoreHeading
627
+ size={headerSize || panelSize}
628
+ customTheme={theme}
629
+ effect={{
630
+ noWrap: true,
631
+ ...headerEffect,
632
+ }}
633
+ tooltip={label}
634
+ >
635
+ {label}
636
+ </ReqoreHeading>
637
+ ) : (
638
+ label
639
+ )}
640
+ </StyledPanelTitleHeaderContent>
641
+ ) : null}
590
642
  {badge || badge === 0 ? (
591
- <>
592
- <ButtonBadge
593
- color={changeLightness(theme.main, 0.18)}
594
- size={getOneHigherSize(panelSize)}
595
- content={badge}
596
- />
597
- </>
643
+ <ButtonBadge
644
+ color={changeLightness(theme.main, 0.18)}
645
+ size={getOneHigherSize(panelSize)}
646
+ content={badge}
647
+ wrapGroup={isSmall}
648
+ />
598
649
  ) : null}
650
+ <ReqorePanelNonResponsiveActions
651
+ show={isSmall}
652
+ isSmall={isSmall}
653
+ showControlButtons
654
+ size={panelSize}
655
+ hasResponsiveActions={hasResponsiveActions(actions)}
656
+ customTheme={theme}
657
+ isCollapsed={_isCollapsed}
658
+ onCollapseClick={collapsible ? handleCollapseClick : undefined}
659
+ onCloseClick={onClose}
660
+ closeButtonProps={closeButtonProps}
661
+ collapseButtonProps={collapseButtonProps}
662
+ fluid={false}
663
+ style={{ marginLeft: 'auto' }}
664
+ />
599
665
  </StyledPanelTitleHeader>
600
666
  )}
601
667
  {hasResponsiveActions(actions) && (
602
668
  <ReqoreControlGroup
603
669
  responsive={responsiveActions}
604
- fluid={responsiveActions || isMobile}
670
+ fluid={responsiveActions || isSmall}
605
671
  horizontalAlign='flex-end'
606
672
  customTheme={theme}
607
673
  size={panelSize}
@@ -611,34 +677,21 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
611
677
  )}
612
678
  {collapsible || onClose || hasNonResponsiveActions(actions) ? (
613
679
  <>
614
- <ReqoreControlGroup
615
- fixed={isMobile ? false : hasResponsiveActions(actions)}
616
- fluid={isMobile ? true : !hasResponsiveActions(actions)}
617
- horizontalAlign='flex-end'
680
+ <ReqorePanelNonResponsiveActions
681
+ show
682
+ isSmall={isSmall}
683
+ showControlButtons={!isSmall}
618
684
  size={panelSize}
685
+ hasResponsiveActions={hasResponsiveActions(actions)}
686
+ customTheme={theme}
687
+ isCollapsed={_isCollapsed}
688
+ onCollapseClick={collapsible ? handleCollapseClick : undefined}
689
+ onCloseClick={onClose}
690
+ closeButtonProps={closeButtonProps}
691
+ collapseButtonProps={collapseButtonProps}
619
692
  >
620
693
  {actions.map(renderNonResponsiveActions())}
621
- {collapsible && (
622
- <ReqoreButton
623
- customTheme={theme}
624
- icon={_isCollapsed ? 'ArrowDownSLine' : 'ArrowUpSLine'}
625
- onClick={handleCollapseClick}
626
- tooltip={_isCollapsed ? 'Expand' : 'Collapse'}
627
- fixed
628
- />
629
- )}
630
- {onClose && (
631
- <ReqoreButton
632
- fixed
633
- customTheme={theme}
634
- icon='CloseLine'
635
- onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
636
- e.stopPropagation();
637
- onClose?.();
638
- }}
639
- />
640
- )}
641
- </ReqoreControlGroup>
694
+ </ReqorePanelNonResponsiveActions>
642
695
  </>
643
696
  ) : null}
644
697
  </StyledPanelTitle>
@@ -14,7 +14,7 @@ export interface IReqoreTagGroup
14
14
  }
15
15
 
16
16
  const StyledTagGroup = styled.div`
17
- flex-shrink: 0;
17
+ flex-shrink: ${({ wrap }: IReqoreTagGroup) => (wrap ? 1 : 0)};
18
18
  display: flex;
19
19
  flex-wrap: ${({ wrap }: IReqoreTagGroup) => (wrap ? 'wrap' : 'nowrap')};
20
20
  gap: ${({ gapSize }: IReqoreTagGroup) => GAP_FROM_SIZE[gapSize]}px;
@@ -1,10 +1,14 @@
1
1
  import { memo, useMemo } from 'react';
2
- import { IReqorePaginationProps, ReqorePagination } from '../components/Paging';
2
+ import {
3
+ IReqorePaginationComponentProps,
4
+ IReqorePaginationProps,
5
+ ReqorePagination,
6
+ } from '../components/Paging';
3
7
  import { ReqoreVerticalSpacer } from '../components/Spacer';
4
8
  import {
9
+ getPaginationOptionsFromType,
5
10
  TReqorePaginationType,
6
11
  TReqorePaginationTypeResult,
7
- getPaginationOptionsFromType,
8
12
  } from '../constants/paging';
9
13
  import { PADDING_FROM_SIZE, TSizes } from '../constants/sizes';
10
14
  import { IReqorePagingResult, useReqorePaging } from '../hooks/usePaging';
@@ -12,7 +16,7 @@ import { IReqorePagingResult, useReqorePaging } from '../hooks/usePaging';
12
16
  export interface IReqorePagingContainerProps<T> {
13
17
  type?: TReqorePaginationType<T>;
14
18
  items: T[];
15
- scrollContainer?: HTMLElement;
19
+ scrollContainer?: IReqorePaginationComponentProps['scrollContainer'];
16
20
  children: (
17
21
  items: T[],
18
22
  Controls: JSX.Element,