@fluidframework/react 2.90.0 → 2.92.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/api-report/react.alpha.api.md +8 -8
  3. package/lib/alpha.d.ts +1 -1
  4. package/lib/beta.d.ts +1 -1
  5. package/lib/index.d.ts +1 -1
  6. package/lib/index.d.ts.map +1 -1
  7. package/lib/index.js +1 -1
  8. package/lib/index.js.map +1 -1
  9. package/lib/public.d.ts +1 -1
  10. package/lib/reactSharedTreeView.d.ts +6 -6
  11. package/lib/reactSharedTreeView.d.ts.map +1 -1
  12. package/lib/reactSharedTreeView.js +16 -18
  13. package/lib/reactSharedTreeView.js.map +1 -1
  14. package/lib/test/reactSharedTreeView.spec.js +3 -3
  15. package/lib/test/reactSharedTreeView.spec.js.map +1 -1
  16. package/lib/test/text/textEditor.test.js +89 -676
  17. package/lib/test/text/textEditor.test.js.map +1 -1
  18. package/lib/test/useObservation.spec.js +8 -8
  19. package/lib/test/useObservation.spec.js.map +1 -1
  20. package/lib/test/useTree.spec.js +15 -15
  21. package/lib/test/useTree.spec.js.map +1 -1
  22. package/lib/text/index.d.ts +3 -2
  23. package/lib/text/index.d.ts.map +1 -1
  24. package/lib/text/index.js +1 -2
  25. package/lib/text/index.js.map +1 -1
  26. package/lib/text/plain/index.d.ts +1 -1
  27. package/lib/text/plain/index.d.ts.map +1 -1
  28. package/lib/text/plain/index.js +1 -1
  29. package/lib/text/plain/index.js.map +1 -1
  30. package/lib/text/plain/plainTextView.d.ts +6 -3
  31. package/lib/text/plain/plainTextView.d.ts.map +1 -1
  32. package/lib/text/plain/plainTextView.js +16 -21
  33. package/lib/text/plain/plainTextView.js.map +1 -1
  34. package/lib/text/plain/plainUtils.d.ts +1 -0
  35. package/lib/text/plain/plainUtils.d.ts.map +1 -1
  36. package/lib/text/plain/plainUtils.js +1 -0
  37. package/lib/text/plain/plainUtils.js.map +1 -1
  38. package/lib/useObservation.js +6 -6
  39. package/lib/useObservation.js.map +1 -1
  40. package/lib/useTree.d.ts +7 -7
  41. package/lib/useTree.d.ts.map +1 -1
  42. package/lib/useTree.js +6 -6
  43. package/lib/useTree.js.map +1 -1
  44. package/package.json +16 -17
  45. package/react.test-files.tar +0 -0
  46. package/src/index.ts +1 -9
  47. package/src/reactSharedTreeView.tsx +11 -13
  48. package/src/text/index.ts +3 -10
  49. package/src/text/plain/index.ts +1 -1
  50. package/src/text/plain/plainTextView.tsx +7 -7
  51. package/src/text/plain/plainUtils.ts +1 -0
  52. package/src/useObservation.ts +6 -6
  53. package/src/useTree.ts +19 -12
  54. package/tsconfig.json +0 -6
  55. package/lib/test/mochaHooks.js +0 -13
  56. package/lib/test/mochaHooks.js.map +0 -1
  57. package/lib/text/formatted/index.d.ts +0 -6
  58. package/lib/text/formatted/index.d.ts.map +0 -1
  59. package/lib/text/formatted/index.js +0 -6
  60. package/lib/text/formatted/index.js.map +0 -1
  61. package/lib/text/formatted/quillFormattedView.d.ts +0 -54
  62. package/lib/text/formatted/quillFormattedView.d.ts.map +0 -1
  63. package/lib/text/formatted/quillFormattedView.js +0 -426
  64. package/lib/text/formatted/quillFormattedView.js.map +0 -1
  65. package/lib/text/plain/quillView.d.ts +0 -22
  66. package/lib/text/plain/quillView.d.ts.map +0 -1
  67. package/lib/text/plain/quillView.js +0 -112
  68. package/lib/text/plain/quillView.js.map +0 -1
  69. package/src/text/formatted/index.ts +0 -11
  70. package/src/text/formatted/quillFormattedView.tsx +0 -509
  71. package/src/text/plain/quillView.tsx +0 -149
package/src/text/index.ts CHANGED
@@ -3,13 +3,6 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- export {
7
- FormattedMainView,
8
- type FormattedMainViewProps,
9
- type FormattedEditorHandle,
10
- } from "./formatted/index.js";
11
- export {
12
- PlainTextMainView,
13
- QuillMainView as PlainQuillView,
14
- type MainViewProps as PlainMainViewProps,
15
- } from "./plain/index.js";
6
+ export { type PropTreeNode } from "../propNode.js";
7
+ export { type UndoRedo } from "../undoRedo.js";
8
+ export { PlainTextMainView, syncTextToTree } from "./plain/index.js";
@@ -4,4 +4,4 @@
4
4
  */
