@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,672 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ 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;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
37
+ import { useState, useCallback, useRef, useEffect } from 'react';
38
+ import { useSPFxPnPContext } from './useSPFxPnPContext';
39
+ // Import PnPjs native search
40
+ import '@pnp/sp/search';
41
+ import { SearchQueryBuilder } from '@pnp/sp/search';
42
+ /**
43
+ * Standard SharePoint Search Verticals (Result Sources).
44
+ * Use these SourceIds to filter search results by content type.
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * import { SearchVerticals } from '@apvee/spfx-react-toolkit';
49
+ *
50
+ * // Search only people
51
+ * search(builder =>
52
+ * builder.text("john").sourceId(SearchVerticals.People)
53
+ * );
54
+ * ```
55
+ */
56
+ export var SearchVerticals = {
57
+ /**
58
+ * All results (default) - no filtering
59
+ */
60
+ All: undefined,
61
+ /**
62
+ * People and user profiles
63
+ */
64
+ People: 'b09a7990-05ea-4af9-81ef-edfab16c4e31',
65
+ /**
66
+ * Video content (.mp4, .avi, embedded videos)
67
+ */
68
+ Videos: '38403c8c-3975-41a8-826e-717f2d41568a',
69
+ /**
70
+ * SharePoint sites, subsites, workspaces
71
+ */
72
+ Sites: 'e1327b9c-2b8c-4b23-99c9-3730cb29c3f7',
73
+ /**
74
+ * Documents (.docx, .pdf, .xlsx, etc.)
75
+ */
76
+ Documents: '8413cd39-2156-4e00-b54d-11efd9abdb89',
77
+ /**
78
+ * Conversations (Yammer, Teams messages)
79
+ */
80
+ Conversations: '6e71030e-5e16-4406-9bff-9c1829843083',
81
+ /**
82
+ * Pages (modern pages, wiki pages)
83
+ */
84
+ Pages: '5e34578e-4d68-4783-8c79-1f07d10bed4f'
85
+ };
86
+ /**
87
+ * Hook for working with SharePoint Search using PnPjs fluent API.
88
+ * Provides search execution, suggestions, refiners, pagination, and state management.
89
+ *
90
+ * **Key Features**:
91
+ * - ✅ Native PnPjs SearchQueryBuilder - full type-safe query building
92
+ * - ✅ Auto-parsing of Cells to typed objects
93
+ * - ✅ Search suggestions (autocomplete)
94
+ * - ✅ Refiners (facets) support
95
+ * - ✅ Pagination with loadMore() and hasMore
96
+ * - ✅ Verticals support (People, Videos, Sites, etc.)
97
+ * - ✅ Cross-site search via PnPContextInfo
98
+ * - ✅ Local state management per component instance
99
+ * - ✅ ES5 compatibility (IE11 support)
100
+ *
101
+ * @template T - The type of the search result data (default: Record<string, string>)
102
+ * @param options - Optional configuration (pageSize, selectProperties, refiners)
103
+ * @param pnpContext - Optional PnP context for cross-site scenarios
104
+ * @returns Object containing search method, results, loading states, and actions
105
+ *
106
+ * @example Basic text search
107
+ * ```tsx
108
+ * import { useSPFxPnPSearch } from '@apvee/spfx-react-toolkit';
109
+ *
110
+ * function DocumentSearch() {
111
+ * const { search, results, loading } = useSPFxPnPSearch({ pageSize: 50 });
112
+ *
113
+ * useEffect(() => {
114
+ * search("ContentType:Document");
115
+ * }, [search]);
116
+ *
117
+ * if (loading) return <Spinner />;
118
+ *
119
+ * return (
120
+ * <ul>
121
+ * {results.map(result => (
122
+ * <li key={result.id}>
123
+ * <a href={result.data.Path}>{result.data.Title}</a>
124
+ * </li>
125
+ * ))}
126
+ * </ul>
127
+ * );
128
+ * }
129
+ * ```
130
+ *
131
+ * @example Advanced search with builder
132
+ * ```tsx
133
+ * interface Document {
134
+ * Title: string;
135
+ * Path: string;
136
+ * FileType: string;
137
+ * Author: string;
138
+ * LastModifiedTime: string;
139
+ * }
140
+ *
141
+ * function AdvancedSearch() {
142
+ * const { search, results } = useSPFxPnPSearch<Document>({
143
+ * selectProperties: ['Title', 'Path', 'FileType', 'Author', 'LastModifiedTime'],
144
+ * pageSize: 100
145
+ * });
146
+ *
147
+ * useEffect(() => {
148
+ * search(builder =>
149
+ * builder
150
+ * .text("training")
151
+ * .rowLimit(100)
152
+ * .sortList({ Property: 'LastModifiedTime', Direction: 1 })
153
+ * );
154
+ * }, [search]);
155
+ *
156
+ * return (
157
+ * <div>
158
+ * {results.map(doc => (
159
+ * <DocumentCard key={doc.id} document={doc.data} />
160
+ * ))}
161
+ * </div>
162
+ * );
163
+ * }
164
+ * ```
165
+ *
166
+ * @example Search with verticals
167
+ * ```tsx
168
+ * import { SearchVerticals } from '@apvee/spfx-react-toolkit';
169
+ *
170
+ * function PeopleSearch() {
171
+ * const { search, results } = useSPFxPnPSearch({
172
+ * selectProperties: ['PreferredName', 'WorkEmail', 'PictureURL', 'JobTitle']
173
+ * });
174
+ *
175
+ * useEffect(() => {
176
+ * search(builder =>
177
+ * builder
178
+ * .text("john")
179
+ * .sourceId(SearchVerticals.People)
180
+ * );
181
+ * }, [search]);
182
+ *
183
+ * return (
184
+ * <div>
185
+ * {results.map(person => (
186
+ * <Persona
187
+ * key={person.id}
188
+ * text={person.data.PreferredName}
189
+ * secondaryText={person.data.JobTitle}
190
+ * imageUrl={person.data.PictureURL}
191
+ * />
192
+ * ))}
193
+ * </div>
194
+ * );
195
+ * }
196
+ * ```
197
+ *
198
+ * @example Pagination with loadMore
199
+ * ```tsx
200
+ * function PaginatedSearch() {
201
+ * const {
202
+ * search,
203
+ * results,
204
+ * hasMore,
205
+ * loadMore,
206
+ * loadingMore
207
+ * } = useSPFxPnPSearch({ pageSize: 20 });
208
+ *
209
+ * useEffect(() => {
210
+ * search("report");
211
+ * }, [search]);
212
+ *
213
+ * return (
214
+ * <div>
215
+ * {results.map(r => <ResultCard key={r.id} result={r} />)}
216
+ * {hasMore && (
217
+ * <button onClick={loadMore} disabled={loadingMore}>
218
+ * {loadingMore ? 'Loading...' : 'Load More'}
219
+ * </button>
220
+ * )}
221
+ * </div>
222
+ * );
223
+ * }
224
+ * ```
225
+ *
226
+ * @example Refiners (facets) filtering
227
+ * ```tsx
228
+ * function RefinedSearch() {
229
+ * const {
230
+ * search,
231
+ * results,
232
+ * refiners,
233
+ * applyRefiner
234
+ * } = useSPFxPnPSearch({
235
+ * refiners: 'FileType,Author',
236
+ * pageSize: 50
237
+ * });
238
+ *
239
+ * useEffect(() => {
240
+ * search("document");
241
+ * }, [search]);
242
+ *
243
+ * return (
244
+ * <div style={{ display: 'flex' }}>
245
+ * {/* Sidebar with refiners *\/}
246
+ * <div>
247
+ * {refiners.map(refiner => (
248
+ * <div key={refiner.name}>
249
+ * <h4>{refiner.name}</h4>
250
+ * {refiner.entries.map(entry => (
251
+ * <button
252
+ * key={entry.value}
253
+ * onClick={() => applyRefiner(refiner.name, entry.value)}
254
+ * >
255
+ * {entry.value} ({entry.count})
256
+ * </button>
257
+ * ))}
258
+ * </div>
259
+ * ))}
260
+ * </div>
261
+ *
262
+ * {/* Results *\/}
263
+ * <div>
264
+ * {results.map(r => <ResultCard key={r.id} result={r} />)}
265
+ * </div>
266
+ * </div>
267
+ * );
268
+ * }
269
+ * ```
270
+ *
271
+ * @example Search suggestions (autocomplete)
272
+ * ```tsx
273
+ * function SearchBox() {
274
+ * const { search, suggest } = useSPFxPnPSearch();
275
+ * const [query, setQuery] = React.useState('');
276
+ * const [suggestions, setSuggestions] = React.useState<string[]>([]);
277
+ *
278
+ * const handleInputChange = async (text: string) => {
279
+ * setQuery(text);
280
+ * if (text.length > 2) {
281
+ * const results = await suggest(text);
282
+ * setSuggestions(results);
283
+ * }
284
+ * };
285
+ *
286
+ * const handleSearch = () => {
287
+ * search(query);
288
+ * setSuggestions([]);
289
+ * };
290
+ *
291
+ * return (
292
+ * <div>
293
+ * <input
294
+ * value={query}
295
+ * onChange={(e) => handleInputChange(e.target.value)}
296
+ * onKeyPress={(e) => e.key === 'Enter' && handleSearch()}
297
+ * />
298
+ * {suggestions.length > 0 && (
299
+ * <ul>
300
+ * {suggestions.map((s, i) => (
301
+ * <li key={i} onClick={() => setQuery(s)}>{s}</li>
302
+ * ))}
303
+ * </ul>
304
+ * )}
305
+ * </div>
306
+ * );
307
+ * }
308
+ * ```
309
+ */
310
+ export function useSPFxPnPSearch(options, pnpContext) {
311
+ var _this = this;
312
+ var _a;
313
+ // Get PnP context
314
+ var context = useSPFxPnPContext(pnpContext === null || pnpContext === void 0 ? void 0 : pnpContext.siteUrl);
315
+ var sp = context.sp;
316
+ // Default options
317
+ var defaultPageSize = (_a = options === null || options === void 0 ? void 0 : options.pageSize) !== null && _a !== void 0 ? _a : 50;
318
+ // State
319
+ var _b = useState([]), results = _b[0], setResults = _b[1];
320
+ var _c = useState(0), totalResults = _c[0], setTotalResults = _c[1];
321
+ var _d = useState([]), refiners = _d[0], setRefiners = _d[1];
322
+ var _e = useState(false), loading = _e[0], setLoading = _e[1];
323
+ var _f = useState(false), loadingMore = _f[0], setLoadingMore = _f[1];
324
+ var _g = useState(undefined), error = _g[0], setError = _g[1];
325
+ var _h = useState(false), hasMore = _h[0], setHasMore = _h[1];
326
+ // Tracking for pagination and refetch
327
+ var _j = useState(null), lastQueryBuilder = _j[0], setLastQueryBuilder = _j[1];
328
+ var _k = useState(null), lastQueryText = _k[0], setLastQueryText = _k[1];
329
+ var _l = useState(undefined), lastPageSize = _l[0], setLastPageSize = _l[1];
330
+ var _m = useState(0), currentStartRow = _m[0], setCurrentStartRow = _m[1];
331
+ var _o = useState(new Map()), appliedRefiners = _o[0], setAppliedRefiners = _o[1];
332
+ // Refs
333
+ var mountedRef = useRef(true);
334
+ // Cleanup on unmount
335
+ useEffect(function () {
336
+ mountedRef.current = true;
337
+ return function cleanup() {
338
+ mountedRef.current = false;
339
+ };
340
+ }, []);
341
+ // Clear error handler
342
+ var clearError = useCallback(function () {
343
+ setError(undefined);
344
+ }, []);
345
+ /**
346
+ * Core search execution logic.
347
+ * Builds query with defaults, executes search, parses results.
348
+ */
349
+ var executeSearch = useCallback(function (query, queryOptions, startRow, appendResults) { return __awaiter(_this, void 0, void 0, function () {
350
+ var err, pageSize, row, builder, refinementFilters_1, searchResults, rawResults, totalRows, parsedResults_1, refinerResults, parsedRefiners, newResultsLength, err_1, error_1;
351
+ var _a, _b, _c, _d, _e, _f, _g, _h;
352
+ return __generator(this, function (_j) {
353
+ switch (_j.label) {
354
+ case 0:
355
+ if (!sp || !(context === null || context === void 0 ? void 0 : context.isInitialized)) {
356
+ err = new Error('[useSPFxPnPSearch] PnP context not initialized. Ensure @pnp/sp/search is imported.');
357
+ setError(err);
358
+ throw err;
359
+ }
360
+ _j.label = 1;
361
+ case 1:
362
+ _j.trys.push([1, 3, , 4]);
363
+ pageSize = (_b = (_a = queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.pageSize) !== null && _a !== void 0 ? _a : lastPageSize) !== null && _b !== void 0 ? _b : defaultPageSize;
364
+ row = startRow !== null && startRow !== void 0 ? startRow : 0;
365
+ builder = void 0;
366
+ if (typeof query === 'string') {
367
+ // String query case
368
+ builder = SearchQueryBuilder(query);
369
+ }
370
+ else {
371
+ // Builder callback case
372
+ builder = SearchQueryBuilder('');
373
+ // Apply default options BEFORE user callback
374
+ if ((options === null || options === void 0 ? void 0 : options.selectProperties) && options.selectProperties.length > 0) {
375
+ builder = builder.selectProperties.apply(builder, options.selectProperties);
376
+ }
377
+ if (options === null || options === void 0 ? void 0 : options.refiners) {
378
+ builder = builder.refiners(options.refiners);
379
+ }
380
+ // Let user override everything
381
+ builder = query(builder);
382
+ }
383
+ // Apply pagination
384
+ builder = builder.rowLimit(pageSize);
385
+ if (row > 0) {
386
+ builder = builder.startRow(row);
387
+ }
388
+ // Apply refinement filters if any
389
+ if (appliedRefiners.size > 0) {
390
+ refinementFilters_1 = [];
391
+ appliedRefiners.forEach(function (values, key) {
392
+ values.forEach(function (value) {
393
+ refinementFilters_1.push(key + ":equals('" + value + "')");
394
+ });
395
+ });
396
+ if (refinementFilters_1.length > 0) {
397
+ builder = builder.refinementFilters.apply(builder, refinementFilters_1);
398
+ }
399
+ }
400
+ return [4 /*yield*/, sp.search(builder)];
401
+ case 2:
402
+ searchResults = _j.sent();
403
+ rawResults = (_c = searchResults.PrimarySearchResults) !== null && _c !== void 0 ? _c : [];
404
+ totalRows = (_d = searchResults.TotalRows) !== null && _d !== void 0 ? _d : 0;
405
+ parsedResults_1 = rawResults.map(function (result) {
406
+ var _a, _b;
407
+ // ISearchResult is already a flat object with all properties
408
+ // Generate ID from Path or DocId
409
+ var id = String((_b = (_a = result.DocId) !== null && _a !== void 0 ? _a : result.Path) !== null && _b !== void 0 ? _b : Math.random());
410
+ var rank = result.Rank ? parseInt(String(result.Rank), 10) : undefined;
411
+ return {
412
+ id: id,
413
+ data: result, // ISearchResult is already the data
414
+ raw: result, // Keep original for reference
415
+ rank: rank
416
+ };
417
+ });
418
+ refinerResults = (_h = (_g = (_f = (_e = searchResults.RawSearchResults) === null || _e === void 0 ? void 0 : _e.PrimaryQueryResult) === null || _f === void 0 ? void 0 : _f.RefinementResults) === null || _g === void 0 ? void 0 : _g.Refiners) !== null && _h !== void 0 ? _h : [];
419
+ parsedRefiners = refinerResults.map(function (refiner) {
420
+ var _a, _b;
421
+ return {
422
+ name: (_a = refiner.Name) !== null && _a !== void 0 ? _a : '',
423
+ entries: ((_b = refiner.Entries) !== null && _b !== void 0 ? _b : []).map(function (entry) {
424
+ var _a, _b;
425
+ return {
426
+ value: (_a = entry.RefinementName) !== null && _a !== void 0 ? _a : '',
427
+ count: parseInt(entry.RefinementCount, 10) || 0,
428
+ token: (_b = entry.RefinementToken) !== null && _b !== void 0 ? _b : ''
429
+ };
430
+ })
431
+ };
432
+ });
433
+ // Update state
434
+ if (!mountedRef.current) {
435
+ return [2 /*return*/, parsedResults_1];
436
+ }
437
+ newResultsLength = appendResults ? results.length + parsedResults_1.length : parsedResults_1.length;
438
+ if (appendResults) {
439
+ setResults(function (prev) { return prev.concat(parsedResults_1); });
440
+ }
441
+ else {
442
+ setResults(parsedResults_1);
443
+ }
444
+ setTotalResults(totalRows);
445
+ setRefiners(parsedRefiners);
446
+ setHasMore(newResultsLength < totalRows);
447
+ return [2 /*return*/, parsedResults_1];
448
+ case 3:
449
+ err_1 = _j.sent();
450
+ error_1 = err_1 instanceof Error ? err_1 : new Error(String(err_1));
451
+ setError(error_1);
452
+ throw error_1;
453
+ case 4: return [2 /*return*/];
454
+ }
455
+ });
456
+ }); }, [sp, context === null || context === void 0 ? void 0 : context.isInitialized, options, defaultPageSize, lastPageSize, appliedRefiners, results.length]);
457
+ /**
458
+ * Executes a search query.
459
+ */
460
+ var search = useCallback(function (query, queryOptions) { return __awaiter(_this, void 0, void 0, function () {
461
+ var parsedResults;
462
+ var _a;
463
+ return __generator(this, function (_b) {
464
+ switch (_b.label) {
465
+ case 0:
466
+ setLoading(true);
467
+ setError(undefined);
468
+ setCurrentStartRow(0);
469
+ setAppliedRefiners(new Map()); // Reset refiners on new search
470
+ _b.label = 1;
471
+ case 1:
472
+ _b.trys.push([1, , 3, 4]);
473
+ // Store query for refetch/loadMore
474
+ if (typeof query === 'string') {
475
+ setLastQueryText(query);
476
+ setLastQueryBuilder(null);
477
+ }
478
+ else {
479
+ setLastQueryBuilder(function () { return query; });
480
+ setLastQueryText(null);
481
+ }
482
+ setLastPageSize((_a = queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.pageSize) !== null && _a !== void 0 ? _a : defaultPageSize);
483
+ return [4 /*yield*/, executeSearch(query, queryOptions, 0, false)];
484
+ case 2:
485
+ parsedResults = _b.sent();
486
+ return [2 /*return*/, parsedResults];
487
+ case 3:
488
+ if (mountedRef.current) {
489
+ setLoading(false);
490
+ }
491
+ return [7 /*endfinally*/];
492
+ case 4: return [2 /*return*/];
493
+ }
494
+ });
495
+ }); }, [executeSearch, defaultPageSize]);
496
+ /**
497
+ * Gets search suggestions.
498
+ */
499
+ var suggest = useCallback(function (queryText) { return __awaiter(_this, void 0, void 0, function () {
500
+ var err, result, err_2, error_2;
501
+ var _a;
502
+ return __generator(this, function (_b) {
503
+ switch (_b.label) {
504
+ case 0:
505
+ if (!sp || !(context === null || context === void 0 ? void 0 : context.isInitialized)) {
506
+ err = new Error('[useSPFxPnPSearch] PnP context not initialized.');
507
+ setError(err);
508
+ throw err;
509
+ }
510
+ _b.label = 1;
511
+ case 1:
512
+ _b.trys.push([1, 3, , 4]);
513
+ return [4 /*yield*/, sp.searchSuggest(queryText)];
514
+ case 2:
515
+ result = _b.sent();
516
+ return [2 /*return*/, (_a = result.Queries) !== null && _a !== void 0 ? _a : []];
517
+ case 3:
518
+ err_2 = _b.sent();
519
+ error_2 = err_2 instanceof Error ? err_2 : new Error(String(err_2));
520
+ setError(error_2);
521
+ throw error_2;
522
+ case 4: return [2 /*return*/];
523
+ }
524
+ });
525
+ }); }, [sp, context === null || context === void 0 ? void 0 : context.isInitialized]);
526
+ /**
527
+ * Loads more results (pagination).
528
+ */
529
+ var loadMore = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
530
+ var err, err, nextStartRow, query, parsedResults;
531
+ return __generator(this, function (_a) {
532
+ switch (_a.label) {
533
+ case 0:
534
+ if (!lastQueryBuilder && !lastQueryText) {
535
+ err = new Error('[useSPFxPnPSearch] No previous search to load more from. Call search() first.');
536
+ setError(err);
537
+ throw err;
538
+ }
539
+ if (!lastPageSize) {
540
+ err = new Error('[useSPFxPnPSearch] Cannot loadMore without pageSize. Specify pageSize in options or search call.');
541
+ setError(err);
542
+ throw err;
543
+ }
544
+ setLoadingMore(true);
545
+ setError(undefined);
546
+ _a.label = 1;
547
+ case 1:
548
+ _a.trys.push([1, , 3, 4]);
549
+ nextStartRow = currentStartRow + lastPageSize;
550
+ query = lastQueryBuilder
551
+ ? lastQueryBuilder
552
+ : lastQueryText;
553
+ return [4 /*yield*/, executeSearch(query, { pageSize: lastPageSize }, nextStartRow, true // Append results
554
+ )];
555
+ case 2:
556
+ parsedResults = _a.sent();
557
+ setCurrentStartRow(nextStartRow);
558
+ return [2 /*return*/, parsedResults];
559
+ case 3:
560
+ if (mountedRef.current) {
561
+ setLoadingMore(false);
562
+ }
563
+ return [7 /*endfinally*/];
564
+ case 4: return [2 /*return*/];
565
+ }
566
+ });
567
+ }); }, [lastQueryBuilder, lastQueryText, lastPageSize, currentStartRow, executeSearch]);
568
+ /**
569
+ * Re-executes the last search.
570
+ */
571
+ var refetch = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
572
+ var err, query;
573
+ return __generator(this, function (_a) {
574
+ switch (_a.label) {
575
+ case 0:
576
+ if (!lastQueryBuilder && !lastQueryText) {
577
+ err = new Error('[useSPFxPnPSearch] No previous search to refetch. Call search() first.');
578
+ setError(err);
579
+ throw err;
580
+ }
581
+ setLoading(true);
582
+ setError(undefined);
583
+ setCurrentStartRow(0);
584
+ _a.label = 1;
585
+ case 1:
586
+ _a.trys.push([1, , 3, 4]);
587
+ query = lastQueryBuilder
588
+ ? lastQueryBuilder
589
+ : lastQueryText;
590
+ return [4 /*yield*/, executeSearch(query, { pageSize: lastPageSize }, 0, false)];
591
+ case 2:
592
+ _a.sent();
593
+ return [3 /*break*/, 4];
594
+ case 3:
595
+ if (mountedRef.current) {
596
+ setLoading(false);
597
+ }
598
+ return [7 /*endfinally*/];
599
+ case 4: return [2 /*return*/];
600
+ }
601
+ });
602
+ }); }, [lastQueryBuilder, lastQueryText, lastPageSize, executeSearch]);
603
+ /**
604
+ * Applies a refiner filter to the current search.
605
+ */
606
+ var applyRefiner = useCallback(function (refinerName, refinerValue) { return __awaiter(_this, void 0, void 0, function () {
607
+ var err;
608
+ return __generator(this, function (_a) {
609
+ switch (_a.label) {
610
+ case 0:
611
+ if (!lastQueryBuilder && !lastQueryText) {
612
+ err = new Error('[useSPFxPnPSearch] No previous search to apply refiner to. Call search() first.');
613
+ setError(err);
614
+ throw err;
615
+ }
616
+ // Update applied refiners map
617
+ setAppliedRefiners(function (prev) {
618
+ var _a;
619
+ var newMap = new Map();
620
+ prev.forEach(function (value, key) {
621
+ newMap.set(key, value);
622
+ });
623
+ var existing = (_a = newMap.get(refinerName)) !== null && _a !== void 0 ? _a : [];
624
+ // Toggle: if already exists, remove; otherwise add
625
+ var index = existing.indexOf(refinerValue);
626
+ if (index > -1) {
627
+ var updated = existing.slice();
628
+ updated.splice(index, 1);
629
+ if (updated.length === 0) {
630
+ newMap.delete(refinerName);
631
+ }
632
+ else {
633
+ newMap.set(refinerName, updated);
634
+ }
635
+ }
636
+ else {
637
+ newMap.set(refinerName, existing.concat([refinerValue]));
638
+ }
639
+ return newMap;
640
+ });
641
+ // Re-execute search with new refiners
642
+ // Note: appliedRefiners state will be updated on next render
643
+ // So we need to wait a tick or use the new map directly
644
+ // For simplicity, we'll call refetch which will use updated appliedRefiners
645
+ return [4 /*yield*/, refetch()];
646
+ case 1:
647
+ // Re-execute search with new refiners
648
+ // Note: appliedRefiners state will be updated on next render
649
+ // So we need to wait a tick or use the new map directly
650
+ // For simplicity, we'll call refetch which will use updated appliedRefiners
651
+ _a.sent();
652
+ return [2 /*return*/];
653
+ }
654
+ });
655
+ }); }, [lastQueryBuilder, lastQueryText, refetch]);
656
+ return {
657
+ search: search,
658
+ suggest: suggest,
659
+ results: results,
660
+ totalResults: totalResults,
661
+ refiners: refiners,
662
+ loading: loading,
663
+ loadingMore: loadingMore,
664
+ hasMore: hasMore,
665
+ error: error,
666
+ loadMore: loadMore,
667
+ refetch: refetch,
668
+ applyRefiner: applyRefiner,
669
+ clearError: clearError
670
+ };
671
+ }
672
+ //# sourceMappingURL=useSPFxPnPSearch.js.map