react-resource-ui 0.1.1 → 0.1.3

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/index.cjs CHANGED
@@ -73,64 +73,84 @@ function useResource(config) {
73
73
  const getData = (0, import_react.useMemo)(() => normalizeSource(source), [source]);
74
74
  const prevScrollTop = (0, import_react.useRef)(0);
75
75
  const scrollRef = (0, import_react.useRef)(null);
76
- const hasMore = (0, import_react.useRef)(true);
77
- async function asyncNormalize() {
76
+ const [hasNext, setHasNext] = (0, import_react.useState)(true);
77
+ const total = (0, import_react.useRef)(null);
78
+ async function asyncNormalize(localPage) {
78
79
  const params = {
79
- page,
80
+ page: localPage,
80
81
  pageSize
81
82
  };
82
- setLoading(true);
83
- requestTracker.current += 1;
84
- const currentRequestId = requestTracker.current;
85
- setError(null);
86
83
  try {
87
84
  const rawData = await getData(params);
88
- if (currentRequestId !== requestTracker.current) {
89
- setLoading(false);
90
- return;
91
- }
92
- ;
93
- setLoading(false);
94
- return rawData;
85
+ return { data: rawData, error: null };
95
86
  } catch (err) {
96
- if (currentRequestId === requestTracker.current) {
97
- if (err instanceof Error) {
98
- setError(err);
99
- } else {
100
- setError(new Error("unknown error"));
101
- }
102
- setLoading(false);
103
- }
87
+ return {
88
+ data: null,
89
+ error: err instanceof Error ? err : new Error("unknown error")
90
+ };
104
91
  }
105
92
  }
106
93
  async function orchestrator() {
107
94
  const isPageMode = pagination?.type === "page";
108
95
  prevScrollTop.current = scrollTop;
109
- const cached = cache.current[page];
110
- if (isPageMode) {
111
- if (cached) {
112
- setData(cached);
113
- return;
96
+ const localPage = page;
97
+ const cached = cache.current[localPage];
98
+ if (isPageMode && cached) {
99
+ setData(cached);
100
+ return;
101
+ }
102
+ setHasNext(true);
103
+ total.current = null;
104
+ requestTracker.current += 1;
105
+ const currentRequestId = requestTracker.current;
106
+ setLoading(true);
107
+ setError(null);
108
+ const result = await asyncNormalize(localPage);
109
+ if (currentRequestId !== requestTracker.current) {
110
+ setLoading(false);
111
+ return;
112
+ }
113
+ ;
114
+ setLoading(false);
115
+ if (result.error) {
116
+ setError(result.error);
117
+ return;
118
+ }
119
+ let rawData;
120
+ if (Array.isArray(result.data)) {
121
+ rawData = result.data;
122
+ } else {
123
+ total.current = result.data.total;
124
+ rawData = result.data.data;
125
+ }
126
+ if (total.current !== null) {
127
+ setHasNext(localPage < Math.ceil(total.current / pageSize));
128
+ } else {
129
+ if (rawData.length < pageSize) {
130
+ setHasNext(false);
114
131
  }
115
132
  }
116
- const rawData = await asyncNormalize();
117
133
  if (!rawData) return;
118
- if (rawData.length < pageSize) hasMore.current = false;
119
134
  setData((prev) => {
120
135
  if (isPageMode) return rawData;
121
- return page === 1 ? rawData : [...prev, ...rawData];
136
+ const indexStart = (localPage - 1) * pageSize;
137
+ const newData = [...prev];
138
+ for (let i = 0; i < rawData.length; i++) {
139
+ newData[indexStart + i] = rawData[i];
140
+ }
141
+ return newData;
122
142
  });
123
143
  if (isPageMode) {
124
- cache.current[page] = rawData;
144
+ cache.current[localPage] = rawData;
125
145
  Object.keys(cache.current).forEach((val) => {
126
- if (Math.abs(page - +val) > 1) {
146
+ if (Math.abs(localPage - +val) > 1) {
127
147
  delete cache.current[+val];
128
148
  }
129
149
  });
130
150
  }
131
151
  }
132
152
  (0, import_react.useEffect)(() => {
133
- if (!hasMore.current) return;
153
+ if (!hasNext) return;
134
154
  if (pagination?.type !== "infinite") return;
135
155
  const el = scrollRef.current;
136
156
  if (!el) return;
@@ -140,7 +160,7 @@ function useResource(config) {
140
160
  setPage((prev) => prev + 1);
141
161
  })();
142
162
  }
143
- }, [scrollTop, pagination?.type, loading]);
163
+ }, [scrollTop, pagination?.type, loading, hasNext]);
144
164
  (0, import_react.useEffect)(() => {
145
165
  orchestrator();
146
166
  }, [page, pageSize, source, pagination?.type]);
@@ -163,39 +183,59 @@ function useResource(config) {
163
183
  let offsetY = 0;
164
184
  let totalHeight = 0;
165
185
  if (shouldVirtualize) {
166
- const total = data.length;
186
+ const total2 = data.length;
167
187
  const rawStart = Math.floor(scrollTop / itemHeight);
168
188
  const startIndex = Math.max(0, rawStart - 2);
169
189
  const visibleCount = Math.ceil(containerHeight / itemHeight);
170
- const endIndex = Math.min(startIndex + visibleCount + 4, total);
190
+ const endIndex = Math.min(startIndex + visibleCount + 4, total2);
171
191
  finalData = data.slice(startIndex, endIndex);
172
192
  offsetY = itemHeight * startIndex;
173
- totalHeight = total * itemHeight;
193
+ totalHeight = total2 * itemHeight;
174
194
  }
175
- return { data: finalData, loading, error, page, setPage, setScrollTop, offsetY, totalHeight, totalItems: data.length, scrollRef };
195
+ return { data: finalData, loading, error, page, setPage, setScrollTop, offsetY, totalHeight, totalItems: data.length, scrollRef, hasNext };
176
196
  }
177
197
 
178
198
  // src/components/DataTable.tsx
179
- var import_react2 = require("react");
180
199
  var import_jsx_runtime = require("react/jsx-runtime");
181
200
  function DataTable(props) {
182
- const { data, loading, error, page, setPage, setScrollTop, type, virtualization } = props;
183
- const isFetchingRef = (0, import_react2.useRef)(false);
184
- (0, import_react2.useEffect)(() => {
185
- isFetchingRef.current = false;
186
- }, [data]);
201
+ const {
202
+ data,
203
+ loading,
204
+ error,
205
+ page,
206
+ setPage,
207
+ setScrollTop,
208
+ type,
209
+ virtualization,
210
+ hasNext
211
+ } = props;
212
+ const offsetY = props.offsetY ?? 0;
213
+ const totalHeight = props.totalHeight ?? 0;
214
+ const itemHeight = 50;
215
+ const colCount = data[0] ? Object.keys(data[0]).length : 1;
187
216
  if (loading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: "Loading..." });
188
217
  if (error) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: error.message });
