@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.
Files changed (220) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2012 -0
  3. package/lib/core/atoms.internal.d.ts +53 -0
  4. package/lib/core/atoms.internal.d.ts.map +1 -0
  5. package/lib/core/atoms.internal.js +35 -0
  6. package/lib/core/atoms.internal.js.map +1 -0
  7. package/lib/core/context.internal.d.ts +23 -0
  8. package/lib/core/context.internal.d.ts.map +1 -0
  9. package/lib/core/context.internal.js +34 -0
  10. package/lib/core/context.internal.js.map +1 -0
  11. package/lib/core/index.d.ts +6 -0
  12. package/lib/core/index.d.ts.map +1 -0
  13. package/lib/core/index.js +6 -0
  14. package/lib/core/index.js.map +1 -0
  15. package/lib/core/provider-application-customizer.d.ts +57 -0
  16. package/lib/core/provider-application-customizer.d.ts.map +1 -0
  17. package/lib/core/provider-application-customizer.js +45 -0
  18. package/lib/core/provider-application-customizer.js.map +1 -0
  19. package/lib/core/provider-base.internal.d.ts +20 -0
  20. package/lib/core/provider-base.internal.d.ts.map +1 -0
  21. package/lib/core/provider-base.internal.js +126 -0
  22. package/lib/core/provider-base.internal.js.map +1 -0
  23. package/lib/core/provider-field-customizer.d.ts +58 -0
  24. package/lib/core/provider-field-customizer.d.ts.map +1 -0
  25. package/lib/core/provider-field-customizer.js +46 -0
  26. package/lib/core/provider-field-customizer.js.map +1 -0
  27. package/lib/core/provider-listview-commandset.d.ts +60 -0
  28. package/lib/core/provider-listview-commandset.d.ts.map +1 -0
  29. package/lib/core/provider-listview-commandset.js +48 -0
  30. package/lib/core/provider-listview-commandset.js.map +1 -0
  31. package/lib/core/provider-webpart.d.ts +48 -0
  32. package/lib/core/provider-webpart.d.ts.map +1 -0
  33. package/lib/core/provider-webpart.js +36 -0
  34. package/lib/core/provider-webpart.js.map +1 -0
  35. package/lib/core/types.d.ts +84 -0
  36. package/lib/core/types.d.ts.map +1 -0
  37. package/lib/core/types.js +4 -0
  38. package/lib/core/types.js.map +1 -0
  39. package/lib/hooks/index.d.ts +34 -0
  40. package/lib/hooks/index.d.ts.map +1 -0
  41. package/lib/hooks/index.js +34 -0
  42. package/lib/hooks/index.js.map +1 -0
  43. package/lib/hooks/useSPFxAadHttpClient.d.ts +231 -0
  44. package/lib/hooks/useSPFxAadHttpClient.d.ts.map +1 -0
  45. package/lib/hooks/useSPFxAadHttpClient.js +299 -0
  46. package/lib/hooks/useSPFxAadHttpClient.js.map +1 -0
  47. package/lib/hooks/useSPFxContainerInfo.d.ts +41 -0
  48. package/lib/hooks/useSPFxContainerInfo.d.ts.map +1 -0
  49. package/lib/hooks/useSPFxContainerInfo.js +47 -0
  50. package/lib/hooks/useSPFxContainerInfo.js.map +1 -0
  51. package/lib/hooks/useSPFxContainerSize.d.ts +119 -0
  52. package/lib/hooks/useSPFxContainerSize.d.ts.map +1 -0
  53. package/lib/hooks/useSPFxContainerSize.js +150 -0
  54. package/lib/hooks/useSPFxContainerSize.js.map +1 -0
  55. package/lib/hooks/useSPFxContext.d.ts +14 -0
  56. package/lib/hooks/useSPFxContext.d.ts.map +1 -0
  57. package/lib/hooks/useSPFxContext.js +16 -0
  58. package/lib/hooks/useSPFxContext.js.map +1 -0
  59. package/lib/hooks/useSPFxCorrelationInfo.d.ts +51 -0
  60. package/lib/hooks/useSPFxCorrelationInfo.d.ts.map +1 -0
  61. package/lib/hooks/useSPFxCorrelationInfo.js +58 -0
  62. package/lib/hooks/useSPFxCorrelationInfo.js.map +1 -0
  63. package/lib/hooks/useSPFxCrossSitePermissions.d.ts +81 -0
  64. package/lib/hooks/useSPFxCrossSitePermissions.d.ts.map +1 -0
  65. package/lib/hooks/useSPFxCrossSitePermissions.js +132 -0
  66. package/lib/hooks/useSPFxCrossSitePermissions.js.map +1 -0
  67. package/lib/hooks/useSPFxDisplayMode.d.ts +61 -0
  68. package/lib/hooks/useSPFxDisplayMode.d.ts.map +1 -0
  69. package/lib/hooks/useSPFxDisplayMode.js +69 -0
  70. package/lib/hooks/useSPFxDisplayMode.js.map +1 -0
  71. package/lib/hooks/useSPFxEnvironmentInfo.d.ts +63 -0
  72. package/lib/hooks/useSPFxEnvironmentInfo.d.ts.map +1 -0
  73. package/lib/hooks/useSPFxEnvironmentInfo.js +91 -0
  74. package/lib/hooks/useSPFxEnvironmentInfo.js.map +1 -0
  75. package/lib/hooks/useSPFxFluent9ThemeInfo.d.ts +105 -0
  76. package/lib/hooks/useSPFxFluent9ThemeInfo.d.ts.map +1 -0
  77. package/lib/hooks/useSPFxFluent9ThemeInfo.js +136 -0
  78. package/lib/hooks/useSPFxFluent9ThemeInfo.js.map +1 -0
  79. package/lib/hooks/useSPFxHubSiteInfo.d.ts +80 -0
  80. package/lib/hooks/useSPFxHubSiteInfo.d.ts.map +1 -0
  81. package/lib/hooks/useSPFxHubSiteInfo.js +127 -0
  82. package/lib/hooks/useSPFxHubSiteInfo.js.map +1 -0
  83. package/lib/hooks/useSPFxInstanceInfo.d.ts +41 -0
  84. package/lib/hooks/useSPFxInstanceInfo.d.ts.map +1 -0
  85. package/lib/hooks/useSPFxInstanceInfo.js +40 -0
  86. package/lib/hooks/useSPFxInstanceInfo.js.map +1 -0
  87. package/lib/hooks/useSPFxListInfo.d.ts +64 -0
  88. package/lib/hooks/useSPFxListInfo.d.ts.map +1 -0
  89. package/lib/hooks/useSPFxListInfo.js +70 -0
  90. package/lib/hooks/useSPFxListInfo.js.map +1 -0
  91. package/lib/hooks/useSPFxLocaleInfo.d.ts +123 -0
  92. package/lib/hooks/useSPFxLocaleInfo.d.ts.map +1 -0
  93. package/lib/hooks/useSPFxLocaleInfo.js +109 -0
  94. package/lib/hooks/useSPFxLocaleInfo.js.map +1 -0
  95. package/lib/hooks/useSPFxLogger.d.ts +108 -0
  96. package/lib/hooks/useSPFxLogger.d.ts.map +1 -0
  97. package/lib/hooks/useSPFxLogger.js +117 -0
  98. package/lib/hooks/useSPFxLogger.js.map +1 -0
  99. package/lib/hooks/useSPFxMSGraphClient.d.ts +200 -0
  100. package/lib/hooks/useSPFxMSGraphClient.d.ts.map +1 -0
  101. package/lib/hooks/useSPFxMSGraphClient.js +264 -0
  102. package/lib/hooks/useSPFxMSGraphClient.js.map +1 -0
  103. package/lib/hooks/useSPFxOneDriveAppData.d.ts +264 -0
  104. package/lib/hooks/useSPFxOneDriveAppData.d.ts.map +1 -0
  105. package/lib/hooks/useSPFxOneDriveAppData.js +395 -0
  106. package/lib/hooks/useSPFxOneDriveAppData.js.map +1 -0
  107. package/lib/hooks/useSPFxPageContext.d.ts +37 -0
  108. package/lib/hooks/useSPFxPageContext.d.ts.map +1 -0
  109. package/lib/hooks/useSPFxPageContext.js +49 -0
  110. package/lib/hooks/useSPFxPageContext.js.map +1 -0
  111. package/lib/hooks/useSPFxPageType.d.ts +82 -0
  112. package/lib/hooks/useSPFxPageType.d.ts.map +1 -0
  113. package/lib/hooks/useSPFxPageType.js +137 -0
  114. package/lib/hooks/useSPFxPageType.js.map +1 -0
  115. package/lib/hooks/useSPFxPerformance.d.ts +72 -0
  116. package/lib/hooks/useSPFxPerformance.d.ts.map +1 -0
  117. package/lib/hooks/useSPFxPerformance.js +167 -0
  118. package/lib/hooks/useSPFxPerformance.js.map +1 -0
  119. package/lib/hooks/useSPFxPermissions.d.ts +61 -0
  120. package/lib/hooks/useSPFxPermissions.d.ts.map +1 -0
  121. package/lib/hooks/useSPFxPermissions.js +73 -0
  122. package/lib/hooks/useSPFxPermissions.js.map +1 -0
  123. package/lib/hooks/useSPFxPnP.d.ts +539 -0
  124. package/lib/hooks/useSPFxPnP.d.ts.map +1 -0
  125. package/lib/hooks/useSPFxPnP.js +533 -0
  126. package/lib/hooks/useSPFxPnP.js.map +1 -0
  127. package/lib/hooks/useSPFxPnPContext.d.ts +290 -0
  128. package/lib/hooks/useSPFxPnPContext.d.ts.map +1 -0
  129. package/lib/hooks/useSPFxPnPContext.js +340 -0
  130. package/lib/hooks/useSPFxPnPContext.js.map +1 -0
  131. package/lib/hooks/useSPFxPnPList.d.ts +545 -0
  132. package/lib/hooks/useSPFxPnPList.d.ts.map +1 -0
  133. package/lib/hooks/useSPFxPnPList.js +906 -0
  134. package/lib/hooks/useSPFxPnPList.js.map +1 -0
  135. package/lib/hooks/useSPFxPnPSearch.d.ts +540 -0
  136. package/lib/hooks/useSPFxPnPSearch.d.ts.map +1 -0
  137. package/lib/hooks/useSPFxPnPSearch.js +672 -0
  138. package/lib/hooks/useSPFxPnPSearch.js.map +1 -0
  139. package/lib/hooks/useSPFxProperties.d.ts +80 -0
  140. package/lib/hooks/useSPFxProperties.d.ts.map +1 -0
  141. package/lib/hooks/useSPFxProperties.js +95 -0
  142. package/lib/hooks/useSPFxProperties.js.map +1 -0
  143. package/lib/hooks/useSPFxSPHttpClient.d.ts +218 -0
  144. package/lib/hooks/useSPFxSPHttpClient.d.ts.map +1 -0
  145. package/lib/hooks/useSPFxSPHttpClient.js +287 -0
  146. package/lib/hooks/useSPFxSPHttpClient.js.map +1 -0
  147. package/lib/hooks/useSPFxServiceScope.d.ts +107 -0
  148. package/lib/hooks/useSPFxServiceScope.d.ts.map +1 -0
  149. package/lib/hooks/useSPFxServiceScope.js +105 -0
  150. package/lib/hooks/useSPFxServiceScope.js.map +1 -0
  151. package/lib/hooks/useSPFxSiteInfo.d.ts +116 -0
  152. package/lib/hooks/useSPFxSiteInfo.d.ts.map +1 -0
  153. package/lib/hooks/useSPFxSiteInfo.js +109 -0
  154. package/lib/hooks/useSPFxSiteInfo.js.map +1 -0
  155. package/lib/hooks/useSPFxStorage.d.ts +81 -0
  156. package/lib/hooks/useSPFxStorage.d.ts.map +1 -0
  157. package/lib/hooks/useSPFxStorage.js +140 -0
  158. package/lib/hooks/useSPFxStorage.js.map +1 -0
  159. package/lib/hooks/useSPFxTeams.d.ts +63 -0
  160. package/lib/hooks/useSPFxTeams.d.ts.map +1 -0
  161. package/lib/hooks/useSPFxTeams.js +198 -0
  162. package/lib/hooks/useSPFxTeams.js.map +1 -0
  163. package/lib/hooks/useSPFxTenantProperty.d.ts +389 -0
  164. package/lib/hooks/useSPFxTenantProperty.d.ts.map +1 -0
  165. package/lib/hooks/useSPFxTenantProperty.js +683 -0
  166. package/lib/hooks/useSPFxTenantProperty.js.map +1 -0
  167. package/lib/hooks/useSPFxThemeInfo.d.ts +27 -0
  168. package/lib/hooks/useSPFxThemeInfo.d.ts.map +1 -0
  169. package/lib/hooks/useSPFxThemeInfo.js +33 -0
  170. package/lib/hooks/useSPFxThemeInfo.js.map +1 -0
  171. package/lib/hooks/useSPFxUserInfo.d.ts +47 -0
  172. package/lib/hooks/useSPFxUserInfo.d.ts.map +1 -0
  173. package/lib/hooks/useSPFxUserInfo.js +47 -0
  174. package/lib/hooks/useSPFxUserInfo.js.map +1 -0
  175. package/lib/hooks/useSPFxUserPhoto.d.ts +270 -0
  176. package/lib/hooks/useSPFxUserPhoto.d.ts.map +1 -0
  177. package/lib/hooks/useSPFxUserPhoto.js +346 -0
  178. package/lib/hooks/useSPFxUserPhoto.js.map +1 -0
  179. package/lib/index.d.ts +3 -0
  180. package/lib/index.d.ts.map +1 -0
  181. package/lib/index.js +3 -0
  182. package/lib/index.js.map +1 -0
  183. package/lib/utils/index.d.ts +1 -0
  184. package/lib/utils/index.d.ts.map +1 -0
  185. package/lib/utils/index.js +3 -0
  186. package/lib/utils/index.js.map +1 -0
  187. package/lib/utils/resize-observer.internal.d.ts +10 -0
  188. package/lib/utils/resize-observer.internal.d.ts.map +1 -0
  189. package/lib/utils/resize-observer.internal.js +34 -0
  190. package/lib/utils/resize-observer.internal.js.map +1 -0
  191. package/lib/utils/theme-subscription.internal.d.ts +11 -0
  192. package/lib/utils/theme-subscription.internal.d.ts.map +1 -0
  193. package/lib/utils/theme-subscription.internal.js +58 -0
  194. package/lib/utils/theme-subscription.internal.js.map +1 -0
  195. package/lib/utils/type-guards.internal.d.ts +35 -0
  196. package/lib/utils/type-guards.internal.d.ts.map +1 -0
  197. package/lib/utils/type-guards.internal.js +88 -0
  198. package/lib/utils/type-guards.internal.js.map +1 -0
  199. package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.d.ts +13 -0
  200. package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.d.ts.map +1 -0
  201. package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.js +67 -0
  202. package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.js.map +1 -0
  203. package/lib/webparts/spFxReactToolkitTest/SpFxReactToolkitTestWebPart.manifest.json +21 -0
  204. package/lib/webparts/spFxReactToolkitTest/assets/welcome-dark.png +0 -0
  205. package/lib/webparts/spFxReactToolkitTest/assets/welcome-light.png +0 -0
  206. package/lib/webparts/spFxReactToolkitTest/components/ISpFxReactToolkitTestProps.d.ts +8 -0
  207. package/lib/webparts/spFxReactToolkitTest/components/ISpFxReactToolkitTestProps.d.ts.map +1 -0
  208. package/lib/webparts/spFxReactToolkitTest/components/ISpFxReactToolkitTestProps.js +2 -0
  209. package/lib/webparts/spFxReactToolkitTest/components/ISpFxReactToolkitTestProps.js.map +1 -0
  210. package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.d.ts +8 -0
  211. package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.d.ts.map +1 -0
  212. package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.js +1351 -0
  213. package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.js.map +1 -0
  214. package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.css +2 -0
  215. package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.scss.d.ts +18 -0
  216. package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.scss.d.ts.map +1 -0
  217. package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.scss.js +19 -0
  218. package/lib/webparts/spFxReactToolkitTest/components/SpFxReactToolkitTest.module.scss.js.map +1 -0
  219. package/lib/webparts/spFxReactToolkitTest/loc/en-us.js +16 -0
  220. package/package.json +95 -0
