@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,1351 @@
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
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
38
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
39
+ if (ar || !(i in from)) {
40
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
41
+ ar[i] = from[i];
42
+ }
43
+ }
44
+ return to.concat(ar || Array.prototype.slice.call(from));
45
+ };
46
+ import * as React from 'react';
47
+ import styles from './SpFxReactToolkitTest.module.scss';
48
+ import { Stack, Pivot, PivotItem, TextField, PrimaryButton, DefaultButton, MessageBar, MessageBarType, Separator, Label, Icon, } from '@fluentui/react';
49
+ // Import all hooks from SPFx React Toolkit
50
+ import { useSPFxProperties, useSPFxThemeInfo, useSPFxUserInfo, useSPFxEnvironmentInfo, useSPFxSiteInfo, useSPFxDisplayMode, useSPFxInstanceInfo, useSPFxPageContext, useSPFxTeams, useSPFxListInfo, useSPFxLocaleInfo, useSPFxHubSiteInfo, useSPFxCorrelationInfo, useSPFxPermissions, useSPFxCrossSitePermissions, useSPFxContainerSize, useSPFxContainerInfo, useSPFxSessionStorage, useSPFxLocalStorage, useSPFxLogger, useSPFxPageType, useSPFxServiceScope, useSPFxSPHttpClient, useSPFxMSGraphClient, useSPFxAadHttpClient, useSPFxPerformance, useSPFxFluent9ThemeInfo, useSPFxOneDriveAppData, useSPFxTenantProperty, useSPFxUserPhoto, useSPFxPnPContext, useSPFxPnP, useSPFxPnPList, useSPFxPnPSearch, SearchVerticals, } from '../../../hooks';
51
+ import '@pnp/sp/webs';
52
+ import '@pnp/sp/lists';
53
+ import '@pnp/sp/items';
54
+ import '@pnp/sp/site-users';
55
+ import { SPPermission } from '@microsoft/sp-page-context';
56
+ // =============================================
57
+ // Helper Components (Must be defined first)
58
+ // =============================================
59
+ // Helper component for displaying info rows
60
+ var InfoRow = function (_a) {
61
+ var label = _a.label, value = _a.value, icon = _a.icon;
62
+ return (React.createElement("div", { className: styles.infoRow },
63
+ icon && React.createElement(Icon, { iconName: icon }),
64
+ React.createElement(Label, null,
65
+ label,
66
+ ":"),
67
+ React.createElement("span", null, value || 'N/A')));
68
+ };
69
+ // Helper component for status badges
70
+ var StatusBadge = function (_a) {
71
+ var available = _a.available, label = _a.label;
72
+ return (React.createElement("div", { className: "".concat(styles.statusBadge, " ").concat(available ? styles.success : styles.error) },
73
+ React.createElement(Icon, { iconName: available ? 'Completed' : 'ErrorBadge' }),
74
+ label));
75
+ };
76
+ // =============================================
77
+ // PnPjs Example Components
78
+ // =============================================
79
+ /**
80
+ * Example 1: useSPFxPnPContext
81
+ * Shows how to create PnP contexts for current and cross-site scenarios
82
+ */
83
+ var PnPContextExample = function () {
84
+ var _a = React.useState(''), crossSiteUrl = _a[0], setCrossSiteUrl = _a[1];
85
+ var _b = React.useState(null), siteInfo = _b[0], setSiteInfo = _b[1];
86
+ var _c = React.useState(false), loading = _c[0], setLoading = _c[1];
87
+ var _d = React.useState(null), errorMsg = _d[0], setErrorMsg = _d[1];
88
+ // Current site context (default)
89
+ var currentContext = useSPFxPnPContext();
90
+ // Cross-site context (only when URL is provided)
91
+ var crossSiteContext = useSPFxPnPContext(crossSiteUrl || undefined);
92
+ var handleLoadCurrentSite = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
93
+ var web, error_1;
94
+ return __generator(this, function (_a) {
95
+ switch (_a.label) {
96
+ case 0:
97
+ if (!currentContext.sp)
98
+ return [2 /*return*/];
99
+ setLoading(true);
100
+ setErrorMsg(null);
101
+ _a.label = 1;
102
+ case 1:
103
+ _a.trys.push([1, 3, 4, 5]);
104
+ return [4 /*yield*/, currentContext.sp.web.select('Title', 'Url', 'Description')()];
105
+ case 2:
106
+ web = _a.sent();
107
+ setSiteInfo({
108
+ title: web.Title,
109
+ url: web.Url,
110
+ description: web.Description || '(no description)'
111
+ });
112
+ return [3 /*break*/, 5];
113
+ case 3:
114
+ error_1 = _a.sent();
115
+ console.error('Error loading site:', error_1);
116
+ setErrorMsg(error_1 instanceof Error ? error_1.message : 'Unknown error');
117
+ setSiteInfo(null);
118
+ return [3 /*break*/, 5];
119
+ case 4:
120
+ setLoading(false);
121
+ return [7 /*endfinally*/];
122
+ case 5: return [2 /*return*/];
123
+ }
124
+ });
125
+ }); }, [currentContext.sp]);
126
+ var handleLoadCrossSite = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
127
+ var web, error_2;
128
+ return __generator(this, function (_a) {
129
+ switch (_a.label) {
130
+ case 0:
131
+ if (!crossSiteContext.sp || !crossSiteUrl)
132
+ return [2 /*return*/];
133
+ setLoading(true);
134
+ setErrorMsg(null);
135
+ _a.label = 1;
136
+ case 1:
137
+ _a.trys.push([1, 3, 4, 5]);
138
+ return [4 /*yield*/, crossSiteContext.sp.web.select('Title', 'Url', 'Description')()];
139
+ case 2:
140
+ web = _a.sent();
141
+ setSiteInfo({
142
+ title: web.Title,
143
+ url: web.Url,
144
+ description: web.Description || '(no description)'
145
+ });
146
+ return [3 /*break*/, 5];
147
+ case 3:
148
+ error_2 = _a.sent();
149
+ console.error('Error loading cross-site:', error_2);
150
+ setErrorMsg(error_2 instanceof Error ? error_2.message : 'Unknown error');
151
+ setSiteInfo(null);
152
+ return [3 /*break*/, 5];
153
+ case 4:
154
+ setLoading(false);
155
+ return [7 /*endfinally*/];
156
+ case 5: return [2 /*return*/];
157
+ }
158
+ });
159
+ }); }, [crossSiteContext.sp, crossSiteUrl]);
160
+ return (React.createElement(Stack, { tokens: { childrenGap: 10 }, styles: { root: { padding: '16px', border: '1px solid #edebe9', borderRadius: '4px' } } },
161
+ React.createElement("h3", null,
162
+ React.createElement(Icon, { iconName: "Globe", style: { marginRight: '8px' } }),
163
+ "Example 1: useSPFxPnPContext - Site Information"),
164
+ React.createElement(Separator, null),
165
+ errorMsg && (React.createElement(MessageBar, { messageBarType: MessageBarType.error, onDismiss: function () { return setErrorMsg(null); } }, errorMsg)),
166
+ React.createElement(Stack, { tokens: { childrenGap: 8 } },
167
+ React.createElement(Label, null, "Current Site Context"),
168
+ React.createElement(InfoRow, { label: "Effective URL", value: currentContext.siteUrl, icon: "Link" }),
169
+ React.createElement(InfoRow, { label: "Is Initialized", value: currentContext.isInitialized ? 'Yes' : 'No', icon: "CheckMark" }),
170
+ currentContext.error && (React.createElement(MessageBar, { messageBarType: MessageBarType.warning },
171
+ "Init Error: ",
172
+ currentContext.error.message)),
173
+ React.createElement(PrimaryButton, { text: loading ? 'Loading...' : 'Load Current Site Info', onClick: handleLoadCurrentSite, disabled: !currentContext.isInitialized || loading, iconProps: { iconName: 'CloudDownload' } })),
174
+ React.createElement(Stack, { tokens: { childrenGap: 8 } },
175
+ React.createElement(Label, null, "Cross-Site Context (Optional)"),
176
+ React.createElement(TextField, { label: "Site URL", value: crossSiteUrl, onChange: function (_, newValue) { return setCrossSiteUrl(newValue !== null && newValue !== void 0 ? newValue : ''); }, placeholder: "e.g., /sites/hr or https://contoso.sharepoint.com/sites/hr", description: "Leave empty to use current site" }),
177
+ crossSiteUrl && (React.createElement(React.Fragment, null,
178
+ React.createElement(InfoRow, { label: "Resolved URL", value: crossSiteContext.siteUrl, icon: "Link" }),
179
+ React.createElement(InfoRow, { label: "Is Initialized", value: crossSiteContext.isInitialized ? 'Yes' : 'No', icon: "CheckMark" }),
180
+ crossSiteContext.error && (React.createElement(MessageBar, { messageBarType: MessageBarType.warning },
181
+ "Init Error: ",
182
+ crossSiteContext.error.message)),
183
+ React.createElement(PrimaryButton, { text: loading ? 'Loading...' : 'Load Cross-Site Info', onClick: handleLoadCrossSite, disabled: !crossSiteContext.isInitialized || loading, iconProps: { iconName: 'Globe' } })))),
184
+ siteInfo && (React.createElement(Stack, { tokens: { childrenGap: 8 }, styles: { root: { padding: '12px', backgroundColor: '#f3f2f1', borderRadius: '4px' } } },
185
+ React.createElement(Label, { style: { fontWeight: 600 } },
186
+ React.createElement(Icon, { iconName: "CheckMark", style: { marginRight: '4px', color: '#107c10' } }),
187
+ "Site Information Loaded:"),
188
+ React.createElement(InfoRow, { label: "Title", value: siteInfo.title, icon: "CityNext" }),
189
+ React.createElement(InfoRow, { label: "URL", value: siteInfo.url, icon: "Link" }),
190
+ React.createElement(InfoRow, { label: "Description", value: siteInfo.description, icon: "Info" }))),
191
+ React.createElement(Label, null,
192
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
193
+ "useSPFxPnPContext creates configured SPFI instances. Use for cross-site scenarios or when you need custom cache/batch config.")));
194
+ };
195
+ /**
196
+ * Example 2: useSPFxPnP
197
+ * Shows invoke() for single operations and batch() for multiple operations
198
+ */
199
+ var PnPOperationsExample = function () {
200
+ var _a = useSPFxPnP(), invoke = _a.invoke, batch = _a.batch, isLoading = _a.isLoading, error = _a.error, clearError = _a.clearError;
201
+ var _b = React.useState([]), lists = _b[0], setLists = _b[1];
202
+ var _c = React.useState(null), batchData = _c[0], setBatchData = _c[1];
203
+ var handleInvokeLists = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
204
+ var result, err_1;
205
+ return __generator(this, function (_a) {
206
+ switch (_a.label) {
207
+ case 0:
208
+ _a.trys.push([0, 2, , 3]);
209
+ clearError();
210
+ return [4 /*yield*/, invoke(function (sp) {
211
+ return sp.web.lists
212
+ .select('Title', 'ItemCount')
213
+ .filter('Hidden eq false')
214
+ .top(10)();
215
+ })];
216
+ case 1:
217
+ result = _a.sent();
218
+ setLists(result);
219
+ return [3 /*break*/, 3];
220
+ case 2:
221
+ err_1 = _a.sent();
222
+ console.error('Invoke error:', err_1);
223
+ return [3 /*break*/, 3];
224
+ case 3: return [2 /*return*/];
225
+ }
226
+ });
227
+ }); }, [invoke, clearError]);
228
+ var handleBatchOperations = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
229
+ var results, listsResult, userResult, webResult, err_2;
230
+ return __generator(this, function (_a) {
231
+ switch (_a.label) {
232
+ case 0:
233
+ _a.trys.push([0, 2, , 3]);
234
+ clearError();
235
+ return [4 /*yield*/, batch(function (batchedSP) { return __awaiter(void 0, void 0, void 0, function () {
236
+ var listsPromise, userPromise, webPromise;
237
+ return __generator(this, function (_a) {
238
+ listsPromise = batchedSP.web.lists.select('Title').top(5)();
239
+ userPromise = batchedSP.web.currentUser.select('Title')();
240
+ webPromise = batchedSP.web.select('Title')();
241
+ // Wait for all batched operations to complete
242
+ return [2 /*return*/, Promise.all([listsPromise, userPromise, webPromise])];
243
+ });
244
+ }); })];
245
+ case 1:
246
+ results = _a.sent();
247
+ listsResult = results[0], userResult = results[1], webResult = results[2];
248
+ setBatchData({
249
+ lists: listsResult,
250
+ user: userResult,
251
+ webTitle: webResult.Title
252
+ });
253
+ return [3 /*break*/, 3];
254
+ case 2:
255
+ err_2 = _a.sent();
256
+ console.error('Batch error:', err_2);
257
+ return [3 /*break*/, 3];
258
+ case 3: return [2 /*return*/];
259
+ }
260
+ });
261
+ }); }, [batch, clearError]);
262
+ return (React.createElement(Stack, { tokens: { childrenGap: 10 }, styles: { root: { padding: '16px', border: '1px solid #edebe9', borderRadius: '4px' } } },
263
+ React.createElement("h3", null,
264
+ React.createElement(Icon, { iconName: "CloudUpload", style: { marginRight: '8px' } }),
265
+ "Example 2: useSPFxPnP - Operations & Batching"),
266
+ React.createElement(Separator, null),
267
+ error && (React.createElement(MessageBar, { messageBarType: MessageBarType.error, onDismiss: clearError }, error.message)),
268
+ React.createElement(Stack, { tokens: { childrenGap: 8 } },
269
+ React.createElement(Label, null, "Single Operation with invoke()"),
270
+ React.createElement(PrimaryButton, { text: isLoading ? 'Loading...' : 'Load Lists (invoke)', onClick: handleInvokeLists, disabled: isLoading, iconProps: { iconName: 'BulletedList' } }),
271
+ lists.length > 0 && (React.createElement(Stack, { tokens: { childrenGap: 4 }, styles: { root: { padding: '12px', backgroundColor: '#f3f2f1', borderRadius: '4px' } } },
272
+ React.createElement(Label, null, "Lists (top 10, non-hidden):"),
273
+ lists.map(function (list, idx) { return (React.createElement("div", { key: idx, style: { padding: '4px 0', borderBottom: idx < lists.length - 1 ? '1px solid #edebe9' : 'none' } },
274
+ React.createElement("strong", null, list.Title),
275
+ " - ",
276
+ list.ItemCount,
277
+ " items")); })))),
278
+ React.createElement(Stack, { tokens: { childrenGap: 8 } },
279
+ React.createElement(Label, null, "Batch Operations with batch()"),
280
+ React.createElement(PrimaryButton, { text: isLoading ? 'Loading...' : 'Load Multiple (batch)', onClick: handleBatchOperations, disabled: isLoading, iconProps: { iconName: 'Streaming' } }),
281
+ batchData && (React.createElement(Stack, { tokens: { childrenGap: 8 }, styles: { root: { padding: '12px', backgroundColor: '#f3f2f1', borderRadius: '4px' } } },
282
+ React.createElement(InfoRow, { label: "Web Title", value: batchData.webTitle, icon: "CityNext" }),
283
+ React.createElement(InfoRow, { label: "Current User", value: batchData.user.Title, icon: "Contact" }),
284
+ React.createElement(Label, null, "Lists (top 5):"),
285
+ batchData.lists.map(function (list, idx) { return (React.createElement("div", { key: idx, style: { paddingLeft: '16px' } },
286
+ "\u2022 ",
287
+ list.Title)); })))),
288
+ React.createElement(Label, null,
289
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
290
+ "invoke() for single operations, batch() combines multiple requests into ONE HTTP call for better performance.")));
291
+ };
292
+ /**
293
+ * Example 3: useSPFxPnPSearch - Basic Search
294
+ */
295
+ var PnPSearchBasicExample = function () {
296
+ var _a = React.useState(''), searchText = _a[0], setSearchText = _a[1];
297
+ var _b = useSPFxPnPSearch({
298
+ pageSize: 10
299
+ }), search = _b.search, results = _b.results, totalResults = _b.totalResults, loading = _b.loading, error = _b.error, clearError = _b.clearError;
300
+ var handleSearch = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
301
+ var searchResults, err_3;
302
+ return __generator(this, function (_a) {
303
+ switch (_a.label) {
304
+ case 0:
305
+ if (!searchText.trim())
306
+ return [2 /*return*/];
307
+ _a.label = 1;
308
+ case 1:
309
+ _a.trys.push([1, 3, , 4]);
310
+ return [4 /*yield*/, search(searchText)];
311
+ case 2:
312
+ searchResults = _a.sent();
313
+ console.log('[PnPSearchBasic] Search completed:', {
314
+ returnedResults: searchResults.length,
315
+ stateResults: results.length,
316
+ totalResults: totalResults
317
+ });
318
+ return [3 /*break*/, 4];
319
+ case 3:
320
+ err_3 = _a.sent();
321
+ console.error('Search error:', err_3);
322
+ return [3 /*break*/, 4];
323
+ case 4: return [2 /*return*/];
324
+ }
325
+ });
326
+ }); }, [searchText, search, results.length, totalResults]);
327
+ // Debug: log quando results cambia
328
+ React.useEffect(function () {
329
+ console.log('[PnPSearchBasic] Results state updated:', {
330
+ resultsLength: results.length,
331
+ totalResults: totalResults,
332
+ loading: loading
333
+ });
334
+ }, [results, totalResults, loading]);
335
+ return (React.createElement(Stack, { tokens: { childrenGap: 10 }, styles: { root: { padding: '16px', border: '1px solid #edebe9', borderRadius: '4px' } } },
336
+ React.createElement("h3", null,
337
+ React.createElement(Icon, { iconName: "Search", style: { marginRight: '8px' } }),
338
+ "Example 1: Basic Search"),
339
+ React.createElement(Separator, null),
340
+ error && (React.createElement(MessageBar, { messageBarType: MessageBarType.error, onDismiss: clearError }, error.message)),
341
+ React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 8 } },
342
+ React.createElement(TextField, { value: searchText, onChange: function (_, newValue) { return setSearchText(newValue !== null && newValue !== void 0 ? newValue : ''); }, placeholder: "Search SharePoint...", styles: { root: { flexGrow: 1 } }, onKeyDown: function (e) {
343
+ if (e.key === 'Enter') {
344
+ handleSearch().catch(function (err) { return console.error('Search error:', err); });
345
+ }
346
+ } }),
347
+ React.createElement(PrimaryButton, { text: loading ? 'Searching...' : 'Search', onClick: handleSearch, disabled: !searchText.trim() || loading, iconProps: { iconName: 'Search' } })),
348
+ totalResults !== undefined && (React.createElement(MessageBar, { messageBarType: MessageBarType.info },
349
+ "Found ",
350
+ totalResults,
351
+ " result",
352
+ totalResults !== 1 ? 's' : '')),
353
+ results.length > 0 ? (React.createElement(Stack, { tokens: { childrenGap: 6 } }, results.map(function (result) { return (React.createElement(Stack, { key: result.id, tokens: { childrenGap: 4 }, styles: { root: { padding: '10px', backgroundColor: '#faf9f8', borderRadius: '4px' } } },
354
+ React.createElement("div", { style: { fontWeight: 600 } }, result.data.Title || '(No Title)'),
355
+ React.createElement("a", { href: result.data.Path, target: "_blank", rel: "noopener noreferrer", style: { fontSize: '12px' } }, result.data.Path),
356
+ result.data.FileType && React.createElement(Label, null,
357
+ "Type: ",
358
+ result.data.FileType))); }))) : totalResults === 0 ? (React.createElement(MessageBar, null, "No results found. Try a different query.")) : null,
359
+ React.createElement(Label, null,
360
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
361
+ "Simple text search. Try: \"document\", \"report\", \"ContentType:Document\"")));
362
+ };
363
+ /**
364
+ * Example 4: Advanced Search with Builder and Verticals
365
+ */
366
+ var PnPSearchAdvancedExample = function () {
367
+ var _a = React.useState('All'), selectedVertical = _a[0], setSelectedVertical = _a[1];
368
+ var _b = useSPFxPnPSearch({
369
+ pageSize: 5,
370
+ selectProperties: ['Title', 'Path', 'Author', 'LastModifiedTime', 'FileType']
371
+ }), search = _b.search, results = _b.results, totalResults = _b.totalResults, loading = _b.loading, loadMore = _b.loadMore, hasMore = _b.hasMore, error = _b.error, clearError = _b.clearError;
372
+ var getVerticalSourceId = function (vertical) {
373
+ switch (vertical) {
374
+ case 'People': return SearchVerticals.People;
375
+ case 'Documents': return SearchVerticals.Documents;
376
+ case 'Pages': return SearchVerticals.Pages;
377
+ case 'Videos': return SearchVerticals.Videos;
378
+ default: return undefined;
379
+ }
380
+ };
381
+ var handleSearch = React.useCallback(function (query) {
382
+ search(function (builder) {
383
+ var result = builder.text(query).sortList({ Property: 'LastModifiedTime', Direction: 1 });
384
+ var sourceId = getVerticalSourceId(selectedVertical);
385
+ if (sourceId)
386
+ result = result.sourceId(sourceId);
387
+ return result;
388
+ }).catch(function (err) { return console.error('Search error:', err); });
389
+ }, [search, selectedVertical]);
390
+ return (React.createElement(Stack, { tokens: { childrenGap: 10 }, styles: { root: { padding: '16px', border: '1px solid #edebe9', borderRadius: '4px' } } },
391
+ React.createElement("h3", null,
392
+ React.createElement(Icon, { iconName: "SearchAndApps", style: { marginRight: '8px' } }),
393
+ "Example 2: Advanced Search with Builder"),
394
+ React.createElement(Separator, null),
395
+ error && (React.createElement(MessageBar, { messageBarType: MessageBarType.error, onDismiss: clearError }, error.message)),
396
+ React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 6 }, wrap: true }, ['All', 'Documents', 'Pages', 'People', 'Videos'].map(function (v) { return (React.createElement(DefaultButton, { key: v, text: v, onClick: function () { return setSelectedVertical(v); }, primary: selectedVertical === v })); })),
397
+ React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 6 } },
398
+ React.createElement(PrimaryButton, { text: "Search All", onClick: function () { return handleSearch('*'); }, disabled: loading }),
399
+ React.createElement(DefaultButton, { text: "Search Documents", onClick: function () { return handleSearch('filetype:docx OR filetype:pdf'); }, disabled: loading })),
400
+ totalResults !== undefined && (React.createElement(MessageBar, { messageBarType: MessageBarType.info },
401
+ "Found ",
402
+ totalResults,
403
+ " result",
404
+ totalResults !== 1 ? 's' : '',
405
+ " in \"",
406
+ selectedVertical,
407
+ "\"")),
408
+ results.length > 0 && (React.createElement(Stack, { tokens: { childrenGap: 6 } },
409
+ results.map(function (result) { return (React.createElement(Stack, { key: result.id, tokens: { childrenGap: 2 }, styles: { root: { padding: '10px', backgroundColor: '#f3f2f1', borderRadius: '4px' } } },
410
+ React.createElement("div", { style: { fontWeight: 600 } }, result.data.Title || '(No Title)'),
411
+ React.createElement(Label, null,
412
+ result.data.Author,
413
+ " - ",
414
+ result.data.LastModifiedTime ? new Date(result.data.LastModifiedTime).toLocaleDateString() : 'N/A'),
415
+ React.createElement("a", { href: result.data.Path, target: "_blank", rel: "noopener noreferrer", style: { fontSize: '11px' } }, result.data.Path))); }),
416
+ hasMore && (React.createElement(PrimaryButton, { text: loading ? 'Loading...' : 'Load More', onClick: loadMore, disabled: loading })))),
417
+ React.createElement(Label, null,
418
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
419
+ "Builder API with verticals (People, Documents, Pages, Videos) and pagination.")));
420
+ };
421
+ /**
422
+ * Example 5: Faceted Search with Refiners
423
+ */
424
+ var PnPSearchRefinersExample = function () {
425
+ var _a = useSPFxPnPSearch({
426
+ pageSize: 10,
427
+ selectProperties: ['Title', 'Path', 'FileType', 'Author'],
428
+ refiners: 'FileType,Author'
429
+ }), search = _a.search, results = _a.results, refiners = _a.refiners, totalResults = _a.totalResults, loading = _a.loading, applyRefiner = _a.applyRefiner, error = _a.error, clearError = _a.clearError;
430
+ var handleSearch = React.useCallback(function () {
431
+ search('*').catch(function (err) { return console.error('Search error:', err); });
432
+ }, [search]);
433
+ return (React.createElement(Stack, { tokens: { childrenGap: 10 }, styles: { root: { padding: '16px', border: '1px solid #edebe9', borderRadius: '4px' } } },
434
+ React.createElement("h3", null,
435
+ React.createElement(Icon, { iconName: "FilterSettings", style: { marginRight: '8px' } }),
436
+ "Example 3: Faceted Search with Refiners"),
437
+ React.createElement(Separator, null),
438
+ error && (React.createElement(MessageBar, { messageBarType: MessageBarType.error, onDismiss: clearError }, error.message)),
439
+ React.createElement(PrimaryButton, { text: loading ? 'Loading...' : 'Search All Content', onClick: handleSearch, disabled: loading, iconProps: { iconName: 'Search' } }),
440
+ totalResults !== undefined && (React.createElement(Label, null,
441
+ React.createElement(Icon, { iconName: "SearchIssue", style: { marginRight: '4px', color: '#0078d4' } }),
442
+ "Found ",
443
+ totalResults,
444
+ " results")),
445
+ React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 12 }, styles: { root: { alignItems: 'flex-start' } } },
446
+ refiners.length > 0 && (React.createElement(Stack, { tokens: { childrenGap: 8 }, styles: { root: { width: '200px', padding: '8px', backgroundColor: '#f3f2f1', borderRadius: '4px' } } },
447
+ React.createElement(Label, { style: { fontWeight: 600 } }, "Filters"),
448
+ refiners.map(function (refiner) { return (React.createElement(Stack, { key: refiner.name, tokens: { childrenGap: 2 } },
449
+ React.createElement(Label, null, refiner.name),
450
+ refiner.entries.slice(0, 5).map(function (entry) { return (React.createElement(DefaultButton, { key: entry.value, text: "".concat(entry.value, " (").concat(entry.count, ")"), onClick: function () { return applyRefiner(refiner.name, entry.value); }, styles: { root: { height: '28px', fontSize: '12px' } } })); }))); }))),
451
+ React.createElement(Stack, { tokens: { childrenGap: 6 }, styles: { root: { flexGrow: 1 } } }, results.length > 0 ? (results.map(function (result) { return (React.createElement(Stack, { key: result.id, tokens: { childrenGap: 2 }, styles: { root: { padding: '8px', backgroundColor: '#faf9f8', borderRadius: '4px' } } },
452
+ React.createElement("div", { style: { fontWeight: 600 } }, result.data.Title || '(No Title)'),
453
+ React.createElement(Label, null,
454
+ result.data.FileType,
455
+ " | ",
456
+ result.data.Author),
457
+ React.createElement("a", { href: result.data.Path, target: "_blank", rel: "noopener noreferrer", style: { fontSize: '11px' } }, result.data.Path))); })) : (React.createElement(Label, null, "Click \"Search All Content\" to see results.")))),
458
+ React.createElement(Label, null,
459
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
460
+ "Faceted search with FileType and Author refiners. Click to filter/toggle.")));
461
+ };
462
+ /**
463
+ * Example 6: Search Suggestions (Autocomplete)
464
+ */
465
+ var PnPSearchSuggestionsExample = function () {
466
+ var _a = React.useState(''), query = _a[0], setQuery = _a[1];
467
+ var _b = React.useState([]), suggestions = _b[0], setSuggestions = _b[1];
468
+ var suggest = useSPFxPnPSearch().suggest;
469
+ // Track if component is mounted to prevent state updates after unmount
470
+ var mountedRef = React.useRef(true);
471
+ // Cleanup on unmount
472
+ React.useEffect(function () {
473
+ mountedRef.current = true;
474
+ return function () {
475
+ mountedRef.current = false;
476
+ };
477
+ }, []);
478
+ var handleSuggest = React.useCallback(function (value) { return __awaiter(void 0, void 0, void 0, function () {
479
+ var results, err_4;
480
+ return __generator(this, function (_a) {
481
+ switch (_a.label) {
482
+ case 0:
483
+ if (!value || value.length < 2) {
484
+ if (mountedRef.current) {
485
+ setSuggestions([]);
486
+ }
487
+ return [2 /*return*/];
488
+ }
489
+ _a.label = 1;
490
+ case 1:
491
+ _a.trys.push([1, 3, , 4]);
492
+ return [4 /*yield*/, suggest(value)];
493
+ case 2:
494
+ results = _a.sent();
495
+ if (mountedRef.current) {
496
+ setSuggestions(results);
497
+ }
498
+ return [3 /*break*/, 4];
499
+ case 3:
500
+ err_4 = _a.sent();
501
+ console.error('[PnPSearchSuggestions] Error:', err_4);
502
+ if (mountedRef.current) {
503
+ setSuggestions([]);
504
+ }
505
+ return [3 /*break*/, 4];
506
+ case 4: return [2 /*return*/];
507
+ }
508
+ });
509
+ }); }, [suggest]);
510
+ // Debounced suggest with proper cleanup
511
+ var debouncedSuggest = React.useMemo(function () {
512
+ var timeoutId;
513
+ // Return debounced function
514
+ var debounced = function (value) {
515
+ if (timeoutId !== undefined) {
516
+ clearTimeout(timeoutId);
517
+ }
518
+ timeoutId = window.setTimeout(function () { return handleSuggest(value); }, 300);
519
+ };
520
+ // Cleanup function stored in the debounced function
521
+ debounced.cancel = function () {
522
+ if (timeoutId !== undefined) {
523
+ clearTimeout(timeoutId);
524
+ timeoutId = undefined;
525
+ }
526
+ };
527
+ return debounced;
528
+ }, [handleSuggest]);
529
+ // Cleanup timeout on unmount
530
+ React.useEffect(function () {
531
+ return function () {
532
+ var _a;
533
+ (_a = debouncedSuggest.cancel) === null || _a === void 0 ? void 0 : _a.call(debouncedSuggest);
534
+ };
535
+ }, [debouncedSuggest]);
536
+ var handleQueryChange = React.useCallback(function (value) {
537
+ setQuery(value);
538
+ debouncedSuggest(value);
539
+ }, [debouncedSuggest]);
540
+ return (React.createElement(Stack, { tokens: { childrenGap: 10 }, styles: { root: { padding: '16px', border: '1px solid #edebe9', borderRadius: '4px' } } },
541
+ React.createElement("h3", null,
542
+ React.createElement(Icon, { iconName: "SearchBookmark", style: { marginRight: '8px' } }),
543
+ "Example 4: Search Suggestions (Autocomplete)"),
544
+ React.createElement(Separator, null),
545
+ React.createElement(TextField, { label: "Search with Autocomplete", value: query, onChange: function (_, newValue) { return handleQueryChange(newValue !== null && newValue !== void 0 ? newValue : ''); }, placeholder: "Type at least 2 characters..." }),
546
+ suggestions.length > 0 ? (React.createElement(Stack, { tokens: { childrenGap: 2 }, styles: { root: { padding: '8px', backgroundColor: '#f3f2f1', borderRadius: '4px' } } },
547
+ React.createElement(Label, null,
548
+ "Suggestions (",
549
+ suggestions.length,
550
+ "):"),
551
+ suggestions.map(function (s, idx) { return (React.createElement("div", { key: idx, style: { padding: '6px', backgroundColor: '#fff', borderRadius: '2px', cursor: 'pointer' }, onClick: function () { return setQuery(s); } }, s)); }))) : query.length >= 2 ? (React.createElement(MessageBar, { messageBarType: MessageBarType.info }, "No suggestions available. This is normal in dev/test environments where there isn't enough indexed content. Try in a production environment with more search activity.")) : null,
552
+ React.createElement(Label, null,
553
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
554
+ "Real-time autocomplete with 300ms debounce. Requires indexed content and search activity.")));
555
+ };
556
+ /**
557
+ * Example 7: useSPFxPnPList - CRUD Operations
558
+ */
559
+ var PnPListExample = function () {
560
+ var _a = React.useState(''), listTitle = _a[0], setListTitle = _a[1];
561
+ var _b = React.useState(''), newTitle = _b[0], setNewTitle = _b[1];
562
+ var _c = React.useState(null), editingId = _c[0], setEditingId = _c[1];
563
+ var _d = React.useState(''), editTitle = _d[0], setEditTitle = _d[1];
564
+ var _e = useSPFxPnPList(listTitle, { pageSize: 10 }), query = _e.query, items = _e.items, loading = _e.loading, error = _e.error, isEmpty = _e.isEmpty, hasMore = _e.hasMore, loadMore = _e.loadMore, clearError = _e.clearError, create = _e.create, update = _e.update, remove = _e.remove;
565
+ var handleLoadList = React.useCallback(function () {
566
+ query(function (q) { return q.select('Id', 'Title').orderBy('Id', false); }).catch(function (err) { return console.error('Load error:', err); });
567
+ }, [query]);
568
+ var handleCreate = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
569
+ var err_5;
570
+ return __generator(this, function (_a) {
571
+ switch (_a.label) {
572
+ case 0:
573
+ if (!newTitle || !listTitle)
574
+ return [2 /*return*/];
575
+ _a.label = 1;
576
+ case 1:
577
+ _a.trys.push([1, 3, , 4]);
578
+ return [4 /*yield*/, create({ Title: newTitle })];
579
+ case 2:
580
+ _a.sent();
581
+ setNewTitle('');
582
+ return [3 /*break*/, 4];
583
+ case 3:
584
+ err_5 = _a.sent();
585
+ console.error('Create error:', err_5);
586
+ return [3 /*break*/, 4];
587
+ case 4: return [2 /*return*/];
588
+ }
589
+ });
590
+ }); }, [create, newTitle, listTitle]);
591
+ var handleUpdate = React.useCallback(function (id) { return __awaiter(void 0, void 0, void 0, function () {
592
+ var err_6;
593
+ return __generator(this, function (_a) {
594
+ switch (_a.label) {
595
+ case 0:
596
+ if (!editTitle)
597
+ return [2 /*return*/];
598
+ _a.label = 1;
599
+ case 1:
600
+ _a.trys.push([1, 3, , 4]);
601
+ return [4 /*yield*/, update(id, { Title: editTitle })];
602
+ case 2:
603
+ _a.sent();
604
+ setEditingId(null);
605
+ setEditTitle('');
606
+ return [3 /*break*/, 4];
607
+ case 3:
608
+ err_6 = _a.sent();
609
+ console.error('Update error:', err_6);
610
+ return [3 /*break*/, 4];
611
+ case 4: return [2 /*return*/];
612
+ }
613
+ });
614
+ }); }, [update, editTitle]);
615
+ var handleDelete = React.useCallback(function (id) { return __awaiter(void 0, void 0, void 0, function () {
616
+ var err_7;
617
+ return __generator(this, function (_a) {
618
+ switch (_a.label) {
619
+ case 0:
620
+ if (!confirm('Delete this item?'))
621
+ return [2 /*return*/];
622
+ _a.label = 1;
623
+ case 1:
624
+ _a.trys.push([1, 3, , 4]);
625
+ return [4 /*yield*/, remove(id)];
626
+ case 2:
627
+ _a.sent();
628
+ return [3 /*break*/, 4];
629
+ case 3:
630
+ err_7 = _a.sent();
631
+ console.error('Delete error:', err_7);
632
+ return [3 /*break*/, 4];
633
+ case 4: return [2 /*return*/];
634
+ }
635
+ });
636
+ }); }, [remove]);
637
+ return (React.createElement(Stack, { tokens: { childrenGap: 10 }, styles: { root: { padding: '16px', border: '1px solid #edebe9', borderRadius: '4px' } } },
638
+ React.createElement("h3", null,
639
+ React.createElement(Icon, { iconName: "BulletedList", style: { marginRight: '8px' } }),
640
+ "Example 3: useSPFxPnPList - CRUD Operations"),
641
+ React.createElement(Separator, null),
642
+ React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 6 } },
643
+ React.createElement(TextField, { label: "List Title", value: listTitle, onChange: function (_, newValue) { return setListTitle(newValue !== null && newValue !== void 0 ? newValue : ''); }, placeholder: "e.g., Site Pages", styles: { root: { flexGrow: 1 } } }),
644
+ React.createElement(PrimaryButton, { text: "Load", onClick: handleLoadList, disabled: !listTitle || loading, styles: { root: { marginTop: '28px' } } })),
645
+ error && (React.createElement(MessageBar, { messageBarType: MessageBarType.error, onDismiss: clearError }, error.message)),
646
+ listTitle && (React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 6 }, styles: { root: { padding: '8px', backgroundColor: '#f3f2f1', borderRadius: '4px' } } },
647
+ React.createElement(TextField, { value: newTitle, onChange: function (_, newValue) { return setNewTitle(newValue !== null && newValue !== void 0 ? newValue : ''); }, placeholder: "New item title...", styles: { root: { flexGrow: 1 } } }),
648
+ React.createElement(PrimaryButton, { text: "Create", onClick: handleCreate, disabled: !newTitle || loading }))),
649
+ loading && React.createElement(MessageBar, null, "Loading..."),
650
+ isEmpty && !loading && React.createElement(MessageBar, null, "No items found."),
651
+ items.length > 0 && (React.createElement(Stack, { tokens: { childrenGap: 3 } },
652
+ React.createElement(Label, null,
653
+ "Items (",
654
+ items.length,
655
+ "):"),
656
+ items.map(function (item) { return (React.createElement(Stack, { key: item.Id, horizontal: true, tokens: { childrenGap: 6 }, styles: { root: { padding: '6px', backgroundColor: '#faf9f8', borderRadius: '4px' } } }, editingId === item.Id ? (React.createElement(React.Fragment, null,
657
+ React.createElement(TextField, { value: editTitle, onChange: function (_, v) { return setEditTitle(v !== null && v !== void 0 ? v : ''); }, styles: { root: { flexGrow: 1 } } }),
658
+ React.createElement(DefaultButton, { text: "Save", onClick: function () { return handleUpdate(item.Id); } }),
659
+ React.createElement(DefaultButton, { text: "Cancel", onClick: function () { setEditingId(null); setEditTitle(''); } }))) : (React.createElement(React.Fragment, null,
660
+ React.createElement("div", { style: { flexGrow: 1 } },
661
+ "#",
662
+ item.Id,
663
+ " - ",
664
+ item.Title),
665
+ React.createElement(DefaultButton, { text: "Edit", onClick: function () { setEditingId(item.Id); setEditTitle(item.Title); } }),
666
+ React.createElement(DefaultButton, { text: "Delete", onClick: function () { return handleDelete(item.Id); } }))))); }),
667
+ hasMore && React.createElement(PrimaryButton, { text: "Load More", onClick: loadMore, disabled: loading }))),
668
+ React.createElement(Label, null,
669
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
670
+ "Complete CRUD with auto-refetch. Try with \"Site Pages\" or \"Documents\".")));
671
+ };
672
+ // Helper function to safely stringify objects with circular references
673
+ var safeStringify = function (obj, indent) {
674
+ if (indent === void 0) { indent = 2; }
675
+ var seen = new WeakSet();
676
+ return JSON.stringify(obj, function (key, value) {
677
+ // Skip private properties and service scopes to avoid circular references
678
+ if (typeof key === 'string' && (key.indexOf('_') === 0 || key === 'serviceScope' || key === 'service')) {
679
+ return '[Circular/Private]';
680
+ }
681
+ if (typeof value === 'object' && value !== null) {
682
+ if (seen.has(value)) {
683
+ return '[Circular Reference]';
684
+ }
685
+ seen.add(value);
686
+ }
687
+ return value;
688
+ }, indent);
689
+ };
690
+ var SpFxReactToolkitTest = function () {
691
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
692
+ // Core Properties & Display
693
+ var _q = useSPFxProperties(), properties = _q.properties, setProperties = _q.setProperties;
694
+ var isEdit = useSPFxDisplayMode().isEdit;
695
+ var _r = useSPFxInstanceInfo(), id = _r.id, kind = _r.kind;
696
+ // Theme & Environment
697
+ var theme = useSPFxThemeInfo();
698
+ var fluent9ThemeInfo = useSPFxFluent9ThemeInfo();
699
+ var envType = useSPFxEnvironmentInfo().type;
700
+ var isDarkTheme = (_a = theme === null || theme === void 0 ? void 0 : theme.isInverted) !== null && _a !== void 0 ? _a : false;
701
+ // User & Site Info
702
+ var displayName = useSPFxUserInfo().displayName;
703
+ var _s = useSPFxSiteInfo(), siteTitle = _s.title, webUrl = _s.webUrl, siteClassification = _s.siteClassification;
704
+ var localeInfo = useSPFxLocaleInfo();
705
+ // Teams Context
706
+ var _t = useSPFxTeams(), hasTeamsContext = _t.supported, teamsTheme = _t.theme;
707
+ // Page Context
708
+ var pageContext = useSPFxPageContext();
709
+ var pageTypeInfo = useSPFxPageType();
710
+ // List & Hub Info (can be undefined)
711
+ var listInfo = useSPFxListInfo();
712
+ var hubInfo = useSPFxHubSiteInfo();
713
+ // Container & Performance
714
+ var containerSize = useSPFxContainerSize();
715
+ var containerInfo = useSPFxContainerInfo();
716
+ var performance = useSPFxPerformance();
717
+ // Permissions
718
+ var hasWebPermission = useSPFxPermissions().hasWebPermission;
719
+ var canManageWeb = hasWebPermission(SPPermission.manageWeb);
720
+ var canManageLists = hasWebPermission(SPPermission.manageLists);
721
+ // Storage
722
+ var sessionStorage = useSPFxSessionStorage('demo-session-key', '');
723
+ var localStorage = useSPFxLocalStorage('demo-local-key', '');
724
+ // Advanced
725
+ var correlationInfo = useSPFxCorrelationInfo();
726
+ var logger = useSPFxLogger();
727
+ var serviceScope = useSPFxServiceScope();
728
+ // HTTP Clients
729
+ var spHttpClient = useSPFxSPHttpClient();
730
+ var msGraphClient = useSPFxMSGraphClient();
731
+ var aadHttpClient = useSPFxAadHttpClient();
732
+ // OneDrive AppData hook (using instance id as folder for isolation)
733
+ var oneDriveData = useSPFxOneDriveAppData('test-data.json', id, // Use instance ID as folder for multi-instance support
734
+ false // Manual load for demo purposes
735
+ );
736
+ // Tenant Property hook (tenant-wide configuration)
737
+ var tenantVersion = useSPFxTenantProperty('spfx-toolkit-test-version', false);
738
+ var tenantCounter = useSPFxTenantProperty('spfx-toolkit-test-counter', false);
739
+ // User Photo hook (current user profile photo)
740
+ var userPhoto = useSPFxUserPhoto();
741
+ // Local state for interactive demos
742
+ var _u = React.useState((_b = properties === null || properties === void 0 ? void 0 : properties.description) !== null && _b !== void 0 ? _b : ''), descriptionInput = _u[0], setDescriptionInput = _u[1];
743
+ var _v = React.useState(''), sessionStorageInput = _v[0], setSessionStorageInput = _v[1];
744
+ var _w = React.useState(''), localStorageInput = _w[0], setLocalStorageInput = _w[1];
745
+ var _x = React.useState(''), oneDriveMessage = _x[0], setOneDriveMessage = _x[1];
746
+ var _y = React.useState(''), tenantVersionInput = _y[0], setTenantVersionInput = _y[1];
747
+ var _z = React.useState(false), showMessage = _z[0], setShowMessage = _z[1];
748
+ var _0 = React.useState(''), messageText = _0[0], setMessageText = _0[1];
749
+ var _1 = React.useState(''), performanceResult = _1[0], setPerformanceResult = _1[1];
750
+ var _2 = React.useState([]), logMessages = _2[0], setLogMessages = _2[1];
751
+ var _3 = React.useState(undefined), crossSiteUrl = _3[0], setCrossSiteUrl = _3[1];
752
+ // Cross-site permissions (fetch only when URL is set)
753
+ var crossSitePermissions = useSPFxCrossSitePermissions(crossSiteUrl);
754
+ // Sync descriptionInput when properties change
755
+ React.useEffect(function () {
756
+ var _a;
757
+ setDescriptionInput((_a = properties === null || properties === void 0 ? void 0 : properties.description) !== null && _a !== void 0 ? _a : '');
758
+ }, [properties === null || properties === void 0 ? void 0 : properties.description]);
759
+ // Handlers
760
+ var handleUpdateProperties = React.useCallback(function () {
761
+ setProperties({ description: descriptionInput });
762
+ setMessageText('Properties updated successfully!');
763
+ setShowMessage(true);
764
+ setTimeout(function () { return setShowMessage(false); }, 3000);
765
+ }, [descriptionInput, setProperties]);
766
+ var handleSaveSessionStorage = React.useCallback(function () {
767
+ sessionStorage.setValue(sessionStorageInput);
768
+ setSessionStorageInput('');
769
+ setMessageText('Value saved to session storage!');
770
+ setShowMessage(true);
771
+ setTimeout(function () { return setShowMessage(false); }, 3000);
772
+ }, [sessionStorageInput, sessionStorage]);
773
+ var handleSaveLocalStorage = React.useCallback(function () {
774
+ localStorage.setValue(localStorageInput);
775
+ setLocalStorageInput('');
776
+ setMessageText('Value saved to local storage!');
777
+ setShowMessage(true);
778
+ setTimeout(function () { return setShowMessage(false); }, 3000);
779
+ }, [localStorageInput, localStorage]);
780
+ var handlePerformanceTest = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
781
+ var result;
782
+ return __generator(this, function (_a) {
783
+ switch (_a.label) {
784
+ case 0: return [4 /*yield*/, performance.time('demo-test', function () { return __awaiter(void 0, void 0, void 0, function () {
785
+ return __generator(this, function (_a) {
786
+ switch (_a.label) {
787
+ case 0:
788
+ // Simulate async operation
789
+ return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 500); })];
790
+ case 1:
791
+ // Simulate async operation
792
+ _a.sent();
793
+ return [2 /*return*/, 'Test completed'];
794
+ }
795
+ });
796
+ }); })];
797
+ case 1:
798
+ result = _a.sent();
799
+ setPerformanceResult("".concat(result.result, " in ").concat(result.durationMs.toFixed(2), "ms"));
800
+ return [2 /*return*/];
801
+ }
802
+ });
803
+ }); }, [performance]);
804
+ var handleLog = React.useCallback(function (level, message) {
805
+ if (level === 'info')
806
+ logger.info(message);
807
+ else if (level === 'warning')
808
+ logger.warn(message);
809
+ else
810
+ logger.error(message);
811
+ setLogMessages(function (prev) { return __spreadArray(__spreadArray([], prev.slice(-4), true), [{ level: level, message: message }], false); });
812
+ }, [logger]);
813
+ var handleLoadOneDrive = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
814
+ var error_3;
815
+ return __generator(this, function (_a) {
816
+ switch (_a.label) {
817
+ case 0:
818
+ _a.trys.push([0, 2, , 3]);
819
+ return [4 /*yield*/, oneDriveData.load()];
820
+ case 1:
821
+ _a.sent();
822
+ setMessageText('Data loaded from OneDrive successfully!');
823
+ setShowMessage(true);
824
+ setTimeout(function () { return setShowMessage(false); }, 3000);
825
+ return [3 /*break*/, 3];
826
+ case 2:
827
+ error_3 = _a.sent();
828
+ setMessageText("Load failed: ".concat(error_3 instanceof Error ? error_3.message : 'Unknown error'));
829
+ setShowMessage(true);
830
+ setTimeout(function () { return setShowMessage(false); }, 5000);
831
+ return [3 /*break*/, 3];
832
+ case 3: return [2 /*return*/];
833
+ }
834
+ });
835
+ }); }, [oneDriveData]);
836
+ var handleSaveOneDrive = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
837
+ var newData, error_4;
838
+ var _a, _b;
839
+ return __generator(this, function (_c) {
840
+ switch (_c.label) {
841
+ case 0:
842
+ _c.trys.push([0, 2, , 3]);
843
+ newData = {
844
+ message: oneDriveMessage,
845
+ counter: ((_b = (_a = oneDriveData.data) === null || _a === void 0 ? void 0 : _a.counter) !== null && _b !== void 0 ? _b : 0) + 1,
846
+ timestamp: Date.now(),
847
+ };
848
+ return [4 /*yield*/, oneDriveData.write(newData)];
849
+ case 1:
850
+ _c.sent();
851
+ setOneDriveMessage('');
852
+ setMessageText('Data saved to OneDrive successfully!');
853
+ setShowMessage(true);
854
+ setTimeout(function () { return setShowMessage(false); }, 3000);
855
+ return [3 /*break*/, 3];
856
+ case 2:
857
+ error_4 = _c.sent();
858
+ setMessageText("Save failed: ".concat(error_4 instanceof Error ? error_4.message : 'Unknown error'));
859
+ setShowMessage(true);
860
+ setTimeout(function () { return setShowMessage(false); }, 5000);
861
+ return [3 /*break*/, 3];
862
+ case 3: return [2 /*return*/];
863
+ }
864
+ });
865
+ }); }, [oneDriveMessage, oneDriveData]);
866
+ var handleLoadTenantProperty = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
867
+ var error_5;
868
+ return __generator(this, function (_a) {
869
+ switch (_a.label) {
870
+ case 0:
871
+ _a.trys.push([0, 2, , 3]);
872
+ return [4 /*yield*/, Promise.all([
873
+ tenantVersion.load(),
874
+ tenantCounter.load()
875
+ ])];
876
+ case 1:
877
+ _a.sent();
878
+ setMessageText('Tenant properties loaded successfully!');
879
+ setShowMessage(true);
880
+ setTimeout(function () { return setShowMessage(false); }, 3000);
881
+ return [3 /*break*/, 3];
882
+ case 2:
883
+ error_5 = _a.sent();
884
+ setMessageText("Load failed: ".concat(error_5 instanceof Error ? error_5.message : 'Unknown error'));
885
+ setShowMessage(true);
886
+ setTimeout(function () { return setShowMessage(false); }, 5000);
887
+ return [3 /*break*/, 3];
888
+ case 3: return [2 /*return*/];
889
+ }
890
+ });
891
+ }); }, [tenantVersion, tenantCounter]);
892
+ var handleSaveTenantVersion = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
893
+ var error_6;
894
+ return __generator(this, function (_a) {
895
+ switch (_a.label) {
896
+ case 0:
897
+ if (!tenantVersion.canWrite) {
898
+ setMessageText('Insufficient permissions to write tenant properties');
899
+ setShowMessage(true);
900
+ setTimeout(function () { return setShowMessage(false); }, 5000);
901
+ return [2 /*return*/];
902
+ }
903
+ _a.label = 1;
904
+ case 1:
905
+ _a.trys.push([1, 3, , 4]);
906
+ return [4 /*yield*/, tenantVersion.write(tenantVersionInput, 'Test version property from SPFx React Toolkit')];
907
+ case 2:
908
+ _a.sent();
909
+ setTenantVersionInput('');
910
+ setMessageText('Version saved to tenant properties!');
911
+ setShowMessage(true);
912
+ setTimeout(function () { return setShowMessage(false); }, 3000);
913
+ return [3 /*break*/, 4];
914
+ case 3:
915
+ error_6 = _a.sent();
916
+ setMessageText("Save failed: ".concat(error_6 instanceof Error ? error_6.message : 'Unknown error'));
917
+ setShowMessage(true);
918
+ setTimeout(function () { return setShowMessage(false); }, 5000);
919
+ return [3 /*break*/, 4];
920
+ case 4: return [2 /*return*/];
921
+ }
922
+ });
923
+ }); }, [tenantVersionInput, tenantVersion]);
924
+ var handleIncrementTenantCounter = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
925
+ var newValue, error_7;
926
+ var _a;
927
+ return __generator(this, function (_b) {
928
+ switch (_b.label) {
929
+ case 0:
930
+ if (!tenantCounter.canWrite) {
931
+ setMessageText('Insufficient permissions to write tenant properties');
932
+ setShowMessage(true);
933
+ setTimeout(function () { return setShowMessage(false); }, 5000);
934
+ return [2 /*return*/];
935
+ }
936
+ _b.label = 1;
937
+ case 1:
938
+ _b.trys.push([1, 3, , 4]);
939
+ newValue = ((_a = tenantCounter.data) !== null && _a !== void 0 ? _a : 0) + 1;
940
+ return [4 /*yield*/, tenantCounter.write(newValue, 'Test counter property from SPFx React Toolkit')];
941
+ case 2:
942
+ _b.sent();
943
+ setMessageText("Counter incremented to ".concat(newValue, "!"));
944
+ setShowMessage(true);
945
+ setTimeout(function () { return setShowMessage(false); }, 3000);
946
+ return [3 /*break*/, 4];
947
+ case 3:
948
+ error_7 = _b.sent();
949
+ setMessageText("Increment failed: ".concat(error_7 instanceof Error ? error_7.message : 'Unknown error'));
950
+ setShowMessage(true);
951
+ setTimeout(function () { return setShowMessage(false); }, 5000);
952
+ return [3 /*break*/, 4];
953
+ case 4: return [2 /*return*/];
954
+ }
955
+ });
956
+ }); }, [tenantCounter]);
957
+ var handleRemoveTenantProperty = React.useCallback(function (propertyName) { return __awaiter(void 0, void 0, void 0, function () {
958
+ var hook, error_8;
959
+ return __generator(this, function (_a) {
960
+ switch (_a.label) {
961
+ case 0:
962
+ hook = propertyName === 'version' ? tenantVersion : tenantCounter;
963
+ if (!hook.canWrite) {
964
+ setMessageText('Insufficient permissions to remove tenant properties');
965
+ setShowMessage(true);
966
+ setTimeout(function () { return setShowMessage(false); }, 5000);
967
+ return [2 /*return*/];
968
+ }
969
+ if (!confirm("Are you sure you want to remove the ".concat(propertyName, " property?"))) {
970
+ return [2 /*return*/];
971
+ }
972
+ _a.label = 1;
973
+ case 1:
974
+ _a.trys.push([1, 3, , 4]);
975
+ return [4 /*yield*/, hook.remove()];
976
+ case 2:
977
+ _a.sent();
978
+ setMessageText("".concat(propertyName, " property removed!"));
979
+ setShowMessage(true);
980
+ setTimeout(function () { return setShowMessage(false); }, 3000);
981
+ return [3 /*break*/, 4];
982
+ case 3:
983
+ error_8 = _a.sent();
984
+ setMessageText("Remove failed: ".concat(error_8 instanceof Error ? error_8.message : 'Unknown error'));
985
+ setShowMessage(true);
986
+ setTimeout(function () { return setShowMessage(false); }, 5000);
987
+ return [3 /*break*/, 4];
988
+ case 4: return [2 /*return*/];
989
+ }
990
+ });
991
+ }); }, [tenantVersion, tenantCounter]);
992
+ return (React.createElement("section", { className: "".concat(styles.spFxReactToolkitTest, " ").concat(hasTeamsContext ? styles.teams : '') },
993
+ showMessage && (React.createElement(MessageBar, { messageBarType: MessageBarType.success, onDismiss: function () { return setShowMessage(false); } }, messageText)),
994
+ React.createElement(Pivot, { "aria-label": "SPFx React Toolkit Demo Tabs", style: { marginTop: '20px' } },
995
+ React.createElement(PivotItem, { headerText: "Overview", itemIcon: "Home" },
996
+ React.createElement(Stack, { tokens: { childrenGap: 4 }, styles: { root: { marginTop: '16px' } } },
997
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
998
+ React.createElement("h3", null,
999
+ React.createElement(Icon, { iconName: "Info", style: { marginRight: '8px' } }),
1000
+ "Core Information",
1001
+ React.createElement(Separator, null)),
1002
+ React.createElement(InfoRow, { label: "Instance ID", value: id, icon: "Fingerprint" }),
1003
+ React.createElement(InfoRow, { label: "Component Kind", value: kind, icon: "CubeShape" }),
1004
+ React.createElement(InfoRow, { label: "Display Mode", value: isEdit ? 'Edit' : 'Read', icon: "Edit" }),
1005
+ React.createElement(InfoRow, { label: "Environment Type", value: envType, icon: "Globe" }),
1006
+ React.createElement(InfoRow, { label: "Page Type", value: pageTypeInfo.pageType, icon: "Page" })),
1007
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1008
+ React.createElement("h3", null,
1009
+ React.createElement(Icon, { iconName: "Settings", style: { marginRight: '8px' } }),
1010
+ "Properties Editor",
1011
+ React.createElement(Separator, null)),
1012
+ React.createElement(TextField, { label: "Description Property", value: descriptionInput, onChange: function (_, newValue) { return setDescriptionInput(newValue !== null && newValue !== void 0 ? newValue : ''); }, placeholder: "Enter description..." }),
1013
+ React.createElement(PrimaryButton, { text: "Update Properties", onClick: handleUpdateProperties, iconProps: { iconName: 'Save' } }),
1014
+ React.createElement(Label, null,
1015
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
1016
+ "Changes will update the WebPart properties and trigger Property Pane refresh")),
1017
+ containerSize && (React.createElement(Stack, { tokens: { childrenGap: 2 } },
1018
+ React.createElement("h3", null,
1019
+ React.createElement(Icon, { iconName: "Resize", style: { marginRight: '8px' } }),
1020
+ "Container Information",
1021
+ React.createElement(Separator, null)),
1022
+ React.createElement(InfoRow, { label: "Width", value: "".concat(containerSize.width, "px"), icon: "ArrowRight" }),
1023
+ React.createElement(InfoRow, { label: "Height", value: "".concat(containerSize.height, "px"), icon: "ArrowUp" }),
1024
+ React.createElement(InfoRow, { label: "DOM Element", value: containerInfo.element ? 'Available' : 'N/A', icon: "DOM" }),
1025
+ React.createElement(InfoRow, { label: "Size Tracking", value: containerInfo.size ? 'Active' : 'Inactive', icon: "RadioBullet" }))))),
1026
+ React.createElement(PivotItem, { headerText: "Context", itemIcon: "Contact" },
1027
+ React.createElement(Stack, { tokens: { childrenGap: 4 }, styles: { root: { marginTop: '16px' } } },
1028
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1029
+ React.createElement("h3", null,
1030
+ React.createElement(Icon, { iconName: "People", style: { marginRight: '8px' } }),
1031
+ "User & Site Information",
1032
+ React.createElement(Separator, null)),
1033
+ React.createElement(InfoRow, { label: "User Name", value: displayName, icon: "Contact" }),
1034
+ React.createElement(InfoRow, { label: "Site Title", value: siteTitle, icon: "CityNext" }),
1035
+ React.createElement(InfoRow, { label: "Site URL", value: webUrl, icon: "Link" }),
1036
+ siteClassification && (React.createElement(InfoRow, { label: "Classification", value: siteClassification, icon: "Tag" }))),
1037
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1038
+ React.createElement("h3", null,
1039
+ React.createElement(Icon, { iconName: "LocaleLanguage", style: { marginRight: '8px' } }),
1040
+ "Locale & Regional Settings",
1041
+ React.createElement(Separator, null)),
1042
+ React.createElement(InfoRow, { label: "Content Locale", value: localeInfo.locale, icon: "Globe" }),
1043
+ React.createElement(InfoRow, { label: "UI Locale", value: localeInfo.uiLocale, icon: "LocaleLanguage" }),
1044
+ React.createElement(InfoRow, { label: "Text Direction", value: localeInfo.isRtl ? 'Right-to-Left (RTL)' : 'Left-to-Right (LTR)', icon: "TextAlignLeft" }),
1045
+ localeInfo.timeZone && (React.createElement(React.Fragment, null,
1046
+ React.createElement(InfoRow, { label: "Time Zone", value: localeInfo.timeZone.description, icon: "Clock" }),
1047
+ React.createElement(InfoRow, { label: "UTC Offset", value: "".concat(localeInfo.timeZone.offset, " minutes"), icon: "DateTime" }),
1048
+ React.createElement(Label, null,
1049
+ React.createElement(Icon, { iconName: "Info", style: { marginRight: '4px', color: '#0078d4' } }),
1050
+ "Current time: ",
1051
+ new Intl.DateTimeFormat(localeInfo.locale, {
1052
+ weekday: 'long',
1053
+ year: 'numeric',
1054
+ month: 'long',
1055
+ day: 'numeric',
1056
+ hour: '2-digit',
1057
+ minute: '2-digit'
1058
+ }).format(new Date())))),
1059
+ React.createElement(Label, null,
1060
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
1061
+ "Use with JavaScript Intl APIs for i18n (dates, numbers, currencies)")),
1062
+ hasTeamsContext && (React.createElement(Stack, { tokens: { childrenGap: 2 } },
1063
+ React.createElement("h3", null,
1064
+ React.createElement(Icon, { iconName: "TeamsLogo", style: { marginRight: '8px' } }),
1065
+ "Microsoft Teams Context",
1066
+ React.createElement(Separator, null)),
1067
+ React.createElement(InfoRow, { label: "Teams Supported", value: "Yes", icon: "CompletedSolid" }),
1068
+ React.createElement(InfoRow, { label: "Teams Theme", value: teamsTheme !== null && teamsTheme !== void 0 ? teamsTheme : 'default', icon: "Color" }))),
1069
+ listInfo && (React.createElement(Stack, { tokens: { childrenGap: 2 } },
1070
+ React.createElement("h3", null,
1071
+ React.createElement(Icon, { iconName: "BulletedList", style: { marginRight: '8px' } }),
1072
+ "List Context",
1073
+ React.createElement(Separator, null)),
1074
+ React.createElement(InfoRow, { label: "List ID", value: listInfo.id, icon: "Fingerprint" }),
1075
+ React.createElement(InfoRow, { label: "List Title", value: listInfo.title, icon: "FabricTextHighlight" }),
1076
+ listInfo.baseTemplate && (React.createElement(InfoRow, { label: "Base Template", value: String(listInfo.baseTemplate), icon: "PageData" })),
1077
+ listInfo.isDocumentLibrary && (React.createElement(Label, null,
1078
+ React.createElement(Icon, { iconName: "FabricFolder", style: { marginRight: '4px', color: '#0078d4' } }),
1079
+ "Document Library")))),
1080
+ (hubInfo === null || hubInfo === void 0 ? void 0 : hubInfo.isHubSite) && (React.createElement(Stack, { tokens: { childrenGap: 2 } },
1081
+ React.createElement("h3", null,
1082
+ React.createElement(Icon, { iconName: "NetworkTower", style: { marginRight: '8px' } }),
1083
+ "Hub Site Association",
1084
+ React.createElement(Separator, null)),
1085
+ hubInfo.error && (React.createElement(MessageBar, { messageBarType: MessageBarType.error },
1086
+ "Failed to load hub site URL: ",
1087
+ hubInfo.error.message)),
1088
+ React.createElement(InfoRow, { label: "Hub Site ID", value: hubInfo.hubSiteId, icon: "Fingerprint" }),
1089
+ hubInfo.isLoading ? (React.createElement(MessageBar, { messageBarType: MessageBarType.info }, "Loading hub site URL...")) : hubInfo.hubSiteUrl ? (React.createElement(InfoRow, { label: "Hub Site URL", value: hubInfo.hubSiteUrl, icon: "Link" })) : null)))),
1090
+ React.createElement(PivotItem, { headerText: "Advanced", itemIcon: "DeveloperTools" },
1091
+ React.createElement(Stack, { tokens: { childrenGap: 4 }, styles: { root: { marginTop: '16px' } } },
1092
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1093
+ React.createElement("h3", null,
1094
+ React.createElement(Icon, { iconName: "Permissions", style: { marginRight: '8px' } }),
1095
+ "Permissions (Current Site)",
1096
+ React.createElement(Separator, null)),
1097
+ React.createElement(StatusBadge, { label: "Can Manage Web", available: canManageWeb }),
1098
+ React.createElement(StatusBadge, { label: "Can Manage Lists", available: canManageLists })),
1099
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1100
+ React.createElement("h3", null,
1101
+ React.createElement(Icon, { iconName: "Globe", style: { marginRight: '8px' } }),
1102
+ "Cross-Site Permissions",
1103
+ React.createElement(Separator, null)),
1104
+ React.createElement(Label, null,
1105
+ React.createElement(Icon, { iconName: "Info", style: { marginRight: '4px', color: '#0078d4' } }),
1106
+ "Check permissions on a different site (auto-fetch when URL is provided)"),
1107
+ React.createElement(TextField, { label: "Target Site URL", value: crossSiteUrl || '', onChange: function (_, value) { return setCrossSiteUrl((value === null || value === void 0 ? void 0 : value.trim()) || undefined); }, placeholder: "https://contoso.sharepoint.com/sites/targetsite", description: "Enter a site URL - permissions will be fetched automatically" }),
1108
+ crossSitePermissions.isLoading && (React.createElement(MessageBar, { messageBarType: MessageBarType.info },
1109
+ "Loading permissions from ",
1110
+ crossSiteUrl,
1111
+ "...")),
1112
+ crossSitePermissions.error && (React.createElement(MessageBar, { messageBarType: MessageBarType.error },
1113
+ "Error: ",
1114
+ crossSitePermissions.error.message)),
1115
+ crossSiteUrl && !crossSitePermissions.isLoading && !crossSitePermissions.error && (React.createElement(Stack, { tokens: { childrenGap: 1 } },
1116
+ React.createElement(InfoRow, { label: "Target Site", value: crossSiteUrl, icon: "Globe" }),
1117
+ React.createElement(StatusBadge, { label: "Can Manage Web (Cross-Site)", available: crossSitePermissions.hasWebPermission(SPPermission.manageWeb) }),
1118
+ React.createElement(StatusBadge, { label: "Can Manage Lists (Cross-Site)", available: crossSitePermissions.hasWebPermission(SPPermission.manageLists) }),
1119
+ React.createElement(StatusBadge, { label: "Can Add Items (Cross-Site)", available: crossSitePermissions.hasWebPermission(SPPermission.addListItems) })))),
1120
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1121
+ React.createElement("h3", null,
1122
+ React.createElement(Icon, { iconName: "ContactCard", style: { marginRight: '8px' } }),
1123
+ "User Photo Demo",
1124
+ React.createElement(Separator, null)),
1125
+ userPhoto.error && (React.createElement(MessageBar, { messageBarType: MessageBarType.error },
1126
+ "Load Error: ",
1127
+ userPhoto.error.message)),
1128
+ userPhoto.isLoading ? (React.createElement(MessageBar, { messageBarType: MessageBarType.info }, "Loading photo from Microsoft Graph...")) : userPhoto.photoUrl ? (React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 10 }, verticalAlign: "center" },
1129
+ React.createElement("img", { src: userPhoto.photoUrl, alt: displayName, style: {
1130
+ width: 120,
1131
+ height: 120,
1132
+ borderRadius: '50%',
1133
+ objectFit: 'cover',
1134
+ border: '3px solid #0078d4',
1135
+ boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
1136
+ } }),
1137
+ React.createElement(Stack, { tokens: { childrenGap: 1 } },
1138
+ React.createElement(InfoRow, { label: "Display Name", value: displayName, icon: "Contact" }),
1139
+ React.createElement(InfoRow, { label: "Photo Size", value: "240x240 (default)", icon: "ResizeMouseMedium" }),
1140
+ React.createElement(InfoRow, { label: "Photo Format", value: "Blob URL", icon: "FileImage" }),
1141
+ React.createElement(InfoRow, { label: "Is Ready", value: userPhoto.isReady ? 'Yes' : 'No', icon: "CheckMark" })))) : (React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 10 }, verticalAlign: "center" },
1142
+ React.createElement("div", { style: {
1143
+ width: 120,
1144
+ height: 120,
1145
+ borderRadius: '50%',
1146
+ backgroundColor: '#0078d4',
1147
+ display: 'flex',
1148
+ alignItems: 'center',
1149
+ justifyContent: 'center',
1150
+ color: 'white',
1151
+ fontSize: 48,
1152
+ fontWeight: 'bold'
1153
+ } }, displayName ? displayName.charAt(0).toUpperCase() : '?'),
1154
+ React.createElement(Label, null,
1155
+ React.createElement(Icon, { iconName: "Info", style: { marginRight: '4px', color: '#0078d4' } }),
1156
+ "No profile photo available. Showing initials fallback."))),
1157
+ React.createElement(PrimaryButton, { text: userPhoto.isLoading ? 'Loading...' : 'Reload Photo', onClick: userPhoto.reload, disabled: userPhoto.isLoading, iconProps: { iconName: 'Refresh' } }),
1158
+ React.createElement(Label, null,
1159
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
1160
+ "Photo loaded from Microsoft Graph API (/me/photos/240x240/$value)"),
1161
+ React.createElement(Label, null,
1162
+ React.createElement(Icon, { iconName: "Warning", style: { marginRight: '4px', color: '#d83b01' } }),
1163
+ "Requires Microsoft Graph permissions: User.Read"),
1164
+ React.createElement(Label, null,
1165
+ React.createElement(Icon, { iconName: "LightningBolt", style: { marginRight: '4px', color: '#107c10' } }),
1166
+ "Blob URL automatically cleaned up on unmount (memory safe)")),
1167
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1168
+ React.createElement("h3", null,
1169
+ React.createElement(Icon, { iconName: "OneDrive", style: { marginRight: '8px' } }),
1170
+ "OneDrive AppData Demo",
1171
+ React.createElement(Separator, null)),
1172
+ oneDriveData.error && (React.createElement(MessageBar, { messageBarType: MessageBarType.error },
1173
+ "Load Error: ",
1174
+ oneDriveData.error.message)),
1175
+ oneDriveData.writeError && (React.createElement(MessageBar, { messageBarType: MessageBarType.warning },
1176
+ "Write Error: ",
1177
+ oneDriveData.writeError.message)),
1178
+ oneDriveData.isLoading ? (React.createElement(MessageBar, { messageBarType: MessageBarType.info }, "Loading from OneDrive...")) : oneDriveData.data ? (React.createElement(Stack, { tokens: { childrenGap: 1 } },
1179
+ React.createElement(InfoRow, { label: "Message", value: oneDriveData.data.message, icon: "Message" }),
1180
+ React.createElement(InfoRow, { label: "Counter", value: String(oneDriveData.data.counter), icon: "NumberField" }),
1181
+ React.createElement(InfoRow, { label: "Last Updated", value: new Date(oneDriveData.data.timestamp).toLocaleString(), icon: "DateTime" }),
1182
+ React.createElement(InfoRow, { label: "Is Ready", value: oneDriveData.isReady ? 'Yes' : 'No', icon: "CheckMark" }))) : (React.createElement(Label, null, "No data loaded yet. Click \"Load\" to fetch from OneDrive.")),
1183
+ React.createElement(TextField, { label: "New Message", value: oneDriveMessage, onChange: function (_, newValue) { return setOneDriveMessage(newValue !== null && newValue !== void 0 ? newValue : ''); }, placeholder: "Enter a message to save...", disabled: oneDriveData.isWriting || oneDriveData.isLoading }),
1184
+ React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
1185
+ React.createElement(PrimaryButton, { text: "Load from OneDrive", onClick: handleLoadOneDrive, disabled: oneDriveData.isLoading || oneDriveData.isWriting, iconProps: { iconName: 'CloudDownload' } }),
1186
+ React.createElement(PrimaryButton, { text: oneDriveData.isWriting ? 'Saving...' : 'Save to OneDrive', onClick: handleSaveOneDrive, disabled: !oneDriveMessage || oneDriveData.isWriting || oneDriveData.isLoading, iconProps: { iconName: 'CloudUpload' } })),
1187
+ React.createElement(Label, null,
1188
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
1189
+ "Data is stored in your OneDrive (appRoot:/",
1190
+ id,
1191
+ "/test-data.json). Each WebPart instance has its own file."),
1192
+ React.createElement(Label, null,
1193
+ React.createElement(Icon, { iconName: "Warning", style: { marginRight: '4px', color: '#d83b01' } }),
1194
+ "Requires Microsoft Graph permissions: Files.ReadWrite or Files.ReadWrite.AppFolder")),
1195
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1196
+ React.createElement("h3", null,
1197
+ React.createElement(Icon, { iconName: "Org", style: { marginRight: '8px' } }),
1198
+ "Tenant Property Demo",
1199
+ React.createElement(Separator, null)),
1200
+ (tenantVersion.error || tenantCounter.error) && (React.createElement(MessageBar, { messageBarType: MessageBarType.error },
1201
+ "Load Error: ",
1202
+ ((_c = tenantVersion.error) === null || _c === void 0 ? void 0 : _c.message) || ((_d = tenantCounter.error) === null || _d === void 0 ? void 0 : _d.message))),
1203
+ (tenantVersion.writeError || tenantCounter.writeError) && (React.createElement(MessageBar, { messageBarType: MessageBarType.warning },
1204
+ "Write Error: ",
1205
+ ((_e = tenantVersion.writeError) === null || _e === void 0 ? void 0 : _e.message) || ((_f = tenantCounter.writeError) === null || _f === void 0 ? void 0 : _f.message))),
1206
+ (tenantVersion.isLoading || tenantCounter.isLoading) ? (React.createElement(MessageBar, { messageBarType: MessageBarType.info }, "Loading from tenant app catalog...")) : (tenantVersion.data || tenantCounter.data) ? (React.createElement(Stack, { tokens: { childrenGap: 1 } },
1207
+ React.createElement(InfoRow, { label: "Version", value: (_g = tenantVersion.data) !== null && _g !== void 0 ? _g : '(not set)', icon: "ServerEnviroment" }),
1208
+ tenantVersion.description && (React.createElement(Label, null,
1209
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
1210
+ tenantVersion.description)),
1211
+ React.createElement(InfoRow, { label: "Counter", value: String((_h = tenantCounter.data) !== null && _h !== void 0 ? _h : 0), icon: "NumberField" }),
1212
+ tenantCounter.description && (React.createElement(Label, null,
1213
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
1214
+ tenantCounter.description)),
1215
+ React.createElement(InfoRow, { label: "Can Write", value: tenantVersion.canWrite ? 'Yes' : 'No', icon: "Permissions" }))) : (React.createElement(Label, null, "No data loaded yet. Click \"Load\" to fetch from tenant properties.")),
1216
+ React.createElement(TextField, { label: "New Version", value: tenantVersionInput, onChange: function (_, newValue) { return setTenantVersionInput(newValue !== null && newValue !== void 0 ? newValue : ''); }, placeholder: "e.g., 1.0.0", disabled: tenantVersion.isWriting || tenantVersion.isLoading || !tenantVersion.canWrite }),
1217
+ React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
1218
+ React.createElement(PrimaryButton, { text: "Load Properties", onClick: handleLoadTenantProperty, disabled: tenantVersion.isLoading || tenantCounter.isLoading, iconProps: { iconName: 'CloudDownload' } }),
1219
+ React.createElement(PrimaryButton, { text: tenantVersion.isWriting ? 'Saving...' : 'Save Version', onClick: handleSaveTenantVersion, disabled: !tenantVersionInput || tenantVersion.isWriting || !tenantVersion.canWrite, iconProps: { iconName: 'Save' } }),
1220
+ React.createElement(PrimaryButton, { text: tenantCounter.isWriting ? 'Incrementing...' : 'Increment Counter', onClick: handleIncrementTenantCounter, disabled: tenantCounter.isWriting || !tenantCounter.canWrite, iconProps: { iconName: 'Add' } })),
1221
+ React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
1222
+ React.createElement(DefaultButton, { text: "Remove Version", onClick: function () { return handleRemoveTenantProperty('version'); }, disabled: tenantVersion.isWriting || !tenantVersion.canWrite || !tenantVersion.data, iconProps: { iconName: 'Delete' } }),
1223
+ React.createElement(DefaultButton, { text: "Remove Counter", onClick: function () { return handleRemoveTenantProperty('counter'); }, disabled: tenantCounter.isWriting || !tenantCounter.canWrite || !tenantCounter.data, iconProps: { iconName: 'Delete' } })),
1224
+ React.createElement(Label, null,
1225
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
1226
+ "Properties are stored tenant-wide in SharePoint StorageEntity. All users can read, only admins can write."),
1227
+ React.createElement(Label, null,
1228
+ React.createElement(Icon, { iconName: "Info", style: { marginRight: '4px', color: '#0078d4' } }),
1229
+ "Keys: spfx-toolkit-test-version (string), spfx-toolkit-test-counter (number)"),
1230
+ React.createElement(Label, null,
1231
+ React.createElement(Icon, { iconName: "Warning", style: { marginRight: '4px', color: '#d83b01' } }),
1232
+ "Requires: Tenant app catalog provisioned, Manage Web permissions to write"),
1233
+ !tenantVersion.canWrite && (React.createElement(MessageBar, { messageBarType: MessageBarType.info }, "\u2139\uFE0F You don't have permission to modify tenant properties. Contact your SharePoint administrator."))),
1234
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1235
+ React.createElement("h3", null,
1236
+ React.createElement(Icon, { iconName: "Database", style: { marginRight: '8px' } }),
1237
+ "Session Storage Demo",
1238
+ React.createElement(Separator, null)),
1239
+ React.createElement(InfoRow, { label: "Current Value", value: sessionStorage.value || '(empty)', icon: "Variable" }),
1240
+ React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
1241
+ React.createElement(TextField, { value: sessionStorageInput, onChange: function (_, newValue) { return setSessionStorageInput(newValue !== null && newValue !== void 0 ? newValue : ''); }, placeholder: "Enter value...", styles: { root: { flexGrow: 1 } } }),
1242
+ React.createElement(PrimaryButton, { text: "Save", onClick: handleSaveSessionStorage, iconProps: { iconName: 'Save' } }),
1243
+ React.createElement(DefaultButton, { text: "Clear", onClick: function () { return sessionStorage.remove(); }, iconProps: { iconName: 'Delete' } })),
1244
+ React.createElement(Label, null,
1245
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
1246
+ "Persists only for current tab/session")),
1247
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1248
+ React.createElement("h3", null,
1249
+ React.createElement(Icon, { iconName: "Save", style: { marginRight: '8px' } }),
1250
+ "Local Storage Demo",
1251
+ React.createElement(Separator, null)),
1252
+ React.createElement(InfoRow, { label: "Current Value", value: localStorage.value || '(empty)', icon: "Variable" }),
1253
+ React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
1254
+ React.createElement(TextField, { value: localStorageInput, onChange: function (_, newValue) { return setLocalStorageInput(newValue !== null && newValue !== void 0 ? newValue : ''); }, placeholder: "Enter value...", styles: { root: { flexGrow: 1 } } }),
1255
+ React.createElement(PrimaryButton, { text: "Save", onClick: handleSaveLocalStorage, iconProps: { iconName: 'Save' } }),
1256
+ React.createElement(DefaultButton, { text: "Clear", onClick: function () { return localStorage.remove(); }, iconProps: { iconName: 'Delete' } })),
1257
+ React.createElement(Label, null,
1258
+ React.createElement(Icon, { iconName: "InfoSolid", style: { marginRight: '4px', color: '#0078d4' } }),
1259
+ "Persists across sessions and page reloads")),
1260
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1261
+ React.createElement("h3", null,
1262
+ React.createElement(Icon, { iconName: "SpeedHigh", style: { marginRight: '8px' } }),
1263
+ "Performance Test",
1264
+ React.createElement(Separator, null)),
1265
+ performanceResult && (React.createElement(MessageBar, { messageBarType: MessageBarType.info }, performanceResult)),
1266
+ React.createElement(PrimaryButton, { text: "Run Performance Test", onClick: handlePerformanceTest, iconProps: { iconName: 'LightningBolt' } })),
1267
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1268
+ React.createElement("h3", null,
1269
+ React.createElement(Icon, { iconName: "Code", style: { marginRight: '8px' } }),
1270
+ "Logger Demo",
1271
+ React.createElement(Separator, null)),
1272
+ React.createElement(Stack, { horizontal: true, tokens: { childrenGap: 2 } },
1273
+ React.createElement(DefaultButton, { text: "Info", onClick: function () { return handleLog('info', 'This is an info message'); }, iconProps: { iconName: 'Info' } }),
1274
+ React.createElement(DefaultButton, { text: "Warning", onClick: function () { return handleLog('warning', 'This is a warning message'); }, iconProps: { iconName: 'Warning' } }),
1275
+ React.createElement(DefaultButton, { text: "Error", onClick: function () { return handleLog('error', 'This is an error message'); }, iconProps: { iconName: 'Error' } })),
1276
+ logMessages.length > 0 && (React.createElement(Stack, { tokens: { childrenGap: 2 }, styles: { root: { marginTop: '8px' } } },
1277
+ React.createElement(Label, null, "Recent Logs (check browser console):"),
1278
+ logMessages.map(function (log, idx) {
1279
+ var levelClass = log.level === 'info' ? styles.info :
1280
+ log.level === 'warning' ? styles.warning :
1281
+ log.level === 'error' ? styles.error :
1282
+ styles.verbose;
1283
+ return (React.createElement("div", { key: idx, className: "".concat(styles.logMessage, " ").concat(levelClass) },
1284
+ React.createElement("strong", null,
1285
+ "[",
1286
+ log.level.toUpperCase(),
1287
+ "]"),
1288
+ ": ",
1289
+ log.message));
1290
+ })))),
1291
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1292
+ React.createElement("h3", null,
1293
+ React.createElement(Icon, { iconName: "CloudUpload", style: { marginRight: '8px' } }),
1294
+ "HTTP Clients Status",
1295
+ React.createElement(Separator, null)),
1296
+ React.createElement(StatusBadge, { label: "SPHttpClient", available: !!spHttpClient }),
1297
+ React.createElement(StatusBadge, { label: "MSGraphClient", available: !!msGraphClient }),
1298
+ React.createElement(StatusBadge, { label: "AadHttpClient", available: !!aadHttpClient })),
1299
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1300
+ React.createElement("h3", null,
1301
+ React.createElement(Icon, { iconName: "Color", style: { marginRight: '8px' } }),
1302
+ "Theme Information",
1303
+ React.createElement(Separator, null)),
1304
+ React.createElement(InfoRow, { label: "Is Dark Theme", value: isDarkTheme ? 'Yes' : 'No', icon: "Brightness" }),
1305
+ React.createElement(InfoRow, { label: "Body Background", value: (_k = (_j = theme === null || theme === void 0 ? void 0 : theme.semanticColors) === null || _j === void 0 ? void 0 : _j.bodyBackground) !== null && _k !== void 0 ? _k : 'N/A', icon: "FabricFolderFill" }),
1306
+ React.createElement(InfoRow, { label: "Body Text", value: (_m = (_l = theme === null || theme === void 0 ? void 0 : theme.semanticColors) === null || _l === void 0 ? void 0 : _l.bodyText) !== null && _m !== void 0 ? _m : 'N/A', icon: "Font" }),
1307
+ React.createElement(InfoRow, { label: "Link Color", value: (_p = (_o = theme === null || theme === void 0 ? void 0 : theme.semanticColors) === null || _o === void 0 ? void 0 : _o.link) !== null && _p !== void 0 ? _p : 'N/A', icon: "Link" })),
1308
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1309
+ React.createElement("h3", null,
1310
+ React.createElement(Icon, { iconName: "Color", style: { marginRight: '8px' } }),
1311
+ "Fluent UI 9 Theme Information",
1312
+ React.createElement(Separator, null)),
1313
+ React.createElement(InfoRow, { label: "Is Teams Context", value: fluent9ThemeInfo.isTeams ? 'Yes' : 'No', icon: "TeamsLogo" }),
1314
+ fluent9ThemeInfo.isTeams && fluent9ThemeInfo.teamsTheme && (React.createElement(InfoRow, { label: "Teams Theme", value: fluent9ThemeInfo.teamsTheme, icon: "Color" })),
1315
+ React.createElement("details", { className: styles.detailsSection },
1316
+ React.createElement("summary", null, "Click to expand Fluent UI 9 Theme (JSON)"),
1317
+ React.createElement("pre", null, safeStringify(fluent9ThemeInfo.theme, 2)))),
1318
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1319
+ React.createElement("h3", null,
1320
+ React.createElement(Icon, { iconName: "DeveloperTools", style: { marginRight: '8px' } }),
1321
+ "Advanced Diagnostics",
1322
+ React.createElement(Separator, null)),
1323
+ React.createElement(InfoRow, { label: "Correlation ID", value: correlationInfo.correlationId, icon: "TrackersMirrored" }),
1324
+ React.createElement(InfoRow, { label: "Tenant ID", value: correlationInfo.tenantId, icon: "CityNext" }),
1325
+ React.createElement(InfoRow, { label: "ServiceScope", value: serviceScope ? 'Available' : 'N/A', icon: "Settings" })),
1326
+ React.createElement(Stack, { tokens: { childrenGap: 2 } },
1327
+ React.createElement("h3", null,
1328
+ React.createElement(Icon, { iconName: "FileCode", style: { marginRight: '8px' } }),
1329
+ "Page Context (Raw JSON)",
1330
+ React.createElement(Separator, null)),
1331
+ React.createElement("details", { className: styles.detailsSection },
1332
+ React.createElement("summary", null, "Click to expand/collapse"),
1333
+ React.createElement("pre", null, safeStringify(pageContext, 2)))))),
1334
+ React.createElement(PivotItem, { headerText: "PnPjs", itemIcon: "CloudDownload" },
1335
+ React.createElement(Stack, { tokens: { childrenGap: 20 }, styles: { root: { marginTop: '16px' } } },
1336
+ React.createElement(PnPContextExample, null),
1337
+ React.createElement(PnPOperationsExample, null),
1338
+ React.createElement(PnPListExample, null))),
1339
+ React.createElement(PivotItem, { headerText: "Search", itemIcon: "Search" },
1340
+ React.createElement(Stack, { tokens: { childrenGap: 20 }, styles: { root: { marginTop: '16px' } } },
1341
+ React.createElement(MessageBar, { messageBarType: MessageBarType.info },
1342
+ React.createElement("strong", null, "useSPFxPnPSearch Hook Examples"),
1343
+ React.createElement("br", null),
1344
+ "These examples demonstrate SharePoint Search capabilities using the native PnPjs SearchQueryBuilder API."),
1345
+ React.createElement(PnPSearchBasicExample, null),
1346
+ React.createElement(PnPSearchAdvancedExample, null),
1347
+ React.createElement(PnPSearchRefinersExample, null),
1348
+ React.createElement(PnPSearchSuggestionsExample, null))))));
1349
+ };
1350
+ export default SpFxReactToolkitTest;
1351
+ //# sourceMappingURL=SpFxReactToolkitTest.js.map