189
- if ((props.totalItems ?? data.length) === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "No Data to create Table" });
218
+ if ((props.totalItems ?? data.length) === 0)
219
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "No Data to create Table" });
190
220
  const content = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { children: [
191
221
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: Object.keys(data[0]).map((val) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: val }, val)) }) }),
192
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: data.map((val, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: Object.keys(val).map((key) => {
193
- const value = val[key];
194
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: value != null ? value.toString() : "-" }, key);
195
- }) }, index)) })
222
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tbody", { children: [
223
+ virtualization && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { style: { height: offsetY }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { colSpan: colCount }) }),
224
+ data.map((val, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: Object.keys(val).map((key) => {
225
+ const value = val[key];
226
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cell", children: value != null ? value.toString() : "-" }) }, key);
227
+ }) }, index)),
228
+ virtualization && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
229
+ "tr",
230
+ {
231
+ style: {
232
+ height: totalHeight - offsetY - data.length * itemHeight
233
+ },
234
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { colSpan: colCount })
235
+ }
236
+ )
237
+ ] })
196
238
  ] });
197
- const offsetY = props.offsetY ?? 0;
198
- const totalHeight = props.totalHeight ?? 0;
199
239
  const finalTable = virtualization ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
200
240
  "div",
201
241
  {
@@ -204,29 +244,33 @@ function DataTable(props) {
204
244
  onScroll: (e) => {
205
245
  setScrollTop(e.currentTarget.scrollTop);
206
246
  },
207
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: totalHeight, position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
208
- "div",
209
- {
210
- style: {
211
- transform: `translateY(${offsetY}px)`,
212
- position: "absolute",
213
- top: 0,
214
- left: 0,
215
- right: 0
216
- },
217
- children: content
218
- }
219
- ) })
247
+ children: content
220
248
  }