5
5
 
6
6
  export { MainView as PlainTextMainView } from "./plainTextView.js";
7
- export { MainView as QuillMainView, type MainViewProps } from "./quillView.js";
7
+ export { syncTextToTree } from "./plainUtils.js";
@@ -4,12 +4,12 @@
4
4
  */
5
5
 
6
6
  import type { TextAsTree } from "@fluidframework/tree/internal";
7
- import * as React from "react";
7
+ import { type ChangeEvent, type FC, useCallback, useRef } from "react";
8
8
 
9
+ import type { PropTreeNode } from "../../propNode.js";
9
10
  import { withMemoizedTreeObservations } from "../../useTree.js";
10
11
 
11
12
  import { syncTextToTree } from "./plainUtils.js";
12
- import type { MainViewProps } from "./quillView.js";
13
13
 
14
14
  /**
15
15
  * A React component for plain text editing.
@@ -17,7 +17,7 @@ import type { MainViewProps } from "./quillView.js";
17
17
  * Uses {@link @fluidframework/tree#TextAsTree.Tree} for the data-model and an HTML textarea for the UI.
18
18
  * @internal
19
19
  */
20
- export const MainView: React.FC<MainViewProps> = ({ root }) => {
20
+ export const MainView: FC<{ root: PropTreeNode<TextAsTree.Tree> }> = ({ root }) => {
21
21
  return <PlainTextEditorView root={root} />;
22
22
  };
23
23
 
@@ -32,17 +32,17 @@ export const MainView: React.FC<MainViewProps> = ({ root }) => {
32
32
  const PlainTextEditorView = withMemoizedTreeObservations(
33
33
  ({ root }: { root: TextAsTree.Tree }) => {
34
34
  // Reference to the textarea element
35
- const textareaRef = React.useRef<HTMLTextAreaElement>(null);
35
+ const textareaRef = useRef<HTMLTextAreaElement>(null);
36
36
  // Guards against update loops between textarea and the tree
37
- const isUpdatingRef = React.useRef<boolean>(false);
37
+ const isUpdatingRef = useRef<boolean>(false);
38
38
 
39
39
  // Access tree content during render to establish observation.
40
40
  // The HOC will automatically re-render when this content changes.
41
41
  const currentText = root.fullString();
42
42
 
43
43
  // Handle textarea changes - sync textarea → tree
44
- const handleChange = React.useCallback(
45
- (event: React.ChangeEvent<HTMLTextAreaElement>) => {
44
+ const handleChange = useCallback(
45
+ (event: ChangeEvent<HTMLTextAreaElement>) => {
46
46
  if (isUpdatingRef.current) {
47
47
  return;
48
48
  }
@@ -7,6 +7,7 @@ import type { TextAsTree } from "@fluidframework/tree/internal";
7
7
 
8
8
  /**
9
9
  * Sync `newText` into the provided `root` tree.
10
+ * @internal
10
11
  */
11
12
  export function syncTextToTree(root: TextAsTree.Tree, newText: string): void {
12
13
  const sync = computeSync(root.charactersCopy(), [...newText]);
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import * as React from "react";
6
+ import { useEffect, useState } from "react";
7
7
 
8
8
  /**
9
9
  * Tracks and subscriptions from the latests render of a given instance of the {@link useObservation} hook.
@@ -68,7 +68,7 @@ export function useObservation<TResult>(
68
68
  options?: ObservationOptions,
69
69
  ): TResult {
70
70
  // Use a React state hook to invalidate this component something tracked by `trackDuring` changes.
71
- const [subscriptions, setSubscriptions] = React.useState<SubscriptionsWrapper>(
71
+ const [subscriptions, setSubscriptions] = useState<SubscriptionsWrapper>(
72
72
  new SubscriptionsWrapper(),
73
73
  );
74
74
 
@@ -115,7 +115,7 @@ export function useObservation<TResult>(
115
115
  // Suppressing that invalidation bug with an extra call to setSubscriptions could work, but would produce incorrect warnings about leaks,
116
116
  // and might cause infinite rerender depending on how StrictMode works.
117
117
  // Such an Effect would look like this:
118
- // React.useEffect(
118
+ // useEffect(
119
119
  // () => () => {
120
120
  // subscriptions.unsubscribe?.();
121
121
  // subscriptions.unsubscribe = undefined;
@@ -179,11 +179,11 @@ function useObservationPure<TResult>(
179
179
  options?: ObservationPureOptions,
180
180
  ): TResult {
181
181
  // Dummy state used to trigger invalidations.
182
- const [_subscriptions, setSubscriptions] = React.useState(0);
182
+ const [_subscriptions, setSubscriptions] = useState(0);
183
183
 
184
184
  const { result, subscribe } = trackDuring();
185
185
 
186
- React.useEffect(() => {
186
+ useEffect(() => {
187
187
  // Subscribe to events from the latest render
188
188
 
189
189
  const invalidate = (): void => {
@@ -363,7 +363,7 @@ export function useObservationStrict<TResult>(
363
363
  ): TResult {
364
364
  // Used to unsubscribe from the previous render's subscriptions.
365
365
  // See `useObservation` for a more documented explanation of this pattern.
366
- const [subscriptions] = React.useState<{
366
+ const [subscriptions] = useState<{
367
367
  previousTracker: SubscriptionTracker | undefined;
368
368
  }>({ previousTracker: undefined });
369
369
 
package/src/useTree.ts CHANGED
@@ -6,7 +6,14 @@
6
6
  import type { TreeLeafValue, TreeNode } from "@fluidframework/tree";
7
7
  import { Tree } from "@fluidframework/tree";
8
8
  import { TreeAlpha } from "@fluidframework/tree/internal";
9
- import * as React from "react";
9
+ import {
10
+ type FC,
11
+ memo,
12
+ type MemoExoticComponent,
13
+ type ReactNode,
14
+ useEffect,
15
+ useState,
16
+ } from "react";
10
17
 
11
18
  import {
12
19
  unwrapPropTreeNode,
@@ -29,10 +36,10 @@ import { useObservation, type ObservationOptions } from "./useObservation.js";
29
36
  export function useTree(subtreeRoot: TreeNode): number {
30
37
  // Use a React effect hook to invalidate this component when the subtreeRoot changes.
31
38
  // We do this by incrementing a counter, which is passed as a dependency to the effect hook.
32
- const [invalidations, setInvalidations] = React.useState(0);
39
+ const [invalidations, setInvalidations] = useState(0);
33
40
 
34
41
  // React effect hook that increments the 'invalidation' counter whenever subtreeRoot or any of its children change.
35
- React.useEffect(() => {
42
+ useEffect(() => {
36
43
  // Returns the cleanup function to be invoked when the component unmounts.
37
44
  return Tree.on(subtreeRoot, "treeChanged", () => {
38
45
  setInvalidations((i) => i + 1);
@@ -52,31 +59,31 @@ export function useTree(subtreeRoot: TreeNode): number {
52
59
  * It is recommended that sub-components which take in TreeNodes, if not defined using this higher order components, take the nodes in as {@link PropTreeNode}s.
53
60
  * Components defined using this higher order component can take in either raw TreeNodes or {@link PropTreeNode}s: the latter will be automatically unwrapped.
54
61
  * @privateRemarks
55
- * `React.FC` does not seem to be covariant over its input type, so to make use of this more ergonomic,
62
+ * `FC` does not seem to be covariant over its input type, so to make use of this more ergonomic,
56
63
  * the return type intersects the various ways this could be used (with or without PropTreeNode wrapping).
57
64
  * @alpha
58
65
  */
59
66
  export function withTreeObservations<TIn>(
60
- component: React.FC<TIn>,
67
+ component: FC<TIn>,
61
68
  options?: ObservationOptions,
62
- ): React.FC<TIn> & React.FC<WrapNodes<TIn>> & React.FC<TIn | WrapNodes<TIn>> {
63
- return (props: TIn | WrapNodes<TIn>): React.ReactNode =>
69
+ ): FC<TIn> & FC<WrapNodes<TIn>> & FC<TIn | WrapNodes<TIn>> {
70
+ return (props: TIn | WrapNodes<TIn>): ReactNode =>
64
71
  useTreeObservations(() => component(props as TIn), options);
65
72
  }
66
73
 
67
74
  /**
68
- * {@link withTreeObservations} wrapped with React.memo.
75
+ * {@link withTreeObservations} wrapped with memo.
69
76
  * @remarks
70
77
  * There is no special logic here, just a convenience wrapper.
71
78
  * @alpha
72
79
  */
73
80
  export function withMemoizedTreeObservations<TIn>(
74
- component: React.FC<TIn>,
81
+ component: FC<TIn>,
75
82
  options?: ObservationOptions & {
76
- readonly propsAreEqual?: Parameters<typeof React.memo>[1];
83
+ readonly propsAreEqual?: Parameters<typeof memo>[1];
77
84
  },
78
- ): React.MemoExoticComponent<ReturnType<typeof withTreeObservations<TIn>>> {
79
- return React.memo(withTreeObservations(component, options), options?.propsAreEqual);
85
+ ): MemoExoticComponent<ReturnType<typeof withTreeObservations<TIn>>> {
86
+ return memo(withTreeObservations(component, options), options?.propsAreEqual);
80
87
  }
81
88
 
82
89
  /**
package/tsconfig.json CHANGED
@@ -9,11 +9,5 @@
9
9
  "noUnusedLocals": false,
10
10
  // ES2021 needed for FinalizationRegistry
11
11
  "lib": ["ES2021", "DOM", "DOM.Iterable"],
12
- // Suppress type errors in Quill's use of quill-delta.
13
- // Without this, the quill code gives a lot of errors like:
14
- // node_modules/.pnpm/quill@2.0.3/node_modules/quill/blots/block.d.ts:6:17 - error TS2709: Cannot use namespace 'Delta' as a type.
15
- // These issues (and others, see imports of quill-delta) are likely related to quill-delta's export style not working well with node16 module resolution.
16
- // Quill internally uses `"moduleResolution": "bundler"` which seems to work properly with quill-delta's exports, but would be inconsistent with the rest of this repo.
17
- "skipLibCheck": true,
18
12
  },
19
13
  }
@@ -1,13 +0,0 @@
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
@@ -1 +0,0 @@
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,6 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- export { FormattedTextAsTree, FormattedMainView, type FormattedMainViewProps, type FormattedEditorHandle, } from "./quillFormattedView.js";
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/text/formatted/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC1B,MAAM,yBAAyB,CAAC"}
@@ -1,6 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- export { FormattedTextAsTree, FormattedMainView, } from "./quillFormattedView.js";
6
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/text/formatted/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,mBAAmB,EACnB,iBAAiB,GAGjB,MAAM,yBAAyB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n\tFormattedTextAsTree,\n\tFormattedMainView,\n\ttype FormattedMainViewProps,\n\ttype FormattedEditorHandle,\n} from \"./quillFormattedView.js\";\n"]}
@@ -1,54 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { FormattedTextAsTree } from "@fluidframework/tree/internal";
6
- export { FormattedTextAsTree } from "@fluidframework/tree/internal";
7
- import DeltaPackage from "quill-delta";
8
- import * as React from "react";
9
- import { type PropTreeNode } from "../../propNode.js";
10
- import type { UndoRedo } from "../../undoRedo.js";
11
- type Delta = DeltaPackage.default;
12
- declare const Delta: typeof DeltaPackage.default;
13
- /**
14
- * Props for the FormattedMainView component.
15
- * @input @internal
16
- */
17
- export interface FormattedMainViewProps {
18
- readonly root: PropTreeNode<FormattedTextAsTree.Tree>;
19
- /** Optional undo/redo stack for the editor. */
20
- readonly undoRedo?: UndoRedo;
21
- }
22
- /**
23
- * Ref handle exposing undo/redo methods for the formatted editor.
24
- * @input @internal
25
- */
26
- export type FormattedEditorHandle = Pick<UndoRedo, "undo" | "redo">;
27
- /**
28
- * A React component for formatted text editing.
29
- * @remarks
30
- * Uses {@link @fluidframework/tree#FormattedTextAsTree.Tree} for the data-model and Quill for the rich text editor UI.
31
- * @internal
32
- */
33
- export declare const FormattedMainView: React.ForwardRefExoticComponent<FormattedMainViewProps & React.RefAttributes<FormattedEditorHandle>>;
34
- /**
35
- * Parse CSS font-size from a pasted HTML element's inline style.
36
- * Returns a Quill size name if the pixel value matches a supported size, undefined otherwise.
37
- * 12px is the default size and returns undefined (no Quill attribute needed).
38
- */
39
- export declare function parseCssFontSize(node: HTMLElement): string | undefined;
40
- /**
41
- * Parse CSS font-family from a pasted HTML element's inline style.
42
- * Tries fonts in priority order (first to last per CSS spec) and returns
43
- * the first recognized Quill font value.
44
- */
45
- export declare function parseCssFontFamily(node: HTMLElement): string | undefined;
46
- /**
47
- * Clipboard matcher that preserves recognized font-size and font-family
48
- * from pasted HTML elements. Applies each format independently via
49
- * compose/retain so new attributes can be added without risk of an
50
- * early return skipping them.
51
- * @see https://quilljs.com/docs/modules/clipboard#addmatcher
52
- */
53
- export declare function clipboardFormatMatcher(node: Node, delta: Delta): Delta;
54
- //# sourceMappingURL=quillFormattedView.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"quillFormattedView.d.ts","sourceRoot":"","sources":["../../../src/text/formatted/quillFormattedView.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAmB,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACrF,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE,OAAO,YAAY,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,mBAAmB,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGlD,KAAK,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC;AAElC,QAAA,MAAM,KAAK,6BAAuB,CAAC;AAEnC;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACtD,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,sGAK5B,CAAC;AAaH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAiBtE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAkBxE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CActE"}