@openmrs/esm-react-utils 10.0.1-pre.5263 → 10.0.1-pre.5299
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/.turbo/turbo-build.log +1 -1
- package/dist/Extension.d.ts.map +1 -1
- package/dist/Extension.js +86 -44
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/useAssignedExtensionIds.d.ts +1 -1
- package/dist/useAssignedExtensionIds.d.ts.map +1 -1
- package/dist/useAssignedExtensionIds.js +7 -14
- package/dist/useAssignedExtensions.d.ts +13 -1
- package/dist/useAssignedExtensions.d.ts.map +1 -1
- package/dist/useAssignedExtensions.js +31 -4
- package/dist/useCandidateExtensions.d.ts +11 -0
- package/dist/useCandidateExtensions.d.ts.map +1 -0
- package/dist/useCandidateExtensions.js +12 -0
- package/dist/useExtensionSlot.d.ts.map +1 -1
- package/dist/useExtensionSlot.js +8 -13
- package/dist/useExtensionSlotStore.d.ts +0 -1
- package/dist/useExtensionSlotStore.d.ts.map +1 -1
- package/dist/useExtensionSlotStore.js +19 -2
- package/dist/useFhirPagination.d.ts +1 -1
- package/dist/useOpenmrsPagination.d.ts +2 -2
- package/dist/useOpenmrsPagination.d.ts.map +1 -1
- package/dist/useOpenmrsPagination.js +66 -15
- package/dist/usePagination.d.ts +5 -0
- package/dist/usePagination.d.ts.map +1 -1
- package/dist/usePagination.js +23 -21
- package/dist/useShallowStableValue.d.ts +13 -0
- package/dist/useShallowStableValue.d.ts.map +1 -0
- package/dist/useShallowStableValue.js +19 -0
- package/dist/useStore.d.ts.map +1 -1
- package/dist/useStore.js +25 -11
- package/package.json +23 -23
- package/src/Extension.tsx +110 -54
- package/src/extensions.test.tsx +112 -0
- package/src/index.ts +2 -0
- package/src/useAssignedExtensionIds.ts +5 -15
- package/src/useAssignedExtensions.ts +30 -3
- package/src/useCandidateExtensions.ts +15 -0
- package/src/useExtensionSlot.ts +7 -17
- package/src/useExtensionSlotStore.ts +23 -3
- package/src/useOpenmrsPagination.test.ts +297 -1
- package/src/useOpenmrsPagination.ts +72 -10
- package/src/usePagination.test.tsx +315 -0
- package/src/usePagination.ts +27 -15
- package/src/useShallowStableValue.test.ts +69 -0
- package/src/useShallowStableValue.ts +24 -0
- package/src/useStore.test.ts +39 -0
- package/src/useStore.ts +17 -10
package/.turbo/turbo-build.log
CHANGED
package/dist/Extension.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Extension.d.ts","sourceRoot":"","sources":["../src/Extension.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAqD,MAAM,OAAO,CAAC;AAI1E,MAAM,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,
|
|
1
|
+
{"version":3,"file":"Extension.d.ts","sourceRoot":"","sources":["../src/Extension.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAqD,MAAM,OAAO,CAAC;AAI1E,MAAM,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAuI9C,CAAC"}
|
package/dist/Extension.js
CHANGED
|
@@ -13,58 +13,100 @@ import { ComponentContext } from "./index.js";
|
|
|
13
13
|
const { extension } = useContext(ComponentContext);
|
|
14
14
|
const parcel = useRef(null);
|
|
15
15
|
const updatePromise = useRef(Promise.resolve());
|
|
16
|
+
const isUnmounted = useRef(false);
|
|
17
|
+
const isRendering = useRef(false);
|
|
18
|
+
const latestState = useRef(state);
|
|
19
|
+
// Takes the parcel to tear down rather than reading `parcel.current`, which can be reassigned
|
|
20
|
+
// between scheduling this and running it.
|
|
21
|
+
const unmountParcel = useCallback((target)=>{
|
|
22
|
+
if (!target) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const unmountWhenMounted = ()=>{
|
|
26
|
+
if (target.getStatus() === 'MOUNTED') {
|
|
27
|
+
target.unmount();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
switch(target.getStatus()){
|
|
31
|
+
case 'MOUNTED':
|
|
32
|
+
target.unmount();
|
|
33
|
+
break;
|
|
34
|
+
case 'UPDATING':
|
|
35
|
+
// The rejection is reported by whoever owns `updatePromise`; here it only matters that a
|
|
36
|
+
// failed update still runs the teardown, or the parcel is left broken and mounted.
|
|
37
|
+
updatePromise.current?.then(unmountWhenMounted, unmountWhenMounted);
|
|
38
|
+
break;
|
|
39
|
+
default:
|
|
40
|
+
// Any other status: the parcel either hasn't finished coming up or is already gone.
|
|
41
|
+
// `mountPromise` has settled or will, and `unmountWhenMounted` re-checks the status.
|
|
42
|
+
target.mountPromise.then(unmountWhenMounted, ()=>{});
|
|
43
|
+
}
|
|
44
|
+
}, []);
|
|
45
|
+
const applyUpdate = useCallback((target, nextState)=>{
|
|
46
|
+
if (!target.update || target.getStatus() === 'UNMOUNTING') {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Every later update chains onto this promise, so it has to settle even when an update fails.
|
|
50
|
+
updatePromise.current = Promise.all([
|
|
51
|
+
target.mountPromise,
|
|
52
|
+
updatePromise.current
|
|
53
|
+
]).then(()=>{
|
|
54
|
+
if (parcel.current?.getStatus() === 'MOUNTED' && parcel.current.update) {
|
|
55
|
+
return parcel.current.update({
|
|
56
|
+
...nextState
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}).catch((err)=>{
|
|
60
|
+
// A parcel torn down while its update was in flight rejects, and that race is expected.
|
|
61
|
+
// We use the status to distinguish reject reasons as the message isn't reliable
|
|
62
|
+
const status = parcel.current?.getStatus();
|
|
63
|
+
if (status !== 'UNMOUNTING' && status !== 'NOT_MOUNTED' && status !== 'UNLOADING') {
|
|
64
|
+
console.error(`The extension '${extension?.extensionId}' failed to update`, err);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}, []);
|
|
16
68
|
const ref = useCallback((node)=>{
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
69
|
+
// React detaches a ref by calling it with null. If we render something in response to this,
|
|
70
|
+
// React ignores it and we're left tracking a parcel with no visible DOM, so skip conditions
|
|
71
|
+
// we can't handle.
|
|
72
|
+
if (!node || parcel.current || isRendering.current || !extension?.extensionSlotName || !extension.extensionSlotModuleName) {
|
|
73
|
+
return;
|
|
21
74
|
}
|
|
75
|
+
isRendering.current = true;
|
|
76
|
+
renderExtension(node, extension.extensionSlotName, extension.extensionSlotModuleName, extension.extensionId, undefined, state).then((newParcel)=>{
|
|
77
|
+
isRendering.current = false;
|
|
78
|
+
parcel.current = newParcel;
|
|
79
|
+
// Loading an extension's bundle can outlast the component that asked for it: the cleanup
|
|
80
|
+
// effect has already run and saw no parcel, so teardown has to happen here instead, or the
|
|
81
|
+
// parcel mounts into a detached node and its rendering record outlives the page.
|
|
82
|
+
if (isUnmounted.current) {
|
|
83
|
+
unmountParcel(newParcel);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// Ensure we update the state of the parcel to the latest version we've received
|
|
87
|
+
if (newParcel && latestState.current !== state) {
|
|
88
|
+
applyUpdate(newParcel, latestState.current);
|
|
89
|
+
}
|
|
90
|
+
}, // Cleared so a later reattach can try again; `renderExtension` reports its own failures.
|
|
91
|
+
()=>{
|
|
92
|
+
isRendering.current = false;
|
|
93
|
+
});
|
|
22
94
|
}, []);
|
|
23
95
|
useEffect(()=>{
|
|
96
|
+
// Reset on every run, not just the first: StrictMode mounts, tears down and mounts again, so
|
|
97
|
+
// a flag only ever set by the cleanup would still read "unmounted" for the live component.
|
|
98
|
+
isUnmounted.current = false;
|
|
24
99
|
return ()=>{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
switch(status){
|
|
28
|
-
case 'MOUNTING':
|
|
29
|
-
parcel.current.mountPromise.then(()=>{
|
|
30
|
-
if (parcel.current?.getStatus() === 'MOUNTED') {
|
|
31
|
-
parcel.current.unmount();
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
break;
|
|
35
|
-
case 'MOUNTED':
|
|
36
|
-
parcel.current.unmount();
|
|
37
|
-
break;
|
|
38
|
-
case 'UPDATING':
|
|
39
|
-
if (updatePromise.current) {
|
|
40
|
-
updatePromise.current.then(()=>{
|
|
41
|
-
if (parcel.current?.getStatus() === 'MOUNTED') {
|
|
42
|
-
parcel.current.unmount();
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
100
|
+
isUnmounted.current = true;
|
|
101
|
+
unmountParcel(parcel.current);
|
|
48
102
|
};
|
|
49
103
|
}, []);
|
|
50
104
|
useEffect(()=>{
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (parcel?.current?.getStatus() === 'MOUNTED' && parcel.current.update) {
|
|
57
|
-
updatePromise.current = parcel.current.update({
|
|
58
|
-
...state
|
|
59
|
-
}).catch((err)=>{
|
|
60
|
-
// if we were trying to update but the component was unmounted
|
|
61
|
-
// while this was happening, ignore the error
|
|
62
|
-
if (!(err instanceof Error) || !err.message.includes('minified message #32') || parcel.current?.getStatus() === 'MOUNTED') {
|
|
63
|
-
throw err;
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
});
|
|
105
|
+
// Recorded before the parcel is checked, so that a state that arrives before there is a parcel
|
|
106
|
+
// to receive it is still the one applied once there is.
|
|
107
|
+
latestState.current = state;
|
|
108
|
+
if (parcel.current) {
|
|
109
|
+
applyUpdate(parcel.current, state);
|
|
68
110
|
}
|
|
69
111
|
}, [
|
|
70
112
|
state
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export * from './useAbortController';
|
|
|
10
10
|
export * from './useAppContext';
|
|
11
11
|
export * from './useAssignedExtensionIds';
|
|
12
12
|
export * from './useAssignedExtensions';
|
|
13
|
+
export * from './useCandidateExtensions';
|
|
14
|
+
export * from './useShallowStableValue';
|
|
13
15
|
export * from './useAttachments';
|
|
14
16
|
export * from './useBodyScrollLock';
|
|
15
17
|
export * from './useConfig';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,oBAAoB,EAAE,KAAK,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAC/F,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,oBAAoB,EAAE,KAAK,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAC/F,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,8 @@ export * from "./useAbortController.js";
|
|
|
10
10
|
export * from "./useAppContext.js";
|
|
11
11
|
export * from "./useAssignedExtensionIds.js";
|
|
12
12
|
export * from "./useAssignedExtensions.js";
|
|
13
|
+
export * from "./useCandidateExtensions.js";
|
|
14
|
+
export * from "./useShallowStableValue.js";
|
|
13
15
|
export * from "./useAttachments.js";
|
|
14
16
|
export * from "./useBodyScrollLock.js";
|
|
15
17
|
export * from "./useConfig.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssignedExtensionIds.d.ts","sourceRoot":"","sources":["../src/useAssignedExtensionIds.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useAssignedExtensionIds.d.ts","sourceRoot":"","sources":["../src/useAssignedExtensionIds.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,YAIvD"}
|
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
/** @module @category Extension */ import {
|
|
2
|
-
import {
|
|
3
|
-
import { isEqual } from "lodash-es";
|
|
1
|
+
/** @module @category Extension */ import { useMemo } from "react";
|
|
2
|
+
import { useAssignedExtensions } from "./useAssignedExtensions.js";
|
|
4
3
|
/**
|
|
5
4
|
* Gets the assigned extension ids for a given extension slot name.
|
|
6
|
-
*
|
|
5
|
+
*
|
|
7
6
|
* @param slotName The name of the slot to get the assigned IDs for.
|
|
8
7
|
*
|
|
9
8
|
* @deprecated Use `useAssignedExtensions`
|
|
10
9
|
*/ export function useAssignedExtensionIds(slotName) {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (!isEqual(newIds, ids)) {
|
|
16
|
-
setIds(newIds);
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
}, []);
|
|
20
|
-
return ids;
|
|
10
|
+
const assignedExtensions = useAssignedExtensions(slotName);
|
|
11
|
+
return useMemo(()=>assignedExtensions.map((extension)=>extension.id), [
|
|
12
|
+
assignedExtensions
|
|
13
|
+
]);
|
|
21
14
|
}
|
|
@@ -1,6 +1,18 @@
|
|
|
1
|
+
import { type ExtensionSlotCustomState } from '@openmrs/esm-extensions';
|
|
1
2
|
/**
|
|
2
3
|
* Gets the assigned extensions for a given extension slot name.
|
|
4
|
+
*
|
|
5
|
+
* The reactive form of `getAssignedExtensions`, and it answers the same thing: display conditions
|
|
6
|
+
* are always applied, so the result is what should actually be displayed. Pass `state` whenever you
|
|
7
|
+
* know it: the same slot can be rendered in several places at once with different state, so
|
|
8
|
+
* conditions are resolved against the state of this rendering. Omitting it resolves them against
|
|
9
|
+
* the session alone, hiding any extension whose condition depends on state.
|
|
10
|
+
*
|
|
11
|
+
* The returned array is a copy, so sorting or filtering it in place can't corrupt the extension
|
|
12
|
+
* store. Its reference is stable for as long as the slot's extensions, the state and the session are.
|
|
13
|
+
*
|
|
3
14
|
* @param slotName The name of the slot to get the assigned extensions for.
|
|
15
|
+
* @param state The state of this rendering of the slot.
|
|
4
16
|
*/
|
|
5
|
-
export declare function useAssignedExtensions(slotName: string): import("@openmrs/esm-extensions").AssignedExtension[];
|
|
17
|
+
export declare function useAssignedExtensions(slotName: string, state?: ExtensionSlotCustomState): import("@openmrs/esm-extensions").AssignedExtension[];
|
|
6
18
|
//# sourceMappingURL=useAssignedExtensions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssignedExtensions.d.ts","sourceRoot":"","sources":["../src/useAssignedExtensions.ts"],"names":[],"mappings":"AAGA
|
|
1
|
+
{"version":3,"file":"useAssignedExtensions.d.ts","sourceRoot":"","sources":["../src/useAssignedExtensions.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,wBAAwB,EAAyB,MAAM,yBAAyB,CAAC;AAO/F;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,wBAAwB,yDAYvF"}
|
|
@@ -1,8 +1,35 @@
|
|
|
1
|
-
/** @module @category Extension */ import {
|
|
1
|
+
/** @module @category Extension */ import { useMemo } from "react";
|
|
2
|
+
import { sessionStore } from "@openmrs/esm-api";
|
|
3
|
+
import { getAssignedExtensions } from "@openmrs/esm-extensions";
|
|
4
|
+
import { useShallowStableValue } from "./useShallowStableValue.js";
|
|
5
|
+
import { useExtensionSlotStore } from "./useExtensionSlotStore.js";
|
|
6
|
+
import { useStore } from "./useStore.js";
|
|
7
|
+
const selectSession = (state)=>state.session;
|
|
2
8
|
/**
|
|
3
9
|
* Gets the assigned extensions for a given extension slot name.
|
|
10
|
+
*
|
|
11
|
+
* The reactive form of `getAssignedExtensions`, and it answers the same thing: display conditions
|
|
12
|
+
* are always applied, so the result is what should actually be displayed. Pass `state` whenever you
|
|
13
|
+
* know it: the same slot can be rendered in several places at once with different state, so
|
|
14
|
+
* conditions are resolved against the state of this rendering. Omitting it resolves them against
|
|
15
|
+
* the session alone, hiding any extension whose condition depends on state.
|
|
16
|
+
*
|
|
17
|
+
* The returned array is a copy, so sorting or filtering it in place can't corrupt the extension
|
|
18
|
+
* store. Its reference is stable for as long as the slot's extensions, the state and the session are.
|
|
19
|
+
*
|
|
4
20
|
* @param slotName The name of the slot to get the assigned extensions for.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
21
|
+
* @param state The state of this rendering of the slot.
|
|
22
|
+
*/ export function useAssignedExtensions(slotName, state) {
|
|
23
|
+
// Subscribes so that this re-runs when the slot's extensions change; `getAssignedExtensions` reads
|
|
24
|
+
// the same store, so the value below is what it is about to return.
|
|
25
|
+
const { candidateExtensions } = useExtensionSlotStore(slotName);
|
|
26
|
+
// Display conditions may refer to `session`, so they have to be re-evaluated when it changes.
|
|
27
|
+
const session = useStore(sessionStore, selectSession);
|
|
28
|
+
const stableState = useShallowStableValue(state);
|
|
29
|
+
return useMemo(()=>getAssignedExtensions(slotName, stableState), [
|
|
30
|
+
slotName,
|
|
31
|
+
stableState,
|
|
32
|
+
session,
|
|
33
|
+
candidateExtensions
|
|
34
|
+
]);
|
|
8
35
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reactive form of `getCandidateExtensions`: everything assigned to a slot, with no display
|
|
3
|
+
* condition evaluated. Intended for tools that present a slot's configuration rather than render it.
|
|
4
|
+
*
|
|
5
|
+
* Use {@link useAssignedExtensions} to decide what to display.
|
|
6
|
+
*
|
|
7
|
+
* @param slotName The name of the slot to get the candidate extensions for.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare function useCandidateExtensions(slotName: string): import("@openmrs/esm-extensions").AssignedExtension[];
|
|
11
|
+
//# sourceMappingURL=useCandidateExtensions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCandidateExtensions.d.ts","sourceRoot":"","sources":["../src/useCandidateExtensions.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,yDAEtD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** @module @category Extension */ import { useExtensionSlotStore } from "./useExtensionSlotStore.js";
|
|
2
|
+
/**
|
|
3
|
+
* The reactive form of `getCandidateExtensions`: everything assigned to a slot, with no display
|
|
4
|
+
* condition evaluated. Intended for tools that present a slot's configuration rather than render it.
|
|
5
|
+
*
|
|
6
|
+
* Use {@link useAssignedExtensions} to decide what to display.
|
|
7
|
+
*
|
|
8
|
+
* @param slotName The name of the slot to get the candidate extensions for.
|
|
9
|
+
* @internal
|
|
10
|
+
*/ export function useCandidateExtensions(slotName) {
|
|
11
|
+
return useExtensionSlotStore(slotName).candidateExtensions;
|
|
12
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useExtensionSlot.d.ts","sourceRoot":"","sources":["../src/useExtensionSlot.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"useExtensionSlot.d.ts","sourceRoot":"","sources":["../src/useExtensionSlot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,wBAAwB,EAAyB,MAAM,yBAAyB,CAAC;AAI/F,gBAAgB;AAChB,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,wBAAwB;;;;EAoBlF"}
|
package/dist/useExtensionSlot.js
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-
import { useContext, useEffect
|
|
2
|
-
import { registerExtensionSlot
|
|
1
|
+
import { useContext, useEffect } from "react";
|
|
2
|
+
import { registerExtensionSlot } from "@openmrs/esm-extensions";
|
|
3
3
|
import { ComponentContext } from "./ComponentContext.js";
|
|
4
4
|
import { useAssignedExtensions } from "./useAssignedExtensions.js";
|
|
5
5
|
/** @internal */ export function useExtensionSlot(slotName, state) {
|
|
6
6
|
const { moduleName } = useContext(ComponentContext);
|
|
7
|
-
const isInitialRender = useRef(true);
|
|
8
7
|
if (!moduleName) {
|
|
9
8
|
throw Error('ComponentContext has not been provided. This should come from @openmrs/esm-react-utils.');
|
|
10
9
|
}
|
|
11
10
|
useEffect(()=>{
|
|
12
|
-
registerExtensionSlot(moduleName, slotName
|
|
13
|
-
isInitialRender.current = false;
|
|
14
|
-
}, []);
|
|
15
|
-
useEffect(()=>{
|
|
16
|
-
if (!isInitialRender.current) {
|
|
17
|
-
updateExtensionSlotState(slotName, state);
|
|
18
|
-
}
|
|
11
|
+
registerExtensionSlot(moduleName, slotName);
|
|
19
12
|
}, [
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
moduleName,
|
|
14
|
+
slotName
|
|
22
15
|
]);
|
|
23
|
-
|
|
16
|
+
// `state` must be local to the rendering rather than written to the store as state is
|
|
17
|
+
// render-specific
|
|
18
|
+
const extensions = useAssignedExtensions(slotName, state);
|
|
24
19
|
return {
|
|
25
20
|
extensions,
|
|
26
21
|
extensionSlotName: slotName,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useExtensionSlotStore.d.ts","sourceRoot":"","sources":["../src/useExtensionSlotStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useExtensionSlotStore.d.ts","sourceRoot":"","sources":["../src/useExtensionSlotStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,kBAAkB,EAGxB,MAAM,yBAAyB,CAAC;AAcjC,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,uBAIjD,CAAC"}
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
-
/** @module @category Extension */ import {
|
|
1
|
+
/** @module @category Extension */ import { useCallback } from "react";
|
|
2
|
+
import { getExtensionStore } from "@openmrs/esm-extensions";
|
|
2
3
|
import { useStore } from "./useStore.js";
|
|
3
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Stands in for a slot that has not been registered or attached to. Shared rather than built per
|
|
6
|
+
* call, so the snapshot stays reference-stable across renders — and frozen because that sharing
|
|
7
|
+
* means an in-place sort or push would otherwise corrupt every unregistered slot in the page.
|
|
8
|
+
*/ const emptyCandidates = [];
|
|
9
|
+
Object.freeze(emptyCandidates);
|
|
10
|
+
const emptySlotState = {
|
|
11
|
+
candidateExtensions: emptyCandidates
|
|
12
|
+
};
|
|
13
|
+
Object.freeze(emptySlotState);
|
|
14
|
+
export const useExtensionSlotStore = (slot)=>{
|
|
15
|
+
// Memoized so that `useStore`'s snapshot function is stable across renders.
|
|
16
|
+
const select = useCallback((state)=>state.slots?.[slot] ?? emptySlotState, [
|
|
17
|
+
slot
|
|
18
|
+
]);
|
|
19
|
+
return useStore(getExtensionStore(), select);
|
|
20
|
+
};
|
|
@@ -28,7 +28,7 @@ export declare function useFhirPagination<T extends fhir.ResourceBase>(url: stri
|
|
|
28
28
|
totalPages: number;
|
|
29
29
|
totalCount: number;
|
|
30
30
|
currentPage: number;
|
|
31
|
-
currentPageSize:
|
|
31
|
+
currentPageSize: number;
|
|
32
32
|
paginated: boolean;
|
|
33
33
|
showNextButton: boolean;
|
|
34
34
|
showPreviousButton: boolean;
|
|
@@ -61,7 +61,7 @@ export declare function useOpenmrsPagination<T>(url: string | URL, pageSize: num
|
|
|
61
61
|
totalPages: number;
|
|
62
62
|
totalCount: number;
|
|
63
63
|
currentPage: number;
|
|
64
|
-
currentPageSize:
|
|
64
|
+
currentPageSize: number;
|
|
65
65
|
paginated: boolean;
|
|
66
66
|
showNextButton: boolean;
|
|
67
67
|
showPreviousButton: boolean;
|
|
@@ -87,7 +87,7 @@ export declare function useServerPagination<T, R>(url: string | URL, pageSize: n
|
|
|
87
87
|
totalPages: number;
|
|
88
88
|
totalCount: number;
|
|
89
89
|
currentPage: number;
|
|
90
|
-
currentPageSize:
|
|
90
|
+
currentPageSize: number;
|
|
91
91
|
paginated: boolean;
|
|
92
92
|
showNextButton: boolean;
|
|
93
93
|
showPreviousButton: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOpenmrsPagination.d.ts","sourceRoot":"","sources":["../src/useOpenmrsPagination.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,OAAO,EAAE,KAAK,aAAa,EAAyB,MAAM,kBAAkB,CAAC;AAE7E,OAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,KAAK,CAAC;AAGpD,MAAM,WAAW,wBAAwB,CAAC,CAAC;IACzC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B,CAAC,CAAC;IAC3C;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAErD;;OAEG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,0BAA0B,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAM;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"useOpenmrsPagination.d.ts","sourceRoot":"","sources":["../src/useOpenmrsPagination.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,OAAO,EAAE,KAAK,aAAa,EAAyB,MAAM,kBAAkB,CAAC;AAE7E,OAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,KAAK,CAAC;AAGpD,MAAM,WAAW,wBAAwB,CAAC,CAAC;IACzC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B,CAAC,CAAC;IAC3C;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAErD;;OAEG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,0BAA0B,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAM;;;;;;;;;;;;;iBAyG5D,MAAM;;;EAtGhB;AAED,KAAK,+BAA+B,CAAC,CAAC,IAAI,wBAAwB,CAAC,CAAC,EAAE,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC;AACnG,eAAO,MAAM,+BAA+B,EAAE,+BAA+B,CAAC,GAAG,CA6BhF,CAAC;AAEF,MAAM,WAAW,wBAAwB,CAAC,CAAC,EAAE,CAAC;IAC5C,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACzF,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,MAAM,GAAG,IAAI,CAAC;IACvD,aAAa,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,MAAM,CAAC;IACnD,kBAAkB,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,MAAM,CAAC;IACxD,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;CAC5D;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,CAAC,EACtC,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,QAAQ,EAAE,MAAM,EAChB,wBAAwB,EAAE,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,EACxD,OAAO,GAAE,0BAA0B,CAAC,CAAC,CAAM;;;;;;;;;;;;;iBAwDlC,MAAM;;;EAoEhB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @module @category UI */ import { makeUrl, openmrsFetch } from "@openmrs/esm-api";
|
|
2
|
-
import { useCallback, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import useSWR from "swr";
|
|
4
4
|
import useSWRImmutable from "swr/immutable";
|
|
5
5
|
/**
|
|
@@ -65,12 +65,31 @@ export function useServerPagination(url, pageSize, serverPaginationHandlers, opt
|
|
|
65
65
|
const { getPaginatedUrl, getTotalCount, getCurrentPageSize, getData } = serverPaginationHandlers;
|
|
66
66
|
const { immutable, swrConfig } = options;
|
|
67
67
|
const fetcher = options.fetcher ?? openmrsFetch;
|
|
68
|
-
|
|
68
|
+
// 1-indexing instead of 0-indexing, to keep consistency with `usePagination`
|
|
69
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
69
70
|
// Cache the totalCount and currentPageSize so we don't lose them
|
|
70
71
|
// as we wait for next page's result to load while navigating to a different page.
|
|
71
72
|
// This can be used to prevent jarring UI changes while loading
|
|
72
73
|
const totalCount = useRef(Number.NaN);
|
|
73
|
-
|
|
74
|
+
// this value is usually same as pageSize, except when currentPage is last page.
|
|
75
|
+
const currentPageSize = useRef(Number.NaN);
|
|
76
|
+
// tracked as a ref so we don't need to make the current page a dependency of `goTo()`, etc.
|
|
77
|
+
const currentPageRef = useRef(currentPage);
|
|
78
|
+
// use to differentiate "endpoint doesn't return a total" from "we haven't run a request yet"
|
|
79
|
+
const hasResponded = useRef(false);
|
|
80
|
+
const warnedMissingTotal = useRef(false);
|
|
81
|
+
// if the URL we're querying changes, reset to page 1
|
|
82
|
+
const urlKey = url?.toString() ?? '';
|
|
83
|
+
const [lastUrlKey, setLastUrlKey] = useState(urlKey);
|
|
84
|
+
if (urlKey !== lastUrlKey) {
|
|
85
|
+
setLastUrlKey(urlKey);
|
|
86
|
+
setCurrentPage(1);
|
|
87
|
+
currentPageRef.current = 1;
|
|
88
|
+
totalCount.current = Number.NaN;
|
|
89
|
+
currentPageSize.current = Number.NaN;
|
|
90
|
+
hasResponded.current = false;
|
|
91
|
+
warnedMissingTotal.current = false;
|
|
92
|
+
}
|
|
74
93
|
const limit = pageSize;
|
|
75
94
|
const startIndex = (currentPage - 1) * pageSize;
|
|
76
95
|
const urlUrl = useMemo(()=>{
|
|
@@ -85,39 +104,71 @@ export function useServerPagination(url, pageSize, serverPaginationHandlers, opt
|
|
|
85
104
|
if (data?.data) {
|
|
86
105
|
totalCount.current = getTotalCount(data?.data);
|
|
87
106
|
currentPageSize.current = getCurrentPageSize(data?.data);
|
|
107
|
+
hasResponded.current = true;
|
|
88
108
|
}
|
|
89
109
|
const totalPages = Math.ceil(totalCount.current / pageSize);
|
|
110
|
+
// The bound is read from `totalCount` at call time rather than captured from the creating render,
|
|
111
|
+
// which is what keeps this callback referentially stable, apart from a change in `pageSize`.
|
|
90
112
|
const goTo = useCallback((page)=>{
|
|
91
|
-
if (
|
|
113
|
+
if (!Number.isInteger(page) || page < 1) {
|
|
114
|
+
console.warn(`useServerPagination: ignoring goTo(${page}); page must be a positive integer.`);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
// page count is not known prior to running any query when `bound` will be `NaN`, so in this
|
|
118
|
+
// case we assume the requested page is fine; after results return, things will settle properly
|
|
119
|
+
// clamped
|
|
120
|
+
const bound = Math.ceil(totalCount.current / pageSize);
|
|
121
|
+
if (!hasResponded.current || Number.isNaN(bound) || page <= bound) {
|
|
122
|
+
currentPageRef.current = page;
|
|
92
123
|
setCurrentPage(page);
|
|
93
124
|
} else {
|
|
94
125
|
console.warn('Invalid attempt to go to out of bounds page: ' + page);
|
|
95
126
|
}
|
|
96
127
|
}, [
|
|
97
|
-
|
|
128
|
+
pageSize
|
|
129
|
+
]);
|
|
130
|
+
// A page accepted before the total was known may turn out not to exist, so put the user on the last
|
|
131
|
+
// real page once the response settles it. Costs an extra request, but only for a page that was out of
|
|
132
|
+
// range to begin with; without it the hook sits on an empty page with no way back.
|
|
133
|
+
useEffect(()=>{
|
|
134
|
+
if (!hasResponded.current) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (Number.isNaN(totalCount.current)) {
|
|
138
|
+
if (!warnedMissingTotal.current) {
|
|
139
|
+
warnedMissingTotal.current = true;
|
|
140
|
+
console.warn(`useServerPagination: ${urlKey} returned no total count, so out-of-range pages cannot be detected.`);
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const lastPage = Math.max(1, Math.ceil(totalCount.current / pageSize));
|
|
145
|
+
if (currentPage > lastPage) {
|
|
146
|
+
console.warn(`Invalid attempt to go to out of bounds page: ${currentPage}; returning to page ${lastPage}.`);
|
|
147
|
+
currentPageRef.current = lastPage;
|
|
148
|
+
setCurrentPage(lastPage);
|
|
149
|
+
}
|
|
150
|
+
}, [
|
|
98
151
|
currentPage,
|
|
99
|
-
|
|
152
|
+
pageSize,
|
|
153
|
+
urlKey,
|
|
154
|
+
data
|
|
100
155
|
]);
|
|
101
156
|
const goToNext = useCallback(()=>{
|
|
102
|
-
goTo(
|
|
157
|
+
goTo(currentPageRef.current + 1);
|
|
103
158
|
}, [
|
|
104
|
-
|
|
105
|
-
currentPage,
|
|
106
|
-
totalPages
|
|
159
|
+
goTo
|
|
107
160
|
]);
|
|
108
161
|
const goToPrevious = useCallback(()=>{
|
|
109
|
-
goTo(
|
|
162
|
+
goTo(currentPageRef.current - 1);
|
|
110
163
|
}, [
|
|
111
|
-
|
|
112
|
-
currentPage,
|
|
113
|
-
totalPages
|
|
164
|
+
goTo
|
|
114
165
|
]);
|
|
115
166
|
return {
|
|
116
167
|
data: getData(data?.data),
|
|
117
168
|
totalPages,
|
|
118
169
|
totalCount: totalCount.current,
|
|
119
170
|
currentPage,
|
|
120
|
-
currentPageSize,
|
|
171
|
+
currentPageSize: currentPageSize.current,
|
|
121
172
|
paginated: totalPages > 1,
|
|
122
173
|
showNextButton: currentPage < totalPages,
|
|
123
174
|
showPreviousButton: currentPage > 1,
|
package/dist/usePagination.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Use this hook to paginate data that already exists on the client side.
|
|
3
3
|
* Note that if the data is obtained from server-side, the caller must handle server-side pagination manually.
|
|
4
|
+
*
|
|
5
|
+
* `goTo`, `goToNext` and `goToPrevious` keep the same identity for the life of the component, so they are
|
|
6
|
+
* safe to list in a dependency array. `currentPage` is bounded by the data, so it can change on its own
|
|
7
|
+
* when the data shrinks; a component reacting to `currentPage` should expect that.
|
|
8
|
+
*
|
|
4
9
|
* @see `useServerPagination` for hook that automatically manages server-side pagination.
|
|
5
10
|
* @see `useServerInfinite` for hook to get all data loaded onto the client-side
|
|
6
11
|
* @param data
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePagination.d.ts","sourceRoot":"","sources":["../src/usePagination.ts"],"names":[],"mappings":"AAKA
|
|
1
|
+
{"version":3,"file":"usePagination.d.ts","sourceRoot":"","sources":["../src/usePagination.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,IAAI,GAAE,KAAK,CAAC,CAAC,CAAM,EAAE,cAAc,SAAwB;;;;;;;iBAwB1D,MAAM;;;EAiCvC"}
|