From 39c7d01e9405d8c5f67a6bf0e96007e16666b72a Mon Sep 17 00:00:00 2001 From: Yann Achard Date: Fri, 3 Jan 2025 17:26:56 -0800 Subject: [PATCH 1/5] docs(tree): updates and fixes --- docs/docs/data-structures/tree/events.mdx | 24 ++++--- docs/docs/data-structures/tree/nodes.mdx | 20 ++++-- .../tree/reading-and-editing.mdx | 63 ++++++++++++------- .../tree/schema-definition.mdx | 3 +- .../data-structures/tree/transactions.mdx | 12 ++-- docs/docs/data-structures/tree/undo-redo.mdx | 2 +- 6 files changed, 79 insertions(+), 45 deletions(-) diff --git a/docs/docs/data-structures/tree/events.mdx b/docs/docs/data-structures/tree/events.mdx index 5ab78b3488a3..f4e766c1ee72 100644 --- a/docs/docs/data-structures/tree/events.mdx +++ b/docs/docs/data-structures/tree/events.mdx @@ -3,20 +3,22 @@ title: Events sidebar_position: 5 --- -`SharedTree` supports two node level events: `nodeChanged` and `treeChanged`. +## Whole-Tree Events -Additionally, the `TreeView` object includes 2 events that operate over the whole tree. -These are `rootChanged` and `commitApplied`. +The `TreeView` object exposes 2 events that communicate changes that affect the whole tree. -`rootChanged` fires when the root field (the field that contains the root node) changes. +`rootChanged` fires when the contents root field (the field that contains the root node) change. That is, if a new root node is assigned or the schema changes. This will not fire when the node itself changes. -`changed` fires whenever a change is applied outside of a transaction or when a transaction is committed. +`commitApplied` fires whenever a change is applied outside of a transaction or when a transaction is committed. This is used to get `Revertible` objects to put on the undo or redo stacks. See [undo redo support](./undo-redo.mdx) and [Transactions](./transactions.mdx). -## Event Handling +## Node-Level Events + +`SharedTree` supports two node-level events: `nodeChanged` and `treeChanged`. +These can be subscribed to using the `Tree.on` method, which has the following signature: ```typescript on( @@ -28,9 +30,12 @@ on( `Tree.on` assigns the specified `listener` function to the specified `eventName` for the specified `node`. The `node` can be any node of the tree. -The `eventName` can be either "treeChanged" or "nodeChanged". -`nodeChanged` fires whenever one or more properties of the specified node change. -`treeChanged` fires whenever one or more properties of the specified node or any node in its subtree, change. + +The `eventName` can be either `"treeChanged"` or `"nodeChanged"`: + +- `nodeChanged` fires whenever one or more properties of the specified node change. +- `treeChanged` fires whenever one or more properties of the specified node or any node in its subtree, change. + We recommend looking at the documentation of each of the events for more details. The `Tree.on()` method returns a function that unsubscribes the handler from the event. This method is typically called in clean up code when the node is being removed. For example: @@ -40,5 +45,4 @@ const unsubscribe = Tree.on(myTreeNode, "nodeChanged", () => {...}); // Later at some point when the event subscription is not needed anymore unsubscribe(); - ``` diff --git a/docs/docs/data-structures/tree/nodes.mdx b/docs/docs/data-structures/tree/nodes.mdx index 05f270272535..725d19ecce83 100644 --- a/docs/docs/data-structures/tree/nodes.mdx +++ b/docs/docs/data-structures/tree/nodes.mdx @@ -10,13 +10,16 @@ See [node types](./node-types.mdx) for details on the types of nodes that can be Below are some utilities provided to make working with nodes easier. -### Node Information +### `Tree.key` ```typescript Tree.key(node: SharedTreeNode): number | string ``` -Returns the key of the `node`. This is a string in all cases, except an array node, in which case it returns the index of the node. +Returns the field key that the `node` is stored under. +This is a string in all cases, except an array node, in which case it returns the index of the node. + +### `Tree.parent` ```typescript Tree.parent(node: SharedTreeNode): SharedTreeNode @@ -33,15 +36,20 @@ if (Tree.is(parent, Notes) || Tree.is(parent, Items)) { } ``` +### `Tree.status` + ```typescript Tree.status(node: SharedTreeNode): TreeStatus ``` Returns the current status of `node`. Possible values are: -- **InDocument**: The node is in the tree. -- **Removed**: The node has been removed from the tree but is still restorable by undo. -- **Deleted**: The node is deleted and unrestorable. +- **New**: The node is created but has not yet been inserted into the tree. +- **InDocument**: The node is parented (either directly or indirectly) under the root field. +- **Removed**: The node is not parented under the root field but may still be restorable by this client or other clients. +- **Deleted**: The node is deleted and cannot be restored by this client, though it may still be restorable by other clients. + +### `Tree.schema` ```typescript Tree.schema(node: SharedTreeNode): TreeNodeSchema @@ -49,7 +57,7 @@ Tree.schema(node: SharedTreeNode): TreeNodeSchema Returns the object that defines the schema of the `node` object. -### Type Guard +### `Tree.is` When your code needs to process nodes only of a certain type and it has a reference to an object of an unknown type, you can use the `Tree.is()` method to test for the desired type as in the following examples. diff --git a/docs/docs/data-structures/tree/reading-and-editing.mdx b/docs/docs/data-structures/tree/reading-and-editing.mdx index 19882016a66e..30b8cba009ef 100644 --- a/docs/docs/data-structures/tree/reading-and-editing.mdx +++ b/docs/docs/data-structures/tree/reading-and-editing.mdx @@ -3,7 +3,7 @@ title: Reading and Editing sidebar_position: 4 --- -The `TreeView` object and its children provide methods that enable your code to add nodes to the tree, remove nodes, and move nodes within the tree. You can also set and read the values of leaf nodes. The APIs have been designed to match as much as possible the syntax of TypeScript primitives, objects, maps, and arrays; although some editing APIs are different for the sake of making the merge semantics clearer. +The `TreeView` object and its children expose properties and methods that allows applications read and edit the tree. The APIs have been designed to match as much as possible the syntax of TypeScript primitives, objects, maps, and arrays; although some editing APIs are different for the sake of making the merge semantics clearer. ## Leaf Node APIs @@ -23,14 +23,14 @@ const pointsForDetroitTigers: number = seasonTree.tigersTeam.game1.points; ### Reading Object Properties -Your code reads object nodes and their properties exactly as it would read a JavaScript object. The following are some examples. +Your code reads object nodes and their properties exactly as it would from a JavaScript object. The following are some examples. ```typescript const pointsForDetroitTigers: number = seasonTree.tigersTeam.game1.points; const counterHandle: FluidHandle = myTree.myObjectNode.myHandle; -const myItems: Array = stickyNotesTree.items; +const myItems: Items = stickyNotesTree.items; ``` ### Creating Objects @@ -52,6 +52,10 @@ We show how to add this note to an array of notes in the tree in [Array node API ### Editing Object Properties To update the property on an object node, you assign a new node or value to it with the assignment operator (`=`). +See [here](https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/docs/user-facing/object-merge-semantics.md) for details on the merge semantics of these edits. + +Note that if the new value is a node (as opposed to a primitive), then its [status](./nodes.mdx#Tree_status) must be `TreeStatus.New`, +In other words, it is not possible to set a node that has already been inserted in the tree in the past, even if that node has since been removed. ```typescript rectangle.topLeft = new Point({ x: 0, y: 0 }); @@ -77,41 +81,46 @@ The read APIs for map nodes have the same names and syntax as the corresponding has(key): boolean ``` -Returns `true`` if the key is present in the map. +Returns `true` if the key is present in the map. ```typescript get(key): T | undefined ``` -Returns the value of the property with the specified key. +Returns the value associated with the specified key if any, and returns `undefined` if no value is associated with that key. ```typescript keys(): IterableIterator ``` -Returns an Iterator that contains the keys in the map node. The keys are iterated in the order that they were added. +Returns an Iterator that contains the keys in the map node. +We do not make guarantees about the ordering of the keys. ```typescript values(): IterableIterator ``` -Returns an Iterator that contains the values in the map node. The values are iterated in the order that they were added. +Returns an Iterator that contains the values in the map node. +We do not make guarantees about the ordering of the values. ```typescript entries(): IterableIterator<[string, T]> ``` -Returns an Iterator that contains the key/value pairs in the map node. The pairs are iterated in the order that they were added. +Returns an Iterator that contains the key/value pairs in the map node. +We do not make guarantees about the ordering of the entries. ```typescript map(callback: ()=>[]): IterableIterator<[string, T]> ``` Returns an array, _not a map node or array node_, that is the result of applying the callback parameter to each member of the original map node. It is just like [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map). +We do not make guarantees about the ordering of the entries. ### Map Node Write APIs -The write methods for map nodes are also the same as the corresponding methods for JavaScript `Map` objects. +The write methods for map nodes are similar to the corresponding methods for JavaScript `Map` objects. +See [here](https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/docs/user-facing/map-merge-semantics.md) for details on the merge semantics of these edits. ```typescript set(key: string, value: T) @@ -120,6 +129,8 @@ set(key: string, value: T) The `set()` method sets/changes the value of the item with the specified key. If the key is not present, the item is added to the map. Note the following: - The `T` can be any type that conforms to the map node's schema. For example, if the schema was defined with `class MyMap extends sf.map([sf.number, sf.string]);`, then `T` could be `number` or `string`. +- If the `value` argument is a node (as opposed to a primitive), then its [status](./nodes.mdx#Tree_status) must be `TreeStatus.New`, + In other words, it is not possible to set a node that has already been inserted in the tree in the past, even if that node has since been removed. - If multiple clients set the same key simultaneously, the key gets the value set by the last edit to apply. For the meaning of "simultaneously", see [Types of distributed data structures](../overview.mdx). ```typescript @@ -145,10 +156,16 @@ Array nodes have all the same non-mutating read methods as the JavaScript [Array ### Array Node Write APIs The write APIs for array nodes are quite different from JavaScript arrays. They are more suitable for data items that are being worked on collaboratively by multiple people. There are three categories of write APIs: Insert, Remove, and Move. +See [here](https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/docs/user-facing/array-merge-semantics.md) for details on the merge semantics of these edits. #### Insert Methods -Array nodes have three methods that insert new items into the node. Note that in all of the following, the `T` can be any type that conforms to the array node's schema. For example, if the schema was defined with `class MyArray extends sf.array([sf.number, sf.string]);`, then `T` could be `number` or `string`. +Array nodes have three methods that insert items into the array. +Note the following: + +- In all of the following, the `T` can be any type that conforms to the array node's schema. For example, if the schema was defined with `class MyArray extends sf.array([sf.number, sf.string]);`, then `T` could be `number` or `string`. +- Inserted values that are nodes (as opposed to a primitive), must have a [status](./nodes.mdx#Tree_status) equal `TreeStatus.New`. + In other words, it is not possible to set a node that has already been inserted in the tree in the past, even if that node has since been removed. ```typescript insertAt(index: number, value: Iterable) @@ -194,27 +211,31 @@ Removes the items indicated by the `start` index (inclusive) and `end` index (ex Array nodes have three methods that move items within an array or from one array node to another. When moving from one array node to another, these methods must be called from the destination array node. Note that in all of the following, the `T` can be any type that is derived from an object that is returned by a call of `SchemaFactory.array()`, such as the `Notes` and `Items` classes in the sticky notes example. +Note the following about these methods: + +- If multiple clients simultaneously move an item, then that item will be moved to the destination indicated by the move of the client whose edit is ordered last. +- A moved item may be removed as a result of a simultaneous remove operation from another client. For example, if one client moves items 3-5, and another client simultaneously removes items 4 and 5, then, if the remove operation is ordered last, items 4 and 5 are removed from their destination by the remove operation. If the move operation is ordered last, then all three items will be moved to the destination. +- We also expose variations of these methods for moving a single item. + +For the meaning of "simultaneously", see [Types of distributed data structures](../overview.mdx). + ```typescript -moveToStart(sourceStartIndex: number, sourceEndIndex: number, source?: T) +moveRangeToStart(sourceStartIndex: number, sourceEndIndex: number, source?: T) ``` Moves the specified items to the start of the array. Specify a `source` array if it is different from the destination array. ```typescript -moveToEnd(sourceStartIndex: number, sourceEndIndex: number, source?: T) +moveRangeToEnd(sourceStartIndex: number, sourceEndIndex: number, source?: T) ``` Moves the specified items to the end of the array. Specify a `source` array if it is different from the destination array. ```typescript -moveToIndex(index: number, sourceStartIndex: number, sourceEndIndex: number, source?: T) +moveRangeToIndex(destinationGap: number, sourceStartIndex: number, sourceEndIndex: number, source?: T) ``` -Moves the items to the specified `index` in the destination array. The item that is at `index` before the method is called will be at the first index position that follows the moved items after the move. Specify a `source` array if it is different from the destination array. If the items are being moved within the same array, the `index` position is calculated including the items being moved (as if a new copy of the moved items were being inserted, without removing the originals). - -Note the following about these methods: - -- If multiple clients simultaneously move an item, then that item will be moved to the destination indicated by the move of the client whose edit is ordered last. -- A moved item may be removed as a result of a simultaneous remove operation from another client. For example, if one client moves items 3-5, and another client simultaneously removes items 4 and 5, then, if the remove operation is ordered last, items 4 and 5 are removed from their destination by the remove operation. If the move operation is ordered last, then all three items will be moved to the destination. - -For the meaning of "simultaneously", see [Types of distributed data structures](../overview.mdx). +Moves the items to the specified `destinationGap` in the destination array. +Specify a `source` array if it is different from the destination array. +If the items are being moved within the same array, the `destinationGap` position is interpreted including the items being moved (as if a new copy of the moved items were being inserted, without removing the originals). +See [the doc comments](https://fluidframework.com/docs/api/tree/treearraynode-interface#moverangetoindex-methodsignature) for details. diff --git a/docs/docs/data-structures/tree/schema-definition.mdx b/docs/docs/data-structures/tree/schema-definition.mdx index 5d7bc67aea3e..4ea4ac399fd7 100644 --- a/docs/docs/data-structures/tree/schema-definition.mdx +++ b/docs/docs/data-structures/tree/schema-definition.mdx @@ -171,12 +171,11 @@ type _check = ValidateRecursiveSchema; ## Setting Properties as Optional -To specify that a property is not required, pass it to the `SchemaFactory.optional()` method inline. The following example shows a schema with two optional properties. +To specify that a property is not required, pass it to the `SchemaFactory.optional()` method inline. The following example shows a schema with an optional property. ```typescript class Proposal = sf.object('Proposal', { id: sf.string, text: sf.optional(sf.string), - comments: sf.optional(sf.array(Comment)), }); ``` diff --git a/docs/docs/data-structures/tree/transactions.mdx b/docs/docs/data-structures/tree/transactions.mdx index 9b6b1ccf5efd..9b2eb23cd7cf 100644 --- a/docs/docs/data-structures/tree/transactions.mdx +++ b/docs/docs/data-structures/tree/transactions.mdx @@ -5,11 +5,13 @@ sidebar_position: 6 TODO:#27374: update this page to describe the new transaction API -If you want the `SharedTree` to treat a set of changes atomically, wrap these changes in a transaction. -Using a transaction guarantees that (if applied) all of the changes will be applied together synchronously and no other changes (either from this client or from a remote client) can be interleaved with those changes. Note that the Fluid Framework guarantees this already for any sequence of changes that are submitted synchronously. However, the changes may not be applied at all if the transaction is given one or more constraints. -If any constraint on a transaction is not met, then the transaction and all its changes will ignored by all clients. -Additionally, all changes in a transaction will be reverted together as a single unit by [undo/redo code](./undo-redo.mdx), because changes within a transaction are exposed through a single `Revertible` object. -It is also more efficient for SharedTree to process a large number of changes in a row as a transaction rather than as changes submitted separately. +If you want the `SharedTree` to treat a set of changes atomically, then you can wrap these changes in a transaction. +Using a transaction guarantees that (if applied) all of the changes will be applied together synchronously and no other changes (either from this client or from a remote client) can be interleaved with those changes. +Note that the Fluid Framework guarantees this already for any sequence of changes that are submitted synchronously. +However, using a transaction has the following additional implications: +- If [reverted](./undo-redo.mdx) (e.g. via an "undo" operation), all the changes in the transaction are reverted together. +- It is also more efficient for SharedTree to process and transmit a large number of changes as a transaction rather than as changes submitted separately. +- It is possible to specify constraints on a transaction so that the transaction will be ignored if one or more of these constraints are not met. To create a transaction use the `Tree.runTransaction()` method. You can cancel a transaction from within the callback function by returning the special "rollback object", available via `Tree.runTransaction.rollback`. Also, if an error occurs within the callback, the transaction will be canceled automatically before propagating the error. diff --git a/docs/docs/data-structures/tree/undo-redo.mdx b/docs/docs/data-structures/tree/undo-redo.mdx index 79dde9f5b462..db5aa2992599 100644 --- a/docs/docs/data-structures/tree/undo-redo.mdx +++ b/docs/docs/data-structures/tree/undo-redo.mdx @@ -12,4 +12,4 @@ sidebar_position: 7 To undo a change, call the `revert` method on the `Revertible` object. This will return the properties of the `TreeView` object last changed by the local client to the their previous state. If changes were made to those properties by other clients in the meantime these changes will be overwritten. For example, if the local client moves 3 items into an array, and then a remote client moves one of those items somewhere else, when the local client reverts their change, the item moved by the remote client will be returned to its original position. -There is an example of a working undo/redo stack here: [Shared Tree Demo](https://github.com/microsoft/FluidExamples/tree/main/brainstorm). +There is an example of a working undo/redo stack here: [Shared Tree Demo](https://github.com/microsoft/FluidExamples/tree/main/brainstorm/src/utils/undo.ts). From 05aa7d97fdc16a1a4e5985359a5dabac1a271de7 Mon Sep 17 00:00:00 2001 From: Yann Achard Date: Fri, 3 Jan 2025 17:40:56 -0800 Subject: [PATCH 2/5] Fix link --- docs/docs/data-structures/tree/reading-and-editing.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/data-structures/tree/reading-and-editing.mdx b/docs/docs/data-structures/tree/reading-and-editing.mdx index 30b8cba009ef..a46d458adefa 100644 --- a/docs/docs/data-structures/tree/reading-and-editing.mdx +++ b/docs/docs/data-structures/tree/reading-and-editing.mdx @@ -54,7 +54,7 @@ We show how to add this note to an array of notes in the tree in [Array node API To update the property on an object node, you assign a new node or value to it with the assignment operator (`=`). See [here](https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/docs/user-facing/object-merge-semantics.md) for details on the merge semantics of these edits. -Note that if the new value is a node (as opposed to a primitive), then its [status](./nodes.mdx#Tree_status) must be `TreeStatus.New`, +Note that if the new value is a node (as opposed to a primitive), then its [status](./nodes.mdx#Treestatus) must be `TreeStatus.New`, In other words, it is not possible to set a node that has already been inserted in the tree in the past, even if that node has since been removed. ```typescript From 63f024c2c791530fe371879a887b17cc0097e937 Mon Sep 17 00:00:00 2001 From: Yann Achard Date: Fri, 3 Jan 2025 17:53:14 -0800 Subject: [PATCH 3/5] More link fixes --- docs/docs/data-structures/tree/reading-and-editing.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/data-structures/tree/reading-and-editing.mdx b/docs/docs/data-structures/tree/reading-and-editing.mdx index a46d458adefa..01393248d8e1 100644 --- a/docs/docs/data-structures/tree/reading-and-editing.mdx +++ b/docs/docs/data-structures/tree/reading-and-editing.mdx @@ -54,7 +54,7 @@ We show how to add this note to an array of notes in the tree in [Array node API To update the property on an object node, you assign a new node or value to it with the assignment operator (`=`). See [here](https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/docs/user-facing/object-merge-semantics.md) for details on the merge semantics of these edits. -Note that if the new value is a node (as opposed to a primitive), then its [status](./nodes.mdx#Treestatus) must be `TreeStatus.New`, +Note that if the new value is a node (as opposed to a primitive), then its [status](./nodes.mdx#treestatus) must be `TreeStatus.New`, In other words, it is not possible to set a node that has already been inserted in the tree in the past, even if that node has since been removed. ```typescript @@ -129,7 +129,7 @@ set(key: string, value: T) The `set()` method sets/changes the value of the item with the specified key. If the key is not present, the item is added to the map. Note the following: - The `T` can be any type that conforms to the map node's schema. For example, if the schema was defined with `class MyMap extends sf.map([sf.number, sf.string]);`, then `T` could be `number` or `string`. -- If the `value` argument is a node (as opposed to a primitive), then its [status](./nodes.mdx#Tree_status) must be `TreeStatus.New`, +- If the `value` argument is a node (as opposed to a primitive), then its [status](./nodes.mdx#treestatus) must be `TreeStatus.New`, In other words, it is not possible to set a node that has already been inserted in the tree in the past, even if that node has since been removed. - If multiple clients set the same key simultaneously, the key gets the value set by the last edit to apply. For the meaning of "simultaneously", see [Types of distributed data structures](../overview.mdx). @@ -164,7 +164,7 @@ Array nodes have three methods that insert items into the array. Note the following: - In all of the following, the `T` can be any type that conforms to the array node's schema. For example, if the schema was defined with `class MyArray extends sf.array([sf.number, sf.string]);`, then `T` could be `number` or `string`. -- Inserted values that are nodes (as opposed to a primitive), must have a [status](./nodes.mdx#Tree_status) equal `TreeStatus.New`. +- Inserted values that are nodes (as opposed to a primitive), must have a [status](./nodes.mdx#treestatus) equal `TreeStatus.New`. In other words, it is not possible to set a node that has already been inserted in the tree in the past, even if that node has since been removed. ```typescript From 30ec5a2fe1aa66c36e2df632bf1fb5cefdf7e200 Mon Sep 17 00:00:00 2001 From: Yann Achard Date: Mon, 6 Jan 2025 20:37:40 -0800 Subject: [PATCH 4/5] PR feedback --- docs/docs/data-structures/tree/events.mdx | 11 +++++++++-- .../data-structures/tree/reading-and-editing.mdx | 14 ++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/docs/docs/data-structures/tree/events.mdx b/docs/docs/data-structures/tree/events.mdx index f4e766c1ee72..71b30b6f68ee 100644 --- a/docs/docs/data-structures/tree/events.mdx +++ b/docs/docs/data-structures/tree/events.mdx @@ -5,9 +5,16 @@ sidebar_position: 5 ## Whole-Tree Events -The `TreeView` object exposes 2 events that communicate changes that affect the whole tree. +The `TreeView` object exposes 2 events that communicate changes that affect the whole tree. For example: -`rootChanged` fires when the contents root field (the field that contains the root node) change. +```typescript +const unsubscribe = treeView.events.on("rootChanged", () => {...}); + +// Later at some point when the event subscription is not needed anymore +unsubscribe(); +``` + +`rootChanged` fires when the contents of the root field (the field that contains the root node) change. That is, if a new root node is assigned or the schema changes. This will not fire when the node itself changes. diff --git a/docs/docs/data-structures/tree/reading-and-editing.mdx b/docs/docs/data-structures/tree/reading-and-editing.mdx index 01393248d8e1..2cfb05a6e6fc 100644 --- a/docs/docs/data-structures/tree/reading-and-editing.mdx +++ b/docs/docs/data-structures/tree/reading-and-editing.mdx @@ -3,7 +3,8 @@ title: Reading and Editing sidebar_position: 4 --- -The `TreeView` object and its children expose properties and methods that allows applications read and edit the tree. The APIs have been designed to match as much as possible the syntax of TypeScript primitives, objects, maps, and arrays; although some editing APIs are different for the sake of making the merge semantics clearer. +The `TreeView` object and its children expose properties and methods that allow applications read and edit the tree. +The APIs have been designed to match as much as possible the syntax of TypeScript primitives, objects, maps, and arrays (although some editing APIs are different for the sake of making the merge semantics clearer). ## Leaf Node APIs @@ -54,9 +55,6 @@ We show how to add this note to an array of notes in the tree in [Array node API To update the property on an object node, you assign a new node or value to it with the assignment operator (`=`). See [here](https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/docs/user-facing/object-merge-semantics.md) for details on the merge semantics of these edits. -Note that if the new value is a node (as opposed to a primitive), then its [status](./nodes.mdx#treestatus) must be `TreeStatus.New`, -In other words, it is not possible to set a node that has already been inserted in the tree in the past, even if that node has since been removed. - ```typescript rectangle.topLeft = new Point({ x: 0, y: 0 }); ``` @@ -71,6 +69,9 @@ Optional properties can be cleared by assigning `undefined` to them. proposal.text = undefined; ``` +Note that if the new value is a node (as opposed to a primitive), then its [status](./nodes.mdx#treestatus) must be `TreeStatus.New`, +In other words, it is not possible to set a node that has already been inserted in the tree in the past, even if that node has since been removed. + ## Map Node APIs ### Map Node Read APIs @@ -94,28 +95,24 @@ keys(): IterableIterator ``` Returns an Iterator that contains the keys in the map node. -We do not make guarantees about the ordering of the keys. ```typescript values(): IterableIterator ``` Returns an Iterator that contains the values in the map node. -We do not make guarantees about the ordering of the values. ```typescript entries(): IterableIterator<[string, T]> ``` Returns an Iterator that contains the key/value pairs in the map node. -We do not make guarantees about the ordering of the entries. ```typescript map(callback: ()=>[]): IterableIterator<[string, T]> ``` Returns an array, _not a map node or array node_, that is the result of applying the callback parameter to each member of the original map node. It is just like [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map). -We do not make guarantees about the ordering of the entries. ### Map Node Write APIs @@ -215,6 +212,7 @@ Note the following about these methods: - If multiple clients simultaneously move an item, then that item will be moved to the destination indicated by the move of the client whose edit is ordered last. - A moved item may be removed as a result of a simultaneous remove operation from another client. For example, if one client moves items 3-5, and another client simultaneously removes items 4 and 5, then, if the remove operation is ordered last, items 4 and 5 are removed from their destination by the remove operation. If the move operation is ordered last, then all three items will be moved to the destination. +- Moved items that are nodes (as opposed to a primitives), must have a [status](./nodes.mdx#treestatus) equal `TreeStatus.InDocument`. - We also expose variations of these methods for moving a single item. For the meaning of "simultaneously", see [Types of distributed data structures](../overview.mdx). From 1accfc1000ba0c75a92d0a6f6ac236e4b82c678a Mon Sep 17 00:00:00 2001 From: Yann Achard Date: Wed, 8 Jan 2025 14:02:46 -0800 Subject: [PATCH 5/5] Move example TreeView even sub down --- docs/docs/data-structures/tree/events.mdx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/docs/data-structures/tree/events.mdx b/docs/docs/data-structures/tree/events.mdx index 71b30b6f68ee..6d65ddb721b1 100644 --- a/docs/docs/data-structures/tree/events.mdx +++ b/docs/docs/data-structures/tree/events.mdx @@ -5,14 +5,7 @@ sidebar_position: 5 ## Whole-Tree Events -The `TreeView` object exposes 2 events that communicate changes that affect the whole tree. For example: - -```typescript -const unsubscribe = treeView.events.on("rootChanged", () => {...}); - -// Later at some point when the event subscription is not needed anymore -unsubscribe(); -``` +The `TreeView` object exposes 2 events that communicate changes that affect the whole tree. `rootChanged` fires when the contents of the root field (the field that contains the root node) change. That is, if a new root node is assigned or the schema changes. @@ -22,6 +15,15 @@ This will not fire when the node itself changes. This is used to get `Revertible` objects to put on the undo or redo stacks. See [undo redo support](./undo-redo.mdx) and [Transactions](./transactions.mdx). +Here is an example of how to subscribe to one of these events: + +```typescript +const unsubscribe = treeView.events.on("rootChanged", () => {...}); + +// Later at some point when the event subscription is not needed anymore +unsubscribe(); +``` + ## Node-Level Events `SharedTree` supports two node-level events: `nodeChanged` and `treeChanged`.