@dreamtree-org/twreact-ui 2.0.1 → 2.0.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/README.md CHANGED
@@ -385,6 +385,7 @@ actions, and expandable row details.
385
385
  - `onSave`: ({ updatedRows, newRows, allData, tableData }) => void | Promise<allData | { data: allData } | void>
386
386
  - `onEdit`: ({ rowKey, colKey, newValue, row, action, isNew }) => void
387
387
  - `showSerial`: boolean (default: true)
388
+ - `paginationPosition`: 'top' | 'bottom' | 'both' (default: 'both') — which pager renders with `pagination`: the toolbar's compact pager, the footer, or both. `'bottom'` keeps the toolbar (search, reload, page size) without the second pager
388
389
  - `showToolbar`: boolean (default: true) — `false` hides the toolbar (reload, page size, result count, pager header) and the column picker; interactive save controls still render
389
390
  - `showColumnPicker`: boolean (default: true) — hide just the column-picker button and its column
390
391
  - `wrapCells`: boolean (default: false) — let every cell wrap; a column's own `wrap` wins
@@ -885,6 +886,8 @@ fetchApi('getUser', 7);
885
886
  fetchApiWith('updateUser', [7, { name: 'Ada' }]);
886
887
  ```
887
888
 
889
+ - `onUnauthorized(error, { apiKey, url, method })` runs once per failing request that `isUnauthorized(error)` matches (default: HTTP 401), before the promise rejects; the promise still rejects. Use it to clear the session and redirect to sign-in — see the "redirect only once" recipe in the doc.
890
+
888
891
  See [doc/useApi.md](doc/useApi.md).
889
892
 
890
893
  #### useHaptics
@@ -142,7 +142,7 @@ The library exports four kinds of things from `@dreamtree-org/twreact-ui`:
142
142
  | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
143
143
  | `useTheme` | Read/write the current theme (`light | dark`); pairs with `<ThemeProvider>`. Throws if used outside the provider. |
144
144
  | `ThemeProvider` | Provider that persists theme to `localStorage` (`dreamtree-theme`) and toggles `data-theme` and the `.dark` class on `<html>`. |
145
- | `useApi` | Thin axios wrapper. Returns `{data, error, loading, lastRequest, fetchData, fetchApi, fetchApiWith}`. Accepts `BASE_URL`, `DEFAULT_HEADERS`, `apiMap`. |
145
+ | `useApi` | Thin axios wrapper. Returns `{data, error, loading, lastRequest, fetchData, fetchApi, fetchApiWith}`. Accepts `BASE_URL`, `DEFAULT_HEADERS`, `apiMap`, `onUnauthorized(error, { apiKey, url, method })`, `isUnauthorized(error)` (default: 401). |
146
146
  | `useHaptics` | Opt-in `navigator.vibrate` wrapper. Returns `{trigger(pattern), supported, reducedMotion}`; patterns `selection` / `success` / `warning` / `error`. No-op on iOS Safari, the server and under reduced motion. |
147
147
  | `useMixins` | Bridge between component state, Redux store, and an in-memory cache. Power-user hook — prefer local React state for new code. |
148
148
 
@@ -385,6 +385,12 @@ fetchApiWith('updateUser', [7, { name: 'A' }]); // apiMap.updateUser(7, {...})
385
385
  `fetchApi(key, data)` always passes the map entry exactly one argument; use
386
386
  `fetchApiWith(key, [a, b])` for multi-argument entries.
387
387
 
388
+ For session expiry pass `onUnauthorized: (error, { apiKey, url, method }) => …`.
389
+ It runs once per request that fails with a 401 (override with `isUnauthorized`),
390
+ before the promise rejects; the promise still rejects. Several requests can fail
391
+ together, so guard the redirect with a module-level `redirecting` flag and skip
392
+ `apiKey === 'login'`. Don't hand-roll an axios interceptor for this.
393
+
388
394
  Treat `useApi` as a thin axios wrapper, not a caching/dedup layer. For
389
395
  cache, the consumer brings their own (React Query, SWR, etc.).
390
396
 
@@ -3455,6 +3455,16 @@
3455
3455
  "required": false,
3456
3456
  "default": "false"
3457
3457
  },
3458
+ "paginationPosition": {
3459
+ "type": "enum",
3460
+ "required": false,
3461
+ "values": [
3462
+ "top",
3463
+ "bottom",
3464
+ "both"
3465
+ ],
3466
+ "default": "'bottom'"
3467
+ },
3458
3468
  "pageSize": {
3459
3469
  "type": "number",
3460
3470
  "required": false,
@@ -1 +1 @@
1
- {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/Table.jsx"],"names":[],"mappings":";AAgDA,+EA+kDG;kBAtnDI,OAAO"}
1
+ {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/Table.jsx"],"names":[],"mappings":";AAgDA,+EA0lDG;kBAjoDI,OAAO"}
@@ -18,7 +18,7 @@ import TableRow from './TableRow.js';
18
18
  import MobileCard from './MobileCard.js';
19
19
  import FieldInput from './FieldInput.js';
20
20
 
21
- var _excluded = ["data", "columns", "sortable", "filterable", "selectable", "pagination", "pageSize", "onSort", "onFilter", "onFetch", "onFilterChange", "onSelectionChange", "onRowClick", "hasDetails", "DetailsComponent", "className", "withAction", "onAction", "actions", "replaceDefaultActions", "showSerial", "cellClass", "rowClass", "globalSearch", "limitOptions", "showLimitSelector", "onLimitChange", "showReloadButton", "renderReloadButton", "onReload", "stripedRows", "theme", "responsiveBreakpoint", "showToolbar", "showColumnPicker", "wrapCells", "mobileMaxFields", "serverSide", "totalRecords", "pageNumber", "onPageChange", "TheadComponent", "TfootComponent", "interactive", "onSave", "onEdit", "onRowAdd", "onRowDelete", "editKeyBinding", "newRowPosition", "addRowRef", "onInitAddRow", "renderAddRowButton", "renderExternalAddRow", "actionMenuPresentation", "defaultMobileView", "mobileFiltersPresentation", "swipeActions", "stickyHeader"],
21
+ var _excluded = ["data", "columns", "sortable", "filterable", "selectable", "pagination", "paginationPosition", "pageSize", "onSort", "onFilter", "onFetch", "onFilterChange", "onSelectionChange", "onRowClick", "hasDetails", "DetailsComponent", "className", "withAction", "onAction", "actions", "replaceDefaultActions", "showSerial", "cellClass", "rowClass", "globalSearch", "limitOptions", "showLimitSelector", "onLimitChange", "showReloadButton", "renderReloadButton", "onReload", "stripedRows", "theme", "responsiveBreakpoint", "showToolbar", "showColumnPicker", "wrapCells", "mobileMaxFields", "serverSide", "totalRecords", "pageNumber", "onPageChange", "TheadComponent", "TfootComponent", "interactive", "onSave", "onEdit", "onRowAdd", "onRowDelete", "editKeyBinding", "newRowPosition", "addRowRef", "onInitAddRow", "renderAddRowButton", "renderExternalAddRow", "actionMenuPresentation", "defaultMobileView", "mobileFiltersPresentation", "swipeActions", "stickyHeader"],
22
22
  _excluded2 = ["_key", "_isNew"];
23
23
  var DEFAULT_DATA = [];
24
24
  var DEFAULT_COLUMNS = [];
@@ -43,6 +43,8 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
43
43
  selectable = _ref$selectable === void 0 ? false : _ref$selectable,
44
44
  _ref$pagination = _ref.pagination,
45
45
  pagination = _ref$pagination === void 0 ? false : _ref$pagination,
46
+ _ref$paginationPositi = _ref.paginationPosition,
47
+ paginationPosition = _ref$paginationPositi === void 0 ? "both" : _ref$paginationPositi,
46
48
  _ref$pageSize = _ref.pageSize,
47
49
  pageSize = _ref$pageSize === void 0 ? 25 : _ref$pageSize,
48
50
  onSort = _ref.onSort,
@@ -1179,6 +1181,12 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1179
1181
  openSwipe: openSwipe,
1180
1182
  setOpenSwipe: setOpenSwipe
1181
1183
  };
1184
+ // Which pager(s) render when `pagination` is on: the toolbar's compact
1185
+ // PaginationHeader ("top"), the PaginationFooter ("bottom"), or both
1186
+ // (default). Unknown values fall back to "both" (#135).
1187
+ var pagerPosition = paginationPosition === "top" || paginationPosition === "bottom" ? paginationPosition : "both";
1188
+ var showHeaderPager = pagination && pagerPosition !== "bottom";
1189
+ var showFooterPager = pagination && pagerPosition !== "top";
1182
1190
  var showToolbarBar = showToolbar || interactive && (isDirty || !!renderAddRowButton || !!renderExternalAddRow);
1183
1191
  var renderAddRowClickableRow = useCallback(function () {
1184
1192
  return jsx("tr", {
@@ -1295,7 +1303,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1295
1303
  }), showToolbar && jsxs("div", {
1296
1304
  className: "text-sm whitespace-nowrap",
1297
1305
  children: [resultRange.start, " - ", resultRange.end, " of ", resultRange.total, " ", "results"]
1298
- }), showToolbar && pagination && jsx(PaginationHeader, {
1306
+ }), showToolbar && showHeaderPager && jsx(PaginationHeader, {
1299
1307
  currentPage: pageIndex,
1300
1308
  totalPages: totalPages,
1301
1309
  onPageChange: handlePageChange,
@@ -1576,7 +1584,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
1576
1584
  }), TfootComponent && typeof TfootComponent === "function" ? jsx(TfootComponent, {
1577
1585
  columns: columnsState,
1578
1586
  data: filteredData
1579
- }) : TfootComponent, pagination && jsx(PaginationFooter, {
1587
+ }) : TfootComponent, showFooterPager && jsx(PaginationFooter, {
1580
1588
  currentPage: pageIndex,
1581
1589
  totalPages: totalPages,
1582
1590
  onPageChange: handlePageChange,
@@ -3,6 +3,10 @@ import { slicedToArray as _slicedToArray, asyncToGenerator as _asyncToGenerator,
3
3
  import { useState } from 'react';
4
4
  import axios from 'axios';
5
5
 
6
+ var defaultIsUnauthorized = function defaultIsUnauthorized(error) {
7
+ var _error$response;
8
+ return (error === null || error === void 0 || (_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.status) === 401;
9
+ };
6
10
  var useApi = function useApi() {
7
11
  var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
8
12
  var _props$BASE_URL = props.BASE_URL,
@@ -37,7 +41,10 @@ var useApi = function useApi() {
37
41
  headers: headers
38
42
  });
39
43
  }
40
- } : _props$sendRequest;
44
+ } : _props$sendRequest,
45
+ onUnauthorized = props.onUnauthorized,
46
+ _props$isUnauthorized = props.isUnauthorized,
47
+ isUnauthorized = _props$isUnauthorized === void 0 ? defaultIsUnauthorized : _props$isUnauthorized;
41
48
  var _useState = useState(null),
42
49
  _useState2 = _slicedToArray(_useState, 2),
43
50
  data = _useState2[0],
@@ -54,20 +61,25 @@ var useApi = function useApi() {
54
61
  _useState8 = _slicedToArray(_useState7, 2),
55
62
  lastRequest = _useState8[0],
56
63
  setLastRequest = _useState8[1];
57
- var fetchData = /*#__PURE__*/function () {
58
- var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(url, method, data, headers) {
59
- var options,
60
- _options$needLoading,
61
- needLoading,
62
- requestInstance,
63
- response,
64
- _error,
65
- _args = arguments,
66
- _t;
64
+ // Runs `onUnauthorized` for a failed request. Never throws: a failing
65
+ // predicate or handler must not replace the request's own error.
66
+ var notifyUnauthorized = function notifyUnauthorized(error, request) {
67
+ if (!onUnauthorized) return;
68
+ try {
69
+ if (isUnauthorized(error)) onUnauthorized(error, request);
70
+ } catch (handlerError) {
71
+ // eslint-disable-next-line no-console
72
+ console.error('useApi: onUnauthorized / isUnauthorized threw', handlerError);
73
+ }
74
+ };
75
+ // Single send path for fetchData and callApi, so `onUnauthorized` fires
76
+ // exactly once per failing request and sees the `apiKey` when there is one.
77
+ var request = /*#__PURE__*/function () {
78
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(url, method, data, headers, options, apiKey) {
79
+ var _options$needLoading, needLoading, requestInstance, response, _error, _t;
67
80
  return _regenerator().w(function (_context) {
68
81
  while (1) switch (_context.p = _context.n) {
69
82
  case 0:
70
- options = _args.length > 4 && _args[4] !== undefined ? _args[4] : {};
71
83
  _options$needLoading = options.needLoading, needLoading = _options$needLoading === void 0 ? true : _options$needLoading;
72
84
  requestInstance = createRequestInstance(BASE_URL, DEFAULT_HEADERS);
73
85
  if (needLoading) setLoading(true);
@@ -83,6 +95,11 @@ var useApi = function useApi() {
83
95
  _t = _context.v;
84
96
  _error = _t;
85
97
  setError(_error);
98
+ notifyUnauthorized(_error, {
99
+ apiKey: apiKey,
100
+ url: url,
101
+ method: String(method).toUpperCase()
102
+ });
86
103
  throw _error;
87
104
  case 4:
88
105
  _context.p = 4;
@@ -93,10 +110,14 @@ var useApi = function useApi() {
93
110
  }
94
111
  }, _callee, null, [[1, 3, 4, 5]]);
95
112
  }));
96
- return function fetchData(_x, _x2, _x3, _x4) {
113
+ return function request(_x, _x2, _x3, _x4, _x5, _x6) {
97
114
  return _ref.apply(this, arguments);
98
115
  };
99
116
  }();
117
+ var fetchData = function fetchData(url, method, data, headers) {
118
+ var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
119
+ return request(url, method, data, headers, options);
120
+ };
100
121
  var callApi = /*#__PURE__*/function () {
101
122
  var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(apiKey, args, needLoading) {
102
123
  var apiResolve, _apiResolve, url, method, headers, payload;
@@ -113,9 +134,9 @@ var useApi = function useApi() {
113
134
  _apiResolve = apiResolve.apply(void 0, _toConsumableArray(args)), url = _apiResolve.url, method = _apiResolve.method, headers = _apiResolve.headers, payload = _apiResolve.data;
114
135
  _context2.p = 2;
115
136
  _context2.n = 3;
116
- return fetchData(url, method, payload, headers, {
137
+ return request(url, method, payload, headers, {
117
138
  needLoading: needLoading
118
- });
139
+ }, apiKey);
119
140
  case 3:
120
141
  return _context2.a(2, _context2.v);
121
142
  case 4:
@@ -127,7 +148,7 @@ var useApi = function useApi() {
127
148
  }
128
149
  }, _callee2, null, [[2,, 4, 5]]);
129
150
  }));
130
- return function callApi(_x5, _x6, _x7) {
151
+ return function callApi(_x7, _x8, _x9) {
131
152
  return _ref2.apply(this, arguments);
132
153
  };
133
154
  }();
@@ -1,10 +1,27 @@
1
1
  import { AxiosInstance, AxiosResponse, Method } from "axios";
2
- interface UseApiProps {
2
+ /** The request that failed, passed to `onUnauthorized`. */
3
+ export interface UseApiUnauthorizedRequest {
4
+ /** `apiMap` key for `fetchApi` / `fetchApiWith`; `undefined` for `fetchData`. */
5
+ apiKey?: string;
6
+ url: string;
7
+ /** Upper-cased HTTP method, e.g. `"GET"`. */
8
+ method: string;
9
+ }
10
+ export interface UseApiProps {
3
11
  BASE_URL?: string | null;
4
12
  DEFAULT_HEADERS?: Record<string, string>;
5
13
  apiMap?: Record<string, (...args: any[]) => ApiConfig>;
6
14
  createRequestInstance?: (baseURL?: string | null, defaultHeaders?: Record<string, string>) => AxiosInstance;
7
15
  sendRequest?: (requestInstance: AxiosInstance, method: string, url: string, data?: any, headers?: Record<string, string>) => Promise<AxiosResponse>;
16
+ /**
17
+ * Called once per failing request that `isUnauthorized` matches (default:
18
+ * HTTP 401), before the returned promise rejects. The promise still
19
+ * rejects with the original error. Errors thrown here are caught and
20
+ * logged so they never replace the request's error.
21
+ */
22
+ onUnauthorized?: (error: any, request: UseApiUnauthorizedRequest) => void;
23
+ /** Decides which errors count as unauthorized. Default: `error?.response?.status === 401`. */
24
+ isUnauthorized?: (error: any) => boolean;
8
25
  }
9
26
  interface ApiConfig {
10
27
  url: string;
@@ -1 +1 @@
1
- {"version":3,"file":"useApi.d.ts","sourceRoot":"","sources":["../../src/hooks/useApi.ts"],"names":[],"mappings":"AACA,OAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAEpE,UAAU,WAAW;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC;IACvD,qBAAqB,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,aAAa,CAAC;IAC5G,WAAW,CAAC,EAAE,CACV,eAAe,EAAE,aAAa,EAC9B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,GAAG,EACV,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC/B,OAAO,CAAC,aAAa,CAAC,CAAC;CAC/B;AAED,UAAU,SAAS;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,GAAG,CAAC;CACd;AAED,UAAU,YAAY;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,UAAU,YAAY,CAAC,CAAC,GAAG,GAAG;IAC1B,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,CACP,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,GAAG,EACV,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,OAAO,CAAC,EAAE,YAAY,KACrB,OAAO,CAAC,CAAC,CAAC,CAAC;IAChB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5E,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACtF;AAED,eAAO,MAAM,MAAM,GAAI,CAAC,GAAG,GAAG,EAAE,QAAO,WAAgB,KAAG,YAAY,CAAC,CAAC,CAiHvE,CAAC"}
1
+ {"version":3,"file":"useApi.d.ts","sourceRoot":"","sources":["../../src/hooks/useApi.ts"],"names":[],"mappings":"AACA,OAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAEpE,2DAA2D;AAC3D,MAAM,WAAW,yBAAyB;IACtC,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC;IACvD,qBAAqB,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,aAAa,CAAC;IAC5G,WAAW,CAAC,EAAE,CACV,eAAe,EAAE,aAAa,EAC9B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,GAAG,EACV,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC/B,OAAO,CAAC,aAAa,CAAC,CAAC;IAC5B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,yBAAyB,KAAK,IAAI,CAAC;IAC1E,8FAA8F;IAC9F,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC;CAC5C;AAID,UAAU,SAAS;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,GAAG,CAAC;CACd;AAED,UAAU,YAAY;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,UAAU,YAAY,CAAC,CAAC,GAAG,GAAG;IAC1B,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,CACP,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,GAAG,EACV,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,OAAO,CAAC,EAAE,YAAY,KACrB,OAAO,CAAC,CAAC,CAAC,CAAC;IAChB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5E,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACtF;AAED,eAAO,MAAM,MAAM,GAAI,CAAC,GAAG,GAAG,EAAE,QAAO,WAAgB,KAAG,YAAY,CAAC,CAAC,CA2IvE,CAAC"}
package/dist/index.esm.js CHANGED
@@ -10646,7 +10646,7 @@ function FieldInput(_ref) {
10646
10646
  });
10647
10647
  }
10648
10648
 
10649
- var _excluded$U = ["data", "columns", "sortable", "filterable", "selectable", "pagination", "pageSize", "onSort", "onFilter", "onFetch", "onFilterChange", "onSelectionChange", "onRowClick", "hasDetails", "DetailsComponent", "className", "withAction", "onAction", "actions", "replaceDefaultActions", "showSerial", "cellClass", "rowClass", "globalSearch", "limitOptions", "showLimitSelector", "onLimitChange", "showReloadButton", "renderReloadButton", "onReload", "stripedRows", "theme", "responsiveBreakpoint", "showToolbar", "showColumnPicker", "wrapCells", "mobileMaxFields", "serverSide", "totalRecords", "pageNumber", "onPageChange", "TheadComponent", "TfootComponent", "interactive", "onSave", "onEdit", "onRowAdd", "onRowDelete", "editKeyBinding", "newRowPosition", "addRowRef", "onInitAddRow", "renderAddRowButton", "renderExternalAddRow", "actionMenuPresentation", "defaultMobileView", "mobileFiltersPresentation", "swipeActions", "stickyHeader"],
10649
+ var _excluded$U = ["data", "columns", "sortable", "filterable", "selectable", "pagination", "paginationPosition", "pageSize", "onSort", "onFilter", "onFetch", "onFilterChange", "onSelectionChange", "onRowClick", "hasDetails", "DetailsComponent", "className", "withAction", "onAction", "actions", "replaceDefaultActions", "showSerial", "cellClass", "rowClass", "globalSearch", "limitOptions", "showLimitSelector", "onLimitChange", "showReloadButton", "renderReloadButton", "onReload", "stripedRows", "theme", "responsiveBreakpoint", "showToolbar", "showColumnPicker", "wrapCells", "mobileMaxFields", "serverSide", "totalRecords", "pageNumber", "onPageChange", "TheadComponent", "TfootComponent", "interactive", "onSave", "onEdit", "onRowAdd", "onRowDelete", "editKeyBinding", "newRowPosition", "addRowRef", "onInitAddRow", "renderAddRowButton", "renderExternalAddRow", "actionMenuPresentation", "defaultMobileView", "mobileFiltersPresentation", "swipeActions", "stickyHeader"],
10650
10650
  _excluded2$8 = ["_key", "_isNew"];
10651
10651
  function ownKeys$_(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
10652
10652
  function _objectSpread$_(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$_(Object(t), true).forEach(function (r) { _defineProperty$4(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$_(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -10673,6 +10673,8 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
10673
10673
  selectable = _ref$selectable === void 0 ? false : _ref$selectable,
10674
10674
  _ref$pagination = _ref.pagination,
10675
10675
  pagination = _ref$pagination === void 0 ? false : _ref$pagination,
10676
+ _ref$paginationPositi = _ref.paginationPosition,
10677
+ paginationPosition = _ref$paginationPositi === void 0 ? "both" : _ref$paginationPositi,
10676
10678
  _ref$pageSize = _ref.pageSize,
10677
10679
  pageSize = _ref$pageSize === void 0 ? 25 : _ref$pageSize,
10678
10680
  onSort = _ref.onSort,
@@ -11810,6 +11812,12 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
11810
11812
  openSwipe: openSwipe,
11811
11813
  setOpenSwipe: setOpenSwipe
11812
11814
  };
11815
+ // Which pager(s) render when `pagination` is on: the toolbar's compact
11816
+ // PaginationHeader ("top"), the PaginationFooter ("bottom"), or both
11817
+ // (default). Unknown values fall back to "both" (#135).
11818
+ var pagerPosition = paginationPosition === "top" || paginationPosition === "bottom" ? paginationPosition : "both";
11819
+ var showHeaderPager = pagination && pagerPosition !== "bottom";
11820
+ var showFooterPager = pagination && pagerPosition !== "top";
11813
11821
  var showToolbarBar = showToolbar || interactive && (isDirty || !!renderAddRowButton || !!renderExternalAddRow);
11814
11822
  var renderAddRowClickableRow = useCallback(function () {
11815
11823
  return jsx("tr", {
@@ -11926,7 +11934,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
11926
11934
  }), showToolbar && jsxs("div", {
11927
11935
  className: "text-sm whitespace-nowrap",
11928
11936
  children: [resultRange.start, " - ", resultRange.end, " of ", resultRange.total, " ", "results"]
11929
- }), showToolbar && pagination && jsx(PaginationHeader, {
11937
+ }), showToolbar && showHeaderPager && jsx(PaginationHeader, {
11930
11938
  currentPage: pageIndex,
11931
11939
  totalPages: totalPages,
11932
11940
  onPageChange: handlePageChange,
@@ -12207,7 +12215,7 @@ var Table = /*#__PURE__*/forwardRef(function Table(_ref, ref) {
12207
12215
  }), TfootComponent && typeof TfootComponent === "function" ? jsx(TfootComponent, {
12208
12216
  columns: columnsState,
12209
12217
  data: filteredData
12210
- }) : TfootComponent, pagination && jsx(PaginationFooter, {
12218
+ }) : TfootComponent, showFooterPager && jsx(PaginationFooter, {
12211
12219
  currentPage: pageIndex,
12212
12220
  totalPages: totalPages,
12213
12221
  onPageChange: handlePageChange,
@@ -38858,6 +38866,10 @@ const {
38858
38866
  mergeConfig
38859
38867
  } = axios;
38860
38868
 
38869
+ var defaultIsUnauthorized = function defaultIsUnauthorized(error) {
38870
+ var _error$response;
38871
+ return (error === null || error === void 0 || (_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.status) === 401;
38872
+ };
38861
38873
  var useApi = function useApi() {
38862
38874
  var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
38863
38875
  var _props$BASE_URL = props.BASE_URL,
@@ -38892,7 +38904,10 @@ var useApi = function useApi() {
38892
38904
  headers: headers
38893
38905
  });
38894
38906
  }
38895
- } : _props$sendRequest;
38907
+ } : _props$sendRequest,
38908
+ onUnauthorized = props.onUnauthorized,
38909
+ _props$isUnauthorized = props.isUnauthorized,
38910
+ isUnauthorized = _props$isUnauthorized === void 0 ? defaultIsUnauthorized : _props$isUnauthorized;
38896
38911
  var _useState = useState(null),
38897
38912
  _useState2 = _slicedToArray(_useState, 2),
38898
38913
  data = _useState2[0],
@@ -38909,20 +38924,25 @@ var useApi = function useApi() {
38909
38924
  _useState8 = _slicedToArray(_useState7, 2),
38910
38925
  lastRequest = _useState8[0],
38911
38926
  setLastRequest = _useState8[1];
38912
- var fetchData = /*#__PURE__*/function () {
38913
- var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(url, method, data, headers) {
38914
- var options,
38915
- _options$needLoading,
38916
- needLoading,
38917
- requestInstance,
38918
- response,
38919
- _error,
38920
- _args = arguments,
38921
- _t;
38927
+ // Runs `onUnauthorized` for a failed request. Never throws: a failing
38928
+ // predicate or handler must not replace the request's own error.
38929
+ var notifyUnauthorized = function notifyUnauthorized(error, request) {
38930
+ if (!onUnauthorized) return;
38931
+ try {
38932
+ if (isUnauthorized(error)) onUnauthorized(error, request);
38933
+ } catch (handlerError) {
38934
+ // eslint-disable-next-line no-console
38935
+ console.error('useApi: onUnauthorized / isUnauthorized threw', handlerError);
38936
+ }
38937
+ };
38938
+ // Single send path for fetchData and callApi, so `onUnauthorized` fires
38939
+ // exactly once per failing request and sees the `apiKey` when there is one.
38940
+ var request = /*#__PURE__*/function () {
38941
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(url, method, data, headers, options, apiKey) {
38942
+ var _options$needLoading, needLoading, requestInstance, response, _error, _t;
38922
38943
  return _regeneratorRuntime.wrap(function (_context) {
38923
38944
  while (1) switch (_context.prev = _context.next) {
38924
38945
  case 0:
38925
- options = _args.length > 4 && _args[4] !== undefined ? _args[4] : {};
38926
38946
  _options$needLoading = options.needLoading, needLoading = _options$needLoading === void 0 ? true : _options$needLoading;
38927
38947
  requestInstance = createRequestInstance(BASE_URL, DEFAULT_HEADERS);
38928
38948
  if (needLoading) setLoading(true);
@@ -38938,6 +38958,11 @@ var useApi = function useApi() {
38938
38958
  _t = _context["catch"](1);
38939
38959
  _error = _t;
38940
38960
  setError(_error);
38961
+ notifyUnauthorized(_error, {
38962
+ apiKey: apiKey,
38963
+ url: url,
38964
+ method: String(method).toUpperCase()
38965
+ });
38941
38966
  throw _error;
38942
38967
  case 4:
38943
38968
  _context.prev = 4;
@@ -38949,10 +38974,14 @@ var useApi = function useApi() {
38949
38974
  }
38950
38975
  }, _callee, null, [[1, 3, 4, 5]]);
38951
38976
  }));
38952
- return function fetchData(_x, _x2, _x3, _x4) {
38977
+ return function request(_x, _x2, _x3, _x4, _x5, _x6) {
38953
38978
  return _ref.apply(this, arguments);
38954
38979
  };
38955
38980
  }();
38981
+ var fetchData = function fetchData(url, method, data, headers) {
38982
+ var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
38983
+ return request(url, method, data, headers, options);
38984
+ };
38956
38985
  var callApi = /*#__PURE__*/function () {
38957
38986
  var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(apiKey, args, needLoading) {
38958
38987
  var apiResolve, _apiResolve, url, method, headers, payload;
@@ -38969,9 +38998,9 @@ var useApi = function useApi() {
38969
38998
  _apiResolve = apiResolve.apply(void 0, _toConsumableArray$1(args)), url = _apiResolve.url, method = _apiResolve.method, headers = _apiResolve.headers, payload = _apiResolve.data;
38970
38999
  _context2.prev = 2;
38971
39000
  _context2.next = 3;
38972
- return fetchData(url, method, payload, headers, {
39001
+ return request(url, method, payload, headers, {
38973
39002
  needLoading: needLoading
38974
- });
39003
+ }, apiKey);
38975
39004
  case 3:
38976
39005
  return _context2.abrupt("return", _context2.sent);
38977
39006
  case 4:
@@ -38984,7 +39013,7 @@ var useApi = function useApi() {
38984
39013
  }
38985
39014
  }, _callee2, null, [[2,, 4, 5]]);
38986
39015
  }));
38987
- return function callApi(_x5, _x6, _x7) {
39016
+ return function callApi(_x7, _x8, _x9) {
38988
39017
  return _ref2.apply(this, arguments);
38989
39018
  };
38990
39019
  }();
package/dist/index.js CHANGED
@@ -10666,7 +10666,7 @@ function FieldInput(_ref) {
10666
10666
  });
10667
10667
  }
10668
10668
 
10669
- var _excluded$U = ["data", "columns", "sortable", "filterable", "selectable", "pagination", "pageSize", "onSort", "onFilter", "onFetch", "onFilterChange", "onSelectionChange", "onRowClick", "hasDetails", "DetailsComponent", "className", "withAction", "onAction", "actions", "replaceDefaultActions", "showSerial", "cellClass", "rowClass", "globalSearch", "limitOptions", "showLimitSelector", "onLimitChange", "showReloadButton", "renderReloadButton", "onReload", "stripedRows", "theme", "responsiveBreakpoint", "showToolbar", "showColumnPicker", "wrapCells", "mobileMaxFields", "serverSide", "totalRecords", "pageNumber", "onPageChange", "TheadComponent", "TfootComponent", "interactive", "onSave", "onEdit", "onRowAdd", "onRowDelete", "editKeyBinding", "newRowPosition", "addRowRef", "onInitAddRow", "renderAddRowButton", "renderExternalAddRow", "actionMenuPresentation", "defaultMobileView", "mobileFiltersPresentation", "swipeActions", "stickyHeader"],
10669
+ var _excluded$U = ["data", "columns", "sortable", "filterable", "selectable", "pagination", "paginationPosition", "pageSize", "onSort", "onFilter", "onFetch", "onFilterChange", "onSelectionChange", "onRowClick", "hasDetails", "DetailsComponent", "className", "withAction", "onAction", "actions", "replaceDefaultActions", "showSerial", "cellClass", "rowClass", "globalSearch", "limitOptions", "showLimitSelector", "onLimitChange", "showReloadButton", "renderReloadButton", "onReload", "stripedRows", "theme", "responsiveBreakpoint", "showToolbar", "showColumnPicker", "wrapCells", "mobileMaxFields", "serverSide", "totalRecords", "pageNumber", "onPageChange", "TheadComponent", "TfootComponent", "interactive", "onSave", "onEdit", "onRowAdd", "onRowDelete", "editKeyBinding", "newRowPosition", "addRowRef", "onInitAddRow", "renderAddRowButton", "renderExternalAddRow", "actionMenuPresentation", "defaultMobileView", "mobileFiltersPresentation", "swipeActions", "stickyHeader"],
10670
10670
  _excluded2$8 = ["_key", "_isNew"];
10671
10671
  function ownKeys$_(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
10672
10672
  function _objectSpread$_(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$_(Object(t), true).forEach(function (r) { _defineProperty$4(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$_(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -10693,6 +10693,8 @@ var Table = /*#__PURE__*/React.forwardRef(function Table(_ref, ref) {
10693
10693
  selectable = _ref$selectable === void 0 ? false : _ref$selectable,
10694
10694
  _ref$pagination = _ref.pagination,
10695
10695
  pagination = _ref$pagination === void 0 ? false : _ref$pagination,
10696
+ _ref$paginationPositi = _ref.paginationPosition,
10697
+ paginationPosition = _ref$paginationPositi === void 0 ? "both" : _ref$paginationPositi,
10696
10698
  _ref$pageSize = _ref.pageSize,
10697
10699
  pageSize = _ref$pageSize === void 0 ? 25 : _ref$pageSize,
10698
10700
  onSort = _ref.onSort,
@@ -11830,6 +11832,12 @@ var Table = /*#__PURE__*/React.forwardRef(function Table(_ref, ref) {
11830
11832
  openSwipe: openSwipe,
11831
11833
  setOpenSwipe: setOpenSwipe
11832
11834
  };
11835
+ // Which pager(s) render when `pagination` is on: the toolbar's compact
11836
+ // PaginationHeader ("top"), the PaginationFooter ("bottom"), or both
11837
+ // (default). Unknown values fall back to "both" (#135).
11838
+ var pagerPosition = paginationPosition === "top" || paginationPosition === "bottom" ? paginationPosition : "both";
11839
+ var showHeaderPager = pagination && pagerPosition !== "bottom";
11840
+ var showFooterPager = pagination && pagerPosition !== "top";
11833
11841
  var showToolbarBar = showToolbar || interactive && (isDirty || !!renderAddRowButton || !!renderExternalAddRow);
11834
11842
  var renderAddRowClickableRow = React.useCallback(function () {
11835
11843
  return jsxRuntime.jsx("tr", {
@@ -11946,7 +11954,7 @@ var Table = /*#__PURE__*/React.forwardRef(function Table(_ref, ref) {
11946
11954
  }), showToolbar && jsxRuntime.jsxs("div", {
11947
11955
  className: "text-sm whitespace-nowrap",
11948
11956
  children: [resultRange.start, " - ", resultRange.end, " of ", resultRange.total, " ", "results"]
11949
- }), showToolbar && pagination && jsxRuntime.jsx(PaginationHeader, {
11957
+ }), showToolbar && showHeaderPager && jsxRuntime.jsx(PaginationHeader, {
11950
11958
  currentPage: pageIndex,
11951
11959
  totalPages: totalPages,
11952
11960
  onPageChange: handlePageChange,
@@ -12227,7 +12235,7 @@ var Table = /*#__PURE__*/React.forwardRef(function Table(_ref, ref) {
12227
12235
  }), TfootComponent && typeof TfootComponent === "function" ? jsxRuntime.jsx(TfootComponent, {
12228
12236
  columns: columnsState,
12229
12237
  data: filteredData
12230
- }) : TfootComponent, pagination && jsxRuntime.jsx(PaginationFooter, {
12238
+ }) : TfootComponent, showFooterPager && jsxRuntime.jsx(PaginationFooter, {
12231
12239
  currentPage: pageIndex,
12232
12240
  totalPages: totalPages,
12233
12241
  onPageChange: handlePageChange,
@@ -38878,6 +38886,10 @@ const {
38878
38886
  mergeConfig
38879
38887
  } = axios;
38880
38888
 
38889
+ var defaultIsUnauthorized = function defaultIsUnauthorized(error) {
38890
+ var _error$response;
38891
+ return (error === null || error === void 0 || (_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.status) === 401;
38892
+ };
38881
38893
  var useApi = function useApi() {
38882
38894
  var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
38883
38895
  var _props$BASE_URL = props.BASE_URL,
@@ -38912,7 +38924,10 @@ var useApi = function useApi() {
38912
38924
  headers: headers
38913
38925
  });
38914
38926
  }
38915
- } : _props$sendRequest;
38927
+ } : _props$sendRequest,
38928
+ onUnauthorized = props.onUnauthorized,
38929
+ _props$isUnauthorized = props.isUnauthorized,
38930
+ isUnauthorized = _props$isUnauthorized === void 0 ? defaultIsUnauthorized : _props$isUnauthorized;
38916
38931
  var _useState = React.useState(null),
38917
38932
  _useState2 = _slicedToArray(_useState, 2),
38918
38933
  data = _useState2[0],
@@ -38929,20 +38944,25 @@ var useApi = function useApi() {
38929
38944
  _useState8 = _slicedToArray(_useState7, 2),
38930
38945
  lastRequest = _useState8[0],
38931
38946
  setLastRequest = _useState8[1];
38932
- var fetchData = /*#__PURE__*/function () {
38933
- var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(url, method, data, headers) {
38934
- var options,
38935
- _options$needLoading,
38936
- needLoading,
38937
- requestInstance,
38938
- response,
38939
- _error,
38940
- _args = arguments,
38941
- _t;
38947
+ // Runs `onUnauthorized` for a failed request. Never throws: a failing
38948
+ // predicate or handler must not replace the request's own error.
38949
+ var notifyUnauthorized = function notifyUnauthorized(error, request) {
38950
+ if (!onUnauthorized) return;
38951
+ try {
38952
+ if (isUnauthorized(error)) onUnauthorized(error, request);
38953
+ } catch (handlerError) {
38954
+ // eslint-disable-next-line no-console
38955
+ console.error('useApi: onUnauthorized / isUnauthorized threw', handlerError);
38956
+ }
38957
+ };
38958
+ // Single send path for fetchData and callApi, so `onUnauthorized` fires
38959
+ // exactly once per failing request and sees the `apiKey` when there is one.
38960
+ var request = /*#__PURE__*/function () {
38961
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(url, method, data, headers, options, apiKey) {
38962
+ var _options$needLoading, needLoading, requestInstance, response, _error, _t;
38942
38963
  return _regeneratorRuntime.wrap(function (_context) {
38943
38964
  while (1) switch (_context.prev = _context.next) {
38944
38965
  case 0:
38945
- options = _args.length > 4 && _args[4] !== undefined ? _args[4] : {};
38946
38966
  _options$needLoading = options.needLoading, needLoading = _options$needLoading === void 0 ? true : _options$needLoading;
38947
38967
  requestInstance = createRequestInstance(BASE_URL, DEFAULT_HEADERS);
38948
38968
  if (needLoading) setLoading(true);
@@ -38958,6 +38978,11 @@ var useApi = function useApi() {
38958
38978
  _t = _context["catch"](1);
38959
38979
  _error = _t;
38960
38980
  setError(_error);
38981
+ notifyUnauthorized(_error, {
38982
+ apiKey: apiKey,
38983
+ url: url,
38984
+ method: String(method).toUpperCase()
38985
+ });
38961
38986
  throw _error;
38962
38987
  case 4:
38963
38988
  _context.prev = 4;
@@ -38969,10 +38994,14 @@ var useApi = function useApi() {
38969
38994
  }
38970
38995
  }, _callee, null, [[1, 3, 4, 5]]);
38971
38996
  }));
38972
- return function fetchData(_x, _x2, _x3, _x4) {
38997
+ return function request(_x, _x2, _x3, _x4, _x5, _x6) {
38973
38998
  return _ref.apply(this, arguments);
38974
38999
  };
38975
39000
  }();
39001
+ var fetchData = function fetchData(url, method, data, headers) {
39002
+ var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
39003
+ return request(url, method, data, headers, options);
39004
+ };
38976
39005
  var callApi = /*#__PURE__*/function () {
38977
39006
  var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(apiKey, args, needLoading) {
38978
39007
  var apiResolve, _apiResolve, url, method, headers, payload;
@@ -38989,9 +39018,9 @@ var useApi = function useApi() {
38989
39018
  _apiResolve = apiResolve.apply(void 0, _toConsumableArray$1(args)), url = _apiResolve.url, method = _apiResolve.method, headers = _apiResolve.headers, payload = _apiResolve.data;
38990
39019
  _context2.prev = 2;
38991
39020
  _context2.next = 3;
38992
- return fetchData(url, method, payload, headers, {
39021
+ return request(url, method, payload, headers, {
38993
39022
  needLoading: needLoading
38994
- });
39023
+ }, apiKey);
38995
39024
  case 3:
38996
39025
  return _context2.abrupt("return", _context2.sent);
38997
39026
  case 4:
@@ -39004,7 +39033,7 @@ var useApi = function useApi() {
39004
39033
  }
39005
39034
  }, _callee2, null, [[2,, 4, 5]]);
39006
39035
  }));
39007
- return function callApi(_x5, _x6, _x7) {
39036
+ return function callApi(_x7, _x8, _x9) {
39008
39037
  return _ref2.apply(this, arguments);
39009
39038
  };
39010
39039
  }();
@@ -366,6 +366,7 @@ export interface TableProps<T = any> extends BaseComponentProps {
366
366
  filterable?: boolean;
367
367
  selectable?: boolean;
368
368
  pagination?: boolean;
369
+ paginationPosition?: 'top' | 'bottom' | 'both';
369
370
  pageSize?: number;
370
371
  onSort?: (key: string, direction: 'asc' | 'desc') => void;
371
372
  onFilter?: (filters: Record<string, any>) => void;