221
249
  ) : content;
222
250
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
223
251
  type === "page" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
224
252
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setPage((prev) => Math.max(prev - 1, 1)), children: "prev" }),
225
253
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: page }),
226
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setPage((prev) => prev + 1), children: "next" })
254
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
255
+ "button",
256
+ {
257
+ onClick: () => setPage((prev) => {
258
+ if (hasNext) return prev + 1;
259
+ return prev;
260
+ }),
261
+ children: "next"
262
+ }
263
+ )
227
264
  ] }),
228
265
  finalTable,
229
- type === "loadmore" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setPage((prev) => prev + 1), children: "load more" })
266
+ type === "loadmore" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
267
+ "button",
268
+ {
269
+ disabled: !hasNext,
270
+ onClick: () => setPage((prev) => prev + 1),
271
+ children: "load more"
272
+ }
273
+ )
230
274
  ] });
231
275
  }
232
276
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.d.cts CHANGED
@@ -5,7 +5,10 @@ type ResourceParams = {
5
5
  page?: number;
6
6
  pageSize?: number;
7
7
  };
8
- type Source<T> = T[] | string | ((params: ResourceParams) => Promise<T[]>);
8
+ type Source<T> = T[] | string | ((params: ResourceParams) => Promise<T[] | {
9
+ data: T[];
10
+ total: number;
11
+ }>);
9
12
 
