@fluidframework/react 2.90.0-378676 → 2.91.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.
- package/CHANGELOG.md +13 -0
- package/README.md +2 -0
- package/api-report/react.alpha.api.md +8 -8
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/propNode.js.map +1 -1
- package/lib/reactSharedTreeView.d.ts +6 -6
- package/lib/reactSharedTreeView.d.ts.map +1 -1
- package/lib/reactSharedTreeView.js +16 -18
- package/lib/reactSharedTreeView.js.map +1 -1
- package/lib/test/mochaHooks.js +13 -0
- package/lib/test/mochaHooks.js.map +1 -0
- package/lib/test/reactSharedTreeView.spec.js +3 -3
- package/lib/test/reactSharedTreeView.spec.js.map +1 -1
- package/lib/test/text/plainUtils.test.js +75 -0
- package/lib/test/text/plainUtils.test.js.map +1 -0
- package/lib/test/text/textEditor.test.js +760 -0
- package/lib/test/text/textEditor.test.js.map +1 -0
- package/lib/test/undoRedo.test.js +62 -0
- package/lib/test/undoRedo.test.js.map +1 -0
- package/lib/test/useObservation.spec.js +8 -9
- package/lib/test/useObservation.spec.js.map +1 -1
- package/lib/test/useTree.spec.js +15 -16
- package/lib/test/useTree.spec.js.map +1 -1
- package/lib/text/formatted/index.d.ts +6 -0
- package/lib/text/formatted/index.d.ts.map +1 -0
- package/lib/text/formatted/index.js +6 -0
- package/lib/text/formatted/index.js.map +1 -0
- package/lib/text/formatted/quillFormattedView.d.ts +66 -0
- package/lib/text/formatted/quillFormattedView.d.ts.map +1 -0
- package/lib/text/formatted/quillFormattedView.js +520 -0
- package/lib/text/formatted/quillFormattedView.js.map +1 -0
- package/lib/text/index.d.ts +7 -0
- package/lib/text/index.d.ts.map +1 -0
- package/lib/text/index.js +7 -0
- package/lib/text/index.js.map +1 -0
- package/lib/text/plain/index.d.ts +7 -0
- package/lib/text/plain/index.d.ts.map +1 -0
- package/lib/text/plain/index.js +7 -0
- package/lib/text/plain/index.js.map +1 -0
- package/lib/text/plain/plainTextView.d.ts +14 -0
- package/lib/text/plain/plainTextView.d.ts.map +1 -0
- package/lib/text/plain/plainTextView.js +70 -0
- package/lib/text/plain/plainTextView.js.map +1 -0
- package/lib/text/plain/plainUtils.d.ts +23 -0
- package/lib/text/plain/plainUtils.d.ts.map +1 -0
- package/lib/text/plain/plainUtils.js +51 -0
- package/lib/text/plain/plainUtils.js.map +1 -0
- package/lib/text/plain/quillView.d.ts +22 -0
- package/lib/text/plain/quillView.d.ts.map +1 -0
- package/lib/text/plain/quillView.js +106 -0
- package/lib/text/plain/quillView.js.map +1 -0
- package/lib/undoRedo.d.ts +51 -0
- package/lib/undoRedo.d.ts.map +1 -0
- package/lib/undoRedo.js +76 -0
- package/lib/undoRedo.js.map +1 -0
- package/lib/useObservation.js +6 -6
- package/lib/useObservation.js.map +1 -1
- package/lib/useTree.d.ts +7 -7
- package/lib/useTree.d.ts.map +1 -1
- package/lib/useTree.js +6 -6
- package/lib/useTree.js.map +1 -1
- package/package.json +28 -46
- package/react.test-files.tar +0 -0
- package/src/index.ts +10 -0
- package/src/propNode.ts +1 -1
- package/src/reactSharedTreeView.tsx +11 -13
- package/src/text/formatted/index.ts +11 -0
- package/src/text/formatted/quillFormattedView.tsx +627 -0
- package/src/text/index.ts +15 -0
- package/src/text/plain/index.ts +7 -0
- package/src/text/plain/plainTextView.tsx +110 -0
- package/src/text/plain/plainUtils.ts +68 -0
- package/src/text/plain/quillView.tsx +149 -0
- package/src/undoRedo.ts +117 -0
- package/src/useObservation.ts +6 -6
- package/src/useTree.ts +19 -12
- package/tsconfig.json +6 -0
- package/api-extractor/api-extractor-lint-alpha.cjs.json +0 -5
- package/api-extractor/api-extractor-lint-beta.cjs.json +0 -5
- package/api-extractor/api-extractor-lint-public.cjs.json +0 -5
- package/dist/alpha.d.ts +0 -45
- package/dist/beta.d.ts +0 -15
- package/dist/index.d.ts +0 -16
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -26
- package/dist/index.js.map +0 -1
- package/dist/package.json +0 -4
- package/dist/propNode.d.ts +0 -114
- package/dist/propNode.d.ts.map +0 -1
- package/dist/propNode.js +0 -43
- package/dist/propNode.js.map +0 -1
- package/dist/public.d.ts +0 -15
- package/dist/reactSharedTreeView.d.ts +0 -119
- package/dist/reactSharedTreeView.d.ts.map +0 -1
- package/dist/reactSharedTreeView.js +0 -206
- package/dist/reactSharedTreeView.js.map +0 -1
- package/dist/simpleIdentifier.d.ts +0 -19
- package/dist/simpleIdentifier.d.ts.map +0 -1
- package/dist/simpleIdentifier.js +0 -33
- package/dist/simpleIdentifier.js.map +0 -1
- package/dist/useObservation.d.ts +0 -83
- package/dist/useObservation.d.ts.map +0 -1
- package/dist/useObservation.js +0 -295
- package/dist/useObservation.js.map +0 -1
- package/dist/useTree.d.ts +0 -80
- package/dist/useTree.d.ts.map +0 -1
- package/dist/useTree.js +0 -137
- package/dist/useTree.js.map +0 -1
- package/tsconfig.cjs.json +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @fluidframework/react
|
|
2
2
|
|
|
3
|
+
## 2.91.0
|
|
4
|
+
|
|
5
|
+
Dependency updates only.
|
|
6
|
+
|
|
7
|
+
## 2.90.0
|
|
8
|
+
|
|
9
|
+
### Minor Changes
|
|
10
|
+
|
|
11
|
+
- @fluidframework/react no longer supports CommonJS ([#26575](https://github.com/microsoft/FluidFramework/pull/26575)) [995c1e44aad](https://github.com/microsoft/FluidFramework/commit/995c1e44aad7368e4e59ac4ff3a7237280506cde)
|
|
12
|
+
|
|
13
|
+
CommonJS support has been removed from `@fluidframework/react`.
|
|
14
|
+
This package currently only has alpha APIs, so this opportunity was taken to simplify and modernize it while we still can.
|
|
15
|
+
|
|
3
16
|
## 2.83.0
|
|
4
17
|
|
|
5
18
|
Dependency updates only.
|
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@ This package currently has some experimental APIs focused on integrating SharedT
|
|
|
6
6
|
|
|
7
7
|
## Known Issues and Limitations
|
|
8
8
|
|
|
9
|
+
This package is currently ESM only and does not support CommonJS.
|
|
10
|
+
|
|
9
11
|
These are a mix of issues that were encountered when authoring this package, as well as limitations of this package.
|
|
10
12
|
|
|
11
13
|
Some of this logic would be useful for non-react applications: to avoid creating even more septate packages, that logic is not split into its own package.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
export interface IReactTreeDataObject<TSchema extends ImplicitFieldSchema> {
|
|
9
9
|
readonly config: TreeViewConfiguration<TSchema>;
|
|
10
10
|
readonly treeView: TreeView<TSchema>;
|
|
11
|
-
readonly TreeViewComponent: (props: TreeViewProps<TSchema>) =>
|
|
11
|
+
readonly TreeViewComponent: (props: TreeViewProps<TSchema>) => JSX_2.Element;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
// @alpha @system
|
|
@@ -55,12 +55,12 @@ export function treeDataObject<TSchema extends ImplicitFieldSchema>(treeConfigur
|
|
|
55
55
|
// @alpha
|
|
56
56
|
export function TreeViewComponent<TSchema extends ImplicitFieldSchema>({ tree, viewComponent: ViewComponent, errorComponent, }: TreeViewProps<TSchema> & {
|
|
57
57
|
tree: Pick<IReactTreeDataObject<TSchema>, "treeView">;
|
|
58
|
-
}):
|
|
58
|
+
}): JSX_2.Element;
|
|
59
59
|
|
|
60
60
|
// @alpha @input
|
|
61
61
|
export interface TreeViewProps<TSchema extends ImplicitFieldSchema> {
|
|
62
|
-
readonly errorComponent?:
|
|
63
|
-
readonly viewComponent:
|
|
62
|
+
readonly errorComponent?: FC<SchemaIncompatibleProps>;
|
|
63
|
+
readonly viewComponent: FC<{
|
|
64
64
|
root: PropTreeValue<TreeFieldFromImplicitField<TSchema>>;
|
|
65
65
|
}>;
|
|
66
66
|
}
|
|
@@ -92,12 +92,12 @@ export function useTree(subtreeRoot: TreeNode): number;
|
|
|
92
92
|
export function useTreeObservations<TResult>(trackDuring: () => TResult, options?: ObservationOptions): TResult;
|
|
93
93
|
|
|
94
94
|
// @alpha
|
|
95
|
-
export function withMemoizedTreeObservations<TIn>(component:
|
|
96
|
-
readonly propsAreEqual?: Parameters<typeof
|
|
97
|
-
}):
|
|
95
|
+
export function withMemoizedTreeObservations<TIn>(component: FC<TIn>, options?: ObservationOptions & {
|
|
96
|
+
readonly propsAreEqual?: Parameters<typeof memo>[1];
|
|
97
|
+
}): MemoExoticComponent<ReturnType<typeof withTreeObservations<TIn>>>;
|
|
98
98
|
|
|
99
99
|
// @alpha
|
|
100
|
-
export function withTreeObservations<TIn>(component:
|
|
100
|
+
export function withTreeObservations<TIn>(component: FC<TIn>, options?: ObservationOptions): FC<TIn> & FC<WrapNodes<TIn>> & FC<TIn | WrapNodes<TIn>>;
|
|
101
101
|
|
|
102
102
|
// @alpha
|
|
103
103
|
export type WrapNodes<T> = T extends TreeNode ? PropTreeNode<T> : T extends readonly (infer U)[] ? readonly WrapNodes<U>[] : T extends infer U ? IsMappableObjectType<U, {
|
package/lib/index.d.ts
CHANGED
|
@@ -13,4 +13,6 @@ export type { NodeRecord, PropTreeNode, PropTreeNodeRecord, PropTreeValue, Unwra
|
|
|
13
13
|
export { toPropTreeNode, toPropTreeRecord, unwrapPropTreeNode, unwrapPropTreeRecord, } from "./propNode.js";
|
|
14
14
|
export { useTree, usePropTreeNode, usePropTreeRecord, useTreeObservations, withTreeObservations, withMemoizedTreeObservations, } from "./useTree.js";
|
|
15
15
|
export { objectIdNumber } from "./simpleIdentifier.js";
|
|
16
|
+
export { FormattedMainView, PlainTextMainView, PlainQuillView, type FormattedMainViewProps, type PlainMainViewProps, type FormattedEditorHandle, } from "./text/index.js";
|
|
17
|
+
export { UndoRedoStacks, type UndoRedo } from "./undoRedo.js";
|
|
16
18
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AAEH,YAAY,EACX,oBAAoB,EACpB,aAAa,EACb,uBAAuB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,cAAc,EACd,sBAAsB,EACtB,iBAAiB,GACjB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,YAAY,EACX,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,SAAS,EACT,oBAAoB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,OAAO,EACP,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,4BAA4B,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AAEH,YAAY,EACX,oBAAoB,EACpB,aAAa,EACb,uBAAuB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,cAAc,EACd,sBAAsB,EACtB,iBAAiB,GACjB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,YAAY,EACX,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,SAAS,EACT,oBAAoB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,OAAO,EACP,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,4BAA4B,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EACN,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -6,4 +6,6 @@ export { treeDataObject, treeDataObjectInternal, TreeViewComponent, } from "./re
|
|
|
6
6
|
export { toPropTreeNode, toPropTreeRecord, unwrapPropTreeNode, unwrapPropTreeRecord, } from "./propNode.js";
|
|
7
7
|
export { useTree, usePropTreeNode, usePropTreeRecord, useTreeObservations, withTreeObservations, withMemoizedTreeObservations, } from "./useTree.js";
|
|
8
8
|
export { objectIdNumber } from "./simpleIdentifier.js";
|
|
9
|
+
export { FormattedMainView, PlainTextMainView, PlainQuillView, } from "./text/index.js";
|
|
10
|
+
export { UndoRedoStacks } from "./undoRedo.js";
|
|
9
11
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,OAAO,EACN,cAAc,EACd,sBAAsB,EACtB,iBAAiB,GACjB,MAAM,0BAA0B,CAAC;AAalC,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,OAAO,EACP,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,4BAA4B,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Utilities for using SharedTree with React.\n * @packageDocumentation\n */\n\nexport type {\n\tIReactTreeDataObject,\n\tTreeViewProps,\n\tSchemaIncompatibleProps,\n} from \"./reactSharedTreeView.js\";\nexport {\n\ttreeDataObject,\n\ttreeDataObjectInternal,\n\tTreeViewComponent,\n} from \"./reactSharedTreeView.js\";\nexport type { ObservationOptions } from \"./useObservation.js\";\nexport type {\n\tNodeRecord,\n\tPropTreeNode,\n\tPropTreeNodeRecord,\n\tPropTreeValue,\n\tUnwrapPropTreeNode,\n\tUnwrapPropTreeNodeRecord,\n\tWrapPropTreeNodeRecord,\n\tWrapNodes,\n\tIsMappableObjectType,\n} from \"./propNode.js\";\nexport {\n\ttoPropTreeNode,\n\ttoPropTreeRecord,\n\tunwrapPropTreeNode,\n\tunwrapPropTreeRecord,\n} from \"./propNode.js\";\nexport {\n\tuseTree,\n\tusePropTreeNode,\n\tusePropTreeRecord,\n\tuseTreeObservations,\n\twithTreeObservations,\n\twithMemoizedTreeObservations,\n} from \"./useTree.js\";\nexport { objectIdNumber } from \"./simpleIdentifier.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,OAAO,EACN,cAAc,EACd,sBAAsB,EACtB,iBAAiB,GACjB,MAAM,0BAA0B,CAAC;AAalC,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,OAAO,EACP,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,4BAA4B,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EACN,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,GAId,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAiB,MAAM,eAAe,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Utilities for using SharedTree with React.\n * @packageDocumentation\n */\n\nexport type {\n\tIReactTreeDataObject,\n\tTreeViewProps,\n\tSchemaIncompatibleProps,\n} from \"./reactSharedTreeView.js\";\nexport {\n\ttreeDataObject,\n\ttreeDataObjectInternal,\n\tTreeViewComponent,\n} from \"./reactSharedTreeView.js\";\nexport type { ObservationOptions } from \"./useObservation.js\";\nexport type {\n\tNodeRecord,\n\tPropTreeNode,\n\tPropTreeNodeRecord,\n\tPropTreeValue,\n\tUnwrapPropTreeNode,\n\tUnwrapPropTreeNodeRecord,\n\tWrapPropTreeNodeRecord,\n\tWrapNodes,\n\tIsMappableObjectType,\n} from \"./propNode.js\";\nexport {\n\ttoPropTreeNode,\n\ttoPropTreeRecord,\n\tunwrapPropTreeNode,\n\tunwrapPropTreeRecord,\n} from \"./propNode.js\";\nexport {\n\tuseTree,\n\tusePropTreeNode,\n\tusePropTreeRecord,\n\tuseTreeObservations,\n\twithTreeObservations,\n\twithMemoizedTreeObservations,\n} from \"./useTree.js\";\nexport { objectIdNumber } from \"./simpleIdentifier.js\";\n\nexport {\n\tFormattedMainView,\n\tPlainTextMainView,\n\tPlainQuillView,\n\ttype FormattedMainViewProps,\n\ttype PlainMainViewProps,\n\ttype FormattedEditorHandle,\n} from \"./text/index.js\";\nexport { UndoRedoStacks, type UndoRedo } from \"./undoRedo.js\";\n"]}
|
package/lib/propNode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"propNode.js","sourceRoot":"","sources":["../src/propNode.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6EH;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CACjC,QAA8B;IAE9B,OAAO,QAAa,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CACnC,KAAQ;IAER,OAAO,KAAoC,CAAC;AAC7C,CAAC;AAgDD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAqC,IAAO;IACzE,OAAO,IAAmC,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAuB,IAAO;IAC7D,OAAO,IAA4C,CAAC;AACrD,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ErasedType } from \"@fluidframework/core-interfaces\";\nimport type { TreeNode, TreeLeafValue } from \"@fluidframework/tree\";\n\n/**\n * A type erased TreeNode for use in react props.\n * @remarks\n * Read content from the node using {@link usePropTreeNode} or {@link usePropTreeRecord}.\n *\n * In events where tracking dependencies is not required, the node can be unwrapped using {@link unwrapPropTreeNode}.\n *\n * To convert a TreeNode to this type use {@link toPropTreeNode} or {@link toPropTreeRecord}.\n * @alpha\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-
|
|
1
|
+
{"version":3,"file":"propNode.js","sourceRoot":"","sources":["../src/propNode.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6EH;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CACjC,QAA8B;IAE9B,OAAO,QAAa,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CACnC,KAAQ;IAER,OAAO,KAAoC,CAAC;AAC7C,CAAC;AAgDD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAqC,IAAO;IACzE,OAAO,IAAmC,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAuB,IAAO;IAC7D,OAAO,IAA4C,CAAC;AACrD,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ErasedType } from \"@fluidframework/core-interfaces\";\nimport type { TreeNode, TreeLeafValue } from \"@fluidframework/tree\";\n\n/**\n * A type erased TreeNode for use in react props.\n * @remarks\n * Read content from the node using {@link usePropTreeNode} or {@link usePropTreeRecord}.\n *\n * In events where tracking dependencies is not required, the node can be unwrapped using {@link unwrapPropTreeNode}.\n *\n * To convert a TreeNode to this type use {@link toPropTreeNode} or {@link toPropTreeRecord}.\n * @alpha\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface PropTreeNode<T extends TreeNode> extends ErasedType<[T, \"PropTreeNode\"]> {}\n\n/**\n * Type TreeNodes in T as {@link PropTreeNode}s.\n * @remarks\n * This only handles a few cases (TreeNode, structurally typed objects fields and arrays) and leaves other types as is.\n * Users which provide other types (e.g. maps) which contain TreeNodes will need to handle wrapping those themselves if the wrapping is desired.\n *\n * Users of this should not rely on a given use of TreeNode not being wrapped:\n * future changes to this API may add more cases which are wrapped, and this will be considered a non-breaking change.\n * @privateRemarks\n * 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.\n * To mitigate this IsMappableObjectType is used for objects, and only mappable types, where the mapping actually impacted the type are modified.\n *\n * This is intended to cover the common cases, and users can handle other cases manually.\n * See the tests for this for more details.\n * @alpha\n */\nexport type WrapNodes<T> = T extends TreeNode\n\t? PropTreeNode<T>\n\t: T extends readonly (infer U)[]\n\t\t? readonly WrapNodes<U>[]\n\t\t: // `T extends (infer U)` distributes over unions, allowing WrapNodes<A|B> to be WrapNodes<A> | WrapNodes<B>.\n\t\t\tT extends infer U\n\t\t\t? IsMappableObjectType<\n\t\t\t\t\tU,\n\t\t\t\t\t{\n\t\t\t\t\t\t[P in keyof U]: WrapNodes<U[P]>;\n\t\t\t\t\t} extends U\n\t\t\t\t\t\t? // Returning U in this case (when assignable to the mapped type) avoids flatting named interfaces when they are unchanged.\n\t\t\t\t\t\t\tU\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t[P in keyof U]: WrapNodes<U[P]>;\n\t\t\t\t\t\t\t},\n\t\t\t\t\tT\n\t\t\t\t>\n\t\t\t: T;\n\n/**\n * Detect if a type is a simple structural object.\n * @remarks\n * This returns the true case if the type is entirely defined by its set of public properties.\n * More concretely, this indicates if creating a mapped type based on `T`\n * will be lossy due to details mapped types cannot access.\n *\n * This is shallow, and distributes over unions.\n *\n * This also returns the true case for primitive types since mapping over them leaves them unchanged if doing so in a generic context:\n * 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.\n * This is fine as the use for this is to detect when making a mapped type from a generic type parameter would be lossy.\n * @system @alpha\n */\nexport type IsMappableObjectType<\n\tT,\n\tTrue = true,\n\tFalse = false,\n\tMapped = {\n\t\t[P in keyof T]: T[P];\n\t},\n> = [Mapped] extends [T] ? ([T] extends [Mapped] ? True : False) : False;\n\n/**\n * Casts a node from a {@link PropTreeNode} back to a TreeNode.\n * @remarks\n * This should only be done in scenarios where tracking observations is not required (such as event handlers),\n * or when taking care to handle invalidation manually.\n * @alpha\n */\nexport function unwrapPropTreeNode<T extends TreeNode | TreeLeafValue>(\n\tpropNode: PropTreeValue<T> | T,\n): T {\n\treturn propNode as T;\n}\n\n/**\n * {@link unwrapPropTreeNode} but for a {@link PropTreeNodeRecord}.\n * @alpha\n */\nexport function unwrapPropTreeRecord<T extends PropTreeNodeRecord>(\n\tprops: T,\n): UnwrapPropTreeNodeRecord<T> {\n\treturn props as UnwrapPropTreeNodeRecord<T>;\n}\n\n/**\n * {@inheritdoc unwrapPropTreeNode}\n * @alpha\n */\nexport type UnwrapPropTreeNode<T extends TreeLeafValue | PropTreeNode<TreeNode> | undefined> =\n\tT extends PropTreeNode<infer Node> ? Node : T;\n\n/**\n * Record that can contain TreeNodes.\n * @alpha\n */\nexport type NodeRecord = Record<string, TreeNode | TreeLeafValue>;\n\n/**\n * Type erase `TreeNode`s from a {@link NodeRecord} as a {@link PropTreeNode}.\n * @alpha\n */\nexport type WrapPropTreeNodeRecord<T extends NodeRecord> = {\n\treadonly [P in keyof T]: PropTreeValue<T[P]>;\n};\n\n/**\n * Type erase `TreeNode`s from a {@link NodeRecord} as a {@link PropTreeNode}.\n * @alpha\n */\nexport type UnwrapPropTreeNodeRecord<T extends PropTreeNodeRecord> = {\n\treadonly [P in keyof T]: UnwrapPropTreeNode<T[P]>;\n};\n\n/**\n * Type erase `TreeNode`s from a {@link NodeRecord} as a {@link PropTreeNode}.\n * @alpha\n */\nexport type PropTreeNodeRecord = Record<\n\tstring,\n\tTreeLeafValue | PropTreeNode<TreeNode> | undefined\n>;\n\n/**\n * Type erase a `TreeNode` from a `TreeNode | TreeLeafValue` as a {@link PropTreeNode}.\n * @alpha\n */\nexport type PropTreeValue<T extends TreeNode | TreeLeafValue | undefined> = T extends TreeNode\n\t? PropTreeNode<T>\n\t: T;\n\n/**\n * Type erase a TreeNode as a {@link PropTreeNode}.\n * @alpha\n */\nexport function toPropTreeNode<T extends TreeNode | TreeLeafValue>(node: T): PropTreeValue<T> {\n\treturn node as unknown as PropTreeValue<T>;\n}\n\n/**\n * Type erase a {@link NodeRecord} as a {@link PropTreeNodeRecord}.\n * @alpha\n */\nexport function toPropTreeRecord<T extends NodeRecord>(node: T): WrapPropTreeNodeRecord<T> {\n\treturn node as unknown as WrapPropTreeNodeRecord<T>;\n}\n"]}
|
|
@@ -7,7 +7,7 @@ import type { IFluidLoadable } from "@fluidframework/core-interfaces";
|
|
|
7
7
|
import type { IFluidDataStoreFactory } from "@fluidframework/runtime-definitions/internal";
|
|
8
8
|
import type { SharedObjectKind } from "@fluidframework/shared-object-base";
|
|
9
9
|
import type { SchemaCompatibilityStatus, TreeViewConfiguration, TreeFieldFromImplicitField, TreeView, ImplicitFieldSchema, InsertableTreeFieldFromImplicitField } from "@fluidframework/tree";
|
|
10
|
-
import
|
|
10
|
+
import { type FC, type JSX } from "react";
|
|
11
11
|
import { type PropTreeValue } from "./propNode.js";
|
|
12
12
|
/**
|
|
13
13
|
* Defines a DataObject for a {@link @fluidframework/tree#SharedTree} with a built in {@link @fluidframework/tree#TreeViewConfiguration}.
|
|
@@ -60,7 +60,7 @@ export interface IReactTreeDataObject<TSchema extends ImplicitFieldSchema> {
|
|
|
60
60
|
* and thus making it a member avoids the user of this from having to explicitly provide the type parameter.
|
|
61
61
|
* This is an arrow function not a method so it gets the correct this when not called as a member.
|
|
62
62
|
*/
|
|
63
|
-
readonly TreeViewComponent: (props: TreeViewProps<TSchema>) =>
|
|
63
|
+
readonly TreeViewComponent: (props: TreeViewProps<TSchema>) => JSX.Element;
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
66
|
* React props for viewing a tree.
|
|
@@ -70,7 +70,7 @@ export interface TreeViewProps<TSchema extends ImplicitFieldSchema> {
|
|
|
70
70
|
/**
|
|
71
71
|
* Component to display the tree content.
|
|
72
72
|
*/
|
|
73
|
-
readonly viewComponent:
|
|
73
|
+
readonly viewComponent: FC<{
|
|
74
74
|
root: PropTreeValue<TreeFieldFromImplicitField<TSchema>>;
|
|
75
75
|
}>;
|
|
76
76
|
/**
|
|
@@ -79,7 +79,7 @@ export interface TreeViewProps<TSchema extends ImplicitFieldSchema> {
|
|
|
79
79
|
*
|
|
80
80
|
* @defaultValue Component which describes the situation (in English) and allows the user to upgrade the schema to match the {@link @fluidframework/tree#TreeViewConfiguration} if possible.
|
|
81
81
|
*/
|
|
82
|
-
readonly errorComponent?:
|
|
82
|
+
readonly errorComponent?: FC<SchemaIncompatibleProps>;
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
85
85
|
* Generic DataObject for shared trees.
|
|
@@ -92,7 +92,7 @@ export declare abstract class ReactTreeDataObject<TSchema extends ImplicitFieldS
|
|
|
92
92
|
* The schema-aware view of the tree.
|
|
93
93
|
*/
|
|
94
94
|
get treeView(): TreeView<TSchema>;
|
|
95
|
-
readonly TreeViewComponent: ({ viewComponent, errorComponent, }: TreeViewProps<TSchema>) =>
|
|
95
|
+
readonly TreeViewComponent: ({ viewComponent, errorComponent, }: TreeViewProps<TSchema>) => JSX.Element;
|
|
96
96
|
}
|
|
97
97
|
/**
|
|
98
98
|
* React component which handles schematizing trees.
|
|
@@ -101,7 +101,7 @@ export declare abstract class ReactTreeDataObject<TSchema extends ImplicitFieldS
|
|
|
101
101
|
*/
|
|
102
102
|
export declare function TreeViewComponent<TSchema extends ImplicitFieldSchema>({ tree, viewComponent: ViewComponent, errorComponent, }: TreeViewProps<TSchema> & {
|
|
103
103
|
tree: Pick<IReactTreeDataObject<TSchema>, "treeView">;
|
|
104
|
-
}):
|
|
104
|
+
}): JSX.Element;
|
|
105
105
|
/**
|
|
106
106
|
* React Props for displaying when the opened document is incompatible with the required view schema.
|
|
107
107
|
* @alpha
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactSharedTreeView.d.ts","sourceRoot":"","sources":["../src/reactSharedTreeView.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEN,cAAc,EAEd,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AAC3F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EACX,yBAAyB,EACzB,qBAAqB,EACrB,0BAA0B,EAC1B,QAAQ,EACR,mBAAmB,EACnB,oCAAoC,EACpC,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"reactSharedTreeView.d.ts","sourceRoot":"","sources":["../src/reactSharedTreeView.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
1
|
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
6
2
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
7
3
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
@@ -14,9 +10,14 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
14
10
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
15
11
|
};
|
|
16
12
|
var _ReactTreeDataObject_treeView;
|
|
13
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
+
/*!
|
|
15
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
16
|
+
* Licensed under the MIT License.
|
|
17
|
+
*/
|
|
17
18
|
import { PureDataObjectFactory, TreeDataObject, createDataObjectKind, } from "@fluidframework/aqueduct/internal";
|
|
18
19
|
import { configuredSharedTree, FormatValidatorBasic } from "@fluidframework/tree/internal";
|
|
19
|
-
import
|
|
20
|
+
import { useCallback, useEffect, useState } from "react";
|
|
20
21
|
import { toPropTreeNode } from "./propNode.js";
|
|
21
22
|
/**
|
|
22
23
|
* Opt into extra validation to detect encoding bugs and data corruption.
|
|
@@ -107,8 +108,8 @@ export class ReactTreeDataObject extends TreeDataObject {
|
|
|
107
108
|
}
|
|
108
109
|
_ReactTreeDataObject_treeView = new WeakMap();
|
|
109
110
|
function useViewCompatibility(view) {
|
|
110
|
-
const [compatibility, setCompatibility] =
|
|
111
|
-
|
|
111
|
+
const [compatibility, setCompatibility] = useState(view.compatibility);
|
|
112
|
+
useEffect(() => {
|
|
112
113
|
const updateCompatibility = () => {
|
|
113
114
|
setCompatibility(view.compatibility);
|
|
114
115
|
};
|
|
@@ -118,8 +119,8 @@ function useViewCompatibility(view) {
|
|
|
118
119
|
return compatibility;
|
|
119
120
|
}
|
|
120
121
|
function useViewRoot(view) {
|
|
121
|
-
const [root, setRoot] =
|
|
122
|
-
|
|
122
|
+
const [root, setRoot] = useState(undefined);
|
|
123
|
+
useEffect(() => {
|
|
123
124
|
const updateRoot = () => {
|
|
124
125
|
if (view.compatibility.canView) {
|
|
125
126
|
setRoot(view.root);
|
|
@@ -142,7 +143,7 @@ export function TreeViewComponent({ tree, viewComponent: ViewComponent, errorCom
|
|
|
142
143
|
const view = tree.treeView;
|
|
143
144
|
const compatibility = useViewCompatibility(view);
|
|
144
145
|
const root = useViewRoot(view);
|
|
145
|
-
const upgradeSchema =
|
|
146
|
+
const upgradeSchema = useCallback(() => view.upgradeSchema(), [view]);
|
|
146
147
|
// Note: this policy is on the stricter side and ensures that clients will only be able to submit edits when their view schema
|
|
147
148
|
// supports exactly the same documents as the stored schema.
|
|
148
149
|
// A realistic production application using this strategy would need to take steps to attempt to open the document using
|
|
@@ -151,12 +152,12 @@ export function TreeViewComponent({ tree, viewComponent: ViewComponent, errorCom
|
|
|
151
152
|
// Alternative policies can be implemented, see "Schema Evolvability" in SharedTree's README for more information.
|
|
152
153
|
if (!compatibility.isEquivalent) {
|
|
153
154
|
const Error = errorComponent ?? TreeErrorComponent;
|
|
154
|
-
return
|
|
155
|
+
return _jsx(Error, { compatibility: compatibility, upgradeSchema: upgradeSchema });
|
|
155
156
|
}
|
|
156
157
|
if (root === undefined) {
|
|
157
|
-
return
|
|
158
|
+
return _jsx("div", { children: "View not set" });
|
|
158
159
|
}
|
|
159
|
-
return
|
|
160
|
+
return _jsx(ViewComponent, { root: toPropTreeNode(root) });
|
|
160
161
|
}
|
|
161
162
|
/**
|
|
162
163
|
* React component which displays schema errors and allows upgrading schema when possible.
|
|
@@ -164,13 +165,10 @@ export function TreeViewComponent({ tree, viewComponent: ViewComponent, errorCom
|
|
|
164
165
|
function TreeErrorComponent({ compatibility, upgradeSchema, }) {
|
|
165
166
|
// eslint-disable-next-line unicorn/prefer-ternary
|
|
166
167
|
if (compatibility.canUpgrade) {
|
|
167
|
-
return (
|
|
168
|
-
React.createElement("div", null, "Document is incompatible with current version of the application, but the document format can be updated. This may prevent other versions of the application from opening this document."),
|
|
169
|
-
React.createElement("button", { onClick: upgradeSchema }, "Upgrade"),
|
|
170
|
-
";"));
|
|
168
|
+
return (_jsxs("div", { children: [_jsx("div", { children: "Document is incompatible with current version of the application, but the document format can be updated. This may prevent other versions of the application from opening this document." }), _jsx("button", { onClick: upgradeSchema, children: "Upgrade" }), ";"] }));
|
|
171
169
|
}
|
|
172
170
|
else {
|
|
173
|
-
return (
|
|
171
|
+
return (_jsx("div", { children: "Document is incompatible with current version of the application, and the document format cannot be updated. The document is likely from a newer or otherwise incompatible version of the application, or a different application." }));
|
|
174
172
|
}
|
|
175
173
|
}
|
|
176
174
|
//# sourceMappingURL=reactSharedTreeView.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactSharedTreeView.js","sourceRoot":"","sources":["../src/reactSharedTreeView.tsx"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tPureDataObjectFactory,\n\tTreeDataObject,\n\tcreateDataObjectKind,\n} from \"@fluidframework/aqueduct/internal\";\nimport type { IFluidLoadable } from \"@fluidframework/core-interfaces\";\nimport type { IFluidDataStoreFactory } from \"@fluidframework/runtime-definitions/internal\";\nimport type { SharedObjectKind } from \"@fluidframework/shared-object-base\";\nimport type {\n\tSchemaCompatibilityStatus,\n\tTreeViewConfiguration,\n\tTreeFieldFromImplicitField,\n\tTreeView,\n\tImplicitFieldSchema,\n\tInsertableTreeFieldFromImplicitField,\n} from \"@fluidframework/tree\";\nimport { configuredSharedTree, FormatValidatorBasic } from \"@fluidframework/tree/internal\";\nimport * as React from \"react\";\n\nimport { toPropTreeNode, type PropTreeValue } from \"./propNode.js\";\n\n/**\n * Opt into extra validation to detect encoding bugs and data corruption.\n * As long as this is an experimental package, opting into extra validation (at a small perf and bundle size cost) seems reasonable.\n */\nconst SharedTree = configuredSharedTree({\n\tjsonValidator: FormatValidatorBasic,\n});\n\n/**\n * Defines a DataObject for a {@link @fluidframework/tree#SharedTree} with a built in {@link @fluidframework/tree#TreeViewConfiguration}.\n * @param treeConfiguration - See {@link IReactTreeDataObject.config}.\n * @param createInitialTree - Function which populates the tree with initial data on document create.\n * @returns A {@link @fluidframework/fluid-static#DataObjectClass} to allow easy use of a SharedTree in a ContainerSchema.\n * @alpha\n */\nexport function treeDataObject<TSchema extends ImplicitFieldSchema>(\n\ttreeConfiguration: TreeViewConfiguration<TSchema>,\n\tcreateInitialTree: () => InsertableTreeFieldFromImplicitField<TSchema>,\n): SharedObjectKind<IReactTreeDataObject<TSchema> & IFluidLoadable> {\n\treturn treeDataObjectInternal(treeConfiguration, createInitialTree);\n}\n\n/**\n * Defines a DataObject for a {@link @fluidframework/tree#SharedTree} with a built in {@link @fluidframework/tree#TreeViewConfiguration}.\n * @param treeConfiguration - See {@link IReactTreeDataObject.config}.\n * @param createInitialTree - Function which populates the tree with initial data on document create.\n * @returns A {@link @fluidframework/fluid-static#DataObjectClass} to allow easy use of a SharedTree in a ContainerSchema.\n * @internal\n */\nexport function treeDataObjectInternal<TSchema extends ImplicitFieldSchema>(\n\ttreeConfiguration: TreeViewConfiguration<TSchema>,\n\tcreateInitialTree: () => InsertableTreeFieldFromImplicitField<TSchema>,\n): SharedObjectKind<IReactTreeDataObject<TSchema> & IFluidLoadable & TreeDataObject> & {\n\treadonly factory: IFluidDataStoreFactory;\n} {\n\tclass SchemaAwareTreeDataObject extends ReactTreeDataObject<TSchema> {\n\t\tpublic override readonly config = treeConfiguration;\n\n\t\tpublic static readonly factory = new PureDataObjectFactory<ReactTreeDataObject<TSchema>>(\n\t\t\t`TreeDataObject`,\n\t\t\tSchemaAwareTreeDataObject,\n\t\t\t[SharedTree.getFactory()],\n\t\t\t{},\n\t\t);\n\n\t\t#treeView: TreeView<TSchema> | undefined;\n\n\t\t/**\n\t\t * The schema-aware view of the tree.\n\t\t */\n\t\tpublic get treeView(): TreeView<TSchema> {\n\t\t\tif (this.#treeView === undefined) {\n\t\t\t\tthrow new Error(\"treeView has not been initialized.\");\n\t\t\t}\n\t\t\treturn this.#treeView;\n\t\t}\n\n\t\t/**\n\t\t * Converts the underlying ITree into a typed TreeView using the provided schema configuration.\n\t\t *\n\t\t * @param tree - The ITree instance to view.\n\t\t * @returns A typed TreeView using the TodoList schema.\n\t\t */\n\t\tprivate initializeView(): void {\n\t\t\tthis.#treeView = this.tree.viewWith(this.config);\n\t\t}\n\n\t\tprotected override async initializingFirstTime(): Promise<void> {\n\t\t\tthis.initializeView();\n\t\t\tthis.treeView.initialize(createInitialTree());\n\t\t}\n\n\t\tprotected override async initializingFromExisting(): Promise<void> {\n\t\t\tthis.initializeView();\n\t\t}\n\t}\n\treturn createDataObjectKind(SchemaAwareTreeDataObject);\n}\n\n/**\n * A schema-aware tree-backed DataObject, extended with a React Component to view the tree.\n * @remarks Allows for the Tree's schema to be baked into the container schema.\n * @sealed @alpha\n */\nexport interface IReactTreeDataObject<TSchema extends ImplicitFieldSchema> {\n\t/**\n\t * The configuration used to initialize new documents, as well as to interpret (schematize) existing ones.\n\t *\n\t * @remarks\n\t * The fact that a single view schema is provided here (on the data object) makes it impossible to try and apply multiple different schema.\n\t * Since the view schema currently does not provide any adapters for handling differences between view and stored schema,\n\t * it's also impossible for this single view schema to handle multiple different stored schema.\n\t * Therefore, with this current API, two different applications (or different versions of the same application)\n\t * with differing stored schema requirements (as implied by their view schema) can not collaborate on the same tree.\n\t * The only schema evolution that's currently possible is upgrading the schema to one that supports a superset of what the old schema allowed,\n\t * and collaborating between clients which have view schema that exactly correspond to that stored schema.\n\t * Future work on tree as well as these utilities should address this limitation.\n\t */\n\treadonly config: TreeViewConfiguration<TSchema>;\n\n\t/**\n\t * The schema-aware view of the tree.\n\t */\n\treadonly treeView: TreeView<TSchema>;\n\n\t/**\n\t * React component which handles schematizing trees.\n\t * This includes displaying errors when the document can not be viewed using the view schema.\n\t *\n\t * @privateRemarks\n\t * This is exposed as a member rather than a free function since type inference for the schema doesn't work when used as a free function,\n\t * and thus making it a member avoids the user of this from having to explicitly provide the type parameter.\n\t * This is an arrow function not a method so it gets the correct this when not called as a member.\n\t */\n\treadonly TreeViewComponent: (props: TreeViewProps<TSchema>) => React.JSX.Element;\n}\n\n/**\n * React props for viewing a tree.\n * @input @alpha\n */\nexport interface TreeViewProps<TSchema extends ImplicitFieldSchema> {\n\t/**\n\t * Component to display the tree content.\n\t */\n\treadonly viewComponent: React.FC<{\n\t\troot: PropTreeValue<TreeFieldFromImplicitField<TSchema>>;\n\t}>;\n\n\t/**\n\t * Component to display instead of the {@link TreeViewProps.viewComponent}\n\t * when tree content is not compatible with the {@link @fluidframework/tree#TreeViewConfiguration}.\n\t *\n\t * @defaultValue Component which describes the situation (in English) and allows the user to upgrade the schema to match the {@link @fluidframework/tree#TreeViewConfiguration} if possible.\n\t */\n\treadonly errorComponent?: React.FC<SchemaIncompatibleProps>;\n\n\t// TODO: Once its possible to query the status of individual schema upgrades, provide more options here for handling such cases.\n}\n\n/**\n * Generic DataObject for shared trees.\n * @internal\n */\nexport abstract class ReactTreeDataObject<\n\t\tTSchema extends ImplicitFieldSchema = ImplicitFieldSchema,\n\t>\n\textends TreeDataObject\n\timplements IReactTreeDataObject<TSchema>\n{\n\tpublic abstract readonly config: TreeViewConfiguration<TSchema>;\n\n\treadonly #treeView: TreeView<TSchema> | undefined;\n\n\t/**\n\t * The schema-aware view of the tree.\n\t */\n\tpublic get treeView(): TreeView<TSchema> {\n\t\tif (this.#treeView === undefined) {\n\t\t\tthrow new Error(\"treeView has not been initialized.\");\n\t\t}\n\t\treturn this.#treeView;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type\n\tpublic readonly TreeViewComponent = ({\n\t\tviewComponent,\n\t\terrorComponent,\n\t}: TreeViewProps<TSchema>) =>\n\t\tTreeViewComponent<TSchema>({\n\t\t\ttree: this,\n\t\t\tviewComponent,\n\t\t\terrorComponent,\n\t\t});\n}\n\nfunction useViewCompatibility<TSchema extends ImplicitFieldSchema>(\n\tview: TreeView<TSchema>,\n): SchemaCompatibilityStatus {\n\tconst [compatibility, setCompatibility] = React.useState<SchemaCompatibilityStatus>(\n\t\tview.compatibility,\n\t);\n\n\tReact.useEffect(() => {\n\t\tconst updateCompatibility = (): void => {\n\t\t\tsetCompatibility(view.compatibility);\n\t\t};\n\n\t\tupdateCompatibility();\n\t\treturn view.events.on(\"schemaChanged\", updateCompatibility);\n\t}, [view]);\n\n\treturn compatibility;\n}\n\nfunction useViewRoot<TSchema extends ImplicitFieldSchema>(\n\tview: TreeView<TSchema>,\n): TreeFieldFromImplicitField<TSchema> | undefined {\n\tconst [root, setRoot] = React.useState<TreeFieldFromImplicitField<TSchema> | undefined>(\n\t\tundefined,\n\t);\n\n\tReact.useEffect(() => {\n\t\tconst updateRoot = (): void => {\n\t\t\tif (view.compatibility.canView) {\n\t\t\t\tsetRoot(view.root);\n\t\t\t} else {\n\t\t\t\tsetRoot(undefined);\n\t\t\t}\n\t\t};\n\n\t\tupdateRoot();\n\t\treturn view.events.on(\"rootChanged\", updateRoot);\n\t}, [view]);\n\n\treturn root;\n}\n\n/**\n * React component which handles schematizing trees.\n * This includes displaying errors when the document can not be schematized.\n * @alpha\n */\nexport function TreeViewComponent<TSchema extends ImplicitFieldSchema>({\n\ttree,\n\tviewComponent: ViewComponent,\n\terrorComponent,\n}: TreeViewProps<TSchema> & {\n\ttree: Pick<IReactTreeDataObject<TSchema>, \"treeView\">;\n}): React.JSX.Element {\n\tconst view = tree.treeView;\n\n\tconst compatibility = useViewCompatibility(view);\n\tconst root = useViewRoot(view);\n\tconst upgradeSchema = React.useCallback((): void => view.upgradeSchema(), [view]);\n\n\t// Note: this policy is on the stricter side and ensures that clients will only be able to submit edits when their view schema\n\t// supports exactly the same documents as the stored schema.\n\t// A realistic production application using this strategy would need to take steps to attempt to open the document using\n\t// several different view schemas in order to ensure that their users don't temporarily lose access to documents while\n\t// code rollout is in progress.\n\t// Alternative policies can be implemented, see \"Schema Evolvability\" in SharedTree's README for more information.\n\tif (!compatibility.isEquivalent) {\n\t\tconst Error = errorComponent ?? TreeErrorComponent;\n\t\treturn <Error compatibility={compatibility} upgradeSchema={upgradeSchema} />;\n\t}\n\n\tif (root === undefined) {\n\t\treturn <div>View not set</div>;\n\t}\n\n\treturn <ViewComponent root={toPropTreeNode(root)} />;\n}\n\n/**\n * React Props for displaying when the opened document is incompatible with the required view schema.\n * @alpha\n */\nexport interface SchemaIncompatibleProps {\n\t/**\n\t * Information about the view schema's compatibility with the stored schema.\n\t */\n\treadonly compatibility: SchemaCompatibilityStatus;\n\t/**\n\t * Callback to request that the stored schema in the document be upgraded.\n\t */\n\treadonly upgradeSchema: () => void;\n}\n\n/**\n * React component which displays schema errors and allows upgrading schema when possible.\n */\nfunction TreeErrorComponent({\n\tcompatibility,\n\tupgradeSchema,\n}: {\n\tcompatibility: SchemaCompatibilityStatus;\n\tupgradeSchema: () => void;\n}): React.JSX.Element {\n\t// eslint-disable-next-line unicorn/prefer-ternary\n\tif (compatibility.canUpgrade) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<div>\n\t\t\t\t\tDocument is incompatible with current version of the application, but the document\n\t\t\t\t\tformat can be updated. This may prevent other versions of the application from\n\t\t\t\t\topening this document.\n\t\t\t\t</div>\n\t\t\t\t<button onClick={upgradeSchema}>Upgrade</button>;\n\t\t\t</div>\n\t\t);\n\t} else {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tDocument is incompatible with current version of the application, and the document\n\t\t\t\tformat cannot be updated. The document is likely from a newer or otherwise incompatible\n\t\t\t\tversion of the application, or a different application.\n\t\t\t</div>\n\t\t);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"reactSharedTreeView.js","sourceRoot":"","sources":["../src/reactSharedTreeView.tsx"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tPureDataObjectFactory,\n\tTreeDataObject,\n\tcreateDataObjectKind,\n} from \"@fluidframework/aqueduct/internal\";\nimport type { IFluidLoadable } from \"@fluidframework/core-interfaces\";\nimport type { IFluidDataStoreFactory } from \"@fluidframework/runtime-definitions/internal\";\nimport type { SharedObjectKind } from \"@fluidframework/shared-object-base\";\nimport type {\n\tSchemaCompatibilityStatus,\n\tTreeViewConfiguration,\n\tTreeFieldFromImplicitField,\n\tTreeView,\n\tImplicitFieldSchema,\n\tInsertableTreeFieldFromImplicitField,\n} from \"@fluidframework/tree\";\nimport { configuredSharedTree, FormatValidatorBasic } from \"@fluidframework/tree/internal\";\nimport { type FC, type JSX, useCallback, useEffect, useState } from \"react\";\n\nimport { toPropTreeNode, type PropTreeValue } from \"./propNode.js\";\n\n/**\n * Opt into extra validation to detect encoding bugs and data corruption.\n * As long as this is an experimental package, opting into extra validation (at a small perf and bundle size cost) seems reasonable.\n */\nconst SharedTree = configuredSharedTree({\n\tjsonValidator: FormatValidatorBasic,\n});\n\n/**\n * Defines a DataObject for a {@link @fluidframework/tree#SharedTree} with a built in {@link @fluidframework/tree#TreeViewConfiguration}.\n * @param treeConfiguration - See {@link IReactTreeDataObject.config}.\n * @param createInitialTree - Function which populates the tree with initial data on document create.\n * @returns A {@link @fluidframework/fluid-static#DataObjectClass} to allow easy use of a SharedTree in a ContainerSchema.\n * @alpha\n */\nexport function treeDataObject<TSchema extends ImplicitFieldSchema>(\n\ttreeConfiguration: TreeViewConfiguration<TSchema>,\n\tcreateInitialTree: () => InsertableTreeFieldFromImplicitField<TSchema>,\n): SharedObjectKind<IReactTreeDataObject<TSchema> & IFluidLoadable> {\n\treturn treeDataObjectInternal(treeConfiguration, createInitialTree);\n}\n\n/**\n * Defines a DataObject for a {@link @fluidframework/tree#SharedTree} with a built in {@link @fluidframework/tree#TreeViewConfiguration}.\n * @param treeConfiguration - See {@link IReactTreeDataObject.config}.\n * @param createInitialTree - Function which populates the tree with initial data on document create.\n * @returns A {@link @fluidframework/fluid-static#DataObjectClass} to allow easy use of a SharedTree in a ContainerSchema.\n * @internal\n */\nexport function treeDataObjectInternal<TSchema extends ImplicitFieldSchema>(\n\ttreeConfiguration: TreeViewConfiguration<TSchema>,\n\tcreateInitialTree: () => InsertableTreeFieldFromImplicitField<TSchema>,\n): SharedObjectKind<IReactTreeDataObject<TSchema> & IFluidLoadable & TreeDataObject> & {\n\treadonly factory: IFluidDataStoreFactory;\n} {\n\tclass SchemaAwareTreeDataObject extends ReactTreeDataObject<TSchema> {\n\t\tpublic override readonly config = treeConfiguration;\n\n\t\tpublic static readonly factory = new PureDataObjectFactory<ReactTreeDataObject<TSchema>>(\n\t\t\t`TreeDataObject`,\n\t\t\tSchemaAwareTreeDataObject,\n\t\t\t[SharedTree.getFactory()],\n\t\t\t{},\n\t\t);\n\n\t\t#treeView: TreeView<TSchema> | undefined;\n\n\t\t/**\n\t\t * The schema-aware view of the tree.\n\t\t */\n\t\tpublic get treeView(): TreeView<TSchema> {\n\t\t\tif (this.#treeView === undefined) {\n\t\t\t\tthrow new Error(\"treeView has not been initialized.\");\n\t\t\t}\n\t\t\treturn this.#treeView;\n\t\t}\n\n\t\t/**\n\t\t * Converts the underlying ITree into a typed TreeView using the provided schema configuration.\n\t\t *\n\t\t * @param tree - The ITree instance to view.\n\t\t * @returns A typed TreeView using the TodoList schema.\n\t\t */\n\t\tprivate initializeView(): void {\n\t\t\tthis.#treeView = this.tree.viewWith(this.config);\n\t\t}\n\n\t\tprotected override async initializingFirstTime(): Promise<void> {\n\t\t\tthis.initializeView();\n\t\t\tthis.treeView.initialize(createInitialTree());\n\t\t}\n\n\t\tprotected override async initializingFromExisting(): Promise<void> {\n\t\t\tthis.initializeView();\n\t\t}\n\t}\n\treturn createDataObjectKind(SchemaAwareTreeDataObject);\n}\n\n/**\n * A schema-aware tree-backed DataObject, extended with a React Component to view the tree.\n * @remarks Allows for the Tree's schema to be baked into the container schema.\n * @sealed @alpha\n */\nexport interface IReactTreeDataObject<TSchema extends ImplicitFieldSchema> {\n\t/**\n\t * The configuration used to initialize new documents, as well as to interpret (schematize) existing ones.\n\t *\n\t * @remarks\n\t * The fact that a single view schema is provided here (on the data object) makes it impossible to try and apply multiple different schema.\n\t * Since the view schema currently does not provide any adapters for handling differences between view and stored schema,\n\t * it's also impossible for this single view schema to handle multiple different stored schema.\n\t * Therefore, with this current API, two different applications (or different versions of the same application)\n\t * with differing stored schema requirements (as implied by their view schema) can not collaborate on the same tree.\n\t * The only schema evolution that's currently possible is upgrading the schema to one that supports a superset of what the old schema allowed,\n\t * and collaborating between clients which have view schema that exactly correspond to that stored schema.\n\t * Future work on tree as well as these utilities should address this limitation.\n\t */\n\treadonly config: TreeViewConfiguration<TSchema>;\n\n\t/**\n\t * The schema-aware view of the tree.\n\t */\n\treadonly treeView: TreeView<TSchema>;\n\n\t/**\n\t * React component which handles schematizing trees.\n\t * This includes displaying errors when the document can not be viewed using the view schema.\n\t *\n\t * @privateRemarks\n\t * This is exposed as a member rather than a free function since type inference for the schema doesn't work when used as a free function,\n\t * and thus making it a member avoids the user of this from having to explicitly provide the type parameter.\n\t * This is an arrow function not a method so it gets the correct this when not called as a member.\n\t */\n\treadonly TreeViewComponent: (props: TreeViewProps<TSchema>) => JSX.Element;\n}\n\n/**\n * React props for viewing a tree.\n * @input @alpha\n */\nexport interface TreeViewProps<TSchema extends ImplicitFieldSchema> {\n\t/**\n\t * Component to display the tree content.\n\t */\n\treadonly viewComponent: FC<{\n\t\troot: PropTreeValue<TreeFieldFromImplicitField<TSchema>>;\n\t}>;\n\n\t/**\n\t * Component to display instead of the {@link TreeViewProps.viewComponent}\n\t * when tree content is not compatible with the {@link @fluidframework/tree#TreeViewConfiguration}.\n\t *\n\t * @defaultValue Component which describes the situation (in English) and allows the user to upgrade the schema to match the {@link @fluidframework/tree#TreeViewConfiguration} if possible.\n\t */\n\treadonly errorComponent?: FC<SchemaIncompatibleProps>;\n\n\t// TODO: Once its possible to query the status of individual schema upgrades, provide more options here for handling such cases.\n}\n\n/**\n * Generic DataObject for shared trees.\n * @internal\n */\nexport abstract class ReactTreeDataObject<\n\t\tTSchema extends ImplicitFieldSchema = ImplicitFieldSchema,\n\t>\n\textends TreeDataObject\n\timplements IReactTreeDataObject<TSchema>\n{\n\tpublic abstract readonly config: TreeViewConfiguration<TSchema>;\n\n\treadonly #treeView: TreeView<TSchema> | undefined;\n\n\t/**\n\t * The schema-aware view of the tree.\n\t */\n\tpublic get treeView(): TreeView<TSchema> {\n\t\tif (this.#treeView === undefined) {\n\t\t\tthrow new Error(\"treeView has not been initialized.\");\n\t\t}\n\t\treturn this.#treeView;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type\n\tpublic readonly TreeViewComponent = ({\n\t\tviewComponent,\n\t\terrorComponent,\n\t}: TreeViewProps<TSchema>) =>\n\t\tTreeViewComponent<TSchema>({\n\t\t\ttree: this,\n\t\t\tviewComponent,\n\t\t\terrorComponent,\n\t\t});\n}\n\nfunction useViewCompatibility<TSchema extends ImplicitFieldSchema>(\n\tview: TreeView<TSchema>,\n): SchemaCompatibilityStatus {\n\tconst [compatibility, setCompatibility] = useState<SchemaCompatibilityStatus>(\n\t\tview.compatibility,\n\t);\n\n\tuseEffect(() => {\n\t\tconst updateCompatibility = (): void => {\n\t\t\tsetCompatibility(view.compatibility);\n\t\t};\n\n\t\tupdateCompatibility();\n\t\treturn view.events.on(\"schemaChanged\", updateCompatibility);\n\t}, [view]);\n\n\treturn compatibility;\n}\n\nfunction useViewRoot<TSchema extends ImplicitFieldSchema>(\n\tview: TreeView<TSchema>,\n): TreeFieldFromImplicitField<TSchema> | undefined {\n\tconst [root, setRoot] = useState<TreeFieldFromImplicitField<TSchema> | undefined>(undefined);\n\n\tuseEffect(() => {\n\t\tconst updateRoot = (): void => {\n\t\t\tif (view.compatibility.canView) {\n\t\t\t\tsetRoot(view.root);\n\t\t\t} else {\n\t\t\t\tsetRoot(undefined);\n\t\t\t}\n\t\t};\n\n\t\tupdateRoot();\n\t\treturn view.events.on(\"rootChanged\", updateRoot);\n\t}, [view]);\n\n\treturn root;\n}\n\n/**\n * React component which handles schematizing trees.\n * This includes displaying errors when the document can not be schematized.\n * @alpha\n */\nexport function TreeViewComponent<TSchema extends ImplicitFieldSchema>({\n\ttree,\n\tviewComponent: ViewComponent,\n\terrorComponent,\n}: TreeViewProps<TSchema> & {\n\ttree: Pick<IReactTreeDataObject<TSchema>, \"treeView\">;\n}): JSX.Element {\n\tconst view = tree.treeView;\n\n\tconst compatibility = useViewCompatibility(view);\n\tconst root = useViewRoot(view);\n\tconst upgradeSchema = useCallback((): void => view.upgradeSchema(), [view]);\n\n\t// Note: this policy is on the stricter side and ensures that clients will only be able to submit edits when their view schema\n\t// supports exactly the same documents as the stored schema.\n\t// A realistic production application using this strategy would need to take steps to attempt to open the document using\n\t// several different view schemas in order to ensure that their users don't temporarily lose access to documents while\n\t// code rollout is in progress.\n\t// Alternative policies can be implemented, see \"Schema Evolvability\" in SharedTree's README for more information.\n\tif (!compatibility.isEquivalent) {\n\t\tconst Error = errorComponent ?? TreeErrorComponent;\n\t\treturn <Error compatibility={compatibility} upgradeSchema={upgradeSchema} />;\n\t}\n\n\tif (root === undefined) {\n\t\treturn <div>View not set</div>;\n\t}\n\n\treturn <ViewComponent root={toPropTreeNode(root)} />;\n}\n\n/**\n * React Props for displaying when the opened document is incompatible with the required view schema.\n * @alpha\n */\nexport interface SchemaIncompatibleProps {\n\t/**\n\t * Information about the view schema's compatibility with the stored schema.\n\t */\n\treadonly compatibility: SchemaCompatibilityStatus;\n\t/**\n\t * Callback to request that the stored schema in the document be upgraded.\n\t */\n\treadonly upgradeSchema: () => void;\n}\n\n/**\n * React component which displays schema errors and allows upgrading schema when possible.\n */\nfunction TreeErrorComponent({\n\tcompatibility,\n\tupgradeSchema,\n}: {\n\tcompatibility: SchemaCompatibilityStatus;\n\tupgradeSchema: () => void;\n}): JSX.Element {\n\t// eslint-disable-next-line unicorn/prefer-ternary\n\tif (compatibility.canUpgrade) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<div>\n\t\t\t\t\tDocument is incompatible with current version of the application, but the document\n\t\t\t\t\tformat can be updated. This may prevent other versions of the application from\n\t\t\t\t\topening this document.\n\t\t\t\t</div>\n\t\t\t\t<button onClick={upgradeSchema}>Upgrade</button>;\n\t\t\t</div>\n\t\t);\n\t} else {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tDocument is incompatible with current version of the application, and the document\n\t\t\t\tformat cannot be updated. The document is likely from a newer or otherwise incompatible\n\t\t\t\tversion of the application, or a different application.\n\t\t\t</div>\n\t\t);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import globalJsdom from "global-jsdom";
|
|
6
|
+
// Set up JSDOM before any modules are loaded (Quill needs document at import time)
|
|
7
|
+
const cleanup = globalJsdom();
|
|
8
|
+
// Remove JSDOM after imports are done, but before we run any tests.
|
|
9
|
+
// Tests which require JSDOM can call globalJsdom() to setup their own clean dom.
|
|
10
|
+
before(() => {
|
|
11
|
+
cleanup();
|
|
12
|
+
});
|
|
13
|
+
//# sourceMappingURL=mochaHooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mochaHooks.js","sourceRoot":"","sources":["../../src/test/mochaHooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,WAAW,MAAM,cAAc,CAAC;AAEvC,mFAAmF;AACnF,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;AAE9B,oEAAoE;AACpE,iFAAiF;AACjF,MAAM,CAAC,GAAG,EAAE;IACX,OAAO,EAAE,CAAC;AACX,CAAC,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport globalJsdom from \"global-jsdom\";\n\n// Set up JSDOM before any modules are loaded (Quill needs document at import time)\nconst cleanup = globalJsdom();\n\n// Remove JSDOM after imports are done, but before we run any tests.\n// Tests which require JSDOM can call globalJsdom() to setup their own clean dom.\nbefore(() => {\n\tcleanup();\n});\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
2
|
/*!
|
|
2
3
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
4
|
* Licensed under the MIT License.
|
|
@@ -8,7 +9,6 @@ import { SchemaFactory, TreeViewConfiguration } from "@fluidframework/tree";
|
|
|
8
9
|
import { independentView } from "@fluidframework/tree/internal";
|
|
9
10
|
import { render } from "@testing-library/react";
|
|
10
11
|
import globalJsdom from "global-jsdom";
|
|
11
|
-
import * as React from "react";
|
|
12
12
|
import { treeDataObject, TreeViewComponent } from "../reactSharedTreeView.js";
|
|
13
13
|
describe("reactSharedTreeView", () => {
|
|
14
14
|
it("treeDataObject", async () => {
|
|
@@ -51,10 +51,10 @@ describe("reactSharedTreeView", () => {
|
|
|
51
51
|
const builder = new SchemaFactory("tree-react-api");
|
|
52
52
|
class Item extends builder.object("Item", {}) {
|
|
53
53
|
}
|
|
54
|
-
const View = ({ root }) => (
|
|
54
|
+
const View = ({ root }) => (_jsx("span", { children: "View" }));
|
|
55
55
|
it("TreeViewComponent", () => {
|
|
56
56
|
const view = independentView(new TreeViewConfiguration({ schema: Item }));
|
|
57
|
-
const content =
|
|
57
|
+
const content = _jsx(TreeViewComponent, { viewComponent: View, tree: { treeView: view } });
|
|
58
58
|
const rendered = render(content, { reactStrictMode });
|
|
59
59
|
// Ensure that viewing an incompatible document displays an error.
|
|
60
60
|
assert.match(rendered.baseElement.textContent ?? "", /Document is incompatible/);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactSharedTreeView.spec.js","sourceRoot":"","sources":["../../src/test/reactSharedTreeView.spec.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,WAAW,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"reactSharedTreeView.spec.js","sourceRoot":"","sources":["../../src/test/reactSharedTreeView.spec.tsx"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport type { ContainerSchema } from \"@fluidframework/fluid-static\";\nimport { TinyliciousClient } from \"@fluidframework/tinylicious-client\";\nimport { SchemaFactory, TreeViewConfiguration } from \"@fluidframework/tree\";\nimport { independentView } from \"@fluidframework/tree/internal\";\nimport { render } from \"@testing-library/react\";\nimport globalJsdom from \"global-jsdom\";\nimport type { JSX } from \"react\";\n\nimport type { PropTreeNode } from \"../propNode.js\";\nimport { treeDataObject, TreeViewComponent } from \"../reactSharedTreeView.js\";\n\ndescribe(\"reactSharedTreeView\", () => {\n\tit(\"treeDataObject\", async () => {\n\t\tconst builder = new SchemaFactory(\"tree-react-api\");\n\n\t\tclass Inventory extends builder.object(\"Contoso:InventoryItem-1.0.0\", {\n\t\t\tnuts: builder.number,\n\t\t\tbolts: builder.number,\n\t\t}) {}\n\n\t\tconst containerSchema = {\n\t\t\tinitialObjects: {\n\t\t\t\t// TODO: it seems odd that DataObjects in container schema need both a key under initialObjects where they are,\n\t\t\t\t// as well as a key under the root data object, and SharedObjects only need one key.\n\t\t\t\t// Maybe we can default the shared object's key to be derived from the data objects key by default?\n\t\t\t\ttree: treeDataObject(\n\t\t\t\t\tnew TreeViewConfiguration({ schema: Inventory }),\n\t\t\t\t\t() => new Inventory({ nuts: 5, bolts: 6 }),\n\t\t\t\t),\n\t\t\t},\n\t\t} satisfies ContainerSchema;\n\n\t\t// TODO: Ideally we would use a local-server service-client, but one does not appear to exist.\n\t\tconst tinyliciousClient = new TinyliciousClient();\n\n\t\tconst { container } = await tinyliciousClient.createContainer(containerSchema, \"2\");\n\t\tconst dataObject = container.initialObjects.tree;\n\t\tassert.equal(dataObject.treeView.root.nuts, 5);\n\t\tdataObject.treeView.root.nuts += 1;\n\t\tassert.equal(dataObject.treeView.root.bolts, 6);\n\t});\n\n\tdescribe(\"dom tests\", () => {\n\t\tlet cleanup: () => void;\n\n\t\tbefore(() => {\n\t\t\tcleanup = globalJsdom();\n\t\t});\n\n\t\tafter(() => {\n\t\t\tcleanup();\n\t\t});\n\n\t\t// Run without strict mode to make sure it works in a normal production setup.\n\t\t// Run with strict mode to potentially detect additional issues.\n\t\t// Note that React's strict mode is not more strict,\n\t\t// but instead drastically changes when the component code and its effects run to exercise more edge cases and detect certain kinds of bugs.\n\t\tfor (const reactStrictMode of [false, true]) {\n\t\t\tdescribe(`StrictMode: ${reactStrictMode}`, () => {\n\t\t\t\tconst builder = new SchemaFactory(\"tree-react-api\");\n\n\t\t\t\tclass Item extends builder.object(\"Item\", {}) {}\n\n\t\t\t\tconst View = ({ root }: { root: PropTreeNode<Item> }): JSX.Element => (\n\t\t\t\t\t<span>View</span>\n\t\t\t\t);\n\n\t\t\t\tit(\"TreeViewComponent\", () => {\n\t\t\t\t\tconst view = independentView(new TreeViewConfiguration({ schema: Item }));\n\t\t\t\t\tconst content = <TreeViewComponent viewComponent={View} tree={{ treeView: view }} />;\n\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t// Ensure that viewing an incompatible document displays an error.\n\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Document is incompatible/);\n\t\t\t\t\t// Ensure that changes in compatibility are detected and invalidate the view,\n\t\t\t\t\t// and that compatible documents show the content from `viewComponent`\n\t\t\t\t\tview.initialize(new Item({}));\n\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\tassert.equal(rendered.baseElement.textContent, \"View\");\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t});\n});\n"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { strict as assert } from "node:assert";
|
|
6
|
+
// Allow import of file being tested
|
|
7
|
+
// eslint-disable-next-line import-x/no-internal-modules
|
|
8
|
+
import { computeSync } from "../../text/plain/plainUtils.js";
|
|
9
|
+
describe("plainUtils", () => {
|
|
10
|
+
describe("computeSync", () => {
|
|
11
|
+
/**
|
|
12
|
+
* Calls computeSync, applies the returned ops to a copy of `existing`,
|
|
13
|
+
* asserts the result equals `final`, and returns the ops for further assertions.
|
|
14
|
+
*/
|
|
15
|
+
function computeSyncAndValidate(existing, final) {
|
|
16
|
+
const ops = computeSync(existing, final);
|
|
17
|
+
const result = [...existing];
|
|
18
|
+
if (ops.remove) {
|
|
19
|
+
result.splice(ops.remove.start, ops.remove.end - ops.remove.start);
|
|
20
|
+
}
|
|
21
|
+
if (ops.insert) {
|
|
22
|
+
result.splice(ops.insert.location, 0, ...ops.insert.slice);
|
|
23
|
+
}
|
|
24
|
+
assert.deepEqual(result, [...final]);
|
|
25
|
+
return ops;
|
|
26
|
+
}
|
|
27
|
+
it("works for two empty arrays", () => {
|
|
28
|
+
computeSyncAndValidate([], []);
|
|
29
|
+
});
|
|
30
|
+
it("returns no ops for identical arrays", () => {
|
|
31
|
+
const ops = computeSyncAndValidate(["a", "b", "c"], ["a", "b", "c"]);
|
|
32
|
+
assert.equal(ops.remove, undefined);
|
|
33
|
+
assert.equal(ops.insert, undefined);
|
|
34
|
+
});
|
|
35
|
+
it("inserts all elements when existing is empty", () => {
|
|
36
|
+
computeSyncAndValidate([], ["a", "b", "c"]);
|
|
37
|
+
});
|
|
38
|
+
it("removes all elements when final is empty", () => {
|
|
39
|
+
computeSyncAndValidate(["a", "b", "c"], []);
|
|
40
|
+
});
|
|
41
|
+
it("replaces all elements when arrays are completely different", () => {
|
|
42
|
+
computeSyncAndValidate(["a", "b"], ["c", "d"]);
|
|
43
|
+
});
|
|
44
|
+
it("appends element to end", () => {
|
|
45
|
+
const ops = computeSyncAndValidate(["a", "b"], ["a", "b", "c"]);
|
|
46
|
+
assert.equal(ops.remove, undefined);
|
|
47
|
+
});
|
|
48
|
+
it("removes element from end", () => {
|
|
49
|
+
const ops = computeSyncAndValidate(["a", "b", "c"], ["a", "b"]);
|
|
50
|
+
assert.equal(ops.insert, undefined);
|
|
51
|
+
});
|
|
52
|
+
it("prepends element at start", () => {
|
|
53
|
+
const ops = computeSyncAndValidate(["b", "c"], ["a", "b", "c"]);
|
|
54
|
+
assert.equal(ops.remove, undefined);
|
|
55
|
+
});
|
|
56
|
+
it("removes element from start", () => {
|
|
57
|
+
const ops = computeSyncAndValidate(["a", "b", "c"], ["b", "c"]);
|
|
58
|
+
assert.equal(ops.insert, undefined);
|
|
59
|
+
});
|
|
60
|
+
it("replaces middle section", () => {
|
|
61
|
+
const ops = computeSyncAndValidate(["a", "b", "c", "d"], ["a", "x", "y", "d"]);
|
|
62
|
+
assert.deepEqual(ops.remove, { start: 1, end: 3 });
|
|
63
|
+
assert.deepEqual(ops.insert, { location: 1, slice: ["x", "y"] });
|
|
64
|
+
});
|
|
65
|
+
it("inserts into the middle of an existing array", () => {
|
|
66
|
+
const ops = computeSyncAndValidate(["a", "d"], ["a", "b", "c", "d"]);
|
|
67
|
+
assert.equal(ops.remove, undefined);
|
|
68
|
+
});
|
|
69
|
+
it("removes from the middle of an existing array", () => {
|
|
70
|
+
const ops = computeSyncAndValidate(["a", "b", "c", "d"], ["a", "d"]);
|
|
71
|
+
assert.equal(ops.insert, undefined);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=plainUtils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plainUtils.test.js","sourceRoot":"","sources":["../../../src/test/text/plainUtils.test.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\n// Allow import of file being tested\n// eslint-disable-next-line import-x/no-internal-modules\nimport { computeSync } from \"../../text/plain/plainUtils.js\";\n\ndescribe(\"plainUtils\", () => {\n\tdescribe(\"computeSync\", () => {\n\t\t/**\n\t\t * Calls computeSync, applies the returned ops to a copy of `existing`,\n\t\t * asserts the result equals `final`, and returns the ops for further assertions.\n\t\t */\n\t\tfunction computeSyncAndValidate<T>(\n\t\t\texisting: readonly T[],\n\t\t\tfinal: readonly T[],\n\t\t): ReturnType<typeof computeSync<T>> {\n\t\t\tconst ops = computeSync(existing, final);\n\t\t\tconst result = [...existing];\n\t\t\tif (ops.remove) {\n\t\t\t\tresult.splice(ops.remove.start, ops.remove.end - ops.remove.start);\n\t\t\t}\n\t\t\tif (ops.insert) {\n\t\t\t\tresult.splice(ops.insert.location, 0, ...ops.insert.slice);\n\t\t\t}\n\t\t\tassert.deepEqual(result, [...final]);\n\t\t\treturn ops;\n\t\t}\n\n\t\tit(\"works for two empty arrays\", () => {\n\t\t\tcomputeSyncAndValidate([], []);\n\t\t});\n\n\t\tit(\"returns no ops for identical arrays\", () => {\n\t\t\tconst ops = computeSyncAndValidate([\"a\", \"b\", \"c\"], [\"a\", \"b\", \"c\"]);\n\t\t\tassert.equal(ops.remove, undefined);\n\t\t\tassert.equal(ops.insert, undefined);\n\t\t});\n\n\t\tit(\"inserts all elements when existing is empty\", () => {\n\t\t\tcomputeSyncAndValidate([], [\"a\", \"b\", \"c\"]);\n\t\t});\n\n\t\tit(\"removes all elements when final is empty\", () => {\n\t\t\tcomputeSyncAndValidate([\"a\", \"b\", \"c\"], []);\n\t\t});\n\n\t\tit(\"replaces all elements when arrays are completely different\", () => {\n\t\t\tcomputeSyncAndValidate([\"a\", \"b\"], [\"c\", \"d\"]);\n\t\t});\n\n\t\tit(\"appends element to end\", () => {\n\t\t\tconst ops = computeSyncAndValidate([\"a\", \"b\"], [\"a\", \"b\", \"c\"]);\n\t\t\tassert.equal(ops.remove, undefined);\n\t\t});\n\n\t\tit(\"removes element from end\", () => {\n\t\t\tconst ops = computeSyncAndValidate([\"a\", \"b\", \"c\"], [\"a\", \"b\"]);\n\t\t\tassert.equal(ops.insert, undefined);\n\t\t});\n\n\t\tit(\"prepends element at start\", () => {\n\t\t\tconst ops = computeSyncAndValidate([\"b\", \"c\"], [\"a\", \"b\", \"c\"]);\n\t\t\tassert.equal(ops.remove, undefined);\n\t\t});\n\n\t\tit(\"removes element from start\", () => {\n\t\t\tconst ops = computeSyncAndValidate([\"a\", \"b\", \"c\"], [\"b\", \"c\"]);\n\t\t\tassert.equal(ops.insert, undefined);\n\t\t});\n\n\t\tit(\"replaces middle section\", () => {\n\t\t\tconst ops = computeSyncAndValidate([\"a\", \"b\", \"c\", \"d\"], [\"a\", \"x\", \"y\", \"d\"]);\n\t\t\tassert.deepEqual(ops.remove, { start: 1, end: 3 });\n\t\t\tassert.deepEqual(ops.insert, { location: 1, slice: [\"x\", \"y\"] });\n\t\t});\n\n\t\tit(\"inserts into the middle of an existing array\", () => {\n\t\t\tconst ops = computeSyncAndValidate([\"a\", \"d\"], [\"a\", \"b\", \"c\", \"d\"]);\n\t\t\tassert.equal(ops.remove, undefined);\n\t\t});\n\n\t\tit(\"removes from the middle of an existing array\", () => {\n\t\t\tconst ops = computeSyncAndValidate([\"a\", \"b\", \"c\", \"d\"], [\"a\", \"d\"]);\n\t\t\tassert.equal(ops.insert, undefined);\n\t\t});\n\t});\n});\n"]}
|