@apvee/spfx-react-toolkit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +2012 -0
- package/lib/core/atoms.internal.d.ts +53 -0
- package/lib/core/atoms.internal.d.ts.map +1 -0
- package/lib/core/atoms.internal.js +35 -0
- package/lib/core/atoms.internal.js.map +1 -0
- package/lib/core/context.internal.d.ts +23 -0
- package/lib/core/context.internal.d.ts.map +1 -0
- package/lib/core/context.internal.js +34 -0
- package/lib/core/context.internal.js.map +1 -0
- package/lib/core/index.d.ts +6 -0
- package/lib/core/index.d.ts.map +1 -0
- package/lib/core/index.js +6 -0
- package/lib/core/index.js.map +1 -0
- package/lib/core/provider-application-customizer.d.ts +57 -0
- package/lib/core/provider-application-customizer.d.ts.map +1 -0
- package/lib/core/provider-application-customizer.js +45 -0
- package/lib/core/provider-application-customizer.js.map +1 -0
- package/lib/core/provider-base.internal.d.ts +20 -0
- package/lib/core/provider-base.internal.d.ts.map +1 -0
- package/lib/core/provider-base.internal.js +126 -0
- package/lib/core/provider-base.internal.js.map +1 -0
- package/lib/core/provider-field-customizer.d.ts +58 -0
- package/lib/core/provider-field-customizer.d.ts.map +1 -0
- package/lib/core/provider-field-customizer.js +46 -0
- package/lib/core/provider-field-customizer.js.map +1 -0
- package/lib/core/provider-listview-commandset.d.ts +60 -0
- package/lib/core/provider-listview-commandset.d.ts.map +1 -0
- package/lib/core/provider-listview-commandset.js +48 -0
- package/lib/core/provider-listview-commandset.js.map +1 -0
- package/lib/core/provider-webpart.d.ts +48 -0
- package/lib/core/provider-webpart.d.ts.map +1 -0
- package/lib/core/provider-webpart.js +36 -0
- package/lib/core/provider-webpart.js.map +1 -0
- package/lib/core/types.d.ts +84 -0
- package/lib/core/types.d.ts.map +1 -0
- package/lib/core/types.js +4 -0
- package/lib/core/types.js.map +1 -0
- package/lib/hooks/index.d.ts +34 -0
- package/lib/hooks/index.d.ts.map +1 -0
- package/lib/hooks/index.js +34 -0
- package/lib/hooks/index.js.map +1 -0
- package/lib/hooks/useSPFxAadHttpClient.d.ts +231 -0
- package/lib/hooks/useSPFxAadHttpClient.d.ts.map +1 -0
- package/lib/hooks/useSPFxAadHttpClient.js +299 -0
- package/lib/hooks/useSPFxAadHttpClient.js.map +1 -0
- package/lib/hooks/useSPFxContainerInfo.d.ts +41 -0
- package/lib/hooks/useSPFxContainerInfo.d.ts.map +1 -0
- package/lib/hooks/useSPFxContainerInfo.js +47 -0
- package/lib/hooks/useSPFxContainerInfo.js.map +1 -0
- package/lib/hooks/useSPFxContainerSize.d.ts +119 -0
- package/lib/hooks/useSPFxContainerSize.d.ts.map +1 -0
- package/lib/hooks/useSPFxContainerSize.js +150 -0
- package/lib/hooks/useSPFxContainerSize.js.map +1 -0
- package/lib/hooks/useSPFxContext.d.ts +14 -0
- package/lib/hooks/useSPFxContext.d.ts.map +1 -0
- package/lib/hooks/useSPFxContext.js +16 -0
- package/lib/hooks/useSPFxContext.js.map +1 -0
- package/lib/hooks/useSPFxCorrelationInfo.d.ts +51 -0
- package/lib/hooks/useSPFxCorrelationInfo.d.ts.map +1 -0
- package/lib/hooks/useSPFxCorrelationInfo.js +58 -0
- package/lib/hooks/useSPFxCorrelationInfo.js.map +1 -0
- package/lib/hooks/useSPFxCrossSitePermissions.d.ts +81 -0
- package/lib/hooks/useSPFxCrossSitePermissions.d.ts.map +1 -0
- package/lib/hooks/useSPFxCrossSitePermissions.js +132 -0
- package/lib/hooks/useSPFxCrossSitePermissions.js.map +1 -0
- package/lib/hooks/useSPFxDisplayMode.d.ts +61 -0
- package/lib/hooks/useSPFxDisplayMode.d.ts.map +1 -0
- package/lib/hooks/useSPFxDisplayMode.js +69 -0
- package/lib/hooks/useSPFxDisplayMode.js.map +1 -0
- package/lib/hooks/useSPFxEnvironmentInfo.d.ts +63 -0
- package/lib/hooks/useSPFxEnvironmentInfo.d.ts.map +1 -0
- package/lib/hooks/useSPFxEnvironmentInfo.js +91 -0
- package/lib/hooks/useSPFxEnvironmentInfo.js.map +1 -0
- package/lib/hooks/useSPFxFluent9ThemeInfo.d.ts +105 -0
- package/lib/hooks/useSPFxFluent9ThemeInfo.d.ts.map +1 -0
- package/lib/hooks/useSPFxFluent9ThemeInfo.js +136 -0
- package/lib/hooks/useSPFxFluent9ThemeInfo.js.map +1 -0
- package/lib/hooks/useSPFxHubSiteInfo.d.ts +80 -0
- package/lib/hooks/useSPFxHubSiteInfo.d.ts.map +1 -0
- package/lib/hooks/useSPFxHubSiteInfo.js +127 -0
- package/lib/hooks/useSPFxHubSiteInfo.js.map +1 -0
- package/lib/hooks/useSPFxInstanceInfo.d.ts +41 -0
- package/lib/hooks/useSPFxInstanceInfo.d.ts.map +1 -0
- package/lib/hooks/useSPFxInstanceInfo.js +40 -0
- package/lib/hooks/useSPFxInstanceInfo.js.map +1 -0
- package/lib/hooks/useSPFxListInfo.d.ts +64 -0
- package/lib/hooks/useSPFxListInfo.d.ts.map +1 -0
- package/lib/hooks/useSPFxListInfo.js +70 -0
- package/lib/hooks/useSPFxListInfo.js.map +1 -0
- package/lib/hooks/useSPFxLocaleInfo.d.ts +123 -0
- package/lib/hooks/useSPFxLocaleInfo.d.ts.map +1 -0
- package/lib/hooks/useSPFxLocaleInfo.js +109 -0
- package/lib/hooks/useSPFxLocaleInfo.js.map +1 -0
- package/lib/hooks/useSPFxLogger.d.ts +108 -0
- package/lib/hooks/useSPFxLogger.d.ts.map +1 -0
- package/lib/hooks/useSPFxLogger.js +117 -0
- package/lib/hooks/useSPFxLogger.js.map +1 -0
- package/lib/hooks/useSPFxMSGraphClient.d.ts +200 -0
- package/lib/hooks/useSPFxMSGraphClient.d.ts.map +1 -0
- package/lib/hooks/useSPFxMSGraphClient.js +264 -0
- package/lib/hooks/useSPFxMSGraphClient.js.map +1 -0
- package/lib/hooks/useSPFxOneDriveAppData.d.ts +264 -0
- package/lib/hooks/useSPFxOneDriveAppData.d.ts.map +1 -0
- package/lib/hooks/useSPFxOneDriveAppData.js +395 -0
- package/lib/hooks/useSPFxOneDriveAppData.js.map +1 -0
- package/lib/hooks/useSPFxPageContext.d.ts +37 -0
- package/lib/hooks/useSPFxPageContext.d.ts.map +1 -0
- package/lib/hooks/useSPFxPageContext.js +49 -0
- package/lib/hooks/useSPFxPageContext.js.map +1 -0
- package/lib/hooks/useSPFxPageType.d.ts +82 -0
- package/lib/hooks/useSPFxPageType.d.ts.map +1 -0
- package/lib/hooks/useSPFxPageType.js +137 -0
- package/lib/hooks/useSPFxPageType.js.map +1 -0
- package/lib/hooks/useSPFxPerformance.d.ts +72 -0
- package/lib/hooks/useSPFxPerformance.d.ts.map +1 -0
- package/lib/hooks/useSPFxPerformance.js +167 -0
- package/lib/hooks/useSPFxPerformance.js.map +1 -0
- package/lib/hooks/useSPFxPermissions.d.ts +61 -0
- package/lib/hooks/useSPFxPermissions.d.ts.map +1 -0
- package/lib/hooks/useSPFxPermissions.js +73 -0
- package/lib/hooks/useSPFxPermissions.js.map +1 -0
- package/lib/hooks/useSPFxPnP.d.ts +539 -0
- package/lib/hooks/useSPFxPnP.d.ts.map +1 -0
- package/lib/hooks/useSPFxPnP.js +533 -0
- package/lib/hooks/useSPFxPnP.js.map +1 -0
- package/lib/hooks/useSPFxPnPContext.d.ts +290 -0
- package/lib/hooks/useSPFxPnPContext.d.ts.map +1 -0
- package/lib/hooks/useSPFxPnPContext.js +340 -0
- package/lib/hooks/useSPFxPnPContext.js.map +1 -0
- package/lib/hooks/useSPFxPnPList.d.ts +545 -0
- package/lib/hooks/useSPFxPnPList.d.ts.map +1 -0
- package/lib/hooks/useSPFxPnPList.js +906 -0
- package/lib/hooks/useSPFxPnPList.js.map +1 -0
- package/lib/hooks/useSPFxPnPSearch.d.ts +540 -0
- package/lib/hooks/useSPFxPnPSearch.d.ts.map +1 -0
- package/lib/hooks/useSPFxPnPSearch.js +672 -0
- package/lib/hooks/useSPFxPnPSearch.js.map +1 -0
- package/lib/hooks/useSPFxProperties.d.ts +80 -0
- package/lib/hooks/useSPFxProperties.d.ts.map +1 -0
- package/lib/hooks/useSPFxProperties.js +95 -0
- package/lib/hooks/useSPFxProperties.js.map +1 -0
- package/lib/hooks/useSPFxSPHttpClient.d.ts +218 -0
- package/lib/hooks/useSPFxSPHttpClient.d.ts.map +1 -0
- package/lib/hooks/useSPFxSPHttpClient.js +287 -0
- package/lib/hooks/useSPFxSPHttpClient.js.map +1 -0
- package/lib/hooks/useSPFxServiceScope.d.ts +107 -0
- package/lib/hooks/useSPFxServiceScope.d.ts.map +1 -0
- package/lib/hooks/useSPFxServiceScope.js +105 -0
- package/lib/hooks/useSPFxServiceScope.js.map +1 -0
- package/lib/hooks/useSPFxSiteInfo.d.ts +116 -0
- package/lib/hooks/useSPFxSiteInfo.d.ts.map +1 -0
- package/lib/hooks/useSPFxSiteInfo.js +109 -0
- package/lib/hooks/useSPFxSiteInfo.js.map +1 -0
- package/lib/hooks/useSPFxStorage.d.ts +81 -0
- package/lib/hooks/useSPFxStorage.d.ts.map +1 -0
- package/lib/hooks/useSPFxStorage.js +140 -0
- package/lib/hooks/useSPFxStorage.js.map +1 -0
- package/lib/hooks/useSPFxTeams.d.ts +63 -0
- package/lib/hooks/useSPFxTeams.d.ts.map +1 -0
- package/lib/hooks/useSPFxTeams.js +198 -0
- package/lib/hooks/useSPFxTeams.js.map +1 -0
- package/lib/hooks/useSPFxTenantProperty.d.ts +389 -0
- package/lib/hooks/useSPFxTenantProperty.d.ts.map +1 -0
- package/lib/hooks/useSPFxTenantProperty.js +683 -0
- package/lib/hooks/useSPFxTenantProperty.js.map +1 -0
- package/lib/hooks/useSPFxThemeInfo.d.ts +27 -0
- package/lib/hooks/useSPFxThemeInfo.d.ts.map +1 -0
- package/lib/hooks/useSPFxThemeInfo.js +33 -0
- package/lib/hooks/useSPFxThemeInfo.js.map +1 -0
- package/lib/hooks/useSPFxUserInfo.d.ts +47 -0
- package/lib/hooks/useSPFxUserInfo.d.ts.map +1 -0
- package/lib/hooks/useSPFxUserInfo.js +47 -0
- package/lib/hooks/useSPFxUserInfo.js.map +1 -0
- package/lib/hooks/useSPFxUserPhoto.d.ts +270 -0
- package/lib/hooks/useSPFxUserPhoto.d.ts.map +1 -0
- package/lib/hooks/useSPFxUserPhoto.js +346 -0
- package/lib/hooks/useSPFxUserPhoto.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/index.js +3 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/resize-observer.internal.d.ts +10 -0
- package/lib/utils/resize-observer.internal.d.ts.map +1 -0
- package/lib/utils/resize-observer.internal.js +34 -0
- package/lib/utils/resize-observer.internal.js.map +1 -0
- package/lib/utils/theme-subscription.internal.d.ts +11 -0
- package/lib/utils/theme-subscription.internal.d.ts.map +1 -0
- package/lib/utils/theme-subscription.internal.js +58 -0
- package/lib/utils/theme-subscription.internal.js.map +1 -0
- package/lib/utils/type-guards.internal.d.ts +35 -0
- package/lib/utils/type-guards.internal.d.ts.map +1 -0
- package/lib/utils/type-guards.internal.js +88 -0
- package/lib/utils/type-guards.internal.js.map +1 -0
- package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.d.ts +13 -0
- package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.d.ts.map +1 -0
- package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.js +67 -0
- package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.js.map +1 -0
- package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.manifest.json +21 -0
- package/lib/webparts/spFxReactToolkitTest/assets/welcome-dark.png +0 -0
- package/lib/webparts/spFxReactToolkitTest/assets/welcome-light.png +0 -0
- package/lib/webparts/spFxReactToolkitTest/components/ISpFxReactToolkitTestProps.d.ts +8 -0
- package/lib/webparts/spFxReactToolkitTest/components/ISpFxReactToolkitTestProps.d.ts.map +1 -0
- package/lib/webparts/spFxReactToolkitTest/components/ISpFxReactToolkitTestProps.js +2 -0
- package/lib/webparts/spFxReactToolkitTest/components/ISpFxReactToolkitTestProps.js.map +1 -0
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.d.ts +8 -0
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.d.ts.map +1 -0
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.js +1351 -0
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.js.map +1 -0
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.css +2 -0
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.scss.d.ts +18 -0
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.scss.d.ts.map +1 -0
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.scss.js +19 -0
- package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.scss.js.map +1 -0
- package/lib/webparts/spFxReactToolkitTest/loc/en-us.js +16 -0
- package/package.json +95 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// useSPFxPermissions.ts
|
|
2
|
+
// Hook for SharePoint permissions checking
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
import { useSPFxPageContext } from './useSPFxPageContext';
|
|
5
|
+
/**
|
|
6
|
+
* Hook for SharePoint permissions checking
|
|
7
|
+
*
|
|
8
|
+
* Provides access to current user's permissions at different scopes:
|
|
9
|
+
* - Site collection level
|
|
10
|
+
* - Web (subsite) level
|
|
11
|
+
* - List level (if applicable)
|
|
12
|
+
*
|
|
13
|
+
* Includes helper methods for permission checks using SPPermission enum.
|
|
14
|
+
*
|
|
15
|
+
* Common permissions to check:
|
|
16
|
+
* - SPPermission.manageWeb
|
|
17
|
+
* - SPPermission.addListItems
|
|
18
|
+
* - SPPermission.editListItems
|
|
19
|
+
* - SPPermission.deleteListItems
|
|
20
|
+
* - SPPermission.viewListItems
|
|
21
|
+
* - SPPermission.managePermissions
|
|
22
|
+
*
|
|
23
|
+
* Useful for:
|
|
24
|
+
* - Conditional UI rendering
|
|
25
|
+
* - Feature availability
|
|
26
|
+
* - Security trimming
|
|
27
|
+
* - Authorization checks
|
|
28
|
+
*
|
|
29
|
+
* @returns Permissions and helper methods
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* function MyComponent() {
|
|
34
|
+
* const { web, hasWebPermission } = useSPFxPermissions();
|
|
35
|
+
* const canManage = hasWebPermission(SPPermission.manageWeb);
|
|
36
|
+
*
|
|
37
|
+
* return (
|
|
38
|
+
* <div>
|
|
39
|
+
* {canManage && <button>Manage Settings</button>}
|
|
40
|
+
* <p>Can manage: {canManage ? 'Yes' : 'No'}</p>
|
|
41
|
+
* </div>
|
|
42
|
+
* );
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function useSPFxPermissions() {
|
|
47
|
+
var _a, _b, _c;
|
|
48
|
+
var pageContext = useSPFxPageContext();
|
|
49
|
+
// Extract permissions from pageContext
|
|
50
|
+
var sitePermissions = (_a = pageContext.site) === null || _a === void 0 ? void 0 : _a.permissions;
|
|
51
|
+
var webPermissions = (_b = pageContext.web) === null || _b === void 0 ? void 0 : _b.permissions;
|
|
52
|
+
var listPermissions = (_c = pageContext.list) === null || _c === void 0 ? void 0 : _c.permissions;
|
|
53
|
+
// Helper to check permission
|
|
54
|
+
var has = useCallback(function (perms, permission) {
|
|
55
|
+
if (!perms) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return perms.hasPermission(permission);
|
|
59
|
+
}, []);
|
|
60
|
+
// Specific helpers for each scope
|
|
61
|
+
var hasWebPermission = useCallback(function (permission) { return has(webPermissions, permission); }, [has, webPermissions]);
|
|
62
|
+
var hasSitePermission = useCallback(function (permission) { return has(sitePermissions, permission); }, [has, sitePermissions]);
|
|
63
|
+
var hasListPermission = useCallback(function (permission) { return has(listPermissions, permission); }, [has, listPermissions]);
|
|
64
|
+
return {
|
|
65
|
+
sitePermissions: sitePermissions,
|
|
66
|
+
webPermissions: webPermissions,
|
|
67
|
+
listPermissions: listPermissions,
|
|
68
|
+
hasWebPermission: hasWebPermission,
|
|
69
|
+
hasSitePermission: hasSitePermission,
|
|
70
|
+
hasListPermission: hasListPermission,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=useSPFxPermissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSPFxPermissions.js","sourceRoot":"","sources":["../../src/hooks/useSPFxPermissions.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,2CAA2C;AAE3C,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAyB1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,UAAU,kBAAkB;;IAChC,IAAM,WAAW,GAAG,kBAAkB,EAAE,CAAC;IAEzC,uCAAuC;IACvC,IAAM,eAAe,GAAG,MAAC,WAAW,CAAC,IAAkD,0CAAE,WAAW,CAAC;IACrG,IAAM,cAAc,GAAG,MAAC,WAAW,CAAC,GAAiD,0CAAE,WAAW,CAAC;IACnG,IAAM,eAAe,GAAG,MAAC,WAAW,CAAC,IAAkD,0CAAE,WAAW,CAAC;IAErG,6BAA6B;IAC7B,IAAM,GAAG,GAAG,WAAW,CACrB,UAAC,KAA+B,EAAE,UAAwB;QACxD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACzC,CAAC,EACD,EAAE,CACH,CAAC;IAEF,kCAAkC;IAClC,IAAM,gBAAgB,GAAG,WAAW,CAClC,UAAC,UAAwB,IAAc,OAAA,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,EAA/B,CAA+B,EACtE,CAAC,GAAG,EAAE,cAAc,CAAC,CACtB,CAAC;IAEF,IAAM,iBAAiB,GAAG,WAAW,CACnC,UAAC,UAAwB,IAAc,OAAA,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,EAAhC,CAAgC,EACvE,CAAC,GAAG,EAAE,eAAe,CAAC,CACvB,CAAC;IAEF,IAAM,iBAAiB,GAAG,WAAW,CACnC,UAAC,UAAwB,IAAc,OAAA,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,EAAhC,CAAgC,EACvE,CAAC,GAAG,EAAE,eAAe,CAAC,CACvB,CAAC;IAEF,OAAO;QACL,eAAe,iBAAA;QACf,cAAc,gBAAA;QACd,eAAe,iBAAA;QACf,gBAAgB,kBAAA;QAChB,iBAAiB,mBAAA;QACjB,iBAAiB,mBAAA;KAClB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
import type { SPFI } from '@pnp/sp';
|
|
2
|
+
import { PnPContextInfo } from './useSPFxPnPContext';
|
|
3
|
+
/**
|
|
4
|
+
* Return type for useSPFxPnP hook
|
|
5
|
+
*/
|
|
6
|
+
export interface SPFxPnPInfo {
|
|
7
|
+
/**
|
|
8
|
+
* Configured SPFI instance for direct access.
|
|
9
|
+
* Undefined if initialization failed.
|
|
10
|
+
*
|
|
11
|
+
* Use this for advanced scenarios or when you need full control:
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const { sp } = useSPFxPnP();
|
|
14
|
+
* const [batchedSP, execute] = sp.batched();
|
|
15
|
+
* // manual batch control
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
readonly sp: SPFI | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Execute single PnPjs operation with automatic state management.
|
|
21
|
+
* Tracks loading state and captures errors automatically.
|
|
22
|
+
* Does NOT track errors from direct sp usage.
|
|
23
|
+
*
|
|
24
|
+
* @param fn - Function that receives SPFI instance and returns a promise
|
|
25
|
+
* @returns Promise with the result
|
|
26
|
+
*
|
|
27
|
+
* @example Basic list query
|
|
28
|
+
* ```tsx
|
|
29
|
+
* const { invoke } = useSPFxPnP();
|
|
30
|
+
*
|
|
31
|
+
* const lists = await invoke(sp => sp.web.lists());
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @example With OData query
|
|
35
|
+
* ```tsx
|
|
36
|
+
* import '@pnp/sp/lists';
|
|
37
|
+
* import '@pnp/sp/items';
|
|
38
|
+
*
|
|
39
|
+
* const items = await invoke(sp =>
|
|
40
|
+
* sp.web.lists
|
|
41
|
+
* .getByTitle('Tasks')
|
|
42
|
+
* .items
|
|
43
|
+
* .select('Id', 'Title', 'Status')
|
|
44
|
+
* .filter("Status eq 'Active'")
|
|
45
|
+
* .orderBy('Created', false)
|
|
46
|
+
* .top(50)()
|
|
47
|
+
* );
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
readonly invoke: <T>(fn: (sp: SPFI) => Promise<T>) => Promise<T>;
|
|
51
|
+
/**
|
|
52
|
+
* Execute multiple PnPjs operations in a single batch request.
|
|
53
|
+
* Automatically handles batch execution and state management.
|
|
54
|
+
*
|
|
55
|
+
* Batching reduces network roundtrips by combining multiple operations
|
|
56
|
+
* into a single HTTP request to SharePoint.
|
|
57
|
+
*
|
|
58
|
+
* @param fn - Function that receives batched SPFI instance and returns a promise
|
|
59
|
+
* @returns Promise with the result
|
|
60
|
+
*
|
|
61
|
+
* @example Load multiple resources in one request
|
|
62
|
+
* ```tsx
|
|
63
|
+
* import '@pnp/sp/lists';
|
|
64
|
+
* import '@pnp/sp/items';
|
|
65
|
+
*
|
|
66
|
+
* const { batch } = useSPFxPnP();
|
|
67
|
+
*
|
|
68
|
+
* const [lists, user, tasks] = await batch(async (batchedSP) => {
|
|
69
|
+
* const lists = batchedSP.web.lists();
|
|
70
|
+
* const user = batchedSP.web.currentUser();
|
|
71
|
+
* const tasks = batchedSP.web.lists.getByTitle('Tasks').items.top(10)();
|
|
72
|
+
*
|
|
73
|
+
* return Promise.all([lists, user, tasks]);
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @example Dashboard with multiple lists
|
|
78
|
+
* ```tsx
|
|
79
|
+
* const results = await batch(async (batchedSP) => {
|
|
80
|
+
* const announcements = batchedSP.web.lists.getByTitle('Announcements').items.top(5)();
|
|
81
|
+
* const events = batchedSP.web.lists.getByTitle('Events').items.top(10)();
|
|
82
|
+
* const tasks = batchedSP.web.lists.getByTitle('Tasks').items.top(20)();
|
|
83
|
+
*
|
|
84
|
+
* return Promise.all([announcements, events, tasks]);
|
|
85
|
+
* });
|
|
86
|
+
*
|
|
87
|
+
* const [announcements, events, tasks] = results;
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
readonly batch: <T>(fn: (batchedSP: SPFI) => Promise<T>) => Promise<T>;
|
|
91
|
+
/**
|
|
92
|
+
* Loading state - true during invoke() or batch() calls.
|
|
93
|
+
* Does not track direct sp usage.
|
|
94
|
+
*
|
|
95
|
+
* Shared between invoke and batch operations.
|
|
96
|
+
*/
|
|
97
|
+
readonly isLoading: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Last error from invoke() or batch() calls, or initialization error from context.
|
|
100
|
+
* Does not capture errors from direct sp usage.
|
|
101
|
+
*
|
|
102
|
+
* Priority: invoke/batch errors take precedence over context initialization errors.
|
|
103
|
+
*/
|
|
104
|
+
readonly error: Error | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* Clear the current error state.
|
|
107
|
+
* Useful for retry patterns in UI.
|
|
108
|
+
*
|
|
109
|
+
* @example Retry pattern
|
|
110
|
+
* ```tsx
|
|
111
|
+
* const { invoke, error, clearError, isLoading } = useSPFxPnP();
|
|
112
|
+
* const [data, setData] = useState(null);
|
|
113
|
+
*
|
|
114
|
+
* const loadData = async () => {
|
|
115
|
+
* try {
|
|
116
|
+
* const items = await invoke(sp => sp.web.lists.getByTitle('Tasks').items());
|
|
117
|
+
* setData(items);
|
|
118
|
+
* } catch (err) {
|
|
119
|
+
* // Error already tracked in state
|
|
120
|
+
* }
|
|
121
|
+
* };
|
|
122
|
+
*
|
|
123
|
+
* if (error) {
|
|
124
|
+
* return (
|
|
125
|
+
* <MessageBar messageBarType={MessageBarType.error}>
|
|
126
|
+
* {error.message}
|
|
127
|
+
* <Link onClick={() => { clearError(); loadData(); }}>
|
|
128
|
+
* Retry
|
|
129
|
+
* </Link>
|
|
130
|
+
* </MessageBar>
|
|
131
|
+
* );
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
readonly clearError: () => void;
|
|
136
|
+
/**
|
|
137
|
+
* True if sp instance is successfully initialized and ready to use.
|
|
138
|
+
* False if initialization failed or context error occurred.
|
|
139
|
+
*/
|
|
140
|
+
readonly isInitialized: boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Effective site URL being used.
|
|
143
|
+
* Resolved from context or current site.
|
|
144
|
+
*/
|
|
145
|
+
readonly siteUrl: string;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Hook to access PnPjs with built-in state management and batching support
|
|
149
|
+
*
|
|
150
|
+
* Provides convenient wrappers around PnPjs SPFI instance with automatic
|
|
151
|
+
* loading and error state tracking. Offers three usage patterns:
|
|
152
|
+
*
|
|
153
|
+
* 1. **invoke()** - Single operations with automatic state management
|
|
154
|
+
* 2. **batch()** - Multiple operations in one request with state management
|
|
155
|
+
* 3. **sp** - Direct access for full control (advanced scenarios)
|
|
156
|
+
*
|
|
157
|
+
* This hook wraps the SPFI instance from useSPFxPnPContext and adds
|
|
158
|
+
* React state management for common patterns.
|
|
159
|
+
*
|
|
160
|
+
* **Selective Imports Required**:
|
|
161
|
+
* This hook provides access to the base PnPjs instance with minimal imports.
|
|
162
|
+
* To use specific PnP modules, import them in your code:
|
|
163
|
+
*
|
|
164
|
+
* ```typescript
|
|
165
|
+
* // For lists and items
|
|
166
|
+
* import '@pnp/sp/lists';
|
|
167
|
+
* import '@pnp/sp/items';
|
|
168
|
+
*
|
|
169
|
+
* // For files and folders
|
|
170
|
+
* import '@pnp/sp/files';
|
|
171
|
+
* import '@pnp/sp/folders';
|
|
172
|
+
*
|
|
173
|
+
* // For search
|
|
174
|
+
* import '@pnp/sp/search';
|
|
175
|
+
*
|
|
176
|
+
* // For user profiles
|
|
177
|
+
* import '@pnp/sp/profiles';
|
|
178
|
+
*
|
|
179
|
+
* // For taxonomy (managed metadata)
|
|
180
|
+
* import '@pnp/sp/taxonomy';
|
|
181
|
+
*
|
|
182
|
+
* // For site users and groups
|
|
183
|
+
* import '@pnp/sp/site-users';
|
|
184
|
+
* import '@pnp/sp/site-groups';
|
|
185
|
+
* ```
|
|
186
|
+
*
|
|
187
|
+
* This approach enables optimal tree-shaking and keeps bundle size minimal.
|
|
188
|
+
*
|
|
189
|
+
* @param pnpContext - Optional PnPContextInfo from useSPFxPnPContext.
|
|
190
|
+
* If not provided, creates default context for current site.
|
|
191
|
+
*
|
|
192
|
+
* @returns SPFxPnPInfo object with sp, invoke, batch, and state management
|
|
193
|
+
*
|
|
194
|
+
* @example Current site with invoke
|
|
195
|
+
* ```tsx
|
|
196
|
+
* import '@pnp/sp/lists';
|
|
197
|
+
*
|
|
198
|
+
* function ListsViewer() {
|
|
199
|
+
* const { invoke, isLoading, error } = useSPFxPnP();
|
|
200
|
+
* const [lists, setLists] = useState([]);
|
|
201
|
+
*
|
|
202
|
+
* useEffect(() => {
|
|
203
|
+
* invoke(sp => sp.web.lists()).then(setLists);
|
|
204
|
+
* }, []);
|
|
205
|
+
*
|
|
206
|
+
* if (isLoading) return <Spinner />;
|
|
207
|
+
* if (error) return <MessageBar messageBarType={MessageBarType.error}>
|
|
208
|
+
* {error.message}
|
|
209
|
+
* </MessageBar>;
|
|
210
|
+
*
|
|
211
|
+
* return <DetailsList items={lists} />;
|
|
212
|
+
* }
|
|
213
|
+
* ```
|
|
214
|
+
*
|
|
215
|
+
* @example Cross-site with context injection
|
|
216
|
+
* ```tsx
|
|
217
|
+
* import '@pnp/sp/lists';
|
|
218
|
+
* import '@pnp/sp/items';
|
|
219
|
+
*
|
|
220
|
+
* function HRDashboard() {
|
|
221
|
+
* // Create context for HR site
|
|
222
|
+
* const hrContext = useSPFxPnPContext('/sites/hr');
|
|
223
|
+
* const { invoke, isLoading, error } = useSPFxPnP(hrContext);
|
|
224
|
+
*
|
|
225
|
+
* const [employees, setEmployees] = useState([]);
|
|
226
|
+
*
|
|
227
|
+
* const loadEmployees = async () => {
|
|
228
|
+
* const items = await invoke(sp =>
|
|
229
|
+
* sp.web.lists
|
|
230
|
+
* .getByTitle('Employees')
|
|
231
|
+
* .items
|
|
232
|
+
* .select('Id', 'Title', 'Department')
|
|
233
|
+
* .top(100)()
|
|
234
|
+
* );
|
|
235
|
+
* setEmployees(items);
|
|
236
|
+
* };
|
|
237
|
+
*
|
|
238
|
+
* if (error) return <MessageBar>{error.message}</MessageBar>;
|
|
239
|
+
*
|
|
240
|
+
* return (
|
|
241
|
+
* <div>
|
|
242
|
+
* <button onClick={loadEmployees} disabled={isLoading}>
|
|
243
|
+
* {isLoading ? 'Loading...' : 'Load Employees'}
|
|
244
|
+
* </button>
|
|
245
|
+
* <DetailsList items={employees} />
|
|
246
|
+
* </div>
|
|
247
|
+
* );
|
|
248
|
+
* }
|
|
249
|
+
* ```
|
|
250
|
+
*
|
|
251
|
+
* @example With caching configuration
|
|
252
|
+
* ```tsx
|
|
253
|
+
* function CachedDataViewer() {
|
|
254
|
+
* // Create context with caching enabled
|
|
255
|
+
* const context = useSPFxPnPContext(undefined, {
|
|
256
|
+
* cache: {
|
|
257
|
+
* enabled: true,
|
|
258
|
+
* storage: 'session',
|
|
259
|
+
* timeout: 600000 // 10 minutes
|
|
260
|
+
* }
|
|
261
|
+
* });
|
|
262
|
+
*
|
|
263
|
+
* const { invoke } = useSPFxPnP(context);
|
|
264
|
+
*
|
|
265
|
+
* // Subsequent calls within 10 minutes use cached data
|
|
266
|
+
* const lists = await invoke(sp => sp.web.lists());
|
|
267
|
+
* }
|
|
268
|
+
* ```
|
|
269
|
+
*
|
|
270
|
+
* @example Batch operations for dashboard
|
|
271
|
+
* ```tsx
|
|
272
|
+
* import '@pnp/sp/lists';
|
|
273
|
+
* import '@pnp/sp/items';
|
|
274
|
+
*
|
|
275
|
+
* function Dashboard() {
|
|
276
|
+
* const { batch, isLoading, error } = useSPFxPnP();
|
|
277
|
+
* const [data, setData] = useState(null);
|
|
278
|
+
*
|
|
279
|
+
* const loadDashboard = async () => {
|
|
280
|
+
* // All operations in ONE HTTP request
|
|
281
|
+
* const [user, tasks, announcements, events] = await batch(async (batchedSP) => {
|
|
282
|
+
* const user = batchedSP.web.currentUser();
|
|
283
|
+
* const tasks = batchedSP.web.lists.getByTitle('Tasks').items.top(10)();
|
|
284
|
+
* const announcements = batchedSP.web.lists.getByTitle('Announcements').items.top(5)();
|
|
285
|
+
* const events = batchedSP.web.lists.getByTitle('Events').items.top(10)();
|
|
286
|
+
*
|
|
287
|
+
* return Promise.all([user, tasks, announcements, events]);
|
|
288
|
+
* });
|
|
289
|
+
*
|
|
290
|
+
* setData({ user, tasks, announcements, events });
|
|
291
|
+
* };
|
|
292
|
+
*
|
|
293
|
+
* useEffect(() => { loadDashboard(); }, []);
|
|
294
|
+
*
|
|
295
|
+
* if (isLoading) return <Spinner label="Loading dashboard..." />;
|
|
296
|
+
* if (error) return <MessageBar messageBarType={MessageBarType.error}>
|
|
297
|
+
* Failed to load dashboard: {error.message}
|
|
298
|
+
* </MessageBar>;
|
|
299
|
+
*
|
|
300
|
+
* return (
|
|
301
|
+
* <Stack tokens={{ childrenGap: 20 }}>
|
|
302
|
+
* <Text variant="xLarge">Welcome, {data?.user?.Title}</Text>
|
|
303
|
+
* <TasksSection items={data?.tasks} />
|
|
304
|
+
* <AnnouncementsSection items={data?.announcements} />
|
|
305
|
+
* <EventsSection items={data?.events} />
|
|
306
|
+
* </Stack>
|
|
307
|
+
* );
|
|
308
|
+
* }
|
|
309
|
+
* ```
|
|
310
|
+
*
|
|
311
|
+
* @example Multi-site dashboard
|
|
312
|
+
* ```tsx
|
|
313
|
+
* function MultiSiteDashboard() {
|
|
314
|
+
* const hrContext = useSPFxPnPContext('/sites/hr');
|
|
315
|
+
* const financeContext = useSPFxPnPContext('/sites/finance');
|
|
316
|
+
*
|
|
317
|
+
* const { invoke: hrInvoke, isLoading: hrLoading } = useSPFxPnP(hrContext);
|
|
318
|
+
* const { invoke: financeInvoke, isLoading: financeLoading } = useSPFxPnP(financeContext);
|
|
319
|
+
*
|
|
320
|
+
* const [hrData, setHrData] = useState([]);
|
|
321
|
+
* const [financeData, setFinanceData] = useState([]);
|
|
322
|
+
*
|
|
323
|
+
* useEffect(() => {
|
|
324
|
+
* hrInvoke(sp => sp.web.lists.getByTitle('Employees').items.top(10)())
|
|
325
|
+
* .then(setHrData);
|
|
326
|
+
*
|
|
327
|
+
* financeInvoke(sp => sp.web.lists.getByTitle('Invoices').items.top(10)())
|
|
328
|
+
* .then(setFinanceData);
|
|
329
|
+
* }, []);
|
|
330
|
+
*
|
|
331
|
+
* return (
|
|
332
|
+
* <Stack tokens={{ childrenGap: 20 }}>
|
|
333
|
+
* <Section title="HR" loading={hrLoading}>
|
|
334
|
+
* <DetailsList items={hrData} />
|
|
335
|
+
* </Section>
|
|
336
|
+
* <Section title="Finance" loading={financeLoading}>
|
|
337
|
+
* <DetailsList items={financeData} />
|
|
338
|
+
* </Section>
|
|
339
|
+
* </Stack>
|
|
340
|
+
* );
|
|
341
|
+
* }
|
|
342
|
+
* ```
|
|
343
|
+
*
|
|
344
|
+
* @example Direct sp access for advanced control
|
|
345
|
+
* ```tsx
|
|
346
|
+
* function AdvancedBatchingComponent() {
|
|
347
|
+
* const { sp, isLoading, error } = useSPFxPnP();
|
|
348
|
+
* const [data, setData] = useState(null);
|
|
349
|
+
* const [customLoading, setCustomLoading] = useState(false);
|
|
350
|
+
*
|
|
351
|
+
* if (!sp) return <Spinner label="Initializing..." />;
|
|
352
|
+
*
|
|
353
|
+
* const loadWithCustomBatch = async () => {
|
|
354
|
+
* setCustomLoading(true);
|
|
355
|
+
* try {
|
|
356
|
+
* // Manual batch control
|
|
357
|
+
* const [batchedSP, execute] = sp.batched();
|
|
358
|
+
*
|
|
359
|
+
* const promise1 = batchedSP.web.lists();
|
|
360
|
+
* const promise2 = batchedSP.web.currentUser();
|
|
361
|
+
*
|
|
362
|
+
* // Execute when ready
|
|
363
|
+
* await execute();
|
|
364
|
+
*
|
|
365
|
+
* const [lists, user] = await Promise.all([promise1, promise2]);
|
|
366
|
+
* setData({ lists, user });
|
|
367
|
+
* } finally {
|
|
368
|
+
* setCustomLoading(false);
|
|
369
|
+
* }
|
|
370
|
+
* };
|
|
371
|
+
*
|
|
372
|
+
* return (
|
|
373
|
+
* <button onClick={loadWithCustomBatch} disabled={customLoading}>
|
|
374
|
+
* {customLoading ? 'Loading...' : 'Load Data'}
|
|
375
|
+
* </button>
|
|
376
|
+
* );
|
|
377
|
+
* }
|
|
378
|
+
* ```
|
|
379
|
+
*
|
|
380
|
+
* @example Combining invoke and batch
|
|
381
|
+
* ```tsx
|
|
382
|
+
* function MixedOperationsComponent() {
|
|
383
|
+
* const { invoke, batch, isLoading } = useSPFxPnP();
|
|
384
|
+
* const [lists, setLists] = useState([]);
|
|
385
|
+
* const [dashboardData, setDashboardData] = useState(null);
|
|
386
|
+
*
|
|
387
|
+
* // Single operation with invoke
|
|
388
|
+
* const loadLists = async () => {
|
|
389
|
+
* const data = await invoke(sp => sp.web.lists());
|
|
390
|
+
* setLists(data);
|
|
391
|
+
* };
|
|
392
|
+
*
|
|
393
|
+
* // Multiple operations with batch
|
|
394
|
+
* const loadDashboard = async () => {
|
|
395
|
+
* const data = await batch(async (batchedSP) => {
|
|
396
|
+
* const tasks = batchedSP.web.lists.getByTitle('Tasks').items.top(10)();
|
|
397
|
+
* const events = batchedSP.web.lists.getByTitle('Events').items.top(10)();
|
|
398
|
+
* return Promise.all([tasks, events]);
|
|
399
|
+
* });
|
|
400
|
+
* setDashboardData(data);
|
|
401
|
+
* };
|
|
402
|
+
*
|
|
403
|
+
* return (
|
|
404
|
+
* <Stack>
|
|
405
|
+
* <button onClick={loadLists} disabled={isLoading}>Load Lists</button>
|
|
406
|
+
* <button onClick={loadDashboard} disabled={isLoading}>Load Dashboard</button>
|
|
407
|
+
* </Stack>
|
|
408
|
+
* );
|
|
409
|
+
* }
|
|
410
|
+
* ```
|
|
411
|
+
*
|
|
412
|
+
* @example Error handling with retry
|
|
413
|
+
* ```tsx
|
|
414
|
+
* function RobustDataLoader() {
|
|
415
|
+
* const { invoke, error, clearError, isLoading } = useSPFxPnP();
|
|
416
|
+
* const [items, setItems] = useState([]);
|
|
417
|
+
* const [retryCount, setRetryCount] = useState(0);
|
|
418
|
+
*
|
|
419
|
+
* const loadItems = async () => {
|
|
420
|
+
* try {
|
|
421
|
+
* const data = await invoke(sp =>
|
|
422
|
+
* sp.web.lists.getByTitle('Tasks').items()
|
|
423
|
+
* );
|
|
424
|
+
* setItems(data);
|
|
425
|
+
* setRetryCount(0); // Reset on success
|
|
426
|
+
* } catch (err) {
|
|
427
|
+
* console.error('Failed to load items:', err);
|
|
428
|
+
* // Error already in state
|
|
429
|
+
* }
|
|
430
|
+
* };
|
|
431
|
+
*
|
|
432
|
+
* const handleRetry = () => {
|
|
433
|
+
* clearError();
|
|
434
|
+
* setRetryCount(prev => prev + 1);
|
|
435
|
+
* loadItems();
|
|
436
|
+
* };
|
|
437
|
+
*
|
|
438
|
+
* useEffect(() => { loadItems(); }, []);
|
|
439
|
+
*
|
|
440
|
+
* if (error) {
|
|
441
|
+
* return (
|
|
442
|
+
* <MessageBar
|
|
443
|
+
* messageBarType={MessageBarType.error}
|
|
444
|
+
* actions={
|
|
445
|
+
* <MessageBarButton onClick={handleRetry}>
|
|
446
|
+
* Retry {retryCount > 0 && `(${retryCount})`}
|
|
447
|
+
* </MessageBarButton>
|
|
448
|
+
* }
|
|
449
|
+
* >
|
|
450
|
+
* {error.message}
|
|
451
|
+
* </MessageBar>
|
|
452
|
+
* );
|
|
453
|
+
* }
|
|
454
|
+
*
|
|
455
|
+
* if (isLoading) {
|
|
456
|
+
* return <Spinner label="Loading items..." />;
|
|
457
|
+
* }
|
|
458
|
+
*
|
|
459
|
+
* return <DetailsList items={items} />;
|
|
460
|
+
* }
|
|
461
|
+
* ```
|
|
462
|
+
*
|
|
463
|
+
* @example Loading states best practices
|
|
464
|
+
* ```tsx
|
|
465
|
+
* function OptimizedLoadingStates() {
|
|
466
|
+
* const { invoke, isLoading, error, isInitialized } = useSPFxPnP();
|
|
467
|
+
* const [items, setItems] = useState([]);
|
|
468
|
+
* const [hasLoaded, setHasLoaded] = useState(false);
|
|
469
|
+
*
|
|
470
|
+
* useEffect(() => {
|
|
471
|
+
* if (isInitialized) {
|
|
472
|
+
* invoke(sp => sp.web.lists.getByTitle('Tasks').items())
|
|
473
|
+
* .then(data => {
|
|
474
|
+
* setItems(data);
|
|
475
|
+
* setHasLoaded(true);
|
|
476
|
+
* });
|
|
477
|
+
* }
|
|
478
|
+
* }, [isInitialized]);
|
|
479
|
+
*
|
|
480
|
+
* // Initial loading (no data yet)
|
|
481
|
+
* if (!hasLoaded && isLoading) {
|
|
482
|
+
* return <Spinner label="Loading tasks..." />;
|
|
483
|
+
* }
|
|
484
|
+
*
|
|
485
|
+
* // Initialization failed
|
|
486
|
+
* if (!isInitialized && error) {
|
|
487
|
+
* return <MessageBar messageBarType={MessageBarType.error}>
|
|
488
|
+
* Failed to initialize: {error.message}
|
|
489
|
+
* </MessageBar>;
|
|
490
|
+
* }
|
|
491
|
+
*
|
|
492
|
+
* // Data error
|
|
493
|
+
* if (error) {
|
|
494
|
+
* return <MessageBar messageBarType={MessageBarType.error}>
|
|
495
|
+
* {error.message}
|
|
496
|
+
* </MessageBar>;
|
|
497
|
+
* }
|
|
498
|
+
*
|
|
499
|
+
* // Refreshing (show data with shimmer)
|
|
500
|
+
* if (hasLoaded && isLoading) {
|
|
501
|
+
* return (
|
|
502
|
+
* <div style={{ position: 'relative' }}>
|
|
503
|
+
* <Shimmer />
|
|
504
|
+
* <DetailsList items={items} />
|
|
505
|
+
* </div>
|
|
506
|
+
* );
|
|
507
|
+
* }
|
|
508
|
+
*
|
|
509
|
+
* // Success
|
|
510
|
+
* return <DetailsList items={items} />;
|
|
511
|
+
* }
|
|
512
|
+
* ```
|
|
513
|
+
*
|
|
514
|
+
* @remarks
|
|
515
|
+
* **State Management**:
|
|
516
|
+
* - `isLoading` is shared between invoke() and batch() operations
|
|
517
|
+
* - `error` prioritizes invoke/batch errors over context initialization errors
|
|
518
|
+
* - Direct `sp` usage does not update isLoading or error states
|
|
519
|
+
*
|
|
520
|
+
* **Performance**:
|
|
521
|
+
* - invoke() and batch() are memoized with useCallback
|
|
522
|
+
* - Reuses SPFI instance from context (no re-initialization)
|
|
523
|
+
* - Batching reduces network roundtrips significantly
|
|
524
|
+
*
|
|
525
|
+
* **Cross-Site Operations**:
|
|
526
|
+
* - Pass PnPContextInfo from useSPFxPnPContext for different sites
|
|
527
|
+
* - Each context maintains separate configuration (cache, headers, etc.)
|
|
528
|
+
* - Requires appropriate permissions on target sites
|
|
529
|
+
*
|
|
530
|
+
* **Tree-Shaking**:
|
|
531
|
+
* - This hook imports no additional PnP modules
|
|
532
|
+
* - User-side selective imports enable optimal bundle size
|
|
533
|
+
* - Only import what you actually use
|
|
534
|
+
*
|
|
535
|
+
* @see {@link useSPFxPnPContext} for creating configured SPFI instances
|
|
536
|
+
* @see {@link useSPFxPnPList} for specialized list operations
|
|
537
|
+
*/
|
|
538
|
+
export declare function useSPFxPnP(pnpContext?: PnPContextInfo): SPFxPnPInfo;
|
|
539
|
+
//# sourceMappingURL=useSPFxPnP.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSPFxPnP.d.ts","sourceRoot":"","sources":["../../src/hooks/useSPFxPnP.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAqB,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAExE;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,EAAE,IAAI,GAAG,SAAS,CAAC;IAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAEvE;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAE5B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IAElC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsYG;AACH,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,cAAc,GAAG,WAAW,CAoGnE"}
|