@qoretechnologies/reqore 0.32.3 → 0.34.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 (109) hide show
  1. package/__tests__/collection.test.tsx +144 -5
  2. package/__tests__/containers/paging.test.tsx +106 -0
  3. package/__tests__/hooks/useLatestZIndex.test.tsx +10 -0
  4. package/__tests__/hooks/useReqorePaging.test.tsx +255 -0
  5. package/__tests__/hooks/useTheme.test.tsx +31 -0
  6. package/__tests__/pagination.test.tsx +305 -0
  7. package/__tests__/popover.test.tsx +20 -6
  8. package/__tests__/setup.js +8 -0
  9. package/__tests__/tree.test.tsx +0 -1
  10. package/dist/components/Button/index.d.ts +1 -0
  11. package/dist/components/Button/index.d.ts.map +1 -1
  12. package/dist/components/Button/index.js +11 -7
  13. package/dist/components/Button/index.js.map +1 -1
  14. package/dist/components/Collection/index.d.ts +4 -3
  15. package/dist/components/Collection/index.d.ts.map +1 -1
  16. package/dist/components/Collection/index.js +31 -13
  17. package/dist/components/Collection/index.js.map +1 -1
  18. package/dist/components/Dropdown/index.d.ts +9 -2
  19. package/dist/components/Dropdown/index.d.ts.map +1 -1
  20. package/dist/components/Dropdown/index.js +2 -2
  21. package/dist/components/Dropdown/index.js.map +1 -1
  22. package/dist/components/Dropdown/list.d.ts +6 -1
  23. package/dist/components/Dropdown/list.d.ts.map +1 -1
  24. package/dist/components/Dropdown/list.js +13 -5
  25. package/dist/components/Dropdown/list.js.map +1 -1
  26. package/dist/components/Menu/index.d.ts +1 -0
  27. package/dist/components/Menu/index.d.ts.map +1 -1
  28. package/dist/components/Menu/index.js +4 -1
  29. package/dist/components/Menu/index.js.map +1 -1
  30. package/dist/components/Menu/item.d.ts +1 -0
  31. package/dist/components/Menu/item.d.ts.map +1 -1
  32. package/dist/components/Menu/item.js +14 -2
  33. package/dist/components/Menu/item.js.map +1 -1
  34. package/dist/components/MultiSelect/index.d.ts +1 -1
  35. package/dist/components/MultiSelect/index.d.ts.map +1 -1
  36. package/dist/components/Paging/index.d.ts +32 -0
  37. package/dist/components/Paging/index.d.ts.map +1 -0
  38. package/dist/components/Paging/index.js +127 -0
  39. package/dist/components/Paging/index.js.map +1 -0
  40. package/dist/components/Panel/index.d.ts +1 -0
  41. package/dist/components/Panel/index.d.ts.map +1 -1
  42. package/dist/components/Panel/index.js +2 -2
  43. package/dist/components/Panel/index.js.map +1 -1
  44. package/dist/components/Tag/index.d.ts +3 -2
  45. package/dist/components/Tag/index.d.ts.map +1 -1
  46. package/dist/components/Tag/index.js +10 -7
  47. package/dist/components/Tag/index.js.map +1 -1
  48. package/dist/constants/colors.d.ts +2 -9
  49. package/dist/constants/colors.d.ts.map +1 -1
  50. package/dist/constants/colors.js +3 -1
  51. package/dist/constants/colors.js.map +1 -1
  52. package/dist/constants/paging.d.ts +17 -0
  53. package/dist/constants/paging.d.ts.map +1 -0
  54. package/dist/constants/paging.js +45 -0
  55. package/dist/constants/paging.js.map +1 -0
  56. package/dist/constants/theme.d.ts.map +1 -1
  57. package/dist/constants/theme.js +8 -7
  58. package/dist/constants/theme.js.map +1 -1
  59. package/dist/containers/Paging.d.ts +15 -0
  60. package/dist/containers/Paging.d.ts.map +1 -0
  61. package/dist/containers/Paging.js +51 -0
  62. package/dist/containers/Paging.js.map +1 -0
  63. package/dist/containers/ReqoreProvider.d.ts.map +1 -1
  64. package/dist/containers/ReqoreProvider.js +2 -2
  65. package/dist/containers/ReqoreProvider.js.map +1 -1
  66. package/dist/containers/UIProvider.d.ts.map +1 -1
  67. package/dist/containers/UIProvider.js +9 -3
  68. package/dist/containers/UIProvider.js.map +1 -1
  69. package/dist/hooks/useCombinedRefs.d.ts +2 -2
  70. package/dist/hooks/useCombinedRefs.d.ts.map +1 -1
  71. package/dist/hooks/useCombinedRefs.js.map +1 -1
  72. package/dist/hooks/usePaging.d.ts +28 -0
  73. package/dist/hooks/usePaging.d.ts.map +1 -0
  74. package/dist/hooks/usePaging.js +85 -0
  75. package/dist/hooks/usePaging.js.map +1 -0
  76. package/dist/index.d.ts +3 -0
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +8 -2
  79. package/dist/index.js.map +1 -1
  80. package/package.json +6 -4
  81. package/src/components/Button/index.tsx +18 -10
  82. package/src/components/Collection/index.tsx +78 -49
  83. package/src/components/ControlGroup/index.tsx +1 -1
  84. package/src/components/Dropdown/index.tsx +27 -12
  85. package/src/components/Dropdown/list.tsx +49 -24
  86. package/src/components/Menu/index.tsx +3 -2
  87. package/src/components/Menu/item.tsx +16 -2
  88. package/src/components/MultiSelect/index.tsx +1 -1
  89. package/src/components/Paging/index.tsx +260 -0
  90. package/src/components/Panel/index.tsx +4 -1
  91. package/src/components/Tag/index.tsx +9 -7
  92. package/src/constants/colors.ts +5 -1
  93. package/src/constants/paging.ts +67 -0
  94. package/src/constants/theme.ts +8 -7
  95. package/src/containers/Paging.tsx +90 -0
  96. package/src/containers/ReqoreProvider.tsx +3 -3
  97. package/src/containers/UIProvider.tsx +17 -4
  98. package/src/hooks/useCombinedRefs.ts +2 -2
  99. package/src/hooks/usePaging.ts +114 -0
  100. package/src/index.tsx +3 -0
  101. package/src/mock/collectionData.tsx +19 -0
  102. package/src/mock/tableData.ts +1 -0
  103. package/src/stories/Button/Button.stories.tsx +25 -8
  104. package/src/stories/Collection/Collection.stories.tsx +51 -42
  105. package/src/stories/Dropdown/Dropdown.stories.tsx +71 -29
  106. package/src/stories/Menu/Menu.stories.tsx +4 -0
  107. package/src/stories/Paging/Paging.stories.tsx +202 -0
  108. package/src/stories/Tag/Tag.stories.tsx +50 -0
  109. package/tests.json +1 -1