@@ -0,0 +1,533 @@
1
+ // useSPFxPnP.ts
2
+ // Hook to access PnPjs with state management and batching support
3
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
+ return new (P || (P = Promise))(function (resolve, reject) {
6
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
9
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
10
+ });
11
+ };
12
+ var __generator = (this && this.__generator) || function (thisArg, body) {
13
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
14
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
15
+ function verb(n) { return function (v) { return step([n, v]); }; }
16
+ function step(op) {
17
+ if (f) throw new TypeError("Generator is already executing.");
18
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
19
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
20
+ if (y = 0, t) op = [op[0] & 2, t.value];
21
+ switch (op[0]) {
22
+ case 0: case 1: t = op; break;
23
+ case 4: _.label++; return { value: op[1], done: false };
24
+ case 5: _.label++; y = op[1]; op = [0]; continue;
25
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
26
+ default:
27
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
28
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
29
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
30
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
31
+ if (t[2]) _.ops.pop();
32
+ _.trys.pop(); continue;
33
+ }
34
+ op = body.call(thisArg, _);
35
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
36
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
37
+ }
38
+ };
39
+ import { useState, useCallback } from 'react';
40
+ import { useSPFxPnPContext } from './useSPFxPnPContext';
41
+ /**
42
+ * Hook to access PnPjs with built-in state management and batching support
43
+ *
44
+ * Provides convenient wrappers around PnPjs SPFI instance with automatic
45
+ * loading and error state tracking. Offers three usage patterns:
46
+ *
47
+ * 1. **invoke()** - Single operations with automatic state management
48
+ * 2. **batch()** - Multiple operations in one request with state management
49
+ * 3. **sp** - Direct access for full control (advanced scenarios)
50
+ *
51
+ * This hook wraps the SPFI instance from useSPFxPnPContext and adds
52
+ * React state management for common patterns.
53
+ *
54
+ * **Selective Imports Required**:
55
+ * This hook provides access to the base PnPjs instance with minimal imports.
56
+ * To use specific PnP modules, import them in your code:
57
+ *
58
+ * ```typescript
59
+ * // For lists and items
60
+ * import '@pnp/sp/lists';
61
+ * import '@pnp/sp/items';
62
+ *
63
+ * // For files and folders
64
+ * import '@pnp/sp/files';
65
+ * import '@pnp/sp/folders';
66
+ *
67
+ * // For search
68
+ * import '@pnp/sp/search';
69
+ *
70
+ * // For user profiles
71
+ * import '@pnp/sp/profiles';
72
+ *
73
+ * // For taxonomy (managed metadata)
74
+ * import '@pnp/sp/taxonomy';
75
+ *
76
+ * // For site users and groups
77
+ * import '@pnp/sp/site-users';
78
+ * import '@pnp/sp/site-groups';
79
+ * ```
80
+ *
81
+ * This approach enables optimal tree-shaking and keeps bundle size minimal.
82
+ *
83
+ * @param pnpContext - Optional PnPContextInfo from useSPFxPnPContext.
84
+ * If not provided, creates default context for current site.
85
+ *
86
+ * @returns SPFxPnPInfo object with sp, invoke, batch, and state management
87
+ *
88
+ * @example Current site with invoke
89
+ * ```tsx
90
+ * import '@pnp/sp/lists';
91
+ *
92
+ * function ListsViewer() {
93
+ * const { invoke, isLoading, error } = useSPFxPnP();
94
+ * const [lists, setLists] = useState([]);
95
+ *
96
+ * useEffect(() => {
97
+ * invoke(sp => sp.web.lists()).then(setLists);
98
+ * }, []);
99
+ *
100
+ * if (isLoading) return <Spinner />;
101
+ * if (error) return <MessageBar messageBarType={MessageBarType.error}>
102
+ * {error.message}
103
+ * </MessageBar>;
104
+ *
105
+ * return <DetailsList items={lists} />;
106
+ * }
107
+ * ```
108
+ *
109
+ * @example Cross-site with context injection
110
+ * ```tsx
111
+ * import '@pnp/sp/lists';
112
+ * import '@pnp/sp/items';
113
+ *
114
+ * function HRDashboard() {
115
+ * // Create context for HR site
116
+ * const hrContext = useSPFxPnPContext('/sites/hr');
117
+ * const { invoke, isLoading, error } = useSPFxPnP(hrContext);
118
+ *
119
+ * const [employees, setEmployees] = useState([]);
120
+ *
121
+ * const loadEmployees = async () => {
122
+ * const items = await invoke(sp =>
123
+ * sp.web.lists
124
+ * .getByTitle('Employees')
125
+ * .items
126
+ * .select('Id', 'Title', 'Department')
127
+ * .top(100)()
128
+ * );
129
+ * setEmployees(items);
130
+ * };
131
+ *
132
+ * if (error) return <MessageBar>{error.message}</MessageBar>;
133
+ *
134
+ * return (
135
+ * <div>
136
+ * <button onClick={loadEmployees} disabled={isLoading}>
137
+ * {isLoading ? 'Loading...' : 'Load Employees'}
138
+ * </button>
139
+ * <DetailsList items={employees} />
140
+ * </div>
141
+ * );
142
+ * }
143
+ * ```
144
+ *
145
+ * @example With caching configuration
146
+ * ```tsx
147
+ * function CachedDataViewer() {
148
+ * // Create context with caching enabled
149
+ * const context = useSPFxPnPContext(undefined, {
150
+ * cache: {
151
+ * enabled: true,
152
+ * storage: 'session',
153
+ * timeout: 600000 // 10 minutes
154
+ * }
155
+ * });
156
+ *
157
+ * const { invoke } = useSPFxPnP(context);
158
+ *
159
+ * // Subsequent calls within 10 minutes use cached data
160
+ * const lists = await invoke(sp => sp.web.lists());
161
+ * }
162
+ * ```
163
+ *
164
+ * @example Batch operations for dashboard
165
+ * ```tsx
166
+ * import '@pnp/sp/lists';
167
+ * import '@pnp/sp/items';
168
+ *
169
+ * function Dashboard() {
170
+ * const { batch, isLoading, error } = useSPFxPnP();
171
+ * const [data, setData] = useState(null);
172
+ *
173
+ * const loadDashboard = async () => {
174
+ * // All operations in ONE HTTP request
175
+ * const [user, tasks, announcements, events] = await batch(async (batchedSP) => {
176
+ * const user = batchedSP.web.currentUser();
177
+ * const tasks = batchedSP.web.lists.getByTitle('Tasks').items.top(10)();
178
+ * const announcements = batchedSP.web.lists.getByTitle('Announcements').items.top(5)();
179
+ * const events = batchedSP.web.lists.getByTitle('Events').items.top(10)();
180
+ *
181
+ * return Promise.all([user, tasks, announcements, events]);
182
+ * });
183
+ *
184
+ * setData({ user, tasks, announcements, events });
185
+ * };
186
+ *
187
+ * useEffect(() => { loadDashboard(); }, []);
188
+ *
189
+ * if (isLoading) return <Spinner label="Loading dashboard..." />;
190
+ * if (error) return <MessageBar messageBarType={MessageBarType.error}>
191
+ * Failed to load dashboard: {error.message}
192
+ * </MessageBar>;
193
+ *
194
+ * return (
195
+ * <Stack tokens={{ childrenGap: 20 }}>
196
+ * <Text variant="xLarge">Welcome, {data?.user?.Title}</Text>
197
+ * <TasksSection items={data?.tasks} />
198
+ * <AnnouncementsSection items={data?.announcements} />
199
+ * <EventsSection items={data?.events} />
200
+ * </Stack>
201
+ * );
202
+ * }
203
+ * ```
204
+ *
205
+ * @example Multi-site dashboard
206
+ * ```tsx
207
+ * function MultiSiteDashboard() {
208
+ * const hrContext = useSPFxPnPContext('/sites/hr');
209
+ * const financeContext = useSPFxPnPContext('/sites/finance');
210
+ *
211
+ * const { invoke: hrInvoke, isLoading: hrLoading } = useSPFxPnP(hrContext);
212
+ * const { invoke: financeInvoke, isLoading: financeLoading } = useSPFxPnP(financeContext);
213
+ *
214
+ * const [hrData, setHrData] = useState([]);
215
+ * const [financeData, setFinanceData] = useState([]);
216
+ *
217
+ * useEffect(() => {
218
+ * hrInvoke(sp => sp.web.lists.getByTitle('Employees').items.top(10)())
219
+ * .then(setHrData);
220
+ *
221
+ * financeInvoke(sp => sp.web.lists.getByTitle('Invoices').items.top(10)())
222
+ * .then(setFinanceData);
223
+ * }, []);
224
+ *
225
+ * return (
226
+ * <Stack tokens={{ childrenGap: 20 }}>
227
+ * <Section title="HR" loading={hrLoading}>
228
+ * <DetailsList items={hrData} />
229
+ * </Section>
230
+ * <Section title="Finance" loading={financeLoading}>
231
+ * <DetailsList items={financeData} />
232
+ * </Section>
233
+ * </Stack>
234
+ * );
235
+ * }
236
+ * ```
237
+ *
238
+ * @example Direct sp access for advanced control
239
+ * ```tsx
240
+ * function AdvancedBatchingComponent() {
241
+ * const { sp, isLoading, error } = useSPFxPnP();
242
+ * const [data, setData] = useState(null);
243
+ * const [customLoading, setCustomLoading] = useState(false);
244
+ *
245
+ * if (!sp) return <Spinner label="Initializing..." />;
246
+ *
247
+ * const loadWithCustomBatch = async () => {
248
+ * setCustomLoading(true);
249
+ * try {
250
+ * // Manual batch control
251
+ * const [batchedSP, execute] = sp.batched();
252
+ *
253
+ * const promise1 = batchedSP.web.lists();
254
+ * const promise2 = batchedSP.web.currentUser();
255
+ *
256
+ * // Execute when ready
257
+ * await execute();
258
+ *
259
+ * const [lists, user] = await Promise.all([promise1, promise2]);
260
+ * setData({ lists, user });
261
+ * } finally {
262
+ * setCustomLoading(false);
263
+ * }
264
+ * };
265
+ *
266
+ * return (
267
+ * <button onClick={loadWithCustomBatch} disabled={customLoading}>
268
+ * {customLoading ? 'Loading...' : 'Load Data'}
269
+ * </button>
270
+ * );
271
+ * }
272
+ * ```
273
+ *
274
+ * @example Combining invoke and batch
275
+ * ```tsx
276
+ * function MixedOperationsComponent() {
277
+ * const { invoke, batch, isLoading } = useSPFxPnP();
278
+ * const [lists, setLists] = useState([]);
279
+ * const [dashboardData, setDashboardData] = useState(null);
280
+ *
281
+ * // Single operation with invoke
282
+ * const loadLists = async () => {
283
+ * const data = await invoke(sp => sp.web.lists());
284
+ * setLists(data);
285
+ * };
286
+ *
287
+ * // Multiple operations with batch
288
+ * const loadDashboard = async () => {
289
+ * const data = await batch(async (batchedSP) => {
290
+ * const tasks = batchedSP.web.lists.getByTitle('Tasks').items.top(10)();
291
+ * const events = batchedSP.web.lists.getByTitle('Events').items.top(10)();
292
+ * return Promise.all([tasks, events]);
293
+ * });
294
+ * setDashboardData(data);
295
+ * };
296
+ *
297
+ * return (
298
+ * <Stack>
299
+ * <button onClick={loadLists} disabled={isLoading}>Load Lists</button>
300
+ * <button onClick={loadDashboard} disabled={isLoading}>Load Dashboard</button>
301
+ * </Stack>
302
+ * );
303
+ * }
304
+ * ```
305
+ *
306
+ * @example Error handling with retry
307
+ * ```tsx
308
+ * function RobustDataLoader() {
309
+ * const { invoke, error, clearError, isLoading } = useSPFxPnP();
310
+ * const [items, setItems] = useState([]);
311
+ * const [retryCount, setRetryCount] = useState(0);
312
+ *
313
+ * const loadItems = async () => {
314
+ * try {
315
+ * const data = await invoke(sp =>
316
+ * sp.web.lists.getByTitle('Tasks').items()
317
+ * );
318
+ * setItems(data);
319
+ * setRetryCount(0); // Reset on success
320
+ * } catch (err) {
321
+ * console.error('Failed to load items:', err);
322
+ * // Error already in state
323
+ * }
324
+ * };
325
+ *
326
+ * const handleRetry = () => {
327
+ * clearError();
328
+ * setRetryCount(prev => prev + 1);
329
+ * loadItems();
330
+ * };
331
+ *
332
+ * useEffect(() => { loadItems(); }, []);
333
+ *
334
+ * if (error) {
335
+ * return (
336
+ * <MessageBar
337
+ * messageBarType={MessageBarType.error}
338
+ * actions={
339
+ * <MessageBarButton onClick={handleRetry}>
340
+ * Retry {retryCount > 0 && `(${retryCount})`}
341
+ * </MessageBarButton>
342
+ * }
343
+ * >
344
+ * {error.message}
345
+ * </MessageBar>
346
+ * );
347
+ * }
348
+ *
349
+ * if (isLoading) {
350
+ * return <Spinner label="Loading items..." />;
351
+ * }
352
+ *
353
+ * return <DetailsList items={items} />;
354
+ * }
355
+ * ```
356
+ *
357
+ * @example Loading states best practices
358
+ * ```tsx
359
+ * function OptimizedLoadingStates() {
360
+ * const { invoke, isLoading, error, isInitialized } = useSPFxPnP();
361
+ * const [items, setItems] = useState([]);
362
+ * const [hasLoaded, setHasLoaded] = useState(false);
363
+ *
364
+ * useEffect(() => {
365
+ * if (isInitialized) {
366
+ * invoke(sp => sp.web.lists.getByTitle('Tasks').items())
367
+ * .then(data => {
368
+ * setItems(data);
369
+ * setHasLoaded(true);
370
+ * });
371
+ * }
372
+ * }, [isInitialized]);
373
+ *
374
+ * // Initial loading (no data yet)
375
+ * if (!hasLoaded && isLoading) {
376
+ * return <Spinner label="Loading tasks..." />;
377
+ * }
378
+ *
379
+ * // Initialization failed
380
+ * if (!isInitialized && error) {
381
+ * return <MessageBar messageBarType={MessageBarType.error}>
382
+ * Failed to initialize: {error.message}
383
+ * </MessageBar>;
384
+ * }
385
+ *
386
+ * // Data error
387
+ * if (error) {
388
+ * return <MessageBar messageBarType={MessageBarType.error}>
389
+ * {error.message}
390
+ * </MessageBar>;
391
+ * }
392
+ *
393
+ * // Refreshing (show data with shimmer)
394
+ * if (hasLoaded && isLoading) {
395
+ * return (
396
+ * <div style={{ position: 'relative' }}>
397
+ * <Shimmer />
398
+ * <DetailsList items={items} />
399
+ * </div>
400
+ * );
401
+ * }
402
+ *
403
+ * // Success
404
+ * return <DetailsList items={items} />;
405
+ * }
406
+ * ```
407
+ *
408
+ * @remarks
409
+ * **State Management**:
410
+ * - `isLoading` is shared between invoke() and batch() operations
411
+ * - `error` prioritizes invoke/batch errors over context initialization errors
412
+ * - Direct `sp` usage does not update isLoading or error states
413
+ *
414
+ * **Performance**:
415
+ * - invoke() and batch() are memoized with useCallback
416
+ * - Reuses SPFI instance from context (no re-initialization)
417
+ * - Batching reduces network roundtrips significantly
418
+ *
419
+ * **Cross-Site Operations**:
420
+ * - Pass PnPContextInfo from useSPFxPnPContext for different sites
421
+ * - Each context maintains separate configuration (cache, headers, etc.)
422
+ * - Requires appropriate permissions on target sites
423
+ *
424
+ * **Tree-Shaking**:
425
+ * - This hook imports no additional PnP modules
426
+ * - User-side selective imports enable optimal bundle size
427
+ * - Only import what you actually use
428
+ *
429
+ * @see {@link useSPFxPnPContext} for creating configured SPFI instances
430
+ * @see {@link useSPFxPnPList} for specialized list operations
431
+ */
432
+ export function useSPFxPnP(pnpContext) {
433
+ var _this = this;
434
+ // If no context provided, create default for current site
435
+ var defaultContext = useSPFxPnPContext();
436
+ var contextToUse = pnpContext || defaultContext;
437
+ var sp = contextToUse.sp, isInitialized = contextToUse.isInitialized, contextError = contextToUse.error, siteUrl = contextToUse.siteUrl;
438
+ // Local state for invoke/batch operations
439
+ var _a = useState(false), isLoading = _a[0], setIsLoading = _a[1];
440
+ var _b = useState(), invokeError = _b[0], setInvokeError = _b[1];
441
+ // Prioritized error: invoke/batch errors take precedence over context errors
442
+ var error = invokeError || contextError;
443
+ /**
444
+ * Execute single PnPjs operation with state management
445
+ */
446
+ var invoke = useCallback(function (fn) { return __awaiter(_this, void 0, void 0, function () {
447
+ var result, err_1, error_1;
448
+ return __generator(this, function (_a) {
449
+ switch (_a.label) {
450
+ case 0:
451
+ if (!sp) {
452
+ throw new Error('SPFI instance not initialized. ' +
453
+ 'Check isInitialized property or context error.');
454
+ }
455
+ setIsLoading(true);
456
+ setInvokeError(undefined);
457
+ _a.label = 1;
458
+ case 1:
459
+ _a.trys.push([1, 3, 4, 5]);
460
+ return [4 /*yield*/, fn(sp)];
461
+ case 2:
462
+ result = _a.sent();
463
+ return [2 /*return*/, result];
464
+ case 3:
465
+ err_1 = _a.sent();
466
+ error_1 = err_1 instanceof Error ? err_1 : new Error(String(err_1));
467
+ setInvokeError(error_1);
468
+ throw error_1;
469
+ case 4:
470
+ setIsLoading(false);
471
+ return [7 /*endfinally*/];
472
+ case 5: return [2 /*return*/];
473
+ }
474
+ });
475
+ }); }, [sp]);
476
+ /**
477
+ * Execute multiple PnPjs operations in a single batch
478
+ */
479
+ var batch = useCallback(function (fn) { return __awaiter(_this, void 0, void 0, function () {
480
+ var _a, batchedSP, execute, resultPromise, result, err_2, error_2;
481
+ return __generator(this, function (_b) {
482
+ switch (_b.label) {
483
+ case 0:
484
+ if (!sp) {
485
+ throw new Error('SPFI instance not initialized. ' +
486
+ 'Check isInitialized property or context error.');
487
+ }
488
+ setIsLoading(true);
489
+ setInvokeError(undefined);
490
+ _b.label = 1;
491
+ case 1:
492
+ _b.trys.push([1, 4, 5, 6]);
493
+ _a = sp.batched(), batchedSP = _a[0], execute = _a[1];
494
+ resultPromise = fn(batchedSP);
495
+ // Execute batch automatically
496
+ return [4 /*yield*/, execute()];
497
+ case 2:
498
+ // Execute batch automatically
499
+ _b.sent();
500
+ return [4 /*yield*/, resultPromise];
501
+ case 3:
502
+ result = _b.sent();
503
+ return [2 /*return*/, result];
504
+ case 4:
505
+ err_2 = _b.sent();
506
+ error_2 = err_2 instanceof Error ? err_2 : new Error(String(err_2));
507
+ setInvokeError(error_2);
508
+ throw error_2;
509
+ case 5:
510
+ setIsLoading(false);
511
+ return [7 /*endfinally*/];
512
+ case 6: return [2 /*return*/];
513
+ }
514
+ });
515
+ }); }, [sp]);
516
+ /**
517
+ * Clear current error state
518
+ */
519
+ var clearError = useCallback(function () {
520
+ setInvokeError(undefined);
521
+ }, []);
522
+ return {
523
+ sp: sp,
524
+ invoke: invoke,
525
+ batch: batch,
526
+ isLoading: isLoading,
527
+ error: error,
528
+ clearError: clearError,
529
+ isInitialized: isInitialized,
530
+ siteUrl: siteUrl,
531
+ };
532
+ }
533
+ //# sourceMappingURL=useSPFxPnP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSPFxPnP.js","sourceRoot":"","sources":["../../src/hooks/useSPFxPnP.ts"],"names":[],"mappings":"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"}