@fluentui-copilot/react-editor-input 0.4.11 → 0.5.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.json CHANGED
@@ -2,7 +2,22 @@
2
2
  "name": "@fluentui-copilot/react-editor-input",
3
3
  "entries": [
4
4
  {
5
- "date": "Mon, 19 May 2025 18:03:23 GMT",
5
+ "date": "Wed, 28 May 2025 23:41:19 GMT",
6
+ "tag": "@fluentui-copilot/react-editor-input_v0.5.0",
7
+ "version": "0.5.0",
8
+ "comments": {
9
+ "minor": [
10
+ {
11
+ "author": "owcampbe@microsoft.com",
12
+ "package": "@fluentui-copilot/react-editor-input",
13
+ "commit": "914b30d1dd5b9e19a2a156578894a7b8163f9caf",
14
+ "comment": "feat: Remove preventDefaultValueOnChange prop."
15
+ }
16
+ ]
17
+ }
18
+ },
19
+ {
20
+ "date": "Mon, 19 May 2025 18:04:27 GMT",
6
21
  "tag": "@fluentui-copilot/react-editor-input_v0.4.11",
7
22
  "version": "0.4.11",
8
23
  "comments": {
package/CHANGELOG.md CHANGED
@@ -1,9 +1,18 @@
1
1
  # Change Log - @fluentui-copilot/react-editor-input
2
2
 
3
- This log was last generated on Sat, 03 May 2025 01:27:44 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 28 May 2025 23:41:19 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## [0.5.0](https://github.com/microsoft/fluentai/tree/@fluentui-copilot/react-editor-input_v0.5.0)
8
+
9
+ Wed, 28 May 2025 23:41:19 GMT
10
+ [Compare changes](https://github.com/microsoft/fluentai/compare/@fluentui-copilot/react-editor-input_v0.4.11..@fluentui-copilot/react-editor-input_v0.5.0)
11
+
12
+ ### Minor changes
13
+
14
+ - feat: Remove preventDefaultValueOnChange prop. ([PR #3032](https://github.com/microsoft/fluentai/pull/3032) by owcampbe@microsoft.com)
15
+
7
16
  ## [0.4.10](https://github.com/microsoft/fluentai/tree/@fluentui-copilot/react-editor-input_v0.4.10)
8
17
 
9
18
  Sat, 03 May 2025 01:27:44 GMT
package/dist/index.d.ts CHANGED
@@ -24,6 +24,13 @@ export declare type EditorInputProps = Omit<ComponentProps<Partial<EditorInputSl
24
24
  * If defaultValue is a function, it can call lexical $ functions to imperatively set the initial content with more complex nodes.
25
25
  */
26
26
  defaultValue?: string | (() => void);
27
+ /**
28
+ * Called when the default value is given to the editor.
29
+ * If `defaultValue` was a function, this will be called with the state of the editor after
30
+ * calling that function.
31
+ * If `defaultValue` was a string, this will be called with the same string.
32
+ */
33
+ onDefaultValueSet?: (defaultValue: string) => void;
27
34
  /**
28
35
  * Callback for when the user changes the value.
29
36
  * TODO: Add proper event type for callback
@@ -63,11 +70,6 @@ export declare type EditorInputProps = Omit<ComponentProps<Partial<EditorInputSl
63
70
  * @default true
64
71
  */
65
72
  isSentinelNodeEnabled?: boolean;
66
- /**
67
- * By default when the `defaultValue` is inserted into the editor, `onChange` is triggered.
68
- * When this prop is true, if `defaultValue` is a string, `onChange` will not be triggered with its value.
69
- */
70
- preventDefaultValueOnChange?: boolean;
71
73
  };
72
74
 
73
75
  export declare type EditorInputSlots = {
@@ -81,7 +83,6 @@ export declare type EditorInputSlots = {
81
83
  */
82
84
  export declare type EditorInputState = ComponentState<EditorInputSlots> & Required<Pick<EditorInputProps, 'disabled' | 'textPlugin' | 'history' | 'trimWhiteSpace' | 'editorRef' | 'isSentinelNodeEnabled'>> & Partial<Pick<EditorInputProps, 'onPaste'>> & {
83
85
  lexicalInitialConfig: InitialConfigType;
84
- defaultValue?: string;
85
86
  handleOnChange: (value: string) => void;
86
87
  };
87
88
 
@@ -1 +1 @@
1
- {"version":3,"sources":["EditorInput.types.ts"],"sourcesContent":["import type { InitialConfigType, LexicalEditor, LexicalPlainTextPlugin } from '@fluentui-copilot/react-text-editor';\nimport type { ComponentProps, ComponentState, Slot } from '@fluentui/react-components';\n\nexport type EditorInputSlots = {\n root: NonNullable<Slot<'span'>>;\n input: NonNullable<Slot<'span'>>;\n placeholderValue?: Slot<'span'>;\n};\n\n/**\n * EditorInput Props\n */\nexport type EditorInputProps = Omit<\n ComponentProps<Partial<EditorInputSlots>, 'input'>,\n 'onChange' | 'onPaste' | 'defaultValue' | 'onSubmit'\n> & {\n disabled?: boolean;\n /**\n * If defaultValue is a string, it will be added to the input on first render.\n * If defaultValue is a function, it can call lexical $ functions to imperatively set the initial content with more complex nodes.\n */\n defaultValue?: string | (() => void);\n /**\n * Callback for when the user changes the value.\n * TODO: Add proper event type for callback\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onChange?: (ev: any, data: EditorInputValueData) => void;\n /**\n * Callback for when content is pasted into the Editor.\n */\n onPaste?: (ev: ClipboardEvent) => void;\n /**\n * When true, the input will be cleared when only whitespace is remaining.\n * @default false\n */\n trimWhiteSpace?: boolean;\n /**\n * Used to register any custom nodes used by plugins added. Can also be used to override the default nodes.\n */\n customNodes?: InitialConfigType['nodes'];\n /**\n * The plugin which is in charge of initializing Lexical and is given the `input` and `placeholder` slots\n * @default LexicalPlainTextPlugin\n */\n textPlugin?: typeof LexicalPlainTextPlugin;\n /**\n * Controls whether history is tracked to provide undo and redo functionality\n * @default true\n */\n history?: boolean;\n\n editorRef?: React.RefObject<LexicalEditor>;\n\n /**\n * Customize the default styles of elements inserted by Lexical in the editor.\n */\n customTheme?: InitialConfigType['theme'];\n\n /**\n * Whether or not to enable the sentinel node. The sentinel node is a node that is inserted at the end of the editor\n * The SentinelNode fixes a Safari bug in lexical versions below 0.20.1\n * @default true\n */\n isSentinelNodeEnabled?: boolean;\n /**\n * By default when the `defaultValue` is inserted into the editor, `onChange` is triggered.\n * When this prop is true, if `defaultValue` is a string, `onChange` will not be triggered with its value.\n */\n preventDefaultValueOnChange?: boolean;\n};\n\n/**\n * State used in rendering EditorInput\n */\nexport type EditorInputState = ComponentState<EditorInputSlots> &\n Required<\n Pick<\n EditorInputProps,\n 'disabled' | 'textPlugin' | 'history' | 'trimWhiteSpace' | 'editorRef' | 'isSentinelNodeEnabled'\n >\n > &\n Partial<Pick<EditorInputProps, 'onPaste'>> & {\n lexicalInitialConfig: InitialConfigType;\n defaultValue?: string;\n handleOnChange: (value: string) => void;\n };\n\n/**\n * Data passed to the `onChange` callback when the chat input's value changes.\n */\nexport type EditorInputValueData = {\n value: string;\n};\n"],"names":[],"rangeMappings":";;","mappings":"AAwFA;;CAEC,GACD,WAEE"}
1
+ {"version":3,"sources":["EditorInput.types.ts"],"sourcesContent":["import type { InitialConfigType, LexicalEditor, LexicalPlainTextPlugin } from '@fluentui-copilot/react-text-editor';\nimport type { ComponentProps, ComponentState, Slot } from '@fluentui/react-components';\n\nexport type EditorInputSlots = {\n root: NonNullable<Slot<'span'>>;\n input: NonNullable<Slot<'span'>>;\n placeholderValue?: Slot<'span'>;\n};\n\n/**\n * EditorInput Props\n */\nexport type EditorInputProps = Omit<\n ComponentProps<Partial<EditorInputSlots>, 'input'>,\n 'onChange' | 'onPaste' | 'defaultValue' | 'onSubmit'\n> & {\n disabled?: boolean;\n /**\n * If defaultValue is a string, it will be added to the input on first render.\n * If defaultValue is a function, it can call lexical $ functions to imperatively set the initial content with more complex nodes.\n */\n defaultValue?: string | (() => void);\n /**\n * Called when the default value is given to the editor.\n * If `defaultValue` was a function, this will be called with the state of the editor after\n * calling that function.\n * If `defaultValue` was a string, this will be called with the same string.\n */\n onDefaultValueSet?: (defaultValue: string) => void;\n /**\n * Callback for when the user changes the value.\n * TODO: Add proper event type for callback\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onChange?: (ev: any, data: EditorInputValueData) => void;\n /**\n * Callback for when content is pasted into the Editor.\n */\n onPaste?: (ev: ClipboardEvent) => void;\n /**\n * When true, the input will be cleared when only whitespace is remaining.\n * @default false\n */\n trimWhiteSpace?: boolean;\n /**\n * Used to register any custom nodes used by plugins added. Can also be used to override the default nodes.\n */\n customNodes?: InitialConfigType['nodes'];\n /**\n * The plugin which is in charge of initializing Lexical and is given the `input` and `placeholder` slots\n * @default LexicalPlainTextPlugin\n */\n textPlugin?: typeof LexicalPlainTextPlugin;\n /**\n * Controls whether history is tracked to provide undo and redo functionality\n * @default true\n */\n history?: boolean;\n\n editorRef?: React.RefObject<LexicalEditor>;\n\n /**\n * Customize the default styles of elements inserted by Lexical in the editor.\n */\n customTheme?: InitialConfigType['theme'];\n\n /**\n * Whether or not to enable the sentinel node. The sentinel node is a node that is inserted at the end of the editor\n * The SentinelNode fixes a Safari bug in lexical versions below 0.20.1\n * @default true\n */\n isSentinelNodeEnabled?: boolean;\n};\n\n/**\n * State used in rendering EditorInput\n */\nexport type EditorInputState = ComponentState<EditorInputSlots> &\n Required<\n Pick<\n EditorInputProps,\n 'disabled' | 'textPlugin' | 'history' | 'trimWhiteSpace' | 'editorRef' | 'isSentinelNodeEnabled'\n >\n > &\n Partial<Pick<EditorInputProps, 'onPaste'>> & {\n lexicalInitialConfig: InitialConfigType;\n handleOnChange: (value: string) => void;\n };\n\n/**\n * Data passed to the `onChange` callback when the chat input's value changes.\n */\nexport type EditorInputValueData = {\n value: string;\n};\n"],"names":[],"rangeMappings":";;","mappings":"AAyFA;;CAEC,GACD,WAEE"}
@@ -19,7 +19,6 @@ export const renderEditorInput_unstable = state => {
19
19
  onContentChange: state.handleOnChange,
20
20
  onPaste: state.onPaste,
21
21
  trimWhitespace: state.trimWhiteSpace,
22
- defaultValue: state.defaultValue,
23
22
  isSentinelNodeEnabled: state.isSentinelNodeEnabled
24
23
  }), state.history && /*#__PURE__*/_jsx(LexicalHistoryPlugin, {})]
25
24
  }), /*#__PURE__*/_jsx(LexicalEditorRefPlugin, {
@@ -1 +1 @@
1
- {"version":3,"sources":["renderEditorInput.tsx"],"sourcesContent":["/** @jsxRuntime automatic */\n/** @jsxImportSource @fluentui/react-jsx-runtime */\n\nimport { assertSlots } from '@fluentui/react-components';\nimport type { EditorInputState, EditorInputSlots } from './EditorInput.types';\nimport {\n LexicalComposer,\n LexicalErrorBoundary,\n LexicalEditorRefPlugin,\n LexicalHistoryPlugin,\n} from '@fluentui-copilot/react-text-editor';\nimport { BasicFunctionalityPlugin } from '@fluentui-copilot/react-chat-input-plugins';\n\n/**\n * Render the final JSX of EditorInput\n */\nexport const renderEditorInput_unstable = (state: EditorInputState) => {\n assertSlots<EditorInputSlots>(state);\n\n return (\n <state.root>\n <LexicalComposer initialConfig={state.lexicalInitialConfig}>\n <state.textPlugin\n contentEditable={<state.input />}\n ErrorBoundary={LexicalErrorBoundary}\n placeholder={state.placeholderValue ? <state.placeholderValue /> : null}\n />\n <>\n <BasicFunctionalityPlugin\n onContentChange={state.handleOnChange}\n onPaste={state.onPaste}\n trimWhitespace={state.trimWhiteSpace}\n defaultValue={state.defaultValue}\n isSentinelNodeEnabled={state.isSentinelNodeEnabled}\n />\n {state.history && <LexicalHistoryPlugin />}\n </>\n <LexicalEditorRefPlugin editorRef={state.editorRef} />\n </LexicalComposer>\n </state.root>\n );\n};\n"],"names":["assertSlots","LexicalComposer","LexicalErrorBoundary","LexicalEditorRefPlugin","LexicalHistoryPlugin","BasicFunctionalityPlugin","renderEditorInput_unstable","state","root","initialConfig","lexicalInitialConfig","textPlugin","contentEditable","input","ErrorBoundary","placeholder","placeholderValue","onContentChange","handleOnChange","onPaste","trimWhitespace","trimWhiteSpace","defaultValue","isSentinelNodeEnabled","history","editorRef"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,0BAA0B,GAC1B,iDAAiD;AAEjD,SAASA,WAAW,QAAQ,6BAA6B;AAEzD,SACEC,eAAe,EACfC,oBAAoB,EACpBC,sBAAsB,EACtBC,oBAAoB,QACf,sCAAsC;AAC7C,SAASC,wBAAwB,QAAQ,6CAA6C;AAEtF;;CAEC,GACD,OAAO,MAAMC,6BAA6B,CAACC;IACzCP,YAA8BO;IAE9B,qBACE,KAACA,MAAMC,IAAI;kBACT,cAAA,MAACP;YAAgBQ,eAAeF,MAAMG,oBAAoB;;8BACxD,KAACH,MAAMI,UAAU;oBACfC,+BAAiB,KAACL,MAAMM,KAAK;oBAC7BC,eAAeZ;oBACfa,aAAaR,MAAMS,gBAAgB,iBAAG,KAACT,MAAMS,gBAAgB,QAAM;;8BAErE;;sCACE,KAACX;4BACCY,iBAAiBV,MAAMW,cAAc;4BACrCC,SAASZ,MAAMY,OAAO;4BACtBC,gBAAgBb,MAAMc,cAAc;4BACpCC,cAAcf,MAAMe,YAAY;4BAChCC,uBAAuBhB,MAAMgB,qBAAqB;;wBAEnDhB,MAAMiB,OAAO,kBAAI,KAACpB;;;8BAErB,KAACD;oBAAuBsB,WAAWlB,MAAMkB,SAAS;;;;;AAI1D,EAAE"}
1
+ {"version":3,"sources":["renderEditorInput.tsx"],"sourcesContent":["/** @jsxRuntime automatic */\n/** @jsxImportSource @fluentui/react-jsx-runtime */\n\nimport { assertSlots } from '@fluentui/react-components';\nimport type { EditorInputState, EditorInputSlots } from './EditorInput.types';\nimport {\n LexicalComposer,\n LexicalErrorBoundary,\n LexicalEditorRefPlugin,\n LexicalHistoryPlugin,\n} from '@fluentui-copilot/react-text-editor';\nimport { BasicFunctionalityPlugin } from '@fluentui-copilot/react-chat-input-plugins';\n\n/**\n * Render the final JSX of EditorInput\n */\nexport const renderEditorInput_unstable = (state: EditorInputState) => {\n assertSlots<EditorInputSlots>(state);\n\n return (\n <state.root>\n <LexicalComposer initialConfig={state.lexicalInitialConfig}>\n <state.textPlugin\n contentEditable={<state.input />}\n ErrorBoundary={LexicalErrorBoundary}\n placeholder={state.placeholderValue ? <state.placeholderValue /> : null}\n />\n <>\n <BasicFunctionalityPlugin\n onContentChange={state.handleOnChange}\n onPaste={state.onPaste}\n trimWhitespace={state.trimWhiteSpace}\n isSentinelNodeEnabled={state.isSentinelNodeEnabled}\n />\n {state.history && <LexicalHistoryPlugin />}\n </>\n <LexicalEditorRefPlugin editorRef={state.editorRef} />\n </LexicalComposer>\n </state.root>\n );\n};\n"],"names":["assertSlots","LexicalComposer","LexicalErrorBoundary","LexicalEditorRefPlugin","LexicalHistoryPlugin","BasicFunctionalityPlugin","renderEditorInput_unstable","state","root","initialConfig","lexicalInitialConfig","textPlugin","contentEditable","input","ErrorBoundary","placeholder","placeholderValue","onContentChange","handleOnChange","onPaste","trimWhitespace","trimWhiteSpace","isSentinelNodeEnabled","history","editorRef"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,0BAA0B,GAC1B,iDAAiD;AAEjD,SAASA,WAAW,QAAQ,6BAA6B;AAEzD,SACEC,eAAe,EACfC,oBAAoB,EACpBC,sBAAsB,EACtBC,oBAAoB,QACf,sCAAsC;AAC7C,SAASC,wBAAwB,QAAQ,6CAA6C;AAEtF;;CAEC,GACD,OAAO,MAAMC,6BAA6B,CAACC;IACzCP,YAA8BO;IAE9B,qBACE,KAACA,MAAMC,IAAI;kBACT,cAAA,MAACP;YAAgBQ,eAAeF,MAAMG,oBAAoB;;8BACxD,KAACH,MAAMI,UAAU;oBACfC,+BAAiB,KAACL,MAAMM,KAAK;oBAC7BC,eAAeZ;oBACfa,aAAaR,MAAMS,gBAAgB,iBAAG,KAACT,MAAMS,gBAAgB,QAAM;;8BAErE;;sCACE,KAACX;4BACCY,iBAAiBV,MAAMW,cAAc;4BACrCC,SAASZ,MAAMY,OAAO;4BACtBC,gBAAgBb,MAAMc,cAAc;4BACpCC,uBAAuBf,MAAMe,qBAAqB;;wBAEnDf,MAAMgB,OAAO,kBAAI,KAACnB;;;8BAErB,KAACD;oBAAuBqB,WAAWjB,MAAMiB,SAAS;;;;;AAI1D,EAAE"}
@@ -1,11 +1,10 @@
1
1
  import * as React from 'react';
2
- import { getPartitionedNativeProps, slot, useId, useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-components';
3
- import { SentinelNode } from '@fluentui-copilot/chat-input-plugins';
2
+ import { getPartitionedNativeProps, slot, useFluent, useId, useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-components';
3
+ import { SentinelNode, SENTINEL_VALUE } from '@fluentui-copilot/chat-input-plugins';
4
+ import { $createTextNode, $insertNodes } from '@fluentui-copilot/react-text-editor';
5
+ import { $getRoot } from '@fluentui-copilot/react-text-editor';
4
6
  import { LexicalPlainTextPlugin, mergeRegister } from '@fluentui-copilot/react-text-editor';
5
- import { useControllableState } from '@fluentui/react-utilities';
6
- export const createInitialEditorState = defaultValue => {
7
- return `{"root":{"type":"root","children":[{"children":[{"text":${JSON.stringify(defaultValue)},"type":"text"}],"type":"paragraph"}]}}`;
8
- };
7
+ import { mergeCallbacks, useControllableState } from '@fluentui/react-utilities';
9
8
  /**
10
9
  * Create the state required to render EditorInput.
11
10
  *
@@ -24,8 +23,7 @@ export const useEditorInput_unstable = (props, ref) => {
24
23
  history = true,
25
24
  editorRef: userEditorRef,
26
25
  customTheme,
27
- isSentinelNodeEnabled = true,
28
- preventDefaultValueOnChange = false
26
+ isSentinelNodeEnabled = true
29
27
  } = props;
30
28
  const {
31
29
  root,
@@ -76,19 +74,7 @@ export const useEditorInput_unstable = (props, ref) => {
76
74
  value: newValue
77
75
  });
78
76
  }, [onChange]);
79
- const [defaultString, lexicalEditorStateDefaultValue] = React.useMemo(() => {
80
- if (typeof props.defaultValue === 'function') {
81
- return [undefined, props.defaultValue];
82
- }
83
- if (preventDefaultValueOnChange && props.defaultValue !== undefined) {
84
- // Any method of providing a default value to lexical which inserts it after initialization
85
- // will trigger a text content change.
86
- // Providing a default value as a stringified editorState will prevent calling onChange
87
- const editorState = createInitialEditorState(props.defaultValue);
88
- return [undefined, editorState];
89
- }
90
- return [props.defaultValue, undefined];
91
- }, [preventDefaultValueOnChange, props.defaultValue]);
77
+ const defaultValueFunction = useDefaultValueFunction(props);
92
78
  const placeholderValue = slot.optional(props.placeholderValue, {
93
79
  elementType: 'span'
94
80
  });
@@ -127,7 +113,7 @@ export const useEditorInput_unstable = (props, ref) => {
127
113
  namespace: 'fai-EditorInput',
128
114
  onError: console.error,
129
115
  nodes: customNodes,
130
- editorState: lexicalEditorStateDefaultValue,
116
+ editorState: defaultValueFunction,
131
117
  theme: customTheme
132
118
  },
133
119
  editorRef,
@@ -135,10 +121,40 @@ export const useEditorInput_unstable = (props, ref) => {
135
121
  textPlugin,
136
122
  onPaste,
137
123
  handleOnChange,
138
- defaultValue: defaultString,
139
124
  trimWhiteSpace,
140
125
  history,
141
126
  isSentinelNodeEnabled
142
127
  };
143
128
  };
129
+ function useDefaultValueFunction(props) {
130
+ var _targetDocument_defaultView;
131
+ const {
132
+ targetDocument
133
+ } = useFluent();
134
+ const requestAnimationFrame = targetDocument === null || targetDocument === void 0 ? void 0 : (_targetDocument_defaultView = targetDocument.defaultView) === null || _targetDocument_defaultView === void 0 ? void 0 : _targetDocument_defaultView.requestAnimationFrame;
135
+ const [defaultValueFunction] = React.useState(() => {
136
+ const {
137
+ defaultValue,
138
+ onDefaultValueSet
139
+ } = props;
140
+ if (defaultValue === undefined) {
141
+ return undefined;
142
+ }
143
+ const insertDefaultValueFunction = typeof defaultValue === 'function' ? defaultValue : () => {
144
+ $insertNodes([$createTextNode(defaultValue)]);
145
+ };
146
+ // After the defaultValue function has run, read back the result and give
147
+ // it to the onDefaultValueSet callback.
148
+ const readDefaultValueFunction = onDefaultValueSet ? () => {
149
+ const text = $getRoot().getTextContent().replace(SENTINEL_VALUE, '');
150
+ // This runs while rendering `LexicalComposer` so delay calling back into the parent
151
+ // until after finished rendering `LexicalComposer`
152
+ requestAnimationFrame === null || requestAnimationFrame === void 0 ? void 0 : requestAnimationFrame(() => {
153
+ onDefaultValueSet === null || onDefaultValueSet === void 0 ? void 0 : onDefaultValueSet(text);
154
+ });
155
+ } : undefined;
156
+ return mergeCallbacks(insertDefaultValueFunction, readDefaultValueFunction);
157
+ });
158
+ return defaultValueFunction;
159
+ }
144
160
  //# sourceMappingURL=useEditorInput.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["useEditorInput.tsx"],"sourcesContent":["import * as React from 'react';\nimport {\n getPartitionedNativeProps,\n slot,\n useId,\n useIsomorphicLayoutEffect,\n useMergedRefs,\n} from '@fluentui/react-components';\nimport type { EditorInputProps, EditorInputState } from './EditorInput.types';\nimport { SentinelNode } from '@fluentui-copilot/chat-input-plugins';\nimport type { LexicalEditor } from '@fluentui-copilot/react-text-editor';\nimport { LexicalPlainTextPlugin, mergeRegister } from '@fluentui-copilot/react-text-editor';\nimport { useControllableState } from '@fluentui/react-utilities';\n\nexport const createInitialEditorState = (defaultValue: string) => {\n return `{\"root\":{\"type\":\"root\",\"children\":[{\"children\":[{\"text\":${JSON.stringify(\n defaultValue,\n )},\"type\":\"text\"}],\"type\":\"paragraph\"}]}}`;\n};\n\n/**\n * Create the state required to render EditorInput.\n *\n * The returned state can be modified with hooks such as useEditorInputStyles_unstable,\n * before being passed to renderEditorInput_unstable.\n *\n * @param props - props from this instance of EditorInput\n * @param ref - reference to root HTMLElement of EditorInput\n */\nexport const useEditorInput_unstable = (props: EditorInputProps, ref: React.Ref<HTMLSpanElement>): EditorInputState => {\n const {\n onChange,\n onPaste,\n trimWhiteSpace = false,\n textPlugin = LexicalPlainTextPlugin,\n history = true,\n editorRef: userEditorRef,\n customTheme,\n isSentinelNodeEnabled = true,\n preventDefaultValueOnChange = false,\n } = props;\n const { root, primary } = getPartitionedNativeProps({\n primarySlotTagName: 'span',\n props,\n excludedPropNames: ['onChange', 'onPaste', 'defaultValue'],\n });\n\n const editorRef = useMergedRefs(React.useRef<LexicalEditor>(null), userEditorRef);\n // The disabled state can also be changed by lexical (e.g. by a custom plugin) so\n // we use `useControllableState` to coordinate\n const [disabled, setDisabled] = useControllableState({\n state: props.disabled,\n initialState: false,\n });\n\n const customNodes = props.customNodes ? [...props.customNodes, SentinelNode] : [SentinelNode];\n\n const spanRef = React.useCallback(\n span => {\n // Register the `input` span with lexical\n editorRef.current?.setRootElement(span);\n },\n [editorRef],\n );\n\n // Update lexical when disabled changes\n useIsomorphicLayoutEffect(() => {\n if (editorRef.current) {\n editorRef.current?.setEditable(!disabled);\n }\n }, [disabled]);\n\n useIsomorphicLayoutEffect(() => {\n if (editorRef.current) {\n return mergeRegister(\n editorRef.current.registerEditableListener(isEditable => {\n setDisabled(!isEditable);\n }),\n editorRef.current?.registerRootListener(root => {\n if (!root) {\n return;\n }\n\n // Remove lexical's inline style so we can apply our own\n // Lexical needs the whitespace style to be either `pre` or `pre-wrap` to work correctly\n root.style.whiteSpace = '';\n }),\n );\n }\n }, [editorRef]);\n\n const handleOnChange = React.useCallback(\n (newValue: string) => {\n onChange?.({}, { value: newValue });\n },\n [onChange],\n );\n\n const [defaultString, lexicalEditorStateDefaultValue] = React.useMemo(() => {\n if (typeof props.defaultValue === 'function') {\n return [undefined, props.defaultValue];\n }\n\n if (preventDefaultValueOnChange && props.defaultValue !== undefined) {\n // Any method of providing a default value to lexical which inserts it after initialization\n // will trigger a text content change.\n // Providing a default value as a stringified editorState will prevent calling onChange\n const editorState = createInitialEditorState(props.defaultValue);\n return [undefined, editorState];\n }\n\n return [props.defaultValue, undefined];\n }, [preventDefaultValueOnChange, props.defaultValue]);\n\n const placeholderValue = slot.optional(props.placeholderValue, { elementType: 'span' });\n const placeholderId = useId('chat-input-placeholder', placeholderValue?.id);\n if (placeholderValue) {\n placeholderValue.id = placeholderId;\n }\n\n return {\n components: {\n root: 'span',\n input: 'span',\n placeholderValue: 'span',\n },\n root: slot.always(props.root, { defaultProps: { ...root }, elementType: 'span' }),\n input: slot.always(props.input, {\n defaultProps: {\n ref: useMergedRefs(ref, spanRef),\n role: 'textbox',\n contentEditable: !disabled,\n 'aria-readonly': disabled ? true : undefined,\n disabled,\n suppressContentEditableWarning: true,\n tabIndex: disabled ? undefined : 0,\n ...primary,\n 'aria-describedby': primary['aria-describedby']\n ? `${primary['aria-describedby']} ${placeholderId}`\n : placeholderId,\n },\n elementType: 'span',\n }),\n placeholderValue,\n lexicalInitialConfig: {\n namespace: 'fai-EditorInput',\n onError: console.error,\n nodes: customNodes,\n editorState: lexicalEditorStateDefaultValue,\n theme: customTheme,\n },\n editorRef,\n disabled,\n textPlugin,\n onPaste,\n handleOnChange,\n defaultValue: defaultString,\n trimWhiteSpace,\n history,\n isSentinelNodeEnabled,\n };\n};\n"],"names":["React","getPartitionedNativeProps","slot","useId","useIsomorphicLayoutEffect","useMergedRefs","SentinelNode","LexicalPlainTextPlugin","mergeRegister","useControllableState","createInitialEditorState","defaultValue","JSON","stringify","useEditorInput_unstable","props","ref","onChange","onPaste","trimWhiteSpace","textPlugin","history","editorRef","userEditorRef","customTheme","isSentinelNodeEnabled","preventDefaultValueOnChange","root","primary","primarySlotTagName","excludedPropNames","useRef","disabled","setDisabled","state","initialState","customNodes","spanRef","useCallback","span","current","setRootElement","setEditable","registerEditableListener","isEditable","registerRootListener","style","whiteSpace","handleOnChange","newValue","value","defaultString","lexicalEditorStateDefaultValue","useMemo","undefined","editorState","placeholderValue","optional","elementType","placeholderId","id","components","input","always","defaultProps","role","contentEditable","suppressContentEditableWarning","tabIndex","lexicalInitialConfig","namespace","onError","console","error","nodes","theme"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["useEditorInput.tsx"],"sourcesContent":["import * as React from 'react';\nimport {\n getPartitionedNativeProps,\n slot,\n useFluent,\n useId,\n useIsomorphicLayoutEffect,\n useMergedRefs,\n} from '@fluentui/react-components';\nimport type { EditorInputProps, EditorInputState } from './EditorInput.types';\nimport { SentinelNode, SENTINEL_VALUE } from '@fluentui-copilot/chat-input-plugins';\nimport type { LexicalEditor } from '@fluentui-copilot/react-text-editor';\nimport { $createTextNode, $insertNodes } from '@fluentui-copilot/react-text-editor';\nimport { $getRoot } from '@fluentui-copilot/react-text-editor';\nimport { LexicalPlainTextPlugin, mergeRegister } from '@fluentui-copilot/react-text-editor';\nimport { mergeCallbacks, useControllableState } from '@fluentui/react-utilities';\n\n/**\n * Create the state required to render EditorInput.\n *\n * The returned state can be modified with hooks such as useEditorInputStyles_unstable,\n * before being passed to renderEditorInput_unstable.\n *\n * @param props - props from this instance of EditorInput\n * @param ref - reference to root HTMLElement of EditorInput\n */\nexport const useEditorInput_unstable = (props: EditorInputProps, ref: React.Ref<HTMLSpanElement>): EditorInputState => {\n const {\n onChange,\n onPaste,\n trimWhiteSpace = false,\n textPlugin = LexicalPlainTextPlugin,\n history = true,\n editorRef: userEditorRef,\n customTheme,\n isSentinelNodeEnabled = true,\n } = props;\n const { root, primary } = getPartitionedNativeProps({\n primarySlotTagName: 'span',\n props,\n excludedPropNames: ['onChange', 'onPaste', 'defaultValue'],\n });\n\n const editorRef = useMergedRefs(React.useRef<LexicalEditor>(null), userEditorRef);\n // The disabled state can also be changed by lexical (e.g. by a custom plugin) so\n // we use `useControllableState` to coordinate\n const [disabled, setDisabled] = useControllableState({\n state: props.disabled,\n initialState: false,\n });\n\n const customNodes = props.customNodes ? [...props.customNodes, SentinelNode] : [SentinelNode];\n\n const spanRef = React.useCallback(\n span => {\n // Register the `input` span with lexical\n editorRef.current?.setRootElement(span);\n },\n [editorRef],\n );\n\n // Update lexical when disabled changes\n useIsomorphicLayoutEffect(() => {\n if (editorRef.current) {\n editorRef.current?.setEditable(!disabled);\n }\n }, [disabled]);\n\n useIsomorphicLayoutEffect(() => {\n if (editorRef.current) {\n return mergeRegister(\n editorRef.current.registerEditableListener(isEditable => {\n setDisabled(!isEditable);\n }),\n editorRef.current?.registerRootListener(root => {\n if (!root) {\n return;\n }\n\n // Remove lexical's inline style so we can apply our own\n // Lexical needs the whitespace style to be either `pre` or `pre-wrap` to work correctly\n root.style.whiteSpace = '';\n }),\n );\n }\n }, [editorRef]);\n\n const handleOnChange = React.useCallback(\n (newValue: string) => {\n onChange?.({}, { value: newValue });\n },\n [onChange],\n );\n\n const defaultValueFunction = useDefaultValueFunction(props);\n\n const placeholderValue = slot.optional(props.placeholderValue, { elementType: 'span' });\n const placeholderId = useId('chat-input-placeholder', placeholderValue?.id);\n if (placeholderValue) {\n placeholderValue.id = placeholderId;\n }\n\n return {\n components: {\n root: 'span',\n input: 'span',\n placeholderValue: 'span',\n },\n root: slot.always(props.root, { defaultProps: { ...root }, elementType: 'span' }),\n input: slot.always(props.input, {\n defaultProps: {\n ref: useMergedRefs(ref, spanRef),\n role: 'textbox',\n contentEditable: !disabled,\n 'aria-readonly': disabled ? true : undefined,\n disabled,\n suppressContentEditableWarning: true,\n tabIndex: disabled ? undefined : 0,\n ...primary,\n 'aria-describedby': primary['aria-describedby']\n ? `${primary['aria-describedby']} ${placeholderId}`\n : placeholderId,\n },\n elementType: 'span',\n }),\n placeholderValue,\n lexicalInitialConfig: {\n namespace: 'fai-EditorInput',\n onError: console.error,\n nodes: customNodes,\n editorState: defaultValueFunction,\n theme: customTheme,\n },\n editorRef,\n disabled,\n textPlugin,\n onPaste,\n handleOnChange,\n trimWhiteSpace,\n history,\n isSentinelNodeEnabled,\n };\n};\n\nfunction useDefaultValueFunction(props: EditorInputProps) {\n const { targetDocument } = useFluent();\n const requestAnimationFrame = targetDocument?.defaultView?.requestAnimationFrame;\n\n const [defaultValueFunction] = React.useState(() => {\n const { defaultValue, onDefaultValueSet } = props;\n if (defaultValue === undefined) {\n return undefined;\n }\n\n const insertDefaultValueFunction =\n typeof defaultValue === 'function'\n ? defaultValue\n : () => {\n $insertNodes([$createTextNode(defaultValue)]);\n };\n\n // After the defaultValue function has run, read back the result and give\n // it to the onDefaultValueSet callback.\n const readDefaultValueFunction = onDefaultValueSet\n ? () => {\n const text = $getRoot().getTextContent().replace(SENTINEL_VALUE, '');\n\n // This runs while rendering `LexicalComposer` so delay calling back into the parent\n // until after finished rendering `LexicalComposer`\n requestAnimationFrame?.(() => {\n onDefaultValueSet?.(text);\n });\n }\n : undefined;\n\n return mergeCallbacks(insertDefaultValueFunction, readDefaultValueFunction);\n });\n\n return defaultValueFunction;\n}\n"],"names":["React","getPartitionedNativeProps","slot","useFluent","useId","useIsomorphicLayoutEffect","useMergedRefs","SentinelNode","SENTINEL_VALUE","$createTextNode","$insertNodes","$getRoot","LexicalPlainTextPlugin","mergeRegister","mergeCallbacks","useControllableState","useEditorInput_unstable","props","ref","onChange","onPaste","trimWhiteSpace","textPlugin","history","editorRef","userEditorRef","customTheme","isSentinelNodeEnabled","root","primary","primarySlotTagName","excludedPropNames","useRef","disabled","setDisabled","state","initialState","customNodes","spanRef","useCallback","span","current","setRootElement","setEditable","registerEditableListener","isEditable","registerRootListener","style","whiteSpace","handleOnChange","newValue","value","defaultValueFunction","useDefaultValueFunction","placeholderValue","optional","elementType","placeholderId","id","components","input","always","defaultProps","role","contentEditable","undefined","suppressContentEditableWarning","tabIndex","lexicalInitialConfig","namespace","onError","console","error","nodes","editorState","theme","targetDocument","requestAnimationFrame","defaultView","useState","defaultValue","onDefaultValueSet","insertDefaultValueFunction","readDefaultValueFunction","text","getTextContent","replace"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["EditorInput.types.ts"],"sourcesContent":["import type { InitialConfigType, LexicalEditor, LexicalPlainTextPlugin } from '@fluentui-copilot/react-text-editor';\nimport type { ComponentProps, ComponentState, Slot } from '@fluentui/react-components';\n\nexport type EditorInputSlots = {\n root: NonNullable<Slot<'span'>>;\n input: NonNullable<Slot<'span'>>;\n placeholderValue?: Slot<'span'>;\n};\n\n/**\n * EditorInput Props\n */\nexport type EditorInputProps = Omit<\n ComponentProps<Partial<EditorInputSlots>, 'input'>,\n 'onChange' | 'onPaste' | 'defaultValue' | 'onSubmit'\n> & {\n disabled?: boolean;\n /**\n * If defaultValue is a string, it will be added to the input on first render.\n * If defaultValue is a function, it can call lexical $ functions to imperatively set the initial content with more complex nodes.\n */\n defaultValue?: string | (() => void);\n /**\n * Callback for when the user changes the value.\n * TODO: Add proper event type for callback\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onChange?: (ev: any, data: EditorInputValueData) => void;\n /**\n * Callback for when content is pasted into the Editor.\n */\n onPaste?: (ev: ClipboardEvent) => void;\n /**\n * When true, the input will be cleared when only whitespace is remaining.\n * @default false\n */\n trimWhiteSpace?: boolean;\n /**\n * Used to register any custom nodes used by plugins added. Can also be used to override the default nodes.\n */\n customNodes?: InitialConfigType['nodes'];\n /**\n * The plugin which is in charge of initializing Lexical and is given the `input` and `placeholder` slots\n * @default LexicalPlainTextPlugin\n */\n textPlugin?: typeof LexicalPlainTextPlugin;\n /**\n * Controls whether history is tracked to provide undo and redo functionality\n * @default true\n */\n history?: boolean;\n\n editorRef?: React.RefObject<LexicalEditor>;\n\n /**\n * Customize the default styles of elements inserted by Lexical in the editor.\n */\n customTheme?: InitialConfigType['theme'];\n\n /**\n * Whether or not to enable the sentinel node. The sentinel node is a node that is inserted at the end of the editor\n * The SentinelNode fixes a Safari bug in lexical versions below 0.20.1\n * @default true\n */\n isSentinelNodeEnabled?: boolean;\n /**\n * By default when the `defaultValue` is inserted into the editor, `onChange` is triggered.\n * When this prop is true, if `defaultValue` is a string, `onChange` will not be triggered with its value.\n */\n preventDefaultValueOnChange?: boolean;\n};\n\n/**\n * State used in rendering EditorInput\n */\nexport type EditorInputState = ComponentState<EditorInputSlots> &\n Required<\n Pick<\n EditorInputProps,\n 'disabled' | 'textPlugin' | 'history' | 'trimWhiteSpace' | 'editorRef' | 'isSentinelNodeEnabled'\n >\n > &\n Partial<Pick<EditorInputProps, 'onPaste'>> & {\n lexicalInitialConfig: InitialConfigType;\n defaultValue?: string;\n handleOnChange: (value: string) => void;\n };\n\n/**\n * Data passed to the `onChange` callback when the chat input's value changes.\n */\nexport type EditorInputValueData = {\n value: string;\n};\n"],"names":[],"rangeMappings":";;","mappings":"AAwFA;;CAEC"}
1
+ {"version":3,"sources":["EditorInput.types.ts"],"sourcesContent":["import type { InitialConfigType, LexicalEditor, LexicalPlainTextPlugin } from '@fluentui-copilot/react-text-editor';\nimport type { ComponentProps, ComponentState, Slot } from '@fluentui/react-components';\n\nexport type EditorInputSlots = {\n root: NonNullable<Slot<'span'>>;\n input: NonNullable<Slot<'span'>>;\n placeholderValue?: Slot<'span'>;\n};\n\n/**\n * EditorInput Props\n */\nexport type EditorInputProps = Omit<\n ComponentProps<Partial<EditorInputSlots>, 'input'>,\n 'onChange' | 'onPaste' | 'defaultValue' | 'onSubmit'\n> & {\n disabled?: boolean;\n /**\n * If defaultValue is a string, it will be added to the input on first render.\n * If defaultValue is a function, it can call lexical $ functions to imperatively set the initial content with more complex nodes.\n */\n defaultValue?: string | (() => void);\n /**\n * Called when the default value is given to the editor.\n * If `defaultValue` was a function, this will be called with the state of the editor after\n * calling that function.\n * If `defaultValue` was a string, this will be called with the same string.\n */\n onDefaultValueSet?: (defaultValue: string) => void;\n /**\n * Callback for when the user changes the value.\n * TODO: Add proper event type for callback\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onChange?: (ev: any, data: EditorInputValueData) => void;\n /**\n * Callback for when content is pasted into the Editor.\n */\n onPaste?: (ev: ClipboardEvent) => void;\n /**\n * When true, the input will be cleared when only whitespace is remaining.\n * @default false\n */\n trimWhiteSpace?: boolean;\n /**\n * Used to register any custom nodes used by plugins added. Can also be used to override the default nodes.\n */\n customNodes?: InitialConfigType['nodes'];\n /**\n * The plugin which is in charge of initializing Lexical and is given the `input` and `placeholder` slots\n * @default LexicalPlainTextPlugin\n */\n textPlugin?: typeof LexicalPlainTextPlugin;\n /**\n * Controls whether history is tracked to provide undo and redo functionality\n * @default true\n */\n history?: boolean;\n\n editorRef?: React.RefObject<LexicalEditor>;\n\n /**\n * Customize the default styles of elements inserted by Lexical in the editor.\n */\n customTheme?: InitialConfigType['theme'];\n\n /**\n * Whether or not to enable the sentinel node. The sentinel node is a node that is inserted at the end of the editor\n * The SentinelNode fixes a Safari bug in lexical versions below 0.20.1\n * @default true\n */\n isSentinelNodeEnabled?: boolean;\n};\n\n/**\n * State used in rendering EditorInput\n */\nexport type EditorInputState = ComponentState<EditorInputSlots> &\n Required<\n Pick<\n EditorInputProps,\n 'disabled' | 'textPlugin' | 'history' | 'trimWhiteSpace' | 'editorRef' | 'isSentinelNodeEnabled'\n >\n > &\n Partial<Pick<EditorInputProps, 'onPaste'>> & {\n lexicalInitialConfig: InitialConfigType;\n handleOnChange: (value: string) => void;\n };\n\n/**\n * Data passed to the `onChange` callback when the chat input's value changes.\n */\nexport type EditorInputValueData = {\n value: string;\n};\n"],"names":[],"rangeMappings":";;","mappings":"AAyFA;;CAEC"}
@@ -29,7 +29,6 @@ const renderEditorInput_unstable = (state)=>{
29
29
  onContentChange: state.handleOnChange,
30
30
  onPaste: state.onPaste,
31
31
  trimWhitespace: state.trimWhiteSpace,
32
- defaultValue: state.defaultValue,
33
32
  isSentinelNodeEnabled: state.isSentinelNodeEnabled
34
33
  }),
35
34
  state.history && /*#__PURE__*/ (0, _jsxruntime.jsx)(_reacttexteditor.LexicalHistoryPlugin, {})
@@ -1 +1 @@
1
- {"version":3,"sources":["renderEditorInput.tsx"],"sourcesContent":["/** @jsxRuntime automatic */\n/** @jsxImportSource @fluentui/react-jsx-runtime */\n\nimport { assertSlots } from '@fluentui/react-components';\nimport type { EditorInputState, EditorInputSlots } from './EditorInput.types';\nimport {\n LexicalComposer,\n LexicalErrorBoundary,\n LexicalEditorRefPlugin,\n LexicalHistoryPlugin,\n} from '@fluentui-copilot/react-text-editor';\nimport { BasicFunctionalityPlugin } from '@fluentui-copilot/react-chat-input-plugins';\n\n/**\n * Render the final JSX of EditorInput\n */\nexport const renderEditorInput_unstable = (state: EditorInputState) => {\n assertSlots<EditorInputSlots>(state);\n\n return (\n <state.root>\n <LexicalComposer initialConfig={state.lexicalInitialConfig}>\n <state.textPlugin\n contentEditable={<state.input />}\n ErrorBoundary={LexicalErrorBoundary}\n placeholder={state.placeholderValue ? <state.placeholderValue /> : null}\n />\n <>\n <BasicFunctionalityPlugin\n onContentChange={state.handleOnChange}\n onPaste={state.onPaste}\n trimWhitespace={state.trimWhiteSpace}\n defaultValue={state.defaultValue}\n isSentinelNodeEnabled={state.isSentinelNodeEnabled}\n />\n {state.history && <LexicalHistoryPlugin />}\n </>\n <LexicalEditorRefPlugin editorRef={state.editorRef} />\n </LexicalComposer>\n </state.root>\n );\n};\n"],"names":["assertSlots","state","_jsx","root","LexicalComposer","initialConfig","lexicalInitialConfig","textPlugin","contentEditable","ErrorBoundary","LexicalErrorBoundary","placeholder","placeholderValue","BasicFunctionalityPlugin","onContentChange","onPaste","trimWhitespace","trimWhiteSpace","defaultValue","isSentinelNodeEnabled","editorRef"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAiBEA;;;eAAAA;;;4BAhBF;iCAE4B;iCAOrB;uCACkC;AAMvCA,MAAAA,6BAA8BC,CAAAA;oCAE9B,EAAAA;sBAEI,GAAAC,IAAAA,eAAA,EAAAD,MAAAE,IAAA,EAACC;kBAAgBC,WAAAA,GAAeJ,IAAAA,gBAAAA,EAAMK,gCAAAA,EAAAA;;;8BACpCJ,IAAAA,eAAA,EAACD,MAAMM,UAAU,EAAA;qCACfC,WAAAA,GAAAA,IAAAA,eAAAA,EAAAA,MAAAA,KAAiB,EAACP,CAAAA;mCAClBQ,qCAAeC;iCACfC,MAAAA,gBAAmBC,GAAAA,WAAgB,GAAAV,IAAAA,eAAA,EAAAD,MAAAW,gBAAUA,EAAAA,CAAAA,KAAAA;;;;mCAE/C,GAAAV,IAAAA,eAAA,EAAAW,+CAAA,EAAA;;;kDAEIC,cAAiBb;gDACjBc,YAASd;mDACTe,MAAAA,qBAAsBC;;yCACtBC,WAAAA,GAAcjB,IAAAA,eAAAA,EAAAA,qCAAkB,EAAA,CAAA;qBAAA;;mDAChCkB,uCAAAA,EAAuBlB;;;;;;gDAIcmB"}
1
+ {"version":3,"sources":["renderEditorInput.tsx"],"sourcesContent":["/** @jsxRuntime automatic */\n/** @jsxImportSource @fluentui/react-jsx-runtime */\n\nimport { assertSlots } from '@fluentui/react-components';\nimport type { EditorInputState, EditorInputSlots } from './EditorInput.types';\nimport {\n LexicalComposer,\n LexicalErrorBoundary,\n LexicalEditorRefPlugin,\n LexicalHistoryPlugin,\n} from '@fluentui-copilot/react-text-editor';\nimport { BasicFunctionalityPlugin } from '@fluentui-copilot/react-chat-input-plugins';\n\n/**\n * Render the final JSX of EditorInput\n */\nexport const renderEditorInput_unstable = (state: EditorInputState) => {\n assertSlots<EditorInputSlots>(state);\n\n return (\n <state.root>\n <LexicalComposer initialConfig={state.lexicalInitialConfig}>\n <state.textPlugin\n contentEditable={<state.input />}\n ErrorBoundary={LexicalErrorBoundary}\n placeholder={state.placeholderValue ? <state.placeholderValue /> : null}\n />\n <>\n <BasicFunctionalityPlugin\n onContentChange={state.handleOnChange}\n onPaste={state.onPaste}\n trimWhitespace={state.trimWhiteSpace}\n isSentinelNodeEnabled={state.isSentinelNodeEnabled}\n />\n {state.history && <LexicalHistoryPlugin />}\n </>\n <LexicalEditorRefPlugin editorRef={state.editorRef} />\n </LexicalComposer>\n </state.root>\n );\n};\n"],"names":["assertSlots","state","_jsx","root","LexicalComposer","initialConfig","lexicalInitialConfig","textPlugin","contentEditable","ErrorBoundary","LexicalErrorBoundary","placeholder","placeholderValue","BasicFunctionalityPlugin","onContentChange","onPaste","trimWhitespace","isSentinelNodeEnabled","editorRef"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAiBEA;;;eAAAA;;;4BAhBF;iCAE4B;iCAOrB;uCACkC;AAMvCA,MAAAA,6BAA8BC,CAAAA;oCAE9B,EAAAA;sBAEI,GAAAC,IAAAA,eAAA,EAAAD,MAAAE,IAAA,EAACC;kBAAgBC,WAAAA,GAAeJ,IAAAA,gBAAAA,EAAMK,gCAAAA,EAAAA;;;8BACpCJ,IAAAA,eAAA,EAACD,MAAMM,UAAU,EAAA;qCACfC,WAAAA,GAAAA,IAAAA,eAAAA,EAAAA,MAAAA,KAAiB,EAACP,CAAAA;mCAClBQ,qCAAeC;iCACfC,MAAAA,gBAAmBC,GAAAA,WAAgB,GAAAV,IAAAA,eAAA,EAAAD,MAAAW,gBAAUA,EAAAA,CAAAA,KAAAA;;;;mCAE/C,GAAAV,IAAAA,eAAA,EAAAW,+CAAA,EAAA;;;kDAEIC,cAAiBb;mDACjBc,MAASd,qBAAa;;yCACtBe,WAAAA,GAAAA,IAAAA,eAAgBf,EAAAA,qCAAoB,EAAA,CAAA;qBAAA;;mDACpCgB,uCAAAA,EAAuBhB;;;;;;gDAIciB"}
@@ -2,17 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- function _export(target, all) {
6
- for(var name in all)Object.defineProperty(target, name, {
7
- enumerable: true,
8
- get: all[name]
9
- });
10
- }
11
- _export(exports, {
12
- createInitialEditorState: function() {
13
- return createInitialEditorState;
14
- },
15
- useEditorInput_unstable: function() {
5
+ Object.defineProperty(exports, "useEditorInput_unstable", {
6
+ enumerable: true,
7
+ get: function() {
16
8
  return useEditorInput_unstable;
17
9
  }
18
10
  });
@@ -22,11 +14,8 @@ const _reactcomponents = require("@fluentui/react-components");
22
14
  const _chatinputplugins = require("@fluentui-copilot/chat-input-plugins");
23
15
  const _reacttexteditor = require("@fluentui-copilot/react-text-editor");
24
16
  const _reactutilities = require("@fluentui/react-utilities");
25
- const createInitialEditorState = (defaultValue)=>{
26
- return `{"root":{"type":"root","children":[{"children":[{"text":${JSON.stringify(defaultValue)},"type":"text"}],"type":"paragraph"}]}}`;
27
- };
28
17
  const useEditorInput_unstable = (props, ref)=>{
29
- const { onChange, onPaste, trimWhiteSpace = false, textPlugin = _reacttexteditor.LexicalPlainTextPlugin, history = true, editorRef: userEditorRef, customTheme, isSentinelNodeEnabled = true, preventDefaultValueOnChange = false } = props;
18
+ const { onChange, onPaste, trimWhiteSpace = false, textPlugin = _reacttexteditor.LexicalPlainTextPlugin, history = true, editorRef: userEditorRef, customTheme, isSentinelNodeEnabled = true } = props;
30
19
  const { root, primary } = (0, _reactcomponents.getPartitionedNativeProps)({
31
20
  primarySlotTagName: 'span',
32
21
  props,
@@ -89,31 +78,7 @@ const useEditorInput_unstable = (props, ref)=>{
89
78
  }, [
90
79
  onChange
91
80
  ]);
92
- const [defaultString, lexicalEditorStateDefaultValue] = _react.useMemo(()=>{
93
- if (typeof props.defaultValue === 'function') {
94
- return [
95
- undefined,
96
- props.defaultValue
97
- ];
98
- }
99
- if (preventDefaultValueOnChange && props.defaultValue !== undefined) {
100
- // Any method of providing a default value to lexical which inserts it after initialization
101
- // will trigger a text content change.
102
- // Providing a default value as a stringified editorState will prevent calling onChange
103
- const editorState = createInitialEditorState(props.defaultValue);
104
- return [
105
- undefined,
106
- editorState
107
- ];
108
- }
109
- return [
110
- props.defaultValue,
111
- undefined
112
- ];
113
- }, [
114
- preventDefaultValueOnChange,
115
- props.defaultValue
116
- ]);
81
+ const defaultValueFunction = useDefaultValueFunction(props);
117
82
  const placeholderValue = _reactcomponents.slot.optional(props.placeholderValue, {
118
83
  elementType: 'span'
119
84
  });
@@ -152,7 +117,7 @@ const useEditorInput_unstable = (props, ref)=>{
152
117
  namespace: 'fai-EditorInput',
153
118
  onError: console.error,
154
119
  nodes: customNodes,
155
- editorState: lexicalEditorStateDefaultValue,
120
+ editorState: defaultValueFunction,
156
121
  theme: customTheme
157
122
  },
158
123
  editorRef,
@@ -160,9 +125,36 @@ const useEditorInput_unstable = (props, ref)=>{
160
125
  textPlugin,
161
126
  onPaste,
162
127
  handleOnChange,
163
- defaultValue: defaultString,
164
128
  trimWhiteSpace,
165
129
  history,
166
130
  isSentinelNodeEnabled
167
131
  };
168
- }; //# sourceMappingURL=useEditorInput.js.map
132
+ };
133
+ function useDefaultValueFunction(props) {
134
+ var _targetDocument_defaultView;
135
+ const { targetDocument } = (0, _reactcomponents.useFluent)();
136
+ const requestAnimationFrame = targetDocument === null || targetDocument === void 0 ? void 0 : (_targetDocument_defaultView = targetDocument.defaultView) === null || _targetDocument_defaultView === void 0 ? void 0 : _targetDocument_defaultView.requestAnimationFrame;
137
+ const [defaultValueFunction] = _react.useState(()=>{
138
+ const { defaultValue, onDefaultValueSet } = props;
139
+ if (defaultValue === undefined) {
140
+ return undefined;
141
+ }
142
+ const insertDefaultValueFunction = typeof defaultValue === 'function' ? defaultValue : ()=>{
143
+ (0, _reacttexteditor.$insertNodes)([
144
+ (0, _reacttexteditor.$createTextNode)(defaultValue)
145
+ ]);
146
+ };
147
+ // After the defaultValue function has run, read back the result and give
148
+ // it to the onDefaultValueSet callback.
149
+ const readDefaultValueFunction = onDefaultValueSet ? ()=>{
150
+ const text = (0, _reacttexteditor.$getRoot)().getTextContent().replace(_chatinputplugins.SENTINEL_VALUE, '');
151
+ // This runs while rendering `LexicalComposer` so delay calling back into the parent
152
+ // until after finished rendering `LexicalComposer`
153
+ requestAnimationFrame === null || requestAnimationFrame === void 0 ? void 0 : requestAnimationFrame(()=>{
154
+ onDefaultValueSet === null || onDefaultValueSet === void 0 ? void 0 : onDefaultValueSet(text);
155
+ });
156
+ } : undefined;
157
+ return (0, _reactutilities.mergeCallbacks)(insertDefaultValueFunction, readDefaultValueFunction);
158
+ });
159
+ return defaultValueFunction;
160
+ } //# sourceMappingURL=useEditorInput.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["useEditorInput.tsx"],"sourcesContent":["import * as React from 'react';\nimport {\n getPartitionedNativeProps,\n slot,\n useId,\n useIsomorphicLayoutEffect,\n useMergedRefs,\n} from '@fluentui/react-components';\nimport type { EditorInputProps, EditorInputState } from './EditorInput.types';\nimport { SentinelNode } from '@fluentui-copilot/chat-input-plugins';\nimport type { LexicalEditor } from '@fluentui-copilot/react-text-editor';\nimport { LexicalPlainTextPlugin, mergeRegister } from '@fluentui-copilot/react-text-editor';\nimport { useControllableState } from '@fluentui/react-utilities';\n\nexport const createInitialEditorState = (defaultValue: string) => {\n return `{\"root\":{\"type\":\"root\",\"children\":[{\"children\":[{\"text\":${JSON.stringify(\n defaultValue,\n )},\"type\":\"text\"}],\"type\":\"paragraph\"}]}}`;\n};\n\n/**\n * Create the state required to render EditorInput.\n *\n * The returned state can be modified with hooks such as useEditorInputStyles_unstable,\n * before being passed to renderEditorInput_unstable.\n *\n * @param props - props from this instance of EditorInput\n * @param ref - reference to root HTMLElement of EditorInput\n */\nexport const useEditorInput_unstable = (props: EditorInputProps, ref: React.Ref<HTMLSpanElement>): EditorInputState => {\n const {\n onChange,\n onPaste,\n trimWhiteSpace = false,\n textPlugin = LexicalPlainTextPlugin,\n history = true,\n editorRef: userEditorRef,\n customTheme,\n isSentinelNodeEnabled = true,\n preventDefaultValueOnChange = false,\n } = props;\n const { root, primary } = getPartitionedNativeProps({\n primarySlotTagName: 'span',\n props,\n excludedPropNames: ['onChange', 'onPaste', 'defaultValue'],\n });\n\n const editorRef = useMergedRefs(React.useRef<LexicalEditor>(null), userEditorRef);\n // The disabled state can also be changed by lexical (e.g. by a custom plugin) so\n // we use `useControllableState` to coordinate\n const [disabled, setDisabled] = useControllableState({\n state: props.disabled,\n initialState: false,\n });\n\n const customNodes = props.customNodes ? [...props.customNodes, SentinelNode] : [SentinelNode];\n\n const spanRef = React.useCallback(\n span => {\n // Register the `input` span with lexical\n editorRef.current?.setRootElement(span);\n },\n [editorRef],\n );\n\n // Update lexical when disabled changes\n useIsomorphicLayoutEffect(() => {\n if (editorRef.current) {\n editorRef.current?.setEditable(!disabled);\n }\n }, [disabled]);\n\n useIsomorphicLayoutEffect(() => {\n if (editorRef.current) {\n return mergeRegister(\n editorRef.current.registerEditableListener(isEditable => {\n setDisabled(!isEditable);\n }),\n editorRef.current?.registerRootListener(root => {\n if (!root) {\n return;\n }\n\n // Remove lexical's inline style so we can apply our own\n // Lexical needs the whitespace style to be either `pre` or `pre-wrap` to work correctly\n root.style.whiteSpace = '';\n }),\n );\n }\n }, [editorRef]);\n\n const handleOnChange = React.useCallback(\n (newValue: string) => {\n onChange?.({}, { value: newValue });\n },\n [onChange],\n );\n\n const [defaultString, lexicalEditorStateDefaultValue] = React.useMemo(() => {\n if (typeof props.defaultValue === 'function') {\n return [undefined, props.defaultValue];\n }\n\n if (preventDefaultValueOnChange && props.defaultValue !== undefined) {\n // Any method of providing a default value to lexical which inserts it after initialization\n // will trigger a text content change.\n // Providing a default value as a stringified editorState will prevent calling onChange\n const editorState = createInitialEditorState(props.defaultValue);\n return [undefined, editorState];\n }\n\n return [props.defaultValue, undefined];\n }, [preventDefaultValueOnChange, props.defaultValue]);\n\n const placeholderValue = slot.optional(props.placeholderValue, { elementType: 'span' });\n const placeholderId = useId('chat-input-placeholder', placeholderValue?.id);\n if (placeholderValue) {\n placeholderValue.id = placeholderId;\n }\n\n return {\n components: {\n root: 'span',\n input: 'span',\n placeholderValue: 'span',\n },\n root: slot.always(props.root, { defaultProps: { ...root }, elementType: 'span' }),\n input: slot.always(props.input, {\n defaultProps: {\n ref: useMergedRefs(ref, spanRef),\n role: 'textbox',\n contentEditable: !disabled,\n 'aria-readonly': disabled ? true : undefined,\n disabled,\n suppressContentEditableWarning: true,\n tabIndex: disabled ? undefined : 0,\n ...primary,\n 'aria-describedby': primary['aria-describedby']\n ? `${primary['aria-describedby']} ${placeholderId}`\n : placeholderId,\n },\n elementType: 'span',\n }),\n placeholderValue,\n lexicalInitialConfig: {\n namespace: 'fai-EditorInput',\n onError: console.error,\n nodes: customNodes,\n editorState: lexicalEditorStateDefaultValue,\n theme: customTheme,\n },\n editorRef,\n disabled,\n textPlugin,\n onPaste,\n handleOnChange,\n defaultValue: defaultString,\n trimWhiteSpace,\n history,\n isSentinelNodeEnabled,\n };\n};\n"],"names":["createInitialEditorState","onChange","trimWhiteSpace","defaultValue","JSON","stringify","primarySlotTagName","props","excludedPropNames","LexicalPlainTextPlugin","userEditorRef","isSentinelNodeEnabled","preventDefaultValueOnChange","useMergedRefs","React","root","state","customNodes","editorRef","useRef","SentinelNode","disabled","spanRef","useCallback","span","useIsomorphicLayoutEffect","current","_editorRef_current","setRootElement","setEditable","mergeRegister","registerRootListener","style","whiteSpace","handleOnChange","value","defaultString","lexicalEditorStateDefaultValue","undefined","editorState","id","placeholderId","input","slot","always","defaultProps","placeholderValue","elementType","ref","components","suppressContentEditableWarning","primary","error"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["useEditorInput.tsx"],"sourcesContent":["import * as React from 'react';\nimport {\n getPartitionedNativeProps,\n slot,\n useFluent,\n useId,\n useIsomorphicLayoutEffect,\n useMergedRefs,\n} from '@fluentui/react-components';\nimport type { EditorInputProps, EditorInputState } from './EditorInput.types';\nimport { SentinelNode, SENTINEL_VALUE } from '@fluentui-copilot/chat-input-plugins';\nimport type { LexicalEditor } from '@fluentui-copilot/react-text-editor';\nimport { $createTextNode, $insertNodes } from '@fluentui-copilot/react-text-editor';\nimport { $getRoot } from '@fluentui-copilot/react-text-editor';\nimport { LexicalPlainTextPlugin, mergeRegister } from '@fluentui-copilot/react-text-editor';\nimport { mergeCallbacks, useControllableState } from '@fluentui/react-utilities';\n\n/**\n * Create the state required to render EditorInput.\n *\n * The returned state can be modified with hooks such as useEditorInputStyles_unstable,\n * before being passed to renderEditorInput_unstable.\n *\n * @param props - props from this instance of EditorInput\n * @param ref - reference to root HTMLElement of EditorInput\n */\nexport const useEditorInput_unstable = (props: EditorInputProps, ref: React.Ref<HTMLSpanElement>): EditorInputState => {\n const {\n onChange,\n onPaste,\n trimWhiteSpace = false,\n textPlugin = LexicalPlainTextPlugin,\n history = true,\n editorRef: userEditorRef,\n customTheme,\n isSentinelNodeEnabled = true,\n } = props;\n const { root, primary } = getPartitionedNativeProps({\n primarySlotTagName: 'span',\n props,\n excludedPropNames: ['onChange', 'onPaste', 'defaultValue'],\n });\n\n const editorRef = useMergedRefs(React.useRef<LexicalEditor>(null), userEditorRef);\n // The disabled state can also be changed by lexical (e.g. by a custom plugin) so\n // we use `useControllableState` to coordinate\n const [disabled, setDisabled] = useControllableState({\n state: props.disabled,\n initialState: false,\n });\n\n const customNodes = props.customNodes ? [...props.customNodes, SentinelNode] : [SentinelNode];\n\n const spanRef = React.useCallback(\n span => {\n // Register the `input` span with lexical\n editorRef.current?.setRootElement(span);\n },\n [editorRef],\n );\n\n // Update lexical when disabled changes\n useIsomorphicLayoutEffect(() => {\n if (editorRef.current) {\n editorRef.current?.setEditable(!disabled);\n }\n }, [disabled]);\n\n useIsomorphicLayoutEffect(() => {\n if (editorRef.current) {\n return mergeRegister(\n editorRef.current.registerEditableListener(isEditable => {\n setDisabled(!isEditable);\n }),\n editorRef.current?.registerRootListener(root => {\n if (!root) {\n return;\n }\n\n // Remove lexical's inline style so we can apply our own\n // Lexical needs the whitespace style to be either `pre` or `pre-wrap` to work correctly\n root.style.whiteSpace = '';\n }),\n );\n }\n }, [editorRef]);\n\n const handleOnChange = React.useCallback(\n (newValue: string) => {\n onChange?.({}, { value: newValue });\n },\n [onChange],\n );\n\n const defaultValueFunction = useDefaultValueFunction(props);\n\n const placeholderValue = slot.optional(props.placeholderValue, { elementType: 'span' });\n const placeholderId = useId('chat-input-placeholder', placeholderValue?.id);\n if (placeholderValue) {\n placeholderValue.id = placeholderId;\n }\n\n return {\n components: {\n root: 'span',\n input: 'span',\n placeholderValue: 'span',\n },\n root: slot.always(props.root, { defaultProps: { ...root }, elementType: 'span' }),\n input: slot.always(props.input, {\n defaultProps: {\n ref: useMergedRefs(ref, spanRef),\n role: 'textbox',\n contentEditable: !disabled,\n 'aria-readonly': disabled ? true : undefined,\n disabled,\n suppressContentEditableWarning: true,\n tabIndex: disabled ? undefined : 0,\n ...primary,\n 'aria-describedby': primary['aria-describedby']\n ? `${primary['aria-describedby']} ${placeholderId}`\n : placeholderId,\n },\n elementType: 'span',\n }),\n placeholderValue,\n lexicalInitialConfig: {\n namespace: 'fai-EditorInput',\n onError: console.error,\n nodes: customNodes,\n editorState: defaultValueFunction,\n theme: customTheme,\n },\n editorRef,\n disabled,\n textPlugin,\n onPaste,\n handleOnChange,\n trimWhiteSpace,\n history,\n isSentinelNodeEnabled,\n };\n};\n\nfunction useDefaultValueFunction(props: EditorInputProps) {\n const { targetDocument } = useFluent();\n const requestAnimationFrame = targetDocument?.defaultView?.requestAnimationFrame;\n\n const [defaultValueFunction] = React.useState(() => {\n const { defaultValue, onDefaultValueSet } = props;\n if (defaultValue === undefined) {\n return undefined;\n }\n\n const insertDefaultValueFunction =\n typeof defaultValue === 'function'\n ? defaultValue\n : () => {\n $insertNodes([$createTextNode(defaultValue)]);\n };\n\n // After the defaultValue function has run, read back the result and give\n // it to the onDefaultValueSet callback.\n const readDefaultValueFunction = onDefaultValueSet\n ? () => {\n const text = $getRoot().getTextContent().replace(SENTINEL_VALUE, '');\n\n // This runs while rendering `LexicalComposer` so delay calling back into the parent\n // until after finished rendering `LexicalComposer`\n requestAnimationFrame?.(() => {\n onDefaultValueSet?.(text);\n });\n }\n : undefined;\n\n return mergeCallbacks(insertDefaultValueFunction, readDefaultValueFunction);\n });\n\n return defaultValueFunction;\n}\n"],"names":["onChange","trimWhiteSpace","primarySlotTagName","props","excludedPropNames","LexicalPlainTextPlugin","userEditorRef","isSentinelNodeEnabled","root","primary","disabled","customNodes","SentinelNode","setDisabled","useControllableState","state","spanRef","React","editorRef","current","useCallback","span","_editorRef_current","useIsomorphicLayoutEffect","setRootElement","isEditable","registerRootListener","style","whiteSpace","handleOnChange","newValue","defaultValueFunction","useDefaultValueFunction","placeholderId","placeholderValue","slot","id","input","defaultProps","always","elementType","ref","useMergedRefs","undefined","suppressContentEditableWarning","lexicalInitialConfig","namespace","onError","_targetDocument_defaultView","targetDocument","requestAnimationFrame","useFluent","defaultValue","$createTextNode","readDefaultValueFunction","onDefaultValueSet","text","$getRoot","getTextContent","replace","SENTINEL_VALUE","mergeCallbacks","insertDefaultValueFunction"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluentui-copilot/react-editor-input",
3
- "version": "0.4.11",
3
+ "version": "0.5.0",
4
4
  "description": "a base rich editor input.",
5
5
  "main": "lib-commonjs/index.js",
6
6
  "module": "lib/index.js",
@@ -12,8 +12,8 @@
12
12
  },
13
13
  "license": "MIT",
14
14
  "dependencies": {
15
- "@fluentui-copilot/chat-input-plugins": "^0.4.2",
16
- "@fluentui-copilot/react-chat-input-plugins": "^0.4.10",
15
+ "@fluentui-copilot/chat-input-plugins": "^0.5.0",
16
+ "@fluentui-copilot/react-chat-input-plugins": "^0.5.0",
17
17
  "@fluentui-copilot/react-text-editor": "^0.4.1",
18
18
  "@fluentui-copilot/tokens": "^0.3.11",
19
19
  "@swc/helpers": "^0.5.1"