@fluidframework/react 0.41.3 → 2.62.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 (342) hide show
  1. package/.eslintrc.cjs +11 -0
  2. package/.mocharc.cjs +15 -0
  3. package/CHANGELOG.md +282 -0
  4. package/README.md +122 -273
  5. package/api-extractor/api-extractor-lint-alpha.cjs.json +5 -0
  6. package/api-extractor/api-extractor-lint-alpha.esm.json +5 -0
  7. package/api-extractor/api-extractor-lint-beta.cjs.json +5 -0
  8. package/api-extractor/api-extractor-lint-beta.esm.json +5 -0
  9. package/api-extractor/api-extractor-lint-bundle.json +5 -0
  10. package/api-extractor/api-extractor-lint-public.cjs.json +5 -0
  11. package/api-extractor/api-extractor-lint-public.esm.json +5 -0
  12. package/api-extractor-lint.json +4 -0
  13. package/api-extractor.json +2 -2
  14. package/api-report/react.alpha.api.md +114 -0
  15. package/api-report/react.beta.api.md +7 -0
  16. package/api-report/react.public.api.md +7 -0
  17. package/biome.jsonc +4 -0
  18. package/dist/alpha.d.ts +45 -0
  19. package/dist/beta.d.ts +15 -0
  20. package/dist/index.d.ts +11 -7
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +19 -17
  23. package/dist/index.js.map +1 -1
  24. package/dist/package.json +4 -0
  25. package/dist/propNode.d.ts +114 -0
  26. package/dist/propNode.d.ts.map +1 -0
  27. package/dist/propNode.js +43 -0
  28. package/dist/propNode.js.map +1 -0
  29. package/dist/public.d.ts +15 -0
  30. package/dist/reactSharedTreeView.d.ts +119 -0
  31. package/dist/reactSharedTreeView.d.ts.map +1 -0
  32. package/dist/reactSharedTreeView.js +206 -0
  33. package/dist/reactSharedTreeView.js.map +1 -0
  34. package/dist/simpleIdentifier.d.ts +19 -0
  35. package/dist/simpleIdentifier.d.ts.map +1 -0
  36. package/dist/simpleIdentifier.js +33 -0
  37. package/dist/simpleIdentifier.js.map +1 -0
  38. package/dist/useObservation.d.ts +83 -0
  39. package/dist/useObservation.d.ts.map +1 -0
  40. package/dist/useObservation.js +295 -0
  41. package/dist/useObservation.js.map +1 -0
  42. package/dist/useTree.d.ts +80 -0
  43. package/dist/useTree.d.ts.map +1 -0
  44. package/dist/useTree.js +137 -0
  45. package/dist/useTree.js.map +1 -0
  46. package/lib/alpha.d.ts +45 -0
  47. package/lib/beta.d.ts +15 -0
  48. package/lib/index.d.ts +16 -0
  49. package/lib/index.d.ts.map +1 -0
  50. package/lib/index.js +4 -7
  51. package/lib/index.js.map +1 -1
  52. package/lib/package.json +4 -0
  53. package/lib/propNode.d.ts +114 -0
  54. package/lib/propNode.d.ts.map +1 -0
  55. package/lib/propNode.js +36 -0
  56. package/lib/propNode.js.map +1 -0
  57. package/lib/public.d.ts +15 -0
  58. package/lib/reactSharedTreeView.d.ts +119 -0
  59. package/lib/reactSharedTreeView.d.ts.map +1 -0
  60. package/lib/reactSharedTreeView.js +176 -0
  61. package/lib/reactSharedTreeView.js.map +1 -0
  62. package/lib/simpleIdentifier.d.ts +19 -0
  63. package/lib/simpleIdentifier.d.ts.map +1 -0
  64. package/lib/simpleIdentifier.js +29 -0
  65. package/lib/simpleIdentifier.js.map +1 -0
  66. package/lib/test/propNode.spec.js +120 -0
  67. package/lib/test/propNode.spec.js.map +1 -0
  68. package/lib/test/reactSharedTreeView.spec.js +71 -0
  69. package/lib/test/reactSharedTreeView.spec.js.map +1 -0
  70. package/lib/test/simpleIdentifier.spec.js +18 -0
  71. package/lib/test/simpleIdentifier.spec.js.map +1 -0
  72. package/lib/test/useObservation.spec.js +162 -0
  73. package/lib/test/useObservation.spec.js.map +1 -0
  74. package/lib/test/useTree.spec.js +165 -0
  75. package/lib/test/useTree.spec.js.map +1 -0
  76. package/lib/tsdoc-metadata.json +11 -0
  77. package/lib/useObservation.d.ts +83 -0
  78. package/lib/useObservation.d.ts.map +1 -0
  79. package/lib/useObservation.js +266 -0
  80. package/lib/useObservation.js.map +1 -0
  81. package/lib/useTree.d.ts +80 -0
  82. package/lib/useTree.d.ts.map +1 -0
  83. package/lib/useTree.js +105 -0
  84. package/lib/useTree.js.map +1 -0
  85. package/package.json +150 -51
  86. package/react.test-files.tar +0 -0
  87. package/src/index.ts +42 -7
  88. package/src/propNode.ts +164 -0
  89. package/src/reactSharedTreeView.tsx +327 -0
  90. package/src/simpleIdentifier.ts +31 -0
  91. package/src/useObservation.ts +376 -0
  92. package/src/useTree.ts +147 -0
  93. package/tsconfig.cjs.json +7 -0
  94. package/tsconfig.json +12 -15
  95. package/tsdoc.json +4 -0
  96. package/.eslintrc.js +0 -11
  97. package/dist/createContextFluid.d.ts +0 -7
  98. package/dist/createContextFluid.d.ts.map +0 -1
  99. package/dist/createContextFluid.js +0 -46
  100. package/dist/createContextFluid.js.map +0 -1
  101. package/dist/helpers/generateFluidObjectSchema.d.ts +0 -16
  102. package/dist/helpers/generateFluidObjectSchema.d.ts.map +0 -1
  103. package/dist/helpers/generateFluidObjectSchema.js +0 -75
  104. package/dist/helpers/generateFluidObjectSchema.js.map +0 -1
  105. package/dist/helpers/getFluidFromView.d.ts +0 -15
  106. package/dist/helpers/getFluidFromView.d.ts.map +0 -1
  107. package/dist/helpers/getFluidFromView.js +0 -30
  108. package/dist/helpers/getFluidFromView.js.map +0 -1
  109. package/dist/helpers/getFluidState.d.ts +0 -15
  110. package/dist/helpers/getFluidState.d.ts.map +0 -1
  111. package/dist/helpers/getFluidState.js +0 -47
  112. package/dist/helpers/getFluidState.js.map +0 -1
  113. package/dist/helpers/getSchema.d.ts +0 -13
  114. package/dist/helpers/getSchema.d.ts.map +0 -1
  115. package/dist/helpers/getSchema.js +0 -15
  116. package/dist/helpers/getSchema.js.map +0 -1
  117. package/dist/helpers/getViewFromFluid.d.ts +0 -18
  118. package/dist/helpers/getViewFromFluid.d.ts.map +0 -1
  119. package/dist/helpers/getViewFromFluid.js +0 -47
  120. package/dist/helpers/getViewFromFluid.js.map +0 -1
  121. package/dist/helpers/index.d.ts +0 -16
  122. package/dist/helpers/index.d.ts.map +0 -1
  123. package/dist/helpers/index.js +0 -28
  124. package/dist/helpers/index.js.map +0 -1
  125. package/dist/helpers/initializeState.d.ts +0 -22
  126. package/dist/helpers/initializeState.d.ts.map +0 -1
  127. package/dist/helpers/initializeState.js +0 -77
  128. package/dist/helpers/initializeState.js.map +0 -1
  129. package/dist/helpers/internalInterface.d.ts +0 -15
  130. package/dist/helpers/internalInterface.d.ts.map +0 -1
  131. package/dist/helpers/internalInterface.js +0 -7
  132. package/dist/helpers/internalInterface.js.map +0 -1
  133. package/dist/helpers/rootCallbackListener.d.ts +0 -24
  134. package/dist/helpers/rootCallbackListener.d.ts.map +0 -1
  135. package/dist/helpers/rootCallbackListener.js +0 -55
  136. package/dist/helpers/rootCallbackListener.js.map +0 -1
  137. package/dist/helpers/setComponentSchema.d.ts +0 -14
  138. package/dist/helpers/setComponentSchema.d.ts.map +0 -1
  139. package/dist/helpers/setComponentSchema.js +0 -18
  140. package/dist/helpers/setComponentSchema.js.map +0 -1
  141. package/dist/helpers/setFluidState.d.ts +0 -20
  142. package/dist/helpers/setFluidState.d.ts.map +0 -1
  143. package/dist/helpers/setFluidState.js +0 -94
  144. package/dist/helpers/setFluidState.js.map +0 -1
  145. package/dist/helpers/syncState.d.ts +0 -25
  146. package/dist/helpers/syncState.d.ts.map +0 -1
  147. package/dist/helpers/syncState.js +0 -98
  148. package/dist/helpers/syncState.js.map +0 -1
  149. package/dist/helpers/updateStateAndFluidObjectMap.d.ts +0 -29
  150. package/dist/helpers/updateStateAndFluidObjectMap.d.ts.map +0 -1
  151. package/dist/helpers/updateStateAndFluidObjectMap.js +0 -30
  152. package/dist/helpers/updateStateAndFluidObjectMap.js.map +0 -1
  153. package/dist/helpers/utils.d.ts +0 -12
  154. package/dist/helpers/utils.d.ts.map +0 -1
  155. package/dist/helpers/utils.js +0 -74
  156. package/dist/helpers/utils.js.map +0 -1
  157. package/dist/interface.d.ts +0 -444
  158. package/dist/interface.d.ts.map +0 -1
  159. package/dist/interface.js +0 -18
  160. package/dist/interface.js.map +0 -1
  161. package/dist/reactView.d.ts +0 -32
  162. package/dist/reactView.d.ts.map +0 -1
  163. package/dist/reactView.js +0 -79
  164. package/dist/reactView.js.map +0 -1
  165. package/dist/syncedDataObject.d.ts +0 -80
  166. package/dist/syncedDataObject.d.ts.map +0 -1
  167. package/dist/syncedDataObject.js +0 -249
  168. package/dist/syncedDataObject.js.map +0 -1
  169. package/dist/syncedObjects/array/fluidSyncedArray.d.ts +0 -11
  170. package/dist/syncedObjects/array/fluidSyncedArray.d.ts.map +0 -1
  171. package/dist/syncedObjects/array/fluidSyncedArray.js +0 -78
  172. package/dist/syncedObjects/array/fluidSyncedArray.js.map +0 -1
  173. package/dist/syncedObjects/array/index.d.ts +0 -7
  174. package/dist/syncedObjects/array/index.d.ts.map +0 -1
  175. package/dist/syncedObjects/array/index.js +0 -19
  176. package/dist/syncedObjects/array/index.js.map +0 -1
  177. package/dist/syncedObjects/array/interface.d.ts +0 -33
  178. package/dist/syncedObjects/array/interface.d.ts.map +0 -1
  179. package/dist/syncedObjects/array/interface.js +0 -3
  180. package/dist/syncedObjects/array/interface.js.map +0 -1
  181. package/dist/syncedObjects/array/syncedArray.d.ts +0 -30
  182. package/dist/syncedObjects/array/syncedArray.d.ts.map +0 -1
  183. package/dist/syncedObjects/array/syncedArray.js +0 -42
  184. package/dist/syncedObjects/array/syncedArray.js.map +0 -1
  185. package/dist/syncedObjects/counter/fluidSyncedCounter.d.ts +0 -11
  186. package/dist/syncedObjects/counter/fluidSyncedCounter.d.ts.map +0 -1
  187. package/dist/syncedObjects/counter/fluidSyncedCounter.js +0 -79
  188. package/dist/syncedObjects/counter/fluidSyncedCounter.js.map +0 -1
  189. package/dist/syncedObjects/counter/index.d.ts +0 -7
  190. package/dist/syncedObjects/counter/index.d.ts.map +0 -1
  191. package/dist/syncedObjects/counter/index.js +0 -19
  192. package/dist/syncedObjects/counter/index.js.map +0 -1
  193. package/dist/syncedObjects/counter/interface.d.ts +0 -32
  194. package/dist/syncedObjects/counter/interface.d.ts.map +0 -1
  195. package/dist/syncedObjects/counter/interface.js +0 -3
  196. package/dist/syncedObjects/counter/interface.js.map +0 -1
  197. package/dist/syncedObjects/counter/syncedCounter.d.ts +0 -29
  198. package/dist/syncedObjects/counter/syncedCounter.d.ts.map +0 -1
  199. package/dist/syncedObjects/counter/syncedCounter.js +0 -36
  200. package/dist/syncedObjects/counter/syncedCounter.js.map +0 -1
  201. package/dist/syncedObjects/index.d.ts +0 -9
  202. package/dist/syncedObjects/index.d.ts.map +0 -1
  203. package/dist/syncedObjects/index.js +0 -21
  204. package/dist/syncedObjects/index.js.map +0 -1
  205. package/dist/syncedObjects/object/index.d.ts +0 -7
  206. package/dist/syncedObjects/object/index.d.ts.map +0 -1
  207. package/dist/syncedObjects/object/index.js +0 -19
  208. package/dist/syncedObjects/object/index.js.map +0 -1
  209. package/dist/syncedObjects/object/interface.d.ts +0 -13
  210. package/dist/syncedObjects/object/interface.d.ts.map +0 -1
  211. package/dist/syncedObjects/object/interface.js +0 -7
  212. package/dist/syncedObjects/object/interface.js.map +0 -1
  213. package/dist/syncedObjects/object/syncedObject.d.ts +0 -22
  214. package/dist/syncedObjects/object/syncedObject.d.ts.map +0 -1
  215. package/dist/syncedObjects/object/syncedObject.js +0 -46
  216. package/dist/syncedObjects/object/syncedObject.js.map +0 -1
  217. package/dist/syncedObjects/string/index.d.ts +0 -7
  218. package/dist/syncedObjects/string/index.d.ts.map +0 -1
  219. package/dist/syncedObjects/string/index.js +0 -19
  220. package/dist/syncedObjects/string/index.js.map +0 -1
  221. package/dist/syncedObjects/string/interface.d.ts +0 -16
  222. package/dist/syncedObjects/string/interface.d.ts.map +0 -1
  223. package/dist/syncedObjects/string/interface.js +0 -7
  224. package/dist/syncedObjects/string/interface.js.map +0 -1
  225. package/dist/syncedObjects/string/syncedString.d.ts +0 -25
  226. package/dist/syncedObjects/string/syncedString.d.ts.map +0 -1
  227. package/dist/syncedObjects/string/syncedString.js +0 -53
  228. package/dist/syncedObjects/string/syncedString.js.map +0 -1
  229. package/dist/useReducerFluid.d.ts +0 -7
  230. package/dist/useReducerFluid.d.ts.map +0 -1
  231. package/dist/useReducerFluid.js +0 -219
  232. package/dist/useReducerFluid.js.map +0 -1
  233. package/dist/useStateFluid.d.ts +0 -10
  234. package/dist/useStateFluid.d.ts.map +0 -1
  235. package/dist/useStateFluid.js +0 -67
  236. package/dist/useStateFluid.js.map +0 -1
  237. package/lib/createContextFluid.js +0 -23
  238. package/lib/createContextFluid.js.map +0 -1
  239. package/lib/helpers/generateFluidObjectSchema.js +0 -71
  240. package/lib/helpers/generateFluidObjectSchema.js.map +0 -1
  241. package/lib/helpers/getFluidFromView.js +0 -26
  242. package/lib/helpers/getFluidFromView.js.map +0 -1
  243. package/lib/helpers/getFluidState.js +0 -43
  244. package/lib/helpers/getFluidState.js.map +0 -1
  245. package/lib/helpers/getSchema.js +0 -11
  246. package/lib/helpers/getSchema.js.map +0 -1
  247. package/lib/helpers/getViewFromFluid.js +0 -43
  248. package/lib/helpers/getViewFromFluid.js.map +0 -1
  249. package/lib/helpers/index.js +0 -16
  250. package/lib/helpers/index.js.map +0 -1
  251. package/lib/helpers/initializeState.js +0 -73
  252. package/lib/helpers/initializeState.js.map +0 -1
  253. package/lib/helpers/internalInterface.js +0 -6
  254. package/lib/helpers/internalInterface.js.map +0 -1
  255. package/lib/helpers/rootCallbackListener.js +0 -51
  256. package/lib/helpers/rootCallbackListener.js.map +0 -1
  257. package/lib/helpers/setComponentSchema.js +0 -14
  258. package/lib/helpers/setComponentSchema.js.map +0 -1
  259. package/lib/helpers/setFluidState.js +0 -90
  260. package/lib/helpers/setFluidState.js.map +0 -1
  261. package/lib/helpers/syncState.js +0 -94
  262. package/lib/helpers/syncState.js.map +0 -1
  263. package/lib/helpers/updateStateAndFluidObjectMap.js +0 -26
  264. package/lib/helpers/updateStateAndFluidObjectMap.js.map +0 -1
  265. package/lib/helpers/utils.js +0 -67
  266. package/lib/helpers/utils.js.map +0 -1
  267. package/lib/interface.js +0 -8
  268. package/lib/interface.js.map +0 -1
  269. package/lib/reactView.js +0 -56
  270. package/lib/reactView.js.map +0 -1
  271. package/lib/syncedDataObject.js +0 -245
  272. package/lib/syncedDataObject.js.map +0 -1
  273. package/lib/syncedObjects/array/fluidSyncedArray.js +0 -72
  274. package/lib/syncedObjects/array/fluidSyncedArray.js.map +0 -1
  275. package/lib/syncedObjects/array/index.js +0 -7
  276. package/lib/syncedObjects/array/index.js.map +0 -1
  277. package/lib/syncedObjects/array/interface.js +0 -2
  278. package/lib/syncedObjects/array/interface.js.map +0 -1
  279. package/lib/syncedObjects/array/syncedArray.js +0 -37
  280. package/lib/syncedObjects/array/syncedArray.js.map +0 -1
  281. package/lib/syncedObjects/counter/fluidSyncedCounter.js +0 -73
  282. package/lib/syncedObjects/counter/fluidSyncedCounter.js.map +0 -1
  283. package/lib/syncedObjects/counter/index.js +0 -7
  284. package/lib/syncedObjects/counter/index.js.map +0 -1
  285. package/lib/syncedObjects/counter/interface.js +0 -2
  286. package/lib/syncedObjects/counter/interface.js.map +0 -1
  287. package/lib/syncedObjects/counter/syncedCounter.js +0 -31
  288. package/lib/syncedObjects/counter/syncedCounter.js.map +0 -1
  289. package/lib/syncedObjects/index.js +0 -9
  290. package/lib/syncedObjects/index.js.map +0 -1
  291. package/lib/syncedObjects/object/index.js +0 -7
  292. package/lib/syncedObjects/object/index.js.map +0 -1
  293. package/lib/syncedObjects/object/interface.js +0 -6
  294. package/lib/syncedObjects/object/interface.js.map +0 -1
  295. package/lib/syncedObjects/object/syncedObject.js +0 -41
  296. package/lib/syncedObjects/object/syncedObject.js.map +0 -1
  297. package/lib/syncedObjects/string/index.js +0 -7
  298. package/lib/syncedObjects/string/index.js.map +0 -1
  299. package/lib/syncedObjects/string/interface.js +0 -6
  300. package/lib/syncedObjects/string/interface.js.map +0 -1
  301. package/lib/syncedObjects/string/syncedString.js +0 -48
  302. package/lib/syncedObjects/string/syncedString.js.map +0 -1
  303. package/lib/useReducerFluid.js +0 -196
  304. package/lib/useReducerFluid.js.map +0 -1
  305. package/lib/useStateFluid.js +0 -44
  306. package/lib/useStateFluid.js.map +0 -1
  307. package/src/createContextFluid.tsx +0 -33
  308. package/src/helpers/generateFluidObjectSchema.ts +0 -95
  309. package/src/helpers/getFluidFromView.ts +0 -38
  310. package/src/helpers/getFluidState.ts +0 -67
  311. package/src/helpers/getSchema.ts +0 -18
  312. package/src/helpers/getViewFromFluid.ts +0 -68
  313. package/src/helpers/index.tsx +0 -16
  314. package/src/helpers/initializeState.ts +0 -162
  315. package/src/helpers/internalInterface.ts +0 -16
  316. package/src/helpers/rootCallbackListener.ts +0 -104
  317. package/src/helpers/setComponentSchema.ts +0 -21
  318. package/src/helpers/setFluidState.ts +0 -116
  319. package/src/helpers/syncState.ts +0 -159
  320. package/src/helpers/updateStateAndFluidObjectMap.ts +0 -85
  321. package/src/helpers/utils.tsx +0 -109
  322. package/src/interface.ts +0 -617
  323. package/src/reactView.tsx +0 -108
  324. package/src/syncedDataObject.ts +0 -337
  325. package/src/syncedObjects/array/fluidSyncedArray.ts +0 -126
  326. package/src/syncedObjects/array/index.ts +0 -7
  327. package/src/syncedObjects/array/interface.ts +0 -45
  328. package/src/syncedObjects/array/syncedArray.ts +0 -65
  329. package/src/syncedObjects/counter/fluidSyncedCounter.ts +0 -122
  330. package/src/syncedObjects/counter/index.ts +0 -7
  331. package/src/syncedObjects/counter/interface.ts +0 -44
  332. package/src/syncedObjects/counter/syncedCounter.ts +0 -64
  333. package/src/syncedObjects/index.ts +0 -9
  334. package/src/syncedObjects/object/index.ts +0 -7
  335. package/src/syncedObjects/object/interface.ts +0 -14
  336. package/src/syncedObjects/object/syncedObject.ts +0 -55
  337. package/src/syncedObjects/string/index.ts +0 -7
  338. package/src/syncedObjects/string/interface.ts +0 -17
  339. package/src/syncedObjects/string/syncedString.ts +0 -61
  340. package/src/useReducerFluid.tsx +0 -436
  341. package/src/useStateFluid.tsx +0 -84
  342. package/tsconfig.esnext.json +0 -7