10
13
  type PaginationConfig = {
11
14
  type: "page" | "loadmore" | "infinite";
@@ -32,6 +35,7 @@ declare function useResource<T>(config: Config<T>): {
32
35
  totalHeight: number;
33
36
  totalItems: number;
34
37
  scrollRef: react.RefObject<HTMLDivElement | null>;
38
+ hasNext: boolean;
35
39
  };
36
40
 
37
41
  type DataTableProps<T extends Record<string, unknown>> = {
@@ -47,6 +51,7 @@ type DataTableProps<T extends Record<string, unknown>> = {
47
51
  totalHeight?: number;
48
52
  totalItems?: number;
49
53
  scrollRef?: React.RefObject<HTMLDivElement> | null;
54
+ hasNext: boolean;
50
55
  };
51
56
  declare function DataTable<T extends Record<string, unknown>>(props: DataTableProps<T>): react_jsx_runtime.JSX.Element;
52
57
 
package/dist/index.d.ts CHANGED
@@ -5,7 +5,10 @@ type ResourceParams = {
5
5
  page?: number;
6
6
  pageSize?: number;
7
7
  };
8
- type Source<T> = T[] | string | ((params: ResourceParams) => Promise<T[]>);
8
+ type Source<T> = T[] | string | ((params: ResourceParams) => Promise<T[] | {
9
+ data: T[];
10
+ total: number;
11
+ }>);
9
12
 
10
13
  type PaginationConfig = {
11
14
  type: "page" | "loadmore" | "infinite";
@@ -32,6 +35,7 @@ declare function useResource<T>(config: Config<T>): {
32
35
  totalHeight: number;
33
36
  totalItems: number;
34
37
  scrollRef: react.RefObject<HTMLDivElement | null>;
38
+ hasNext: boolean;
35
39
  };
36
40
 
37
41
  type DataTableProps<T extends Record<string, unknown>> = {
@@ -47,6 +51,7 @@ type DataTableProps<T extends Record<string, unknown>> = {
47
51
  totalHeight?: number;
48
52
  totalItems?: number;
49
53
  scrollRef?: React.RefObject<HTMLDivElement> | null;
54
+ hasNext: boolean;
50
55
  };
51
56
  declare function DataTable<T extends Record<string, unknown>>(props: DataTableProps<T>): react_jsx_runtime.JSX.Element;
52
57
 
package/dist/index.js CHANGED
@@ -46,64 +46,84 @@ function useResource(config) {
46
46
  const getData = useMemo(() => normalizeSource(source), [source]);
47
47
  const prevScrollTop = useRef(0);
48
48
  const scrollRef = useRef(null);
49
- const hasMore = useRef(true);
50
- async function asyncNormalize() {
49
+ const [hasNext, setHasNext] = useState(true);
50
+ const total = useRef(null);
51
+ async function asyncNormalize(localPage) {
51
52
  const params = {
52
- page,
53
+ page: localPage,
53
54
  pageSize
54
55
  };
55
- setLoading(true);
56
- requestTracker.current += 1;
57
- const currentRequestId = requestTracker.current;
58
- setError(null);
59
56
  try {
60
57
  const rawData = await getData(params);
61
- if (currentRequestId !== requestTracker.current) {
62
- setLoading(false);
63
- return;
64
- }
65
- ;
66
- setLoading(false);
67
- return rawData;
58
+ return { data: rawData, error: null };
68
59
  } catch (err) {
69
- if (currentRequestId === requestTracker.current) {
70
- if (err instanceof Error) {
71
- setError(err);
72
- } else {
73
- setError(new Error("unknown error"));
74
- }
75
- setLoading(false);
76
- }
60
+ return {
61
+ data: null,
62
+ error: err instanceof Error ? err : new Error("unknown error")
63
+ };
77
64
  }
78
65
  }
79
66
  async function orchestrator() {
80
67
  const isPageMode = pagination?.type === "page";
81
68
  prevScrollTop.current = scrollTop;
82
- const cached = cache.current[page];
83
- if (isPageMode) {
84
- if (cached) {
85
- setData(cached);
86
- return;
69
+ const localPage = page;
70
+ const cached = cache.current[localPage];
71
+ if (isPageMode && cached) {
72
+ setData(cached);
73
+ return;
74
+ }
75
+ setHasNext(true);
76
+ total.current = null;
77
+ requestTracker.current += 1;
78
+ const currentRequestId = requestTracker.current;
79
+ setLoading(true);
80
+ setError(null);
81
+ const result = await asyncNormalize(localPage);
82
+ if (currentRequestId !== requestTracker.current) {
83
+ setLoading(false);
84
+ return;
85
+ }
86
+ ;
87
+ setLoading(false);
88
+ if (result.error) {
89
+ setError(result.error);
90
+ return;
91
+ }
92
+ let rawData;
93
+ if (Array.isArray(result.data)) {
94
+ rawData = result.data;
95
+ } else {
96
+ total.current = result.data.total;
97
+ rawData = result.data.data;
98
+ }
99
+ if (total.current !== null) {
100
+ setHasNext(localPage < Math.ceil(total.current / pageSize));
101
+ } else {
102
+ if (rawData.length < pageSize) {
103
+ setHasNext(false);
87
104
  }
88
105
  }
89
- const rawData = await asyncNormalize();
90
106
  if (!rawData) return;
91
- if (rawData.length < pageSize) hasMore.current = false;
92
107
  setData((prev) => {
93
108
  if (isPageMode) return rawData;
94
- return page === 1 ? rawData : [...prev, ...rawData];
109
+ const indexStart = (localPage - 1) * pageSize;
110
+ const newData = [...prev];
111
+ for (let i = 0; i < rawData.length; i++) {
112
+ newData[indexStart + i] = rawData[i];
113
+ }
114
+ return newData;
95
115
  });
96
116
  if (isPageMode) {
97
- cache.current[page] = rawData;
117
+ cache.current[localPage] = rawData;
98
118
  Object.keys(cache.current).forEach((val) => {
99
- if (Math.abs(page - +val) > 1) {
119
+ if (Math.abs(localPage - +val) > 1) {
100
120
  delete cache.current[+val];
101
121
  }
102
122
  });
103
123
  }
104
124
  }
105
125
  useEffect(() => {
106
- if (!hasMore.current) return;
126
+ if (!hasNext) return;
107
127
  if (pagination?.type !== "infinite") return;
108
128
  const el = scrollRef.current;
109
129
  if (!el) return;
@@ -113,7 +133,7 @@ function useResource(config) {
113
133
  setPage((prev) => prev + 1);
114
134
  })();
115
135
  }
116
- }, [scrollTop, pagination?.type, loading]);
136
+ }, [scrollTop, pagination?.type, loading, hasNext]);
117
137
  useEffect(() => {
118
138
  orchestrator();
119
139
  }, [page, pageSize, source, pagination?.type]);
@@ -136,39 +156,59 @@ function useResource(config) {
136
156
  let offsetY = 0;
137
157
  let totalHeight = 0;
138
158
  if (shouldVirtualize) {
139
- const total = data.length;
159
+ const total2 = data.length;
140
160
  const rawStart = Math.floor(scrollTop / itemHeight);
141
161
  const startIndex = Math.max(0, rawStart - 2);
142
162
  const visibleCount = Math.ceil(containerHeight / itemHeight);
143
- const endIndex = Math.min(startIndex + visibleCount + 4, total);
163
+ const endIndex = Math.min(startIndex + visibleCount + 4, total2);
144
164
  finalData = data.slice(startIndex, endIndex);
145
165
  offsetY = itemHeight * startIndex;
146
- totalHeight = total * itemHeight;
166
+ totalHeight = total2 * itemHeight;
147
167
  }
148
- return { data: finalData, loading, error, page, setPage, setScrollTop, offsetY, totalHeight, totalItems: data.length, scrollRef };
168
+ return { data: finalData, loading, error, page, setPage, setScrollTop, offsetY, totalHeight, totalItems: data.length, scrollRef, hasNext };
149
169
  }
150
170
 
151
171
  // src/components/DataTable.tsx
152
- import { useEffect as useEffect2, useRef as useRef2 } from "react";
153
172
  import { jsx, jsxs } from "react/jsx-runtime";
154
173
  function DataTable(props) {
155
- const { data, loading, error, page, setPage, setScrollTop, type, virtualization } = props;
156
- const isFetchingRef = useRef2(false);
157
- useEffect2(() => {
158
- isFetchingRef.current = false;
159
- }, [data]);
174
+ const {
175
+ data,
176
+ loading,
177
+ error,
178
+ page,
179
+ setPage,
180
+ setScrollTop,
181
+ type,
182
+ virtualization,
183
+ hasNext
184
+ } = props;
185
+ const offsetY = props.offsetY ?? 0;
186
+ const totalHeight = props.totalHeight ?? 0;
187
+ const itemHeight = 50;
188
+ const colCount = data[0] ? Object.keys(data[0]).length : 1;
160
189
  if (loading) return /* @__PURE__ */ jsx("div", { children: "Loading..." });
161
190
  if (error) return /* @__PURE__ */ jsx("div", { children: error.message });
162
- if ((props.totalItems ?? data.length) === 0) return /* @__PURE__ */ jsx("p", { children: "No Data to create Table" });
191
+ if ((props.totalItems ?? data.length) === 0)
192
+ return /* @__PURE__ */ jsx("p", { children: "No Data to create Table" });
163
193
  const content = /* @__PURE__ */ jsxs("table", { children: [
164
194
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: Object.keys(data[0]).map((val) => /* @__PURE__ */ jsx("th", { children: val }, val)) }) }),
165
- /* @__PURE__ */ jsx("tbody", { children: data.map((val, index) => /* @__PURE__ */ jsx("tr", { children: Object.keys(val).map((key) => {
166
- const value = val[key];
167
- return /* @__PURE__ */ jsx("td", { children: value != null ? value.toString() : "-" }, key);
168
- }) }, index)) })
195
+ /* @__PURE__ */ jsxs("tbody", { children: [
196
+ virtualization && /* @__PURE__ */ jsx("tr", { style: { height: offsetY }, children: /* @__PURE__ */ jsx("td", { colSpan: colCount }) }),
197
+ data.map((val, index) => /* @__PURE__ */ jsx("tr", { children: Object.keys(val).map((key) => {
198
+ const value = val[key];
199
+ return /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("div", { className: "cell", children: value != null ? value.toString() : "-" }) }, key);
200
+ }) }, index)),
201
+ virtualization && /* @__PURE__ */ jsx(
202
+ "tr",
203
+ {
204
+ style: {
205
+ height: totalHeight - offsetY - data.length * itemHeight
206
+ },
207
+ children: /* @__PURE__ */ jsx("td", { colSpan: colCount })
208
+ }
209
+ )
210
+ ] })
169
211
  ] });