@@ -0,0 +1,260 @@
1
+ import { memo, useEffect, useRef, useState } from 'react';
2
+ import { useUnmount, useUpdateEffect } from 'react-use';
3
+ import styled from 'styled-components';
4
+ import { ReqoreDropdown } from '../..';
5
+ import { IReqorePagingResult } from '../../hooks/usePaging';
6
+ import ReqoreButton, { IReqoreButtonProps, StyledButton } from '../Button';
7
+ import ReqoreControlGroup, { IReqoreControlGroupProps } from '../ControlGroup';
8
+ import { IReqoreDropdownProps } from '../Dropdown';
9
+ import { IReqoreDropdownItemProps } from '../Dropdown/item';
10
+
11
+ export interface IReqorePaginationComponentProps
12
+ extends Omit<IReqoreControlGroupProps, 'children'> {
13
+ pageButtonProps?: IReqoreButtonProps;
14
+ activePageButtonProps?: IReqoreButtonProps;
15
+ listPageButtonProps?: IReqoreDropdownProps;
16
+ controlPageButtonProps?: IReqoreButtonProps;
17
+ loadMoreButtonProps?: IReqoreButtonProps;
18
+ firstPageLabel?: string;
19
+ lastPageLabel?: string;
20
+ nextPageLabel?: string;
21
+ previousPageLabel?: string;
22
+ pageLabel?: string;
23
+ loadMoreLabel?: string;
24
+ showPages?: boolean;
25
+ showControls?: boolean;
26
+ showPagesAs?: 'buttons' | 'list';
27
+ showLabels?: boolean;
28
+ scrollOnLoadMore?: boolean;
29
+ autoLoadMore?: boolean;
30
+ scrollContainer?: HTMLElement;
31
+ scrollToTopOnPageChange?: boolean;
32
+ }
33
+ export interface IReqorePaginationProps<T>
34
+ extends Omit<IReqorePagingResult<T>, 'items'>,
35
+ IReqorePaginationComponentProps {}
36
+
37
+ export const StyledPagesWrapper = styled(ReqoreControlGroup)`
38
+ width: unset;
39
+ flex: 0 auto;
40
+ justify-content: center;
41
+
42
+ & > ${StyledButton} {
43
+ margin: 0;
44
+ }
45
+ `;
46
+
47
+ function Pagination<T>({
48
+ allPages,
49
+ back,
50
+ first,
51
+ currentPage,
52
+ isLastPage,
53
+ isFirstPage,
54
+ pageCount,
55
+ pages,
56
+ last,
57
+ next,
58
+ setPage,
59
+ infinite,
60
+ itemsLeft,
61
+ showPagesAs = 'buttons',
62
+ pageButtonProps = {},
63
+ activePageButtonProps = {},
64
+ listPageButtonProps = {},
65
+ controlPageButtonProps = {},
66
+ loadMoreButtonProps = {},
67
+ firstPageLabel = 'First',
68
+ lastPageLabel = 'Last',
69
+ nextPageLabel = 'Next',
70
+ previousPageLabel = 'Back',
71
+ pageLabel = 'Page',
72
+ loadMoreLabel = 'Load more',
73
+ showLabels,
74
+ showPages = true,
75
+ showControls = true,
76
+ scrollOnLoadMore,
77
+ autoLoadMore,
78
+ itemsPerPage,
79
+ renderControls,
80
+ scrollContainer,
81
+ scrollToTopOnPageChange = true,
82
+ ...rest
83
+ }: IReqorePaginationProps<T>) {
84
+ const [loadMoreRef, setLoadMoreRef] = useState<HTMLButtonElement>(undefined);
85
+ const [scrollTargetRef, setScrollTargetRef] = useState<HTMLDivElement>(undefined);
86
+ const observer = useRef<IntersectionObserver>(null);
87
+
88
+ useEffect(() => {
89
+ if (scrollTargetRef && scrollOnLoadMore && !isLastPage && !isFirstPage) {
90
+ scrollTargetRef.scrollIntoView({
91
+ behavior: 'smooth',
92
+ block: 'end',
93
+ inline: 'nearest',
94
+ });
95
+ }
96
+ }, [currentPage, scrollTargetRef, scrollOnLoadMore, isLastPage, isFirstPage]);
97
+
98
+ // Scroll to bottom on load more
99
+ useEffect(() => {
100
+ if (scrollContainer && scrollOnLoadMore && !isFirstPage) {
101
+ scrollContainer.scrollBy?.({
102
+ top: scrollContainer.scrollHeight,
103
+ behavior: 'smooth',
104
+ });
105
+ }
106
+ }, [currentPage, scrollContainer, scrollOnLoadMore, isFirstPage]);
107
+
108
+ // Scroll to top on page change
109
+ useEffect(() => {
110
+ if (scrollContainer && scrollToTopOnPageChange && !infinite) {
111
+ scrollContainer.scrollTo?.({
112
+ top: 0,
113
+ behavior: 'smooth',
114
+ });
115
+ }
116
+ }, [currentPage, scrollContainer, scrollToTopOnPageChange, infinite]);
117
+
118
+ useUpdateEffect(() => {
119
+ if (loadMoreRef && autoLoadMore) {
120
+ observer.current = new IntersectionObserver(
121
+ (entries: IntersectionObserverEntry[]) => {
122
+ entries.forEach((entry) => {
123
+ if (entry.isIntersecting) {
124
+ next();
125
+ }
126
+ });
127
+ },
128
+ {
129
+ threshold: 0.8,
130
+ }
131
+ );
132
+
133
+ observer.current.observe(loadMoreRef);
134
+ }
135
+ }, [loadMoreRef, autoLoadMore, isLastPage]);
136
+
137
+ useUnmount(() => {
138
+ observer.current?.disconnect();
139
+ });
140
+
141
+ if (!renderControls) {
142
+ return null;
143
+ }
144
+
145
+ return (
146
+ <ReqoreControlGroup
147
+ {...rest}
148
+ className={`${rest.className || ''} reqore-pagination-wrapper`}
149
+ style={{ justifyContent: 'center' }}
150
+ >
151
+ {infinite && !isLastPage ? (
152
+ <ReqoreControlGroup vertical>
153
+ <div className='reqore-auto-scroll-target' ref={setScrollTargetRef} />
154
+ <ReqoreButton
155
+ icon='ArrowDropDownLine'
156
+ badge={itemsLeft}
157
+ iconsAlign='center'
158
+ {...loadMoreButtonProps}
159
+ onClick={next}
160
+ ref={setLoadMoreRef}
161
+ style={{
162
+ scrollMarginTop: '200px',
163
+ }}
164
+ >
165
+ {showLabels && loadMoreLabel}
166
+ </ReqoreButton>
167
+ </ReqoreControlGroup>
168
+ ) : null}
169
+ {!infinite ? (
170
+ <>
171
+ {showPagesAs === 'list' || (showControls && !showPages) ? (
172
+ <ReqoreButton
173
+ icon='RewindMiniLine'
174
+ fixed
175
+ {...controlPageButtonProps}
176
+ onClick={first}
177
+ disabled={isFirstPage}
178
+ tooltip={!showLabels && firstPageLabel}
179
+ >
180
+ {showLabels && firstPageLabel}
181
+ </ReqoreButton>
182
+ ) : null}
183
+ {showControls && (
184
+ <ReqoreButton
185
+ icon='ArrowDropLeftLine'
186
+ fixed
187
+ {...controlPageButtonProps}
188
+ onClick={back}
189
+ disabled={isFirstPage}
190
+ tooltip={!showLabels && previousPageLabel}
191
+ >
192
+ {showLabels && previousPageLabel}
193
+ </ReqoreButton>
194
+ )}
195
+ {showPages && (
196
+ <StyledPagesWrapper wrap horizontalAlign='center'>
197
+ {showPagesAs === 'buttons' ? (
198
+ pages.map((page) => (
199
+ <ReqoreButton
200
+ textAlign='center'
201
+ fixed
202
+ key={page}
203
+ onClick={() => setPage(page)}
204
+ active={page === currentPage}
205
+ {...(page === currentPage ? activePageButtonProps : pageButtonProps)}
206
+ >
207
+ {page}
208
+ </ReqoreButton>
209
+ ))
210
+ ) : (
211
+ <ReqoreDropdown
212
+ filterable
213
+ label={`${showLabels ? `${pageLabel} ` : ''}${currentPage} / ${pageCount}`}
214
+ items={pages.map((page) => ({
215
+ label: `${showLabels ? `${pageLabel} ` : ''}${page}`,
216
+ onClick: () => setPage(page),
217
+ selected: page === currentPage,
218
+ ...(page === currentPage
219
+ ? (activePageButtonProps as IReqoreDropdownItemProps)
220
+ : (pageButtonProps as IReqoreDropdownItemProps)),
221
+ }))}
222
+ placement='bottom'
223
+ inputProps={{ focusRules: { type: 'auto', viewportOnly: true } }}
224
+ scrollToSelected
225
+ {...listPageButtonProps}
226
+ />
227
+ )}
228
+ </StyledPagesWrapper>
229
+ )}
230
+ {showControls && (
231
+ <ReqoreButton
232
+ icon='ArrowDropRightLine'
233
+ fixed
234
+ {...controlPageButtonProps}
235
+ onClick={next}
236
+ disabled={isLastPage}
237
+ tooltip={!showLabels && nextPageLabel}
238
+ >
239
+ {showLabels && nextPageLabel}
240
+ </ReqoreButton>
241
+ )}
242
+ {showPagesAs === 'list' || (showControls && !showPages) ? (
243
+ <ReqoreButton
244
+ icon='SpeedMiniLine'
245
+ fixed
246
+ {...controlPageButtonProps}
247
+ onClick={last}
248
+ disabled={isLastPage}
249
+ tooltip={!showLabels && lastPageLabel}
250
+ >
251
+ {showLabels && lastPageLabel}
252
+ </ReqoreButton>
253
+ ) : null}
254
+ </>
255
+ ) : null}
256
+ </ReqoreControlGroup>
257
+ );
258
+ }
259
+
260
+ export const ReqorePagination = memo(Pagination) as typeof Pagination;
@@ -1,6 +1,6 @@
1
1
  import { size } from 'lodash';