package/lib/useTree.js ADDED
@@ -0,0 +1,105 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { Tree } from "@fluidframework/tree";
6
+ import { TreeAlpha } from "@fluidframework/tree/internal";
7
+ import * as React from "react";
8
+ import { unwrapPropTreeNode, unwrapPropTreeRecord, } from "./propNode.js";
9
+ import { useObservation } from "./useObservation.js";
10
+ /**
11
+ * Custom hook which invalidates a React Component when there is a change in the subtree defined by `subtreeRoot`.
12
+ * This includes changes to the tree's content, but not changes to its parentage.
13
+ * See {@link @fluidframework/tree#TreeChangeEvents.treeChanged} for details.
14
+ * @remarks
15
+ * Consider using {@link useTreeObservations} instead which tracks what was observed and only invalidates if it changes.
16
+ * @alpha
17
+ */
18
+ export function useTree(subtreeRoot) {
19
+ // Use a React effect hook to invalidate this component when the subtreeRoot changes.
20
+ // We do this by incrementing a counter, which is passed as a dependency to the effect hook.
21
+ const [invalidations, setInvalidations] = React.useState(0);
22
+ // React effect hook that increments the 'invalidation' counter whenever subtreeRoot or any of its children change.
23
+ React.useEffect(() => {
24
+ // Returns the cleanup function to be invoked when the component unmounts.
25
+ return Tree.on(subtreeRoot, "treeChanged", () => {
26
+ setInvalidations((i) => i + 1);
27
+ });
28
+ }, [invalidations, subtreeRoot]);
29
+ return invalidations;
30
+ }
31
+ /**
32
+ * Higher order component which wraps a component to use {@link useTreeObservations}.
33
+ *
34
+ * @remarks
35
+ * When passing TreeNodes in props, care must be taken to not observe their content outside of a context which does observation tracking (or manual invalidation).
36
+ * This wraps a component in such tracking.
37
+ *
38
+ * It is recommended that sub-components which take in TreeNodes, if not defined using this higher order components, take the nodes in as {@link PropTreeNode}s.
39
+ * Components defined using this higher order component can take in either raw TreeNodes or {@link PropTreeNode}s: the latter will be automatically unwrapped.
40
+ * @privateRemarks
41
+ * `React.FC` does not seem to be covariant over its input type, so to make use of this more ergonomic,
42
+ * the return type intersects the various ways this could be used (with or without PropTreeNode wrapping).
43
+ * @alpha
44
+ */
45
+ export function withTreeObservations(component, options) {
46
+ return (props) => useTreeObservations(() => component(props), options);
47
+ }
48
+ /**
49
+ * {@link withTreeObservations} wrapped with React.memo.
50
+ * @remarks
51
+ * There is no special logic here, just a convenience wrapper.
52
+ * @alpha
53
+ */
54
+ export function withMemoizedTreeObservations(component, options) {
55
+ return React.memo(withTreeObservations(component, options), options?.propsAreEqual);
56
+ }
57
+ /**
58
+ * Custom hook which invalidates a React Component when there is a change in tree content observed during `trackDuring`.
59
+ *
60
+ * @param trackDuring - Called synchronously, and will have its tree observations tracked.
61
+ *
62
+ * @remarks
63
+ * This includes changes to the tree's content.
64
+ * Currently this will throw if observing a node's parentage to be undefined,
65
+ * and node status changes will not cause invalidation.
66
+ *
67
+ * For additional type safety to help avoid observing TreeNode content outside of this hook, see {@link PropTreeNode}.
68
+ * @alpha
69
+ */
70
+ export function useTreeObservations(trackDuring, options) {
71
+ return useObservation((invalidate) => TreeAlpha.trackObservationsOnce(invalidate, trackDuring), options);
72
+ }
73
+ /**
74
+ * Custom hook for using a prop tree node.
75
+ *
76
+ * @param propNode - Input, automatically unwrapped TreeNode from a {@link PropTreeNode} if needed.
77
+ * @param trackDuring - Callback which reads from the node and returns a result.
78
+ * If the result is a TreeNode or {@link NodeRecord} it will be wrapped as a {@link PropTreeNode} or {@link PropTreeNodeRecord}, see {@link WrapNodes}.
79
+ *
80
+ * It is recommended that when returning data containing TreeNodes,
81
+ * use a format supported by {@link WrapNodes} or wrap the nodes manually using {@link toPropTreeNode}.
82
+ * This improves the type safety, reducing the risk of invalidation bugs due to untracked access of tree content contained in the return value.
83
+ *
84
+ * Note that is is fine to observe any node inside the callback, not just the provided node: all accesses will be tracked.
85
+ * The input node is just provided as a way to automatically unwrap the {@link PropTreeNode}
86
+ *
87
+ * @remarks
88
+ * Reads content using {@link useTreeObservations} to track dependencies.
89
+ * @alpha
90
+ */
91
+ export function usePropTreeNode(propNode, trackDuring) {
92
+ const node = unwrapPropTreeNode(propNode);
93
+ const result = useTreeObservations(() => trackDuring(node));
94
+ return result;
95
+ }
96
+ /**
97
+ * {@link usePropTreeNode} but takes in a {@link PropTreeNodeRecord}.
98
+ * @alpha
99
+ */
100
+ export function usePropTreeRecord(props, f) {
101
+ const record = unwrapPropTreeRecord(props);
102
+ const result = useTreeObservations(() => f(record));
103
+ return result;
104
+ }
105
+ //# sourceMappingURL=useTree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTree.js","sourceRoot":"","sources":["../src/useTree.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EACN,kBAAkB,EAClB,oBAAoB,GAKpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,cAAc,EAA2B,MAAM,qBAAqB,CAAC;AAE9E;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,WAAqB;IAC5C,qFAAqF;IACrF,4FAA4F;IAC5F,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE5D,mHAAmH;IACnH,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,0EAA0E;QAC1E,OAAO,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,aAAa,EAAE,GAAG,EAAE;YAC/C,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;IAEjC,OAAO,aAAa,CAAC;AACtB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CACnC,SAAwB,EACxB,OAA4B;IAE5B,OAAO,CAAC,KAA2B,EAAmB,EAAE,CACvD,mBAAmB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAY,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAC3C,SAAwB,EACxB,OAEC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;AACrF,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAClC,WAA0B,EAC1B,OAA4B;IAE5B,OAAO,cAAc,CACpB,CAAC,UAAU,EAAE,EAAE,CAAC,SAAS,CAAC,qBAAqB,CAAC,UAAU,EAAE,WAAW,CAAC,EACxE,OAAO,CACP,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,eAAe,CAC9B,QAA8B,EAC9B,WAAiC;IAEjC,MAAM,IAAI,GAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG,mBAAmB,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IAE5D,OAAO,MAA4B,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAChC,KAAQ,EACR,CAAiD;IAEjD,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAG,mBAAmB,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAEpD,OAAO,MAA4B,CAAC;AACrC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { TreeLeafValue, TreeNode } from \"@fluidframework/tree\";\nimport { Tree } from \"@fluidframework/tree\";\nimport { TreeAlpha } from \"@fluidframework/tree/internal\";\nimport * as React from \"react\";\n\nimport {\n\tunwrapPropTreeNode,\n\tunwrapPropTreeRecord,\n\ttype PropTreeNodeRecord,\n\ttype PropTreeValue,\n\ttype UnwrapPropTreeNodeRecord,\n\ttype WrapNodes,\n} from \"./propNode.js\";\nimport { useObservation, type ObservationOptions } from \"./useObservation.js\";\n\n/**\n * Custom hook which invalidates a React Component when there is a change in the subtree defined by `subtreeRoot`.\n * This includes changes to the tree's content, but not changes to its parentage.\n * See {@link @fluidframework/tree#TreeChangeEvents.treeChanged} for details.\n * @remarks\n * Consider using {@link useTreeObservations} instead which tracks what was observed and only invalidates if it changes.\n * @alpha\n */\nexport function useTree(subtreeRoot: TreeNode): number {\n\t// Use a React effect hook to invalidate this component when the subtreeRoot changes.\n\t// We do this by incrementing a counter, which is passed as a dependency to the effect hook.\n\tconst [invalidations, setInvalidations] = React.useState(0);\n\n\t// React effect hook that increments the 'invalidation' counter whenever subtreeRoot or any of its children change.\n\tReact.useEffect(() => {\n\t\t// Returns the cleanup function to be invoked when the component unmounts.\n\t\treturn Tree.on(subtreeRoot, \"treeChanged\", () => {\n\t\t\tsetInvalidations((i) => i + 1);\n\t\t});\n\t}, [invalidations, subtreeRoot]);\n\n\treturn invalidations;\n}\n\n/**\n * Higher order component which wraps a component to use {@link useTreeObservations}.\n *\n * @remarks\n * When passing TreeNodes in props, care must be taken to not observe their content outside of a context which does observation tracking (or manual invalidation).\n * This wraps a component in such tracking.\n *\n * It is recommended that sub-components which take in TreeNodes, if not defined using this higher order components, take the nodes in as {@link PropTreeNode}s.\n * Components defined using this higher order component can take in either raw TreeNodes or {@link PropTreeNode}s: the latter will be automatically unwrapped.\n * @privateRemarks\n * `React.FC` does not seem to be covariant over its input type, so to make use of this more ergonomic,\n * the return type intersects the various ways this could be used (with or without PropTreeNode wrapping).\n * @alpha\n */\nexport function withTreeObservations<TIn>(\n\tcomponent: React.FC<TIn>,\n\toptions?: ObservationOptions,\n): React.FC<TIn> & React.FC<WrapNodes<TIn>> & React.FC<TIn | WrapNodes<TIn>> {\n\treturn (props: TIn | WrapNodes<TIn>): React.ReactNode =>\n\t\tuseTreeObservations(() => component(props as TIn), options);\n}\n\n/**\n * {@link withTreeObservations} wrapped with React.memo.\n * @remarks\n * There is no special logic here, just a convenience wrapper.\n * @alpha\n */\nexport function withMemoizedTreeObservations<TIn>(\n\tcomponent: React.FC<TIn>,\n\toptions?: ObservationOptions & {\n\t\treadonly propsAreEqual?: Parameters<typeof React.memo>[1];\n\t},\n): React.MemoExoticComponent<ReturnType<typeof withTreeObservations<TIn>>> {\n\treturn React.memo(withTreeObservations(component, options), options?.propsAreEqual);\n}\n\n/**\n * Custom hook which invalidates a React Component when there is a change in tree content observed during `trackDuring`.\n *\n * @param trackDuring - Called synchronously, and will have its tree observations tracked.\n *\n * @remarks\n * This includes changes to the tree's content.\n * Currently this will throw if observing a node's parentage to be undefined,\n * and node status changes will not cause invalidation.\n *\n * For additional type safety to help avoid observing TreeNode content outside of this hook, see {@link PropTreeNode}.\n * @alpha\n */\nexport function useTreeObservations<TResult>(\n\ttrackDuring: () => TResult,\n\toptions?: ObservationOptions,\n): TResult {\n\treturn useObservation(\n\t\t(invalidate) => TreeAlpha.trackObservationsOnce(invalidate, trackDuring),\n\t\toptions,\n\t);\n}\n\n/**\n * Custom hook for using a prop tree node.\n *\n * @param propNode - Input, automatically unwrapped TreeNode from a {@link PropTreeNode} if needed.\n * @param trackDuring - Callback which reads from the node and returns a result.\n * If the result is a TreeNode or {@link NodeRecord} it will be wrapped as a {@link PropTreeNode} or {@link PropTreeNodeRecord}, see {@link WrapNodes}.\n *\n * It is recommended that when returning data containing TreeNodes,\n * use a format supported by {@link WrapNodes} or wrap the nodes manually using {@link toPropTreeNode}.\n * This improves the type safety, reducing the risk of invalidation bugs due to untracked access of tree content contained in the return value.\n *\n * Note that is is fine to observe any node inside the callback, not just the provided node: all accesses will be tracked.\n * The input node is just provided as a way to automatically unwrap the {@link PropTreeNode}\n *\n * @remarks\n * Reads content using {@link useTreeObservations} to track dependencies.\n * @alpha\n */\nexport function usePropTreeNode<T extends TreeNode | TreeLeafValue, TResult>(\n\tpropNode: PropTreeValue<T> | T,\n\ttrackDuring: (node: T) => TResult,\n): WrapNodes<TResult> {\n\tconst node: T = unwrapPropTreeNode(propNode);\n\n\tconst result = useTreeObservations(() => trackDuring(node));\n\n\treturn result as WrapNodes<TResult>;\n}\n\n/**\n * {@link usePropTreeNode} but takes in a {@link PropTreeNodeRecord}.\n * @alpha\n */\nexport function usePropTreeRecord<const T extends PropTreeNodeRecord, TResult>(\n\tprops: T,\n\tf: (node: UnwrapPropTreeNodeRecord<T>) => TResult,\n): WrapNodes<TResult> {\n\tconst record = unwrapPropTreeRecord(props);\n\n\tconst result = useTreeObservations(() => f(record));\n\n\treturn result as WrapNodes<TResult>;\n}\n"]}
package/package.json CHANGED
@@ -1,63 +1,162 @@
1
1
  {
2
2
  "name": "@fluidframework/react",
3
- "version": "0.41.3",
4
- "description": "Base views and hooks for building Fluid React views",
3
+ "version": "2.62.0",
4
+ "description": "Utilities for integrating content powered by the Fluid Framework into React applications",
5
5
  "homepage": "https://fluidframework.com",
6
- "repository": "https://github.com/microsoft/FluidFramework",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/microsoft/FluidFramework.git",
9
+ "directory": "packages/framework/react"
10
+ },
7
11
  "license": "MIT",
