@7span/react-list 0.0.5 → 1.0.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/dist/react-list.js +400 -310
- package/dist/react-list.umd.cjs +1 -1
- package/package.json +11 -3
- package/src/components/attributes.jsx +53 -0
- package/src/components/empty.jsx +22 -0
- package/src/components/error.jsx +27 -0
- package/src/components/go-to.jsx +58 -0
- package/src/components/initial-loader.jsx +25 -0
- package/src/components/items.jsx +50 -0
- package/src/components/list.jsx +361 -0
- package/src/components/load-more.jsx +39 -0
- package/src/components/loader.jsx +29 -0
- package/src/components/pagination.jsx +158 -0
- package/src/components/per-page.jsx +65 -0
- package/src/components/refresh.jsx +34 -0
- package/src/components/search.jsx +59 -0
- package/src/components/summary.jsx +51 -0
- package/src/components/utils.js +42 -0
- package/src/context/list-provider.jsx +55 -0
- package/src/index.js +15 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { memo, useCallback, useMemo } from "react";
|
|
2
|
+
import { useListContext } from "../context/list-provider";
|
|
3
|
+
|
|
4
|
+
export const ReactListLoadMore = memo(({ children }) => {
|
|
5
|
+
const { listState } = useListContext();
|
|
6
|
+
const { data, count, pagination, setPage, loader, error } = listState;
|
|
7
|
+
const { page, perPage } = pagination;
|
|
8
|
+
const { isLoading } = loader;
|
|
9
|
+
|
|
10
|
+
const hasMoreItems = useMemo(
|
|
11
|
+
() => page * perPage < count,
|
|
12
|
+
[page, perPage, count]
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const loadMore = useCallback(() => {
|
|
16
|
+
if (hasMoreItems && !isLoading) {
|
|
17
|
+
setPage(page + 1);
|
|
18
|
+
}
|
|
19
|
+
}, [hasMoreItems, isLoading, setPage, page]);
|
|
20
|
+
|
|
21
|
+
const scope = useMemo(
|
|
22
|
+
() => ({
|
|
23
|
+
isLoading,
|
|
24
|
+
loadMore,
|
|
25
|
+
hasMoreItems,
|
|
26
|
+
}),
|
|
27
|
+
[isLoading, loadMore, hasMoreItems]
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
if (!data || data.length === 0) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (error) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return children(scope);
|
|
39
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { memo, useMemo } from "react";
|
|
2
|
+
import { useListContext } from "../context/list-provider";
|
|
3
|
+
|
|
4
|
+
export const ReactListLoader = memo(({ children, position = "overlay" }) => {
|
|
5
|
+
const { listState } = useListContext();
|
|
6
|
+
const { loader } = listState;
|
|
7
|
+
const { isLoading, initializingState } = loader;
|
|
8
|
+
|
|
9
|
+
const scope = useMemo(
|
|
10
|
+
() => ({
|
|
11
|
+
isLoading,
|
|
12
|
+
}),
|
|
13
|
+
[isLoading]
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
if (!initializingState && !isLoading) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div>
|
|
22
|
+
{children || (
|
|
23
|
+
<div>
|
|
24
|
+
<p>Loading...</p>
|
|
25
|
+
</div>
|
|
26
|
+
)}
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
});
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { memo, useMemo } from "react";
|
|
2
|
+
import { useListContext } from "../context/list-provider";
|
|
3
|
+
|
|
4
|
+
export const ReactListPagination = memo(
|
|
5
|
+
({
|
|
6
|
+
children,
|
|
7
|
+
pageLinks = 5,
|
|
8
|
+
renderFirst,
|
|
9
|
+
renderPrev,
|
|
10
|
+
renderPages,
|
|
11
|
+
renderPage,
|
|
12
|
+
renderNext,
|
|
13
|
+
renderLast,
|
|
14
|
+
}) => {
|
|
15
|
+
const { listState } = useListContext();
|
|
16
|
+
const { data, count, pagination, setPage, loader, error } = listState;
|
|
17
|
+
const { page, perPage } = pagination;
|
|
18
|
+
const { initialLoading, isLoading } = loader;
|
|
19
|
+
|
|
20
|
+
const paginationState = useMemo(() => {
|
|
21
|
+
const pagesCount = Math.ceil(count / perPage);
|
|
22
|
+
const halfWay = Math.floor(pageLinks / 2);
|
|
23
|
+
const hasNext = page * perPage < count;
|
|
24
|
+
const hasPrev = page !== 1;
|
|
25
|
+
return { pagesCount, halfWay, hasNext, hasPrev };
|
|
26
|
+
}, [count, perPage, page, pageLinks]);
|
|
27
|
+
|
|
28
|
+
const pagesToDisplay = useMemo(() => {
|
|
29
|
+
const { pagesCount, halfWay } = paginationState;
|
|
30
|
+
const pages = Array.from({ length: Math.min(pageLinks, pagesCount) });
|
|
31
|
+
|
|
32
|
+
if (page <= halfWay) {
|
|
33
|
+
return pages.map((_, index) => index + 1);
|
|
34
|
+
} else if (pagesCount - page < halfWay) {
|
|
35
|
+
return pages.map((_, index) => pagesCount - index).reverse();
|
|
36
|
+
} else {
|
|
37
|
+
return pages.map((_, index) => page - halfWay + index);
|
|
38
|
+
}
|
|
39
|
+
}, [page, pageLinks, paginationState]);
|
|
40
|
+
|
|
41
|
+
const navigation = useMemo(
|
|
42
|
+
() => ({
|
|
43
|
+
prev: () => setPage(page - 1),
|
|
44
|
+
next: () => setPage(page + 1),
|
|
45
|
+
first: () => setPage(1),
|
|
46
|
+
last: () => setPage(paginationState.pagesCount),
|
|
47
|
+
setPage: (newPage) => setPage(newPage),
|
|
48
|
+
}),
|
|
49
|
+
[setPage, page, paginationState.pagesCount]
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const scope = useMemo(
|
|
53
|
+
() => ({
|
|
54
|
+
page,
|
|
55
|
+
perPage,
|
|
56
|
+
count,
|
|
57
|
+
...paginationState,
|
|
58
|
+
pagesToDisplay,
|
|
59
|
+
...navigation,
|
|
60
|
+
}),
|
|
61
|
+
[page, perPage, count, paginationState, pagesToDisplay, navigation]
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (initialLoading) return null;
|
|
65
|
+
|
|
66
|
+
if (!data || data.length === 0) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (error) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (children) {
|
|
75
|
+
return children(scope);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div className="react-list-pagination">
|
|
80
|
+
{renderFirst ? (
|
|
81
|
+
renderFirst(scope)
|
|
82
|
+
) : (
|
|
83
|
+
<button
|
|
84
|
+
type="button"
|
|
85
|
+
disabled={!paginationState.hasPrev}
|
|
86
|
+
onClick={navigation.first}
|
|
87
|
+
>
|
|
88
|
+
First
|
|
89
|
+
</button>
|
|
90
|
+
)}
|
|
91
|
+
|
|
92
|
+
{renderPrev ? (
|
|
93
|
+
renderPrev(scope)
|
|
94
|
+
) : (
|
|
95
|
+
<button
|
|
96
|
+
type="button"
|
|
97
|
+
disabled={!paginationState.hasPrev}
|
|
98
|
+
onClick={navigation.prev}
|
|
99
|
+
>
|
|
100
|
+
Prev
|
|
101
|
+
</button>
|
|
102
|
+
)}
|
|
103
|
+
|
|
104
|
+
{renderPages ? (
|
|
105
|
+
renderPages(scope)
|
|
106
|
+
) : (
|
|
107
|
+
<div>
|
|
108
|
+
{pagesToDisplay.map((pageNum) => {
|
|
109
|
+
const isActive = pageNum === page;
|
|
110
|
+
const pageScope = { ...scope, page: pageNum, isActive };
|
|
111
|
+
|
|
112
|
+
return renderPage ? (
|
|
113
|
+
renderPage(pageScope)
|
|
114
|
+
) : (
|
|
115
|
+
<div key={`page-${pageNum}`}>
|
|
116
|
+
{isActive ? (
|
|
117
|
+
<span>{pageNum}</span>
|
|
118
|
+
) : (
|
|
119
|
+
<button
|
|
120
|
+
type="button"
|
|
121
|
+
onClick={() => navigation.setPage(pageNum)}
|
|
122
|
+
>
|
|
123
|
+
{pageNum}
|
|
124
|
+
</button>
|
|
125
|
+
)}
|
|
126
|
+
</div>
|
|
127
|
+
);
|
|
128
|
+
})}
|
|
129
|
+
</div>
|
|
130
|
+
)}
|
|
131
|
+
|
|
132
|
+
{renderNext ? (
|
|
133
|
+
renderNext(scope)
|
|
134
|
+
) : (
|
|
135
|
+
<button
|
|
136
|
+
type="button"
|
|
137
|
+
disabled={!paginationState.hasNext}
|
|
138
|
+
onClick={navigation.next}
|
|
139
|
+
>
|
|
140
|
+
Next
|
|
141
|
+
</button>
|
|
142
|
+
)}
|
|
143
|
+
|
|
144
|
+
{renderLast ? (
|
|
145
|
+
renderLast(scope)
|
|
146
|
+
) : (
|
|
147
|
+
<button
|
|
148
|
+
type="button"
|
|
149
|
+
disabled={!paginationState.hasNext}
|
|
150
|
+
onClick={navigation.last}
|
|
151
|
+
>
|
|
152
|
+
Last
|
|
153
|
+
</button>
|
|
154
|
+
)}
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { memo, useCallback, useMemo } from "react";
|
|
2
|
+
import { useListContext } from "../context/list-provider";
|
|
3
|
+
|
|
4
|
+
export const ReactListPerPage = memo(
|
|
5
|
+
({ children, options = [10, 25, 50, 100] }) => {
|
|
6
|
+
const { listState } = useListContext();
|
|
7
|
+
const { data, pagination, setPerPage, loader, error } = listState;
|
|
8
|
+
const { perPage } = pagination;
|
|
9
|
+
const { initialLoading } = loader;
|
|
10
|
+
|
|
11
|
+
const serializedOptions = useMemo(() => {
|
|
12
|
+
return options.map((item) => {
|
|
13
|
+
if (typeof item !== "object") {
|
|
14
|
+
return {
|
|
15
|
+
value: item,
|
|
16
|
+
label: item,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return item;
|
|
20
|
+
});
|
|
21
|
+
}, [options]);
|
|
22
|
+
|
|
23
|
+
const handlePerPageChange = useCallback(
|
|
24
|
+
(e) => {
|
|
25
|
+
setPerPage(Number(e.target.value));
|
|
26
|
+
},
|
|
27
|
+
[setPerPage]
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const scope = useMemo(
|
|
31
|
+
() => ({
|
|
32
|
+
perPage,
|
|
33
|
+
setPerPage,
|
|
34
|
+
options: serializedOptions,
|
|
35
|
+
}),
|
|
36
|
+
[perPage, setPerPage, serializedOptions]
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (initialLoading) return null;
|
|
40
|
+
|
|
41
|
+
if (!data || data.length === 0) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (error) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div className="react-list-per-page">
|
|
51
|
+
{children ? (
|
|
52
|
+
children(scope)
|
|
53
|
+
) : (
|
|
54
|
+
<select value={perPage} onChange={handlePerPageChange}>
|
|
55
|
+
{serializedOptions.map((option) => (
|
|
56
|
+
<option key={`option-${option.value}`} value={option.value}>
|
|
57
|
+
{option.label} items per page
|
|
58
|
+
</option>
|
|
59
|
+
))}
|
|
60
|
+
</select>
|
|
61
|
+
)}
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { memo, useCallback, useMemo } from "react";
|
|
2
|
+
import { useListContext } from "../context/list-provider";
|
|
3
|
+
|
|
4
|
+
export const ReactListRefresh = memo(({ children }) => {
|
|
5
|
+
const { listState } = useListContext();
|
|
6
|
+
const { loader, refresh } = listState;
|
|
7
|
+
const { isLoading, initialLoading } = loader;
|
|
8
|
+
|
|
9
|
+
const handleRefresh = useCallback(() => {
|
|
10
|
+
refresh({ isRefresh: true });
|
|
11
|
+
}, [refresh]);
|
|
12
|
+
|
|
13
|
+
const scope = useMemo(
|
|
14
|
+
() => ({
|
|
15
|
+
isLoading,
|
|
16
|
+
refresh: handleRefresh,
|
|
17
|
+
}),
|
|
18
|
+
[isLoading, handleRefresh]
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
if (initialLoading) return null;
|
|
22
|
+
|
|
23
|
+
if (children) {
|
|
24
|
+
return children(scope);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="react-list-refresh">
|
|
29
|
+
<button onClick={handleRefresh} disabled={isLoading}>
|
|
30
|
+
{isLoading ? "Loading..." : "Refresh"}
|
|
31
|
+
</button>
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { memo, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { useListContext } from "../context/list-provider";
|
|
3
|
+
|
|
4
|
+
export const ReactListSearch = memo(({ children, debounceTime = 500 }) => {
|
|
5
|
+
const { listState } = useListContext();
|
|
6
|
+
const { search, setSearch } = listState;
|
|
7
|
+
const [localSearch, setLocalSearch] = useState(search ?? "");
|
|
8
|
+
const debounceTimerRef = useRef(null);
|
|
9
|
+
|
|
10
|
+
// Sync local state with context when search prop changes
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (search !== localSearch) {
|
|
13
|
+
setLocalSearch(search ?? "");
|
|
14
|
+
}
|
|
15
|
+
}, [search]);
|
|
16
|
+
|
|
17
|
+
const handleChange = (value) => {
|
|
18
|
+
setLocalSearch(value);
|
|
19
|
+
|
|
20
|
+
// Clear any existing timer
|
|
21
|
+
if (debounceTimerRef.current) {
|
|
22
|
+
clearTimeout(debounceTimerRef.current);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Set a new timer
|
|
26
|
+
debounceTimerRef.current = setTimeout(() => {
|
|
27
|
+
setSearch(value);
|
|
28
|
+
}, debounceTime);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Clean up timer on unmount
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
return () => {
|
|
34
|
+
if (debounceTimerRef.current) {
|
|
35
|
+
clearTimeout(debounceTimerRef.current);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}, []);
|
|
39
|
+
|
|
40
|
+
const scope = {
|
|
41
|
+
search: localSearch,
|
|
42
|
+
setSearch: handleChange,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div className="react-list-search">
|
|
47
|
+
{children ? (
|
|
48
|
+
children(scope)
|
|
49
|
+
) : (
|
|
50
|
+
<input
|
|
51
|
+
type="text"
|
|
52
|
+
value={localSearch}
|
|
53
|
+
onChange={(e) => handleChange(e.target.value)}
|
|
54
|
+
placeholder="Search..."
|
|
55
|
+
/>
|
|
56
|
+
)}
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { memo, useMemo } from "react";
|
|
2
|
+
import { useListContext } from "../context/list-provider";
|
|
3
|
+
|
|
4
|
+
export const ReactListSummary = memo(({ children }) => {
|
|
5
|
+
const { listState } = useListContext();
|
|
6
|
+
const { data, count, pagination, loader, error } = listState;
|
|
7
|
+
const { page, perPage } = pagination;
|
|
8
|
+
const { initialLoading, isLoading } = loader;
|
|
9
|
+
|
|
10
|
+
const summaryData = useMemo(() => {
|
|
11
|
+
const from = page * perPage - perPage + 1;
|
|
12
|
+
const to = Math.min(page * perPage, count);
|
|
13
|
+
const visibleCount = data?.length || 0;
|
|
14
|
+
|
|
15
|
+
return { from, to, visibleCount };
|
|
16
|
+
}, [page, perPage, count, data]);
|
|
17
|
+
|
|
18
|
+
const scope = useMemo(
|
|
19
|
+
() => ({
|
|
20
|
+
...summaryData,
|
|
21
|
+
count,
|
|
22
|
+
}),
|
|
23
|
+
[summaryData, count]
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
if (initialLoading) return null;
|
|
27
|
+
|
|
28
|
+
if (!data || data.length === 0) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (error) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div className="react-list-summary">
|
|
38
|
+
{children ? (
|
|
39
|
+
children(scope)
|
|
40
|
+
) : (
|
|
41
|
+
<span>
|
|
42
|
+
Showing <span>{summaryData.visibleCount}</span> items (
|
|
43
|
+
<span>
|
|
44
|
+
{summaryData.from} - {summaryData.to}
|
|
45
|
+
</span>
|
|
46
|
+
) out of <span>{count}</span>
|
|
47
|
+
</span>
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export const deepEqual = (obj1, obj2) => {
|
|
2
|
+
if (obj1 === obj2) return true;
|
|
3
|
+
|
|
4
|
+
if (obj1 == null || obj2 == null) return obj1 === obj2;
|
|
5
|
+
|
|
6
|
+
if (typeof obj1 !== "object" || typeof obj2 !== "object")
|
|
7
|
+
return obj1 === obj2;
|
|
8
|
+
|
|
9
|
+
if (Array.isArray(obj1) && Array.isArray(obj2)) {
|
|
10
|
+
if (obj1.length !== obj2.length) return false;
|
|
11
|
+
for (let i = 0; i < obj1.length; i++) {
|
|
12
|
+
if (!deepEqual(obj1[i], obj2[i])) return false;
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (Array.isArray(obj1) || Array.isArray(obj2)) return false;
|
|
18
|
+
|
|
19
|
+
const keys1 = Object.keys(obj1).filter((key) => obj1[key] !== undefined);
|
|
20
|
+
const keys2 = Object.keys(obj2).filter((key) => obj2[key] !== undefined);
|
|
21
|
+
|
|
22
|
+
if (keys1.length !== keys2.length) return false;
|
|
23
|
+
|
|
24
|
+
for (let key of keys1) {
|
|
25
|
+
if (!keys2.includes(key)) return false;
|
|
26
|
+
if (!deepEqual(obj1[key], obj2[key])) return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return true;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const hasActiveFilters = (currentFilters, initialFilters) => {
|
|
33
|
+
if (!initialFilters || Object.keys(initialFilters).length === 0) {
|
|
34
|
+
return currentFilters && Object.keys(currentFilters).length > 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!currentFilters || Object.keys(currentFilters).length === 0) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return !deepEqual(currentFilters, initialFilters);
|
|
42
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createContext, useContext, useMemo, useState } from "react";
|
|
2
|
+
|
|
3
|
+
const ListContext = createContext(null);
|
|
4
|
+
|
|
5
|
+
export const ReactListProvider = ({ children, config }) => {
|
|
6
|
+
const { requestHandler, stateManager = {} } = config;
|
|
7
|
+
const [listState, setListState] = useState({
|
|
8
|
+
data: [],
|
|
9
|
+
response: null,
|
|
10
|
+
error: null,
|
|
11
|
+
count: 0,
|
|
12
|
+
selection: [],
|
|
13
|
+
pagination: {
|
|
14
|
+
page: 1,
|
|
15
|
+
perPage: 25,
|
|
16
|
+
},
|
|
17
|
+
loader: {
|
|
18
|
+
isLoading: false,
|
|
19
|
+
initialLoading: true,
|
|
20
|
+
},
|
|
21
|
+
sort: {
|
|
22
|
+
sortBy: null,
|
|
23
|
+
sortOrder: "desc",
|
|
24
|
+
},
|
|
25
|
+
search: "",
|
|
26
|
+
filters: {},
|
|
27
|
+
attrs: [],
|
|
28
|
+
isEmpty: true,
|
|
29
|
+
isInitializing: true,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (!requestHandler) {
|
|
33
|
+
throw new Error("ListProvider: requestHandler is required.");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const value = useMemo(
|
|
37
|
+
() => ({
|
|
38
|
+
requestHandler,
|
|
39
|
+
stateManager,
|
|
40
|
+
listState,
|
|
41
|
+
setListState,
|
|
42
|
+
}),
|
|
43
|
+
[requestHandler, stateManager, listState]
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
return <ListContext.Provider value={value}>{children}</ListContext.Provider>;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const useListContext = () => {
|
|
50
|
+
const context = useContext(ListContext);
|
|
51
|
+
if (!context) {
|
|
52
|
+
throw new Error("useListContext must be used within a ListProvider");
|
|
53
|
+
}
|
|
54
|
+
return context;
|
|
55
|
+
};
|
package/src/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { ReactListAttributes } from "./components/attributes";
|
|
2
|
+
export { ReactListEmpty } from "./components/empty";
|
|
3
|
+
export { ReactListError } from "./components/error";
|
|
4
|
+
export { ReactListGoTo } from "./components/go-to";
|
|
5
|
+
export { ReactListInitialLoader } from "./components/initial-loader";
|
|
6
|
+
export { ReactListItems } from "./components/items";
|
|
7
|
+
export { default } from "./components/list";
|
|
8
|
+
export { ReactListLoadMore } from "./components/load-more";
|
|
9
|
+
export { ReactListLoader } from "./components/loader";
|
|
10
|
+
export { ReactListPagination } from "./components/pagination";
|
|
11
|
+
export { ReactListPerPage } from "./components/per-page";
|
|
12
|
+
export { ReactListRefresh } from "./components/refresh";
|
|
13
|
+
export { ReactListSearch } from "./components/search";
|
|
14
|
+
export { ReactListSummary } from "./components/summary";
|
|
15
|
+
export { ReactListProvider } from "./context/list-provider";
|