@qoretechnologies/reqore 0.32.3 → 0.33.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.
- package/__tests__/collection.test.tsx +123 -5
- package/__tests__/hooks/useLatestZIndex.test.tsx +10 -0
- package/__tests__/hooks/useReqorePaging.test.tsx +251 -0
- package/__tests__/hooks/useTheme.test.tsx +31 -0
- package/__tests__/pagination.test.tsx +301 -0
- package/__tests__/popover.test.tsx +20 -6
- package/__tests__/setup.js +8 -0
- package/__tests__/tree.test.tsx +0 -1
- package/dist/components/Button/index.d.ts +1 -0
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +11 -7
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Collection/index.d.ts +9 -3
- package/dist/components/Collection/index.d.ts.map +1 -1
- package/dist/components/Collection/index.js +34 -8
- package/dist/components/Collection/index.js.map +1 -1
- package/dist/components/Dropdown/index.d.ts +5 -2
- package/dist/components/Dropdown/index.d.ts.map +1 -1
- package/dist/components/Dropdown/index.js +2 -2
- package/dist/components/Dropdown/index.js.map +1 -1
- package/dist/components/Dropdown/list.d.ts +4 -1
- package/dist/components/Dropdown/list.d.ts.map +1 -1
- package/dist/components/Dropdown/list.js +3 -3
- package/dist/components/Dropdown/list.js.map +1 -1
- package/dist/components/Menu/item.d.ts +1 -0
- package/dist/components/Menu/item.d.ts.map +1 -1
- package/dist/components/Menu/item.js +14 -2
- package/dist/components/Menu/item.js.map +1 -1
- package/dist/components/MultiSelect/index.d.ts +1 -1
- package/dist/components/MultiSelect/index.d.ts.map +1 -1
- package/dist/components/Paging/index.d.ts +30 -0
- package/dist/components/Paging/index.d.ts.map +1 -0
- package/dist/components/Paging/index.js +106 -0
- package/dist/components/Paging/index.js.map +1 -0
- package/dist/components/Tag/index.d.ts +3 -2
- package/dist/components/Tag/index.d.ts.map +1 -1
- package/dist/components/Tag/index.js +10 -7
- package/dist/components/Tag/index.js.map +1 -1
- package/dist/constants/colors.d.ts +2 -9
- package/dist/constants/colors.d.ts.map +1 -1
- package/dist/constants/colors.js +3 -1
- package/dist/constants/colors.js.map +1 -1
- package/dist/constants/paging.d.ts +10 -0
- package/dist/constants/paging.d.ts.map +1 -0
- package/dist/constants/paging.js +41 -0
- package/dist/constants/paging.js.map +1 -0
- package/dist/constants/theme.d.ts.map +1 -1
- package/dist/constants/theme.js +8 -7
- package/dist/constants/theme.js.map +1 -1
- package/dist/containers/ReqoreProvider.d.ts.map +1 -1
- package/dist/containers/ReqoreProvider.js +2 -2
- package/dist/containers/ReqoreProvider.js.map +1 -1
- package/dist/containers/UIProvider.d.ts.map +1 -1
- package/dist/containers/UIProvider.js +9 -3
- package/dist/containers/UIProvider.js.map +1 -1
- package/dist/hooks/useCombinedRefs.d.ts +2 -2
- package/dist/hooks/useCombinedRefs.d.ts.map +1 -1
- package/dist/hooks/useCombinedRefs.js.map +1 -1
- package/dist/hooks/usePaging.d.ts +27 -0
- package/dist/hooks/usePaging.d.ts.map +1 -0
- package/dist/hooks/usePaging.js +83 -0
- package/dist/hooks/usePaging.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
- package/src/components/Button/index.tsx +18 -10
- package/src/components/Collection/index.tsx +96 -44
- package/src/components/ControlGroup/index.tsx +1 -1
- package/src/components/Dropdown/index.tsx +8 -2
- package/src/components/Dropdown/list.tsx +7 -1
- package/src/components/Menu/item.tsx +16 -2
- package/src/components/MultiSelect/index.tsx +1 -1
- package/src/components/Paging/index.tsx +232 -0
- package/src/components/Tag/index.tsx +9 -7
- package/src/constants/colors.ts +5 -1
- package/src/constants/paging.ts +48 -0
- package/src/constants/theme.ts +8 -7
- package/src/containers/ReqoreProvider.tsx +3 -3
- package/src/containers/UIProvider.tsx +17 -4
- package/src/hooks/useCombinedRefs.ts +2 -2
- package/src/hooks/usePaging.ts +110 -0
- package/src/index.tsx +2 -0
- package/src/mock/collectionData.tsx +19 -0
- package/src/mock/tableData.ts +1 -0
- package/src/stories/Button/Button.stories.tsx +25 -8
- package/src/stories/Collection/Collection.stories.tsx +32 -42
- package/src/stories/Dropdown/Dropdown.stories.tsx +24 -1
- package/src/stories/Paging/Paging.stories.tsx +184 -0
- package/src/stories/Tag/Tag.stories.tsx +50 -0
- package/tests.json +1 -1
|
@@ -0,0 +1,232 @@
|
|
|
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
|
+
}
|
|
31
|
+
export interface IReqorePaginationProps<T>
|
|
32
|
+
extends Omit<IReqorePagingResult<T>, 'items'>,
|
|
33
|
+
IReqorePaginationComponentProps {}
|
|
34
|
+
|
|
35
|
+
export const StyledPagesWrapper = styled(ReqoreControlGroup)`
|
|
36
|
+
width: unset;
|
|
37
|
+
max-width: 100%;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
|
|
40
|
+
& > ${StyledButton} {
|
|
41
|
+
margin: 0;
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
function Pagination<T>({
|
|
46
|
+
allPages,
|
|
47
|
+
back,
|
|
48
|
+
first,
|
|
49
|
+
currentPage,
|
|
50
|
+
isLastPage,
|
|
51
|
+
isFirstPage,
|
|
52
|
+
pageCount,
|
|
53
|
+
pages,
|
|
54
|
+
last,
|
|
55
|
+
next,
|
|
56
|
+
setPage,
|
|
57
|
+
infinite,
|
|
58
|
+
itemsLeft,
|
|
59
|
+
showPagesAs = 'buttons',
|
|
60
|
+
pageButtonProps = {},
|
|
61
|
+
activePageButtonProps = {},
|
|
62
|
+
listPageButtonProps = {},
|
|
63
|
+
controlPageButtonProps = {},
|
|
64
|
+
loadMoreButtonProps = {},
|
|
65
|
+
firstPageLabel = 'First',
|
|
66
|
+
lastPageLabel = 'Last',
|
|
67
|
+
nextPageLabel = 'Next',
|
|
68
|
+
previousPageLabel = 'Back',
|
|
69
|
+
pageLabel = 'Page',
|
|
70
|
+
loadMoreLabel = 'Load more',
|
|
71
|
+
showLabels,
|
|
72
|
+
showPages = true,
|
|
73
|
+
showControls = true,
|
|
74
|
+
scrollOnLoadMore,
|
|
75
|
+
autoLoadMore,
|
|
76
|
+
itemsPerPage,
|
|
77
|
+
...rest
|
|
78
|
+
}: IReqorePaginationProps<T>) {
|
|
79
|
+
const [loadMoreRef, setLoadMoreRef] = useState<HTMLButtonElement>(undefined);
|
|
80
|
+
const [scrollTargetRef, setScrollTargetRef] = useState<HTMLDivElement>(undefined);
|
|
81
|
+
const observer = useRef<IntersectionObserver>(null);
|
|
82
|
+
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (scrollTargetRef && scrollOnLoadMore && !isLastPage && !isFirstPage) {
|
|
85
|
+
scrollTargetRef.scrollIntoView({
|
|
86
|
+
behavior: 'smooth',
|
|
87
|
+
block: 'end',
|
|
88
|
+
inline: 'nearest',
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}, [currentPage, scrollTargetRef, scrollOnLoadMore, isLastPage, isFirstPage]);
|
|
92
|
+
|
|
93
|
+
useUpdateEffect(() => {
|
|
94
|
+
if (loadMoreRef && autoLoadMore) {
|
|
95
|
+
observer.current = new IntersectionObserver(
|
|
96
|
+
(entries: IntersectionObserverEntry[]) => {
|
|
97
|
+
entries.forEach((entry) => {
|
|
98
|
+
if (entry.isIntersecting) {
|
|
99
|
+
next();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
threshold: 0.8,
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
observer.current.observe(loadMoreRef);
|
|
109
|
+
}
|
|
110
|
+
}, [loadMoreRef, autoLoadMore, isLastPage]);
|
|
111
|
+
|
|
112
|
+
useUnmount(() => {
|
|
113
|
+
observer.current?.disconnect();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
if (pageCount === 1 || pageCount === 0) return null;
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<ReqoreControlGroup
|
|
120
|
+
{...rest}
|
|
121
|
+
className={`${rest.className || ''} reqore-pagination-wrapper`}
|
|
122
|
+
style={{ justifyContent: 'center' }}
|
|
123
|
+
>
|
|
124
|
+
{infinite && !isLastPage ? (
|
|
125
|
+
<ReqoreControlGroup vertical>
|
|
126
|
+
<div className='reqore-auto-scroll-target' ref={setScrollTargetRef} />
|
|
127
|
+
<ReqoreButton
|
|
128
|
+
icon='ArrowDropDownLine'
|
|
129
|
+
badge={itemsLeft}
|
|
130
|
+
iconsAlign='center'
|
|
131
|
+
{...loadMoreButtonProps}
|
|
132
|
+
onClick={next}
|
|
133
|
+
ref={setLoadMoreRef}
|
|
134
|
+
style={{
|
|
135
|
+
scrollMarginTop: '200px',
|
|
136
|
+
}}
|
|
137
|
+
>
|
|
138
|
+
{showLabels && loadMoreLabel}
|
|
139
|
+
</ReqoreButton>
|
|
140
|
+
</ReqoreControlGroup>
|
|
141
|
+
) : (
|
|
142
|
+
<>
|
|
143
|
+
{showPagesAs === 'list' || (showControls && !showPages) ? (
|
|
144
|
+
<ReqoreButton
|
|
145
|
+
icon='RewindMiniLine'
|
|
146
|
+
fixed
|
|
147
|
+
{...controlPageButtonProps}
|
|
148
|
+
onClick={first}
|
|
149
|
+
disabled={isFirstPage}
|
|
150
|
+
tooltip={!showLabels && firstPageLabel}
|
|
151
|
+
>
|
|
152
|
+
{showLabels && firstPageLabel}
|
|
153
|
+
</ReqoreButton>
|
|
154
|
+
) : null}
|
|
155
|
+
{showControls && (
|
|
156
|
+
<ReqoreButton
|
|
157
|
+
icon='ArrowDropLeftLine'
|
|
158
|
+
fixed
|
|
159
|
+
{...controlPageButtonProps}
|
|
160
|
+
onClick={back}
|
|
161
|
+
disabled={isFirstPage}
|
|
162
|
+
tooltip={!showLabels && previousPageLabel}
|
|
163
|
+
>
|
|
164
|
+
{showLabels && previousPageLabel}
|
|
165
|
+
</ReqoreButton>
|
|
166
|
+
)}
|
|
167
|
+
{showPages && (
|
|
168
|
+
<StyledPagesWrapper wrap horizontalAlign='center'>
|
|
169
|
+
{showPagesAs === 'buttons' ? (
|
|
170
|
+
pages.map((page) => (
|
|
171
|
+
<ReqoreButton
|
|
172
|
+
textAlign='center'
|
|
173
|
+
fixed
|
|
174
|
+
key={page}
|
|
175
|
+
onClick={() => setPage(page)}
|
|
176
|
+
active={page === currentPage}
|
|
177
|
+
{...(page === currentPage ? activePageButtonProps : pageButtonProps)}
|
|
178
|
+
>
|
|
179
|
+
{page}
|
|
180
|
+
</ReqoreButton>
|
|
181
|
+
))
|
|
182
|
+
) : (
|
|
183
|
+
<ReqoreDropdown
|
|
184
|
+
filterable
|
|
185
|
+
label={`${showLabels ? `${pageLabel} ` : ''}${currentPage} / ${pageCount}`}
|
|
186
|
+
items={pages.map((page) => ({
|
|
187
|
+
label: `${showLabels ? `${pageLabel} ` : ''}${page}`,
|
|
188
|
+
onClick: () => setPage(page),
|
|
189
|
+
selected: page === currentPage,
|
|
190
|
+
...(page === currentPage
|
|
191
|
+
? (activePageButtonProps as IReqoreDropdownItemProps)
|
|
192
|
+
: (pageButtonProps as IReqoreDropdownItemProps)),
|
|
193
|
+
}))}
|
|
194
|
+
placement='bottom'
|
|
195
|
+
inputProps={{ focusRules: { type: 'auto', viewportOnly: true } }}
|
|
196
|
+
scrollToSelected
|
|
197
|
+
{...listPageButtonProps}
|
|
198
|
+
/>
|
|
199
|
+
)}
|
|
200
|
+
</StyledPagesWrapper>
|
|
201
|
+
)}
|
|
202
|
+
{showControls && (
|
|
203
|
+
<ReqoreButton
|
|
204
|
+
icon='ArrowDropRightLine'
|
|
205
|
+
fixed
|
|
206
|
+
{...controlPageButtonProps}
|
|
207
|
+
onClick={next}
|
|
208
|
+
disabled={isLastPage}
|
|
209
|
+
tooltip={!showLabels && nextPageLabel}
|
|
210
|
+
>
|
|
211
|
+
{showLabels && nextPageLabel}
|
|
212
|
+
</ReqoreButton>
|
|
213
|
+
)}
|
|
214
|
+
{showPagesAs === 'list' || (showControls && !showPages) ? (
|
|
215
|
+
<ReqoreButton
|
|
216
|
+
icon='SpeedMiniLine'
|
|
217
|
+
fixed
|
|
218
|
+
{...controlPageButtonProps}
|
|
219
|
+
onClick={last}
|
|
220
|
+
disabled={isLastPage}
|
|
221
|
+
tooltip={!showLabels && lastPageLabel}
|
|
222
|
+
>
|
|
223
|
+
{showLabels && lastPageLabel}
|
|
224
|
+
</ReqoreButton>
|
|
225
|
+
) : null}
|
|
226
|
+
</>
|
|
227
|
+
)}
|
|
228
|
+
</ReqoreControlGroup>
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export const ReqorePagination = memo(Pagination) as typeof Pagination;
|
|
@@ -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 }) => (
|
|
97
|
-
flex: ${({ fluid, fixed }) => (fixed ? '0 0 auto' : fluid ? '1 auto' : '0 0 auto')};
|
|
98
|
-
align-self: ${({ fixed, fluid }) =>
|
|
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
|
package/src/constants/colors.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
|
|
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,48 @@
|
|
|
1
|
+
import { IReqoreCollectionPagingOptions } from '../components/Collection';
|
|
2
|
+
import { IReqorePaginationProps } from '../components/Paging';
|
|
3
|
+
import { IReqorePagingOptions } from '../hooks/usePaging';
|
|
4
|
+
|
|
5
|
+
export type TReqorePaginationType =
|
|
6
|
+
| true
|
|
7
|
+
| 'list'
|
|
8
|
+
| 'infinite'
|
|
9
|
+
| 'auto-load'
|
|
10
|
+
| IReqoreCollectionPagingOptions;
|
|
11
|
+
|
|
12
|
+
export function getPaginationOptionsFromType<T>(type: TReqorePaginationType): {
|
|
13
|
+
pagingOptions?: Omit<IReqorePagingOptions<T>, 'items'>;
|
|
14
|
+
componentOptions?: Partial<Omit<IReqorePaginationProps<T>, 'items'>>;
|
|
15
|
+
pageControlsPosition?: 'top' | 'bottom' | 'both';
|
|
16
|
+
} {
|
|
17
|
+
if (!type) return {};
|
|
18
|
+
|
|
19
|
+
if (typeof type === 'object') {
|
|
20
|
+
const {
|
|
21
|
+
infinite,
|
|
22
|
+
itemsPerPage,
|
|
23
|
+
pagesToShow,
|
|
24
|
+
startPage,
|
|
25
|
+
pageControlsPosition = 'bottom',
|
|
26
|
+
...componentOptions
|
|
27
|
+
} = type;
|
|
28
|
+
return {
|
|
29
|
+
pagingOptions: { infinite, itemsPerPage, pagesToShow, startPage },
|
|
30
|
+
pageControlsPosition,
|
|
31
|
+
componentOptions,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
switch (type) {
|
|
36
|
+
case true:
|
|
37
|
+
return {};
|
|
38
|
+
case 'list':
|
|
39
|
+
return {
|
|
40
|
+
componentOptions: {
|
|
41
|
+
showPagesAs: 'list',
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
case 'infinite':
|
|
45
|
+
case 'auto-load':
|
|
46
|
+
return { pagingOptions: { infinite: true } };
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/constants/theme.ts
CHANGED
|
@@ -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:
|
|
98
|
-
success:
|
|
99
|
-
pending:
|
|
100
|
-
warning:
|
|
101
|
-
danger:
|
|
102
|
-
muted:
|
|
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:
|
|
107
|
+
main: Colors.DARK_THEME,
|
|
107
108
|
text: {
|
|
108
109
|
dim: true,
|
|
109
110
|
},
|
|
@@ -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) => {
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { merge, size } from 'lodash';
|
|
2
|
+
import { useEffect, useMemo } from 'react';
|
|
3
|
+
import { useUpdateEffect } from 'react-use';
|
|
4
|
+
import usePagination, { usePaginationReturn } from 'react-use-pagination-hook';
|
|
5
|
+
|
|
6
|
+
export interface IReqorePagingOptions<T> {
|
|
7
|
+
items: T[];
|
|
8
|
+
startPage?: number;
|
|
9
|
+
pagesToShow?: number;
|
|
10
|
+
itemsPerPage?: number;
|
|
11
|
+
infinite?: boolean;
|
|
12
|
+
enabled?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface IReqorePagingResult<T>
|
|
16
|
+
extends Pick<usePaginationReturn, 'setPage' | 'currentPage'> {
|
|
17
|
+
pages: number[];
|
|
18
|
+
allPages: number[];
|
|
19
|
+
items: T[];
|
|
20
|
+
itemsPerPage: number;
|
|
21
|
+
itemsLeft: number;
|
|
22
|
+
isLastPage: boolean;
|
|
23
|
+
isFirstPage: boolean;
|
|
24
|
+
next: usePaginationReturn['goNext'];
|
|
25
|
+
back: usePaginationReturn['goBefore'];
|
|
26
|
+
first: () => void;
|
|
27
|
+
last: () => void;
|
|
28
|
+
pageCount: number;
|
|
29
|
+
infinite: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const defaultPagingOptions: IReqorePagingOptions<any> = {
|
|
33
|
+
items: [],
|
|
34
|
+
itemsPerPage: 10,
|
|
35
|
+
infinite: false,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const useReqorePaging = <T>(
|
|
39
|
+
options: IReqorePagingOptions<T> = defaultPagingOptions
|
|
40
|
+
): IReqorePagingResult<T> => {
|
|
41
|
+
const {
|
|
42
|
+
items,
|
|
43
|
+
itemsPerPage,
|
|
44
|
+
infinite,
|
|
45
|
+
pagesToShow,
|
|
46
|
+
startPage,
|
|
47
|
+
enabled = true,
|
|
48
|
+
}: IReqorePagingOptions<T> = merge({}, defaultPagingOptions, options);
|
|
49
|
+
const allPageCount = useMemo(() => Math.ceil(size(items) / itemsPerPage), [items, itemsPerPage]);
|
|
50
|
+
const { pagelist, currentPage, setPage, setTotalPage, goNext, goBefore } = usePagination({
|
|
51
|
+
numOfPage: allPageCount,
|
|
52
|
+
totalPage: allPageCount,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
setPage(startPage || 1);
|
|
57
|
+
}, [startPage]);
|
|
58
|
+
|
|
59
|
+
useUpdateEffect(() => {
|
|
60
|
+
setPage(1);
|
|
61
|
+
setTotalPage(Math.ceil(size(items) / itemsPerPage));
|
|
62
|
+
}, [size(items), itemsPerPage]);
|
|
63
|
+
|
|
64
|
+
const slicedItems: T[] = useMemo(() => {
|
|
65
|
+
return items.slice(infinite ? 0 : (currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
|
|
66
|
+
}, [items, currentPage, itemsPerPage, infinite]);
|
|
67
|
+
|
|
68
|
+
const pages: number[] = useMemo(() => {
|
|
69
|
+
if (!pagesToShow || pagesToShow >= allPageCount) {
|
|
70
|
+
return pagelist;
|
|
71
|
+
}
|
|
72
|
+
// Get the middle of the desired page count
|
|
73
|
+
const middle = Math.ceil(pagesToShow / 2);
|
|
74
|
+
// Get the start number of the pages to show
|
|
75
|
+
// If the current page is the last page, we need to subtract the number of pages to show from the total number of pages
|
|
76
|
+
const start =
|
|
77
|
+
currentPage === allPageCount ? allPageCount - pagesToShow : Math.max(currentPage - middle, 0);
|
|
78
|
+
// Get the end number of the pages to show
|
|
79
|
+
// If the start number is 0, we need to add the number of pages to show to the total number of pages
|
|
80
|
+
const end = Math.min(start + pagesToShow, allPageCount);
|
|
81
|
+
|
|
82
|
+
let newPages = pagelist.slice(start, end);
|
|
83
|
+
// Always remove the first page
|
|
84
|
+
newPages = newPages.filter((page) => page !== 1);
|
|
85
|
+
// Always remove the last page
|
|
86
|
+
newPages = newPages.filter((page) => page !== allPageCount);
|
|
87
|
+
// Add the first and last page
|
|
88
|
+
newPages = [1, ...newPages, allPageCount];
|
|
89
|
+
|
|
90
|
+
return newPages;
|
|
91
|
+
}, [pagesToShow, allPageCount, currentPage, pagelist]);
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
pages,
|
|
95
|
+
allPages: pagelist,
|
|
96
|
+
pageCount: allPageCount,
|
|
97
|
+
items: enabled ? slicedItems : items,
|
|
98
|
+
itemsPerPage,
|
|
99
|
+
itemsLeft: items.length - slicedItems.length,
|
|
100
|
+
infinite,
|
|
101
|
+
setPage,
|
|
102
|
+
currentPage,
|
|
103
|
+
next: goNext,
|
|
104
|
+
back: goBefore,
|
|
105
|
+
isLastPage: currentPage === allPageCount,
|
|
106
|
+
isFirstPage: currentPage === 1,
|
|
107
|
+
first: () => setPage(1),
|
|
108
|
+
last: () => setPage(allPageCount),
|
|
109
|
+
};
|
|
110
|
+
};
|
package/src/index.tsx
CHANGED
|
@@ -37,6 +37,7 @@ export { default as ReqoreNavbarGroup } from './components/Navbar/group';
|
|
|
37
37
|
export { default as ReqoreNavbarItem } from './components/Navbar/item';
|
|
38
38
|
export { default as ReqoreNotificationsWrapper } from './components/Notifications';
|
|
39
39
|
export { default as ReqoreNotification } from './components/Notifications/notification';
|
|
40
|
+
export { ReqorePagination } from './components/Paging';
|
|
40
41
|
export { ReqorePanel } from './components/Panel';
|
|
41
42
|
export { ReqoreP, ReqoreP as ReqoreParagraph } from './components/Paragraph';
|
|
42
43
|
export { default as ReqorePopover } from './components/Popover';
|
|
@@ -62,6 +63,7 @@ export { default as ReqoreUIProvider } from './containers/UIProvider';
|
|
|
62
63
|
export { default as ReqoreContext } from './context/ReqoreContext';
|
|
63
64
|
export { default as ReqoreThemeContext } from './context/ThemeContext';
|
|
64
65
|
export { default as useLatestZIndex } from './hooks/useLatestZIndex';
|
|
66
|
+
export { useReqorePaging } from './hooks/usePaging';
|
|
65
67
|
export { useReqore } from './hooks/useReqore';
|
|
66
68
|
export { useReqoreProperty } from './hooks/useReqoreContext';
|
|
67
69
|
export { useReqoreTheme } from './hooks/useTheme';
|
|
@@ -5,6 +5,25 @@ import ReqoreMessage from '../components/Message';
|
|
|
5
5
|
import { ReqoreP } from '../components/Paragraph';
|
|
6
6
|
import { ReqoreSpacer } from '../components/Spacer';
|
|
7
7
|
import ReqoreTag from '../components/Tag';
|
|
8
|
+
import data from './data.json';
|
|
9
|
+
|
|
10
|
+
export const bigCollection = data.slice(0, 100).map((datum) => ({
|
|
11
|
+
label: `${datum.firstName} ${datum.lastName}`,
|
|
12
|
+
badge: datum.id,
|
|
13
|
+
size: 'small',
|
|
14
|
+
expandable: true,
|
|
15
|
+
content: datum.address,
|
|
16
|
+
tags: [
|
|
17
|
+
{
|
|
18
|
+
labelKey: 'Age',
|
|
19
|
+
label: datum.age,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
labelKey: 'Occupation',
|
|
23
|
+
label: datum.occupation,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
})) as IReqoreCollectionItemProps[];
|
|
8
27
|
|
|
9
28
|
export default [
|
|
10
29
|
{
|