170
- const offsetY = props.offsetY ?? 0;
171
- const totalHeight = props.totalHeight ?? 0;
172
212
  const finalTable = virtualization ? /* @__PURE__ */ jsx(
173
213
  "div",
174
214
  {
@@ -177,29 +217,33 @@ function DataTable(props) {
177
217
  onScroll: (e) => {
178
218
  setScrollTop(e.currentTarget.scrollTop);
179
219
  },
180
- children: /* @__PURE__ */ jsx("div", { style: { height: totalHeight, position: "relative" }, children: /* @__PURE__ */ jsx(
181
- "div",
182
- {
183
- style: {
184
- transform: `translateY(${offsetY}px)`,
185
- position: "absolute",
186
- top: 0,
187
- left: 0,
188
- right: 0
189
- },
190
- children: content
191
- }
192
- ) })
220
+ children: content
193
221
  }
194
222
  ) : content;
195
223
  return /* @__PURE__ */ jsxs("div", { children: [
196
224
  type === "page" && /* @__PURE__ */ jsxs("div", { children: [
197
225
  /* @__PURE__ */ jsx("button", { onClick: () => setPage((prev) => Math.max(prev - 1, 1)), children: "prev" }),
198
226
  /* @__PURE__ */ jsx("span", { children: page }),
199
- /* @__PURE__ */ jsx("button", { onClick: () => setPage((prev) => prev + 1), children: "next" })
227
+ /* @__PURE__ */ jsx(
228
+ "button",
229
+ {
230
+ onClick: () => setPage((prev) => {
231
+ if (hasNext) return prev + 1;
232
+ return prev;
233
+ }),
234
+ children: "next"
235
+ }
236
+ )
200
237
  ] }),
201
238
  finalTable,
202
- type === "loadmore" && /* @__PURE__ */ jsx("button", { onClick: () => setPage((prev) => prev + 1), children: "load more" })
239
+ type === "loadmore" && /* @__PURE__ */ jsx(
240
+ "button",
241
+ {
242
+ disabled: !hasNext,
243
+ onClick: () => setPage((prev) => prev + 1),
244
+ children: "load more"
245
+ }
246
+ )
203
247
  ] });
204
248
  }
205
249
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-resource-ui",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "A high-level data orchestration hook for React with pagination, caching, and virtualization",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",