2
2
  import { darken, rgba } from 'polished';
3
- import { forwardRef, ReactElement, useCallback, useMemo, useState } from 'react';
3
+ import { ReactElement, forwardRef, useCallback, useMemo, useState } from 'react';
4
4
  import { useUpdateEffect } from 'react-use';
5
5
  import styled, { css } from 'styled-components';
6
6
  import {
@@ -103,6 +103,7 @@ export interface IReqorePanelProps
103
103
  iconColor?: TReqoreEffectColor;
104
104
  responsiveActions?: boolean;
105
105
  responsiveTitle?: boolean;
106
+ getContentRef?: (ref: HTMLDivElement) => any;
106
107
  }
107
108
 
108
109
  export interface IStyledPanel extends IReqorePanelProps {
@@ -298,6 +299,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
298
299
  responsiveActions = true,
299
300
  responsiveTitle = true,
300
301
  size: panelSize = 'normal',
302
+ getContentRef,
301
303
  ...rest
302
304
  }: IReqorePanelProps,
303
305
  ref
@@ -643,6 +645,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
643
645
  padded={padded}
644
646
  minimal={minimal}
645
647
  size={contentSize || panelSize}
648
+ ref={getContentRef}
646
649
  noHorizontalPadding={noHorizontalPadding}
647
650
  >
648
651
  {children}
@@ -25,7 +25,6 @@ import {
25
25
  IReqoreDisabled,
26
26
  IReqoreIntent,
27
27
  IWithReqoreEffect,
28
- IWithReqoreFixed,
29
28
  IWithReqoreFluid,
30
29
  IWithReqoreMinimal,
31
30
  IWithReqoreTooltip,
@@ -52,8 +51,8 @@ export interface IReqoreTagProps
52
51
  IReqoreDisabled,
53
52
  IWithReqoreMinimal,
54
53
  IWithReqoreFluid,
55
- IWithReqoreFixed,
56
54
  IWithReqoreEffect {
55
+ fixed?: boolean | 'key' | 'label';
57
56
  size?: TSizes;
58
57
  label?: string | number;
59
58
  labelKey?: string | number;
@@ -93,9 +92,10 @@ export const StyledTag = styled(StyledEffect)<IReqoreTagStyle>`
93
92
  font-size: ${({ size }) => TEXT_FROM_SIZE[size]}px;
94
93
 
95
94
  min-width: ${({ size }) => SIZE_TO_PX[size]}px;
96
- max-width: ${({ fixed }) => (!fixed ? '100%' : undefined)};
97
- flex: ${({ fluid, fixed }) => (fixed ? '0 0 auto' : fluid ? '1 auto' : '0 0 auto')};
98
- align-self: ${({ fixed, fluid }) => (fixed ? 'flex-start' : fluid ? 'stretch' : undefined)};
95
+ max-width: ${({ fixed }) => (fixed !== true ? '100%' : undefined)};
96
+ flex: ${({ fluid, fixed }) => (fixed === true ? '0 0 auto' : fluid ? '1 auto' : '0 0 auto')};
97
+ align-self: ${({ fixed, fluid }) =>
98
+ fixed === true ? 'flex-start' : fluid ? 'stretch' : undefined};
99
99
  border-radius: ${({ asBadge, size }) => (asBadge ? 18 : RADIUS_FROM_SIZE[size])}px;
100
100
  width: ${({ width }) => width || undefined};
101
101
  transition: all 0.2s ease-out;
@@ -163,7 +163,7 @@ const StyledTagKeyWrapper = styled.span<{ size: TSizes }>`
163
163
  display: flex;
164
164
  align-items: center;
165
165
  justify-content: center;
166
- flex: ${({ hasKey }) => (hasKey ? 1 : undefined)};
166
+ flex: ${({ hasKey, fixed }) => (hasKey ? (fixed === 'key' ? '0 0 auto' : 1) : undefined)};
167
167
  flex-shrink: 0;
168
168
  min-height: 100%;
169
169
  `;
@@ -172,7 +172,7 @@ const StyledTagContentWrapper = styled.span<{ size: TSizes }>`
172
172
  display: flex;
173
173
  align-items: center;
174
174
  justify-content: center;
175
- flex: 1;
175
+ flex: ${({ fixed }) => (fixed === 'label' ? '0 0 auto' : 1)};
176
176
  flex-shrink: 0;
177
177
  min-height: 100%;
178
178
  `;
@@ -311,6 +311,7 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
311
311
  wrap={wrap}
312
312
  hasWidth={!!width}
313
313
  hasKey={!!labelKey}
314
+ fixed={rest.fixed}
314
315
  >
315
316
  {icon && (
316
317
  <ReqoreIcon
@@ -345,6 +346,7 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
345
346
  wrap={wrap}
346
347
  hasWidth={!!width}
347
348
  hasKey={!!labelKey}
349
+ fixed={rest.fixed}
348
350
  >
349
351
  {label || label === 0 ? (
350
352
  <StyledTagContent
@@ -1,9 +1,13 @@
1
- export const Colors = {
1
+ import { TReqoreHexColor } from '../components/Effect';
2
+
3
+ export const Colors: Record<string, TReqoreHexColor> = {
2
4
  DARK: '#000000',
5
+ DARK_THEME: '#333333',
3
6
  LIGHT: '#ffffff',
4
7
  BLUE: '#0E5A8A',
5
8
  GREEN: '#0A6640',
6
9
  YELLOW: '#d1a036',
7
10
  ORANGE: '#A66321',
8
11
  RED: '#A82A2A',
12
+ GRAY: '#444444',
9
13
  };
@@ -0,0 +1,67 @@
1
+ import { IReqorePaginationComponentProps, IReqorePaginationProps } from '../components/Paging';
2
+ import { IReqorePagingOptions } from '../hooks/usePaging';
3
+
4
+ export type TReqorePaginationType<T> =
5
+ | 'buttons'
6
+ | 'list'
7
+ | 'infinite'
8
+ | 'auto-load'
9
+ | IReqoreComponentPagingOptions<T>;
10
+
11
+ export interface IReqoreComponentPagingOptions<T>
12
+ extends Omit<IReqorePagingOptions<T>, 'items'>,
13
+ IReqorePaginationComponentProps {
14
+ pageControlsPosition?: 'top' | 'bottom' | 'both';
15
+ includeTopControls?: boolean;
16
+ includeBottomControls?: boolean;
17
+ }
18
+
19
+ export type TReqorePaginationTypeResult<T> = {
20
+ pagingOptions?: Omit<IReqorePagingOptions<T>, 'items'>;
21
+ componentOptions?: Partial<Omit<IReqorePaginationProps<T>, 'items'>>;
22
+ pageControlsPosition?: 'top' | 'bottom' | 'both';
23
+ includeTopControls?: boolean;
24
+ includeBottomControls?: boolean;
25
+ };
26
+
27
+ export function getPaginationOptionsFromType<T>(
28
+ type: TReqorePaginationType<T>
29
+ ): TReqorePaginationTypeResult<T> {
30
+ if (!type) return {};
31
+
32
+ if (typeof type === 'object') {
33
+ const {
34
+ infinite,
35
+ itemsPerPage,
36
+ pagesToShow,
37
+ startPage,
38
+ pageControlsPosition = 'bottom',
39
+ includeBottomControls,
40
+ includeTopControls,
41
+ ...componentOptions
42
+ } = type;
43
+ return {
44
+ pagingOptions: { infinite, itemsPerPage, pagesToShow, startPage },
45
+ pageControlsPosition,
46
+ componentOptions,
47
+ includeBottomControls,
48
+ includeTopControls,
49
+ };
50
+ }
51
+
52
+ switch (type) {
53
+ case 'buttons':
54
+ return {};
55
+ case 'list':
56
+ return {
57
+ componentOptions: {
58
+ showPagesAs: 'list',
59
+ },
60
+ };
61
+ case 'infinite':
62
+ case 'auto-load':
63
+ return { pagingOptions: { infinite: true } };
64
+ default:
65
+ return {};
66
+ }
67
+ }
@@ -3,6 +3,7 @@ import {
3
3
  TReqoreEffectGradientAnimationTrigger,
4
4
  TReqoreHexColor,
5
5
  } from '../components/Effect';
6
+ import { Colors } from './colors';
6
7
 
7
8
  export interface IReqoreSidebarTheme {
8
9
  main?: TReqoreHexColor;
@@ -94,16 +95,16 @@ export interface IReqoreIntents {
94
95
  export type TReqoreIntent = 'info' | 'success' | 'pending' | 'warning' | 'danger' | 'muted';
95
96
 
96
97
  export const DEFAULT_INTENTS: IReqoreIntents = {
97
- info: '#0E5A8A',
98
- success: '#0A6640',
99
- pending: '#d1a036',
100
- warning: '#A66321',
101
- danger: '#A82A2A',
102
- muted: '#444444',
98
+ info: Colors.BLUE,
99
+ success: Colors.GREEN,
100
+ pending: Colors.YELLOW,
101
+ warning: Colors.ORANGE,
102
+ danger: Colors.RED,
103
+ muted: Colors.GRAY,
103
104
  };
104
105
 
105
106
  export const DEFAULT_THEME: IReqoreTheme = {
106
- main: '#333333',
107
+ main: Colors.DARK_THEME,
107
108
  text: {
108
109
  dim: true,
109
110
  },
@@ -0,0 +1,90 @@
1
+ import { memo, useMemo } from 'react';
2
+ import { IReqorePaginationProps, ReqorePagination } from '../components/Paging';
3
+ import { ReqoreVerticalSpacer } from '../components/Spacer';
4
+ import {
5
+ TReqorePaginationType,
6
+ TReqorePaginationTypeResult,
7
+ getPaginationOptionsFromType,
8
+ } from '../constants/paging';
9
+ import { PADDING_FROM_SIZE, TSizes } from '../constants/sizes';
10
+ import { useReqorePaging } from '../hooks/usePaging';
11
+
12
+ export interface IReqorePagingContainerProps<T> {
13
+ type?: TReqorePaginationType<T>;
14
+ items: T[];
15
+ scrollContainer?: HTMLElement;
16
+ children: (
17
+ items: T[],
18
+ Controls: React.FC<Partial<IReqorePaginationProps<T>>>,
19
+ options: TReqorePaginationTypeResult<T>
20
+ ) => React.ReactNode;
21
+ size?: TSizes;
22
+ }
23
+
24
+ function PagingContainer<T>({
25
+ type,
26
+ items,
27
+ scrollContainer,
28
+ children,
29
+ size = 'normal',
30
+ }: IReqorePagingContainerProps<T>) {
31
+ const {
32
+ pagingOptions = {},
33
+ componentOptions = {},
34
+ pageControlsPosition = 'bottom',
35
+ includeTopControls = true,
36
+ includeBottomControls = true,
37
+ } = useMemo(() => getPaginationOptionsFromType(type), [type]);
38
+
39
+ const { items: finalItems, ...pagingData } = useReqorePaging({
40
+ items,
41
+ ...pagingOptions,
42
+ enabled: !!type,
43
+ });
44
+
45
+ const Controls = ({
46
+ withSpacer,
47
+ position,
48
+ ...pagingProps
49
+ }: Partial<IReqorePaginationProps<T>> & { withSpacer?: boolean; position?: 'top' | 'bottom' }) =>
50
+ pagingData.renderControls ? (
51
+ <>
52
+ {withSpacer && position === 'bottom' ? (
53
+ <ReqoreVerticalSpacer height={PADDING_FROM_SIZE[size]} />
54
+ ) : null}
55
+ <ReqorePagination
56
+ size={size}
57
+ {...pagingData}
58
+ {...componentOptions}
59
+ scrollContainer={scrollContainer}
60
+ {...pagingProps}
61
+ />
62
+ {withSpacer && position === 'top' ? (
63
+ <ReqoreVerticalSpacer height={PADDING_FROM_SIZE[size]} />
64
+ ) : null}
65
+ </>
66
+ ) : null;
67
+
68
+ return (
69
+ <>
70
+ {includeTopControls && (pageControlsPosition === 'top' || pageControlsPosition === 'both') ? (
71
+ <Controls autoLoadMore={false} scrollOnLoadMore={false} position='top' withSpacer />
72
+ ) : null}
73
+
74
+ {children(finalItems, Controls, {
75
+ pagingOptions,
76
+ componentOptions,
77
+ pageControlsPosition,
78
+ includeTopControls,
79
+ includeBottomControls,
80
+ })}
81
+
82
+ {includeBottomControls &&
83
+ (pageControlsPosition === 'bottom' || pageControlsPosition === 'both') ? (
84
+ <Controls position='bottom' withSpacer />
85
+ ) : null}
86
+ </>
87
+ );
88
+ }
89
+
90
+ export const ReqorePaginationContainer = memo(PagingContainer) as typeof PagingContainer;
@@ -1,5 +1,5 @@
1
1
  import { size } from 'lodash';
2
- import React, { useRef, useState } from 'react';
2
+ import React, { useCallback, useRef, useState } from 'react';
3
3
  import { useMedia } from 'react-use';
4
4
  import shortid from 'shortid';
5
5
  import { useContext } from 'use-context-selector';
@@ -62,11 +62,11 @@ const ReqoreProvider: React.FC<IReqoreNotifications> = ({ children, options = {}
62
62
  : useMedia('(min-width: 480px) and (max-width: 1200px)');
63
63
  const isMobileOrTablet = isMobile || isTablet;
64
64
 
65
- const getAndIncreaseZIndex = (): number => {
65
+ const getAndIncreaseZIndex = useCallback((): number => {
66
66
  latestZIndex.current += 1;
67
67
 
68
68
  return latestZIndex.current;
69
- };
69
+ }, [latestZIndex.current]);
70
70
 
71
71
  const confirmAction = (data: IReqoreConfirmationModal): void => {
72
72
  setConfirmationModal({
@@ -1,13 +1,13 @@
1
1
  import { cloneDeep } from 'lodash';
2
2
  import merge from 'lodash/merge';
3
3
  import { rgba } from 'polished';
4
- import React, { useState } from 'react';
5
- import styled, { createGlobalStyle } from 'styled-components';
4
+ import React, { forwardRef, useState } from 'react';
5
+ import styled, { createGlobalStyle, css } from 'styled-components';
6
6
  import ReqoreLayoutWrapper from '../components/Layout';
7
7
  import { IReqoreNotificationsPosition } from '../components/Notifications';
8
8
  import { DEFAULT_THEME, IReqoreTheme } from '../constants/theme';
9
9
  import ThemeContext from '../context/ThemeContext';
10
- import { buildTheme, getMainBackgroundColor } from '../helpers/colors';
10
+ import { buildTheme, getMainBackgroundColor, getReadableColor } from '../helpers/colors';
11
11
  import PopoverProvider from './PopoverProvider';
12
12
  import ReqoreProvider from './ReqoreProvider';
13
13
  import ReqoreThemeProvider from './ThemeProvider';
@@ -56,11 +56,24 @@ const GlobalStyle = createGlobalStyle`
56
56
 
57
57
  const StyledPortal = styled.div`
58
58
  z-index: 9999;
59
+
59
60
  * {
60
61
  box-sizing: border-box;
61
62
  }
63
+
64
+ ${({ theme }) => css`
65
+ color: ${getReadableColor(theme, undefined, undefined, true)};
66
+ `}
62
67
  `;
63
68
 
69
+ const ReqorePortal = forwardRef<HTMLDivElement, {}>((_props, ref) => {
70
+ return (
71
+ <ReqoreThemeProvider>
72
+ <StyledPortal id='reqore-portal' ref={ref} />
73
+ </ReqoreThemeProvider>
74
+ );
75
+ });
76
+
64
77
  const ReqoreUIProvider: React.FC<IReqoreUIProviderProps> = ({ children, theme, options }) => {
65
78
  const [modalPortal, setModalPortal] = useState<any>(false);
66
79
 
@@ -81,8 +94,8 @@ const ReqoreUIProvider: React.FC<IReqoreUIProviderProps> = ({ children, theme, o
81
94
  </ReqoreProvider>
82
95
  ) : null}
83
96
  </ReqoreLayoutWrapper>
97
+ <ReqorePortal ref={setModalPortal} />
84
98
  </ThemeContext.Provider>
85
- <StyledPortal id='reqore-portal' ref={setModalPortal} />
86
99
  </>
87
100
  );
88
101
  };
@@ -6,9 +6,9 @@ import React from 'react';
6
6
  * @param refs - An array of refs to combine.
7
7
  * @returns A ref object.
8
8
  */
9
- export function useCombinedRefs(...refs) {
9
+ export function useCombinedRefs<T = any>(...refs) {
10
10
  const [_innerRef, setInnerRef] = React.useState(null);
11
- const targetRef = React.useRef();
11
+ const targetRef = React.useRef<T>();
12
12
 
13
13
  React.useEffect(() => {
14
14
  [...refs, setInnerRef].forEach((ref) => {