8
12
  "author": "Microsoft and contributors",
9
13
  "sideEffects": false,
14
+ "type": "module",
15
+ "exports": {
16
+ ".": {
17
+ "import": {
18
+ "types": "./lib/public.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "require": {
22
+ "types": "./dist/public.d.ts",
23
+ "default": "./dist/index.js"
24
+ }
25
+ },
26
+ "./alpha": {
27
+ "import": {
28
+ "types": "./lib/alpha.d.ts",
29
+ "default": "./lib/index.js"
30
+ },
31
+ "require": {
32
+ "types": "./dist/alpha.d.ts",
33
+ "default": "./dist/index.js"
34
+ }
35
+ },
36
+ "./beta": {
37
+ "import": {
38
+ "types": "./lib/beta.d.ts",
39
+ "default": "./lib/index.js"
40
+ },
41
+ "require": {
42
+ "types": "./dist/beta.d.ts",
43
+ "default": "./dist/index.js"
44
+ }
45
+ },
46
+ "./internal": {
47
+ "import": {
48
+ "types": "./lib/index.d.ts",
49
+ "default": "./lib/index.js"
50
+ },
51
+ "require": {
52
+ "types": "./dist/index.d.ts",
53
+ "default": "./dist/index.js"
54
+ }
55
+ }
56
+ },
10
57
  "main": "dist/index.js",
11
- "module": "lib/index.js",
12
- "types": "dist/index.d.ts",
13
- "scripts": {
14
- "build": "concurrently npm:build:compile npm:lint && npm run build:docs",
15
- "build:compile": "concurrently npm:tsc npm:build:esnext",
16
- "build:docs": "api-extractor run --local && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
17
- "build:esnext": "tsc --project ./tsconfig.esnext.json",
18
- "build:full": "npm run build",
19
- "build:full:compile": "npm run build:compile",
20
- "ci:build:docs": "api-extractor run && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
21
- "clean": "rimraf dist lib *.tsbuildinfo *.build.log",
22
- "eslint": "eslint --format stylish src",
23
- "eslint:fix": "eslint --format stylish src --fix",
24
- "lint": "npm run eslint",
25
- "lint:fix": "npm run eslint:fix",
26
- "tsc": "tsc",
27
- "tsfmt": "tsfmt --verify",
28
- "tsfmt:fix": "tsfmt --replace"
58
+ "types": "./dist/public.d.ts",
59
+ "c8": {
60
+ "all": true,
61
+ "cache-dir": "nyc/.cache",
62
+ "exclude": [
63
+ "src/test/**/*.*ts",
64
+ "dist/test/**/*.*js",
65
+ "lib/test/**/*.*js"
66
+ ],
67
+ "exclude-after-remap": false,
68
+ "include": [
69
+ "src/**/*.*ts",
70
+ "dist/**/*.*js",
71
+ "lib/**/*.*js"
72
+ ],
73
+ "report-dir": "nyc/report",
74
+ "reporter": [
75
+ "cobertura",
76
+ "html",
77
+ "text"
78
+ ],
79
+ "temp-directory": "nyc/.nyc_output"
29
80
  },
30
81
  "dependencies": {
31
- "@fluidframework/aqueduct": "^0.41.3",
32
- "@fluidframework/common-definitions": "^0.20.1",
33
- "@fluidframework/core-interfaces": "^0.39.0",
34
- "@fluidframework/counter": "^0.41.3",
35
- "@fluidframework/datastore-definitions": "^0.41.3",
36
- "@fluidframework/map": "^0.41.3",
37
- "@fluidframework/sequence": "^0.41.3",
38
- "@fluidframework/shared-object-base": "^0.41.3",
39
- "@fluidframework/view-interfaces": "^0.41.3",
40
- "react": "^16.10.2"
82
+ "@fluidframework/aqueduct": "~2.62.0",
83
+ "@fluidframework/core-interfaces": "~2.62.0",
84
+ "@fluidframework/datastore-definitions": "~2.62.0",
85
+ "@fluidframework/fluid-static": "~2.62.0",
86
+ "@fluidframework/runtime-definitions": "~2.62.0",
87
+ "@fluidframework/shared-object-base": "~2.62.0",
88
+ "@fluidframework/tree": "~2.62.0",
89
+ "react": "^18.3.1"
41
90
  },
42
91
  "devDependencies": {
43
- "@fluidframework/build-common": "^0.22.0",
44
- "@fluidframework/eslint-config-fluid": "^0.23.0",
45
- "@microsoft/api-extractor": "^7.13.1",
46
- "@types/node": "^12.19.0",
47
- "@types/react": "^16.9.15",
48
- "@typescript-eslint/eslint-plugin": "~4.14.0",
49
- "@typescript-eslint/parser": "~4.14.0",
50
- "concurrently": "^5.2.0",
51
- "copyfiles": "^2.1.0",
52
- "eslint": "~7.18.0",
53
- "eslint-plugin-eslint-comments": "~3.2.0",
54
- "eslint-plugin-import": "~2.22.1",
55
- "eslint-plugin-no-null": "~1.0.2",
56
- "eslint-plugin-prefer-arrow": "~1.2.2",
57
- "eslint-plugin-react": "~7.22.0",
58
- "eslint-plugin-unicorn": "~26.0.1",
59
- "rimraf": "^2.6.2",
60
- "typescript": "~4.1.3",
61
- "typescript-formatter": "7.1.0"
92
+ "@arethetypeswrong/cli": "^0.17.1",
93
+ "@biomejs/biome": "~1.9.3",
94
+ "@fluid-internal/mocha-test-setup": "~2.62.0",
95
+ "@fluid-tools/build-cli": "^0.58.3",
96
+ "@fluidframework/build-common": "^2.0.3",
97
+ "@fluidframework/build-tools": "^0.58.3",
98
+ "@fluidframework/eslint-config-fluid": "^6.0.0",
99
+ "@fluidframework/tinylicious-client": "~2.62.0",
100
+ "@microsoft/api-extractor": "7.52.11",
101
+ "@testing-library/react": "^16.3.0",
102
+ "@types/mocha": "^10.0.10",
103
+ "@types/node": "^18.19.0",
104
+ "@types/react": "^18.3.11",
105
+ "c8": "^10.1.3",
106
+ "concurrently": "^8.2.1",
107
+ "copyfiles": "^2.4.1",
108
+ "cross-env": "^7.0.3",
109
+ "eslint": "~8.55.0",
110
+ "eslint-config-prettier": "~9.0.0",
111
+ "global-jsdom": "^26.0.0",
112
+ "mocha": "^10.8.2",
113
+ "mocha-multi-reporters": "^1.5.1",
114
+ "rimraf": "^4.4.0",
115
+ "typescript": "~5.4.5"
116
+ },
117
+ "typeValidation": {
118
+ "disabled": true,
119
+ "broken": {},
120
+ "entrypoint": "internal"
121
+ },
122
+ "scripts": {
123
+ "api": "fluid-build . --task api",
124
+ "api-extractor:commonjs": "flub generate entrypoints --outDir ./dist",
125
+ "api-extractor:esnext": "flub generate entrypoints --outDir ./lib",
126
+ "build": "fluid-build . --task build",
127
+ "build:commonjs": "fluid-build . --task commonjs",
128
+ "build:compile": "fluid-build . --task compile",
129
+ "build:docs": "api-extractor run --local",
130
+ "build:esnext": "tsc --project ./tsconfig.json && copyfiles -f ../../../common/build/build-common/src/esm/package.json ./lib",
131
+ "build:test": "npm run build:test:esm && npm run build:test:cjs",
132
+ "build:test:cjs": "fluid-tsc commonjs --project ./src/test/tsconfig.cjs.json",
133
+ "build:test:esm": "tsc --project ./src/test/tsconfig.json",
134
+ "check:are-the-types-wrong": "attw --pack . --entrypoints .",
135
+ "check:biome": "biome check .",
136
+ "check:exports": "concurrently \"npm:check:exports:*\"",
137
+ "check:exports:bundle-release-tags": "api-extractor run --config api-extractor/api-extractor-lint-bundle.json",
138
+ "check:exports:cjs:alpha": "api-extractor run --config api-extractor/api-extractor-lint-alpha.cjs.json",
139
+ "check:exports:cjs:beta": "api-extractor run --config api-extractor/api-extractor-lint-beta.cjs.json",
140
+ "check:exports:cjs:public": "api-extractor run --config api-extractor/api-extractor-lint-public.cjs.json",
141
+ "check:exports:esm:alpha": "api-extractor run --config api-extractor/api-extractor-lint-alpha.esm.json",
142
+ "check:exports:esm:beta": "api-extractor run --config api-extractor/api-extractor-lint-beta.esm.json",
143
+ "check:exports:esm:public": "api-extractor run --config api-extractor/api-extractor-lint-public.esm.json",
144
+ "check:format": "npm run check:biome",
145
+ "ci:build:docs": "api-extractor run",
146
+ "clean": "rimraf --glob dist lib {alpha,beta,internal,legacy}.d.ts \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
147
+ "eslint": "eslint --format stylish src",
148
+ "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
149
+ "format": "npm run format:biome",
150
+ "format:biome": "biome check . --write",
151
+ "lint": "fluid-build . --task lint",
152
+ "lint:fix": "fluid-build . --task eslint:fix --task format",
153
+ "pack:tests": "tar -cf ./react.test-files.tar ./src/test ./dist/test ./lib/test",
154
+ "test": "npm run test:mocha",
155
+ "test:coverage": "c8 npm test",
156
+ "test:mocha": "npm run test:mocha:esm && echo skipping cjs to avoid overhead - npm run test:mocha:cjs",
157
+ "test:mocha:cjs": "cross-env FLUID_TEST_MODULE_SYSTEM=CJS mocha",
158
+ "test:mocha:esm": "mocha",
159
+ "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
160
+ "tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json && copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist"
62
161
  }
63
- }
162
+ }
Binary file
package/src/index.ts CHANGED
@@ -3,10 +3,45 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- export * from "./reactView";
7
- export * from "./useStateFluid";
8
- export * from "./useReducerFluid";
9
- export * from "./createContextFluid";
10
- export * from "./interface";
11
- export * from "./syncedDataObject";
12
- export * from "./syncedObjects";
6
+ /**
7
+ * Utilities for using SharedTree with React.
8
+ * @packageDocumentation
9
+ */
10
+
11
+ export type {
12
+ IReactTreeDataObject,
13
+ TreeViewProps,
14
+ SchemaIncompatibleProps,
15
+ } from "./reactSharedTreeView.js";
16
+ export {
17
+ treeDataObject,
18
+ treeDataObjectInternal,
19
+ TreeViewComponent,
20
+ } from "./reactSharedTreeView.js";
21
+ export type { ObservationOptions } from "./useObservation.js";
22
+ export type {
23
+ NodeRecord,
24
+ PropTreeNode,
25
+ PropTreeNodeRecord,
26
+ PropTreeValue,
27
+ UnwrapPropTreeNode,
28
+ UnwrapPropTreeNodeRecord,
29
+ WrapPropTreeNodeRecord,
30
+ WrapNodes,
31
+ IsMappableObjectType,
32
+ } from "./propNode.js";
33
+ export {
34
+ toPropTreeNode,
35
+ toPropTreeRecord,
36
+ unwrapPropTreeNode,
37
+ unwrapPropTreeRecord,
38
+ } from "./propNode.js";
39
+ export {
40
+ useTree,
41
+ usePropTreeNode,
42
+ usePropTreeRecord,
43
+ useTreeObservations,
44
+ withTreeObservations,
45
+ withMemoizedTreeObservations,
46
+ } from "./useTree.js";
47
+ export { objectIdNumber } from "./simpleIdentifier.js";
@@ -0,0 +1,164 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import type { ErasedType } from "@fluidframework/core-interfaces";
7
+ import type { TreeNode, TreeLeafValue } from "@fluidframework/tree";
8
+
9
+ /**
10
+ * A type erased TreeNode for use in react props.
11
+ * @remarks
12
+ * Read content from the node using {@link usePropTreeNode} or {@link usePropTreeRecord}.
13
+ *
14
+ * In events where tracking dependencies is not required, the node can be unwrapped using {@link unwrapPropTreeNode}.
15
+ *
16
+ * To convert a TreeNode to this type use {@link toPropTreeNode} or {@link toPropTreeRecord}.
17
+ * @alpha
18
+ */
19
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
20
+ export interface PropTreeNode<T extends TreeNode> extends ErasedType<[T, "PropTreeNode"]> {}
21
+
22
+ /**
23
+ * Type TreeNodes in T as {@link PropTreeNode}s.
24
+ * @remarks
25
+ * This only handles a few cases (TreeNode, structurally typed objects fields and arrays) and leaves other types as is.
26
+ * Users which provide other types (e.g. maps) which contain TreeNodes will need to handle wrapping those themselves if the wrapping is desired.
27
+ *
28
+ * Users of this should not rely on a given use of TreeNode not being wrapped:
29
+ * future changes to this API may add more cases which are wrapped, and this will be considered a non-breaking change.
30
+ * @privateRemarks
31
+ * Covering all cases is impossible, and trying to cover more with recursive mapped types can break some of the types by losing methods, private members, etc.
32
+ * To mitigate this IsMappableObjectType is used for objects, and only mappable types, where the mapping actually impacted the type are modified.
33
+ *
34
+ * This is intended to cover the common cases, and users can handle other cases manually.
35
+ * See the tests for this for more details.
36
+ * @alpha
37
+ */
38
+ export type WrapNodes<T> = T extends TreeNode
39
+ ? PropTreeNode<T>
40
+ : T extends readonly (infer U)[]
41
+ ? readonly WrapNodes<U>[]
42
+ : // `T extends (infer U)` distributes over unions, allowing WrapNodes<A|B> to be WrapNodes<A> | WrapNodes<B>.
43
+ T extends infer U
44
+ ? IsMappableObjectType<
45
+ U,
46
+ {
47
+ [P in keyof U]: WrapNodes<U[P]>;
48
+ } extends U
49
+ ? // Returning U in this case (when assignable to the mapped type) avoids flatting named interfaces when they are unchanged.
50
+ U
51
+ : {
52
+ [P in keyof U]: WrapNodes<U[P]>;
53
+ },
54
+ T
55
+ >
56
+ : T;
57
+
58
+ /**
59
+ * Detect if a type is a simple structural object.
60
+ * @remarks
61
+ * This returns the true case if the type is entirely defined by its set of public properties.
62
+ * More concretely, this indicates if creating a mapped type based on `T`
63
+ * will be lossy due to details mapped types cannot access.
64
+ *
65
+ * This is shallow, and distributes over unions.
66
+ *
67
+ * This also returns the true case for primitive types since mapping over them leaves them unchanged if doing so in a generic context:
68
+ * Mapping over a primitive does not leave them unchanged if done directly (not to a generic type parameter), but this can not detect that behavior.
69
+ * This is fine as the use for this is to detect when making a mapped type from a generic type parameter would be lossy.
70
+ * @system @alpha
71
+ */
72
+ export type IsMappableObjectType<
73
+ T,
74
+ True = true,
75
+ False = false,
76
+ Mapped = {
77
+ [P in keyof T]: T[P];
78
+ },
79
+ > = [Mapped] extends [T] ? ([T] extends [Mapped] ? True : False) : False;
80
+
81
+ /**
82
+ * Casts a node from a {@link PropTreeNode} back to a TreeNode.
83
+ * @remarks
84
+ * This should only be done in scenarios where tracking observations is not required (such as event handlers),
85
+ * or when taking care to handle invalidation manually.
86
+ * @alpha
87
+ */
88
+ export function unwrapPropTreeNode<T extends TreeNode | TreeLeafValue>(
89
+ propNode: PropTreeValue<T> | T,
90
+ ): T {
91
+ return propNode as T;
92
+ }
93
+
94
+ /**
95
+ * {@link unwrapPropTreeNode} but for a {@link PropTreeNodeRecord}.
96
+ * @alpha
97
+ */
98
+ export function unwrapPropTreeRecord<T extends PropTreeNodeRecord>(
99
+ props: T,
100
+ ): UnwrapPropTreeNodeRecord<T> {
101
+ return props as UnwrapPropTreeNodeRecord<T>;
102
+ }
103
+
104
+ /**
105
+ * {@inheritdoc unwrapPropTreeNode}
106
+ * @alpha
107
+ */
108
+ export type UnwrapPropTreeNode<T extends TreeLeafValue | PropTreeNode<TreeNode> | undefined> =
109
+ T extends PropTreeNode<infer Node> ? Node : T;
110
+
111
+ /**
112
+ * Record that can contain TreeNodes.
113
+ * @alpha
114
+ */
115
+ export type NodeRecord = Record<string, TreeNode | TreeLeafValue>;
116
+
117
+ /**
118
+ * Type erase `TreeNode`s from a {@link NodeRecord} as a {@link PropTreeNode}.
119
+ * @alpha
120
+ */
121
+ export type WrapPropTreeNodeRecord<T extends NodeRecord> = {
122
+ readonly [P in keyof T]: PropTreeValue<T[P]>;
123
+ };
124
+
125
+ /**
126
+ * Type erase `TreeNode`s from a {@link NodeRecord} as a {@link PropTreeNode}.
127
+ * @alpha
128
+ */
129
+ export type UnwrapPropTreeNodeRecord<T extends PropTreeNodeRecord> = {
130
+ readonly [P in keyof T]: UnwrapPropTreeNode<T[P]>;
131
+ };
132
+
133
+ /**
134
+ * Type erase `TreeNode`s from a {@link NodeRecord} as a {@link PropTreeNode}.
135
+ * @alpha
136
+ */
137
+ export type PropTreeNodeRecord = Record<
138
+ string,
139
+ TreeLeafValue | PropTreeNode<TreeNode> | undefined
140
+ >;
141
+
142
+ /**
143
+ * Type erase a `TreeNode` from a `TreeNode | TreeLeafValue` as a {@link PropTreeNode}.
144
+ * @alpha
145
+ */
146
+ export type PropTreeValue<T extends TreeNode | TreeLeafValue | undefined> = T extends TreeNode
147
+ ? PropTreeNode<T>
148
+ : T;
149
+
150
+ /**
151
+ * Type erase a TreeNode as a {@link PropTreeNode}.
152
+ * @alpha
153
+ */
154
+ export function toPropTreeNode<T extends TreeNode | TreeLeafValue>(node: T): PropTreeValue<T> {
155
+ return node as unknown as PropTreeValue<T>;
156
+ }
157
+
158
+ /**
159
+ * Type erase a {@link NodeRecord} as a {@link PropTreeNodeRecord}.
160
+ * @alpha
161
+ */
162
+ export function toPropTreeRecord<T extends NodeRecord>(node: T): WrapPropTreeNodeRecord<T> {
163
+ return node as unknown as WrapPropTreeNodeRecord<T>;
164
+ }