@fluentui-copilot/chat-input-plugins 0.5.2 → 0.5.3

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/chat-input-plugins",
3
3
  "entries": [
4
4
  {
5
- "date": "Tue, 14 Oct 2025 00:02:53 GMT",
5
+ "date": "Wed, 22 Oct 2025 17:50:53 GMT",
6
+ "tag": "@fluentui-copilot/chat-input-plugins_v0.5.3",
7
+ "version": "0.5.3",
8
+ "comments": {
9
+ "none": [
10
+ {
11
+ "author": "hochelmartin@gmail.com",
12
+ "package": "@fluentui-copilot/chat-input-plugins",
13
+ "commit": "85efb411485b778327290c03aacb479fc9779dab",
14
+ "comment": "chore: migrate to dts generation against public api instead of internal path aliases tsc resolution"
15
+ }
16
+ ]
17
+ }
18
+ },
19
+ {
20
+ "date": "Tue, 14 Oct 2025 00:04:52 GMT",
6
21
  "tag": "@fluentui-copilot/chat-input-plugins_v0.5.2",
7
22
  "version": "0.5.2",
8
23
  "comments": {
package/CHANGELOG.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Change Log - @fluentui-copilot/chat-input-plugins
2
2
 
3
- This log was last generated on Tue, 14 Oct 2025 00:02:53 GMT and should not be manually modified.
3
+ This log was last generated on Tue, 14 Oct 2025 00:04:52 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
7
  ## [0.5.2](https://github.com/microsoft/fluentai/tree/@fluentui-copilot/chat-input-plugins_v0.5.2)
8
8
 
9
- Tue, 14 Oct 2025 00:02:53 GMT
9
+ Tue, 14 Oct 2025 00:04:52 GMT
10
10
  [Compare changes](https://github.com/microsoft/fluentai/compare/@fluentui-copilot/chat-input-plugins_v0.5.1..@fluentui-copilot/chat-input-plugins_v0.5.2)
11
11
 
12
12
  ### Patches
@@ -92,9 +92,9 @@ export class GhostTextPluginBase {
92
92
  }
93
93
  if ($isRangeSelection(selection) && selection.isCollapsed()) {
94
94
  var _selectedNode_getPreviousSibling;
95
- var _selection_getNodes_at;
95
+ var _selection_getNodes_;
96
96
  // All the `$isXNode` functions prefer `null` over `undefined`
97
- const selectedNode = (_selection_getNodes_at = selection.getNodes().at(0)) !== null && _selection_getNodes_at !== void 0 ? _selection_getNodes_at : null;
97
+ const selectedNode = (_selection_getNodes_ = selection.getNodes()[0]) !== null && _selection_getNodes_ !== void 0 ? _selection_getNodes_ : null;
98
98
  const previousNodeKey = selectedNode === null || selectedNode === void 0 ? void 0 : (_selectedNode_getPreviousSibling = selectedNode.getPreviousSibling()) === null || _selectedNode_getPreviousSibling === void 0 ? void 0 : _selectedNode_getPreviousSibling.getKey();
99
99
  const previousNodeIsGhostText = previousNodeKey === ghostTextNodeKey;
100
100
  // If the ghost text is active and we're navigating past it, act as if the ghost text is not there and move 1 extra character
@@ -1 +1 @@
1
- {"version":3,"sources":["GhostText.base.ts"],"sourcesContent":["import type { EditorState, Klass, LexicalEditor, LexicalNode, UpdateListener } from '@fluentui-copilot/text-editor';\nimport {\n $createTextNode,\n $getNodeByKey,\n $getSelection,\n $isRangeSelection,\n $isTextNode,\n $setSelection,\n COMMAND_PRIORITY_LOW,\n KEY_TAB_COMMAND,\n mergeRegister,\n} from '@fluentui-copilot/text-editor';\nimport { $isSentinelNode } from '../BasicFunctionality';\n\nexport type GetGhostTextFunction = (\n editor: LexicalEditor,\n editorState: EditorState,\n prevEditorState: EditorState,\n) => Promise<string | undefined>;\n\nexport interface IGhostTextNode<ComponentPropsType> extends LexicalNode {\n __content: string;\n __id: string;\n __allowCommitting?: boolean;\n __componentProps?: ComponentPropsType;\n __exposeText?: boolean;\n}\n\nexport class GhostTextPluginBase<ComponentPropsType> {\n private __id: string;\n private __$getGhostText: GetGhostTextFunction;\n private __componentProps?: ComponentPropsType;\n private __exposeText?: boolean;\n private __allowCompletion?: boolean;\n\n private __cleanup?: () => void;\n\n cleanup(): void {\n this.__cleanup?.();\n }\n\n constructor(\n editor: LexicalEditor,\n id: string,\n $getGhostText: GetGhostTextFunction,\n nodeClass: Klass<IGhostTextNode<ComponentPropsType>>,\n createNode: (\n id: string,\n content: string,\n exposeText?: boolean,\n componentProps?: ComponentPropsType,\n ) => IGhostTextNode<ComponentPropsType>,\n componentProps?: ComponentPropsType,\n // Whether or not the ghost text should count as text inside the input for submitting and character count\n exposeText?: boolean,\n allowCompletion?: boolean,\n ) {\n this.__id = id;\n this.__$getGhostText = $getGhostText;\n this.__componentProps = componentProps;\n this.__exposeText = exposeText;\n this.__allowCompletion = allowCompletion;\n\n let ghostTextNodeKey: string | null = null;\n let lastText: string | undefined = undefined;\n let justRemovedGhostText = false;\n let justAddedGhostText = false;\n\n function $clearGhostText() {\n const ghostTextNode = ghostTextNodeKey !== null ? $getNodeByKey(ghostTextNodeKey) : null;\n ghostTextNodeKey = null;\n lastText = undefined;\n if (ghostTextNode && ghostTextNode.isAttached()) {\n ghostTextNode.remove();\n justRemovedGhostText = true;\n }\n }\n function handleGhostTextNodeTransform(node: IGhostTextNode<ComponentPropsType>) {\n const key = node.getKey();\n\n if (node.__id === id && key !== ghostTextNodeKey) {\n // Only one ghost text\n node.remove();\n $clearGhostText();\n }\n }\n\n const handleGhostTextResponse = (text?: string) => {\n if (text === lastText) {\n return;\n }\n\n editor.update(\n () => {\n $clearGhostText();\n\n const selection = $getSelection();\n if (!text || !selection) {\n return;\n }\n\n const selectionCopy = selection.clone();\n\n const node = createNode(this.__id, text, this.__exposeText, this.__componentProps);\n ghostTextNodeKey = node.getKey();\n lastText = text;\n\n selection.insertNodes([node]);\n $setSelection(selectionCopy);\n justAddedGhostText = true;\n justRemovedGhostText = false;\n },\n { tag: 'historic' },\n );\n };\n\n const handleUpdate: UpdateListener = props => {\n const { editorState, prevEditorState } = props;\n\n // If this update was caused by adding or deleting ghost text, don't recheck the ghost text function until a subsequent update\n if (justRemovedGhostText || justAddedGhostText) {\n justRemovedGhostText = false;\n justAddedGhostText = false;\n return;\n }\n\n editorState.read(() => {\n // We only update the ghost text if the user selection is inside the input\n const selection = $getSelection();\n if (!$getSelection()) {\n return;\n }\n\n if ($isRangeSelection(selection) && selection.isCollapsed()) {\n // All the `$isXNode` functions prefer `null` over `undefined`\n const selectedNode = selection.getNodes().at(0) ?? null;\n const previousNodeKey = selectedNode?.getPreviousSibling()?.getKey();\n const previousNodeIsGhostText = previousNodeKey === ghostTextNodeKey;\n // If the ghost text is active and we're navigating past it, act as if the ghost text is not there and move 1 extra character\n if (\n previousNodeIsGhostText &&\n !$isSentinelNode(selectedNode) &&\n $isTextNode(selectedNode) &&\n selection.anchor.offset === 0\n ) {\n editor.update(\n () => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n selection.modify('move', false, 'character');\n }\n $clearGhostText();\n },\n { tag: 'historic' },\n );\n // Defer checking the ghost text until after this update has finished\n return;\n }\n\n // If the ghost text is the last node before the sentinel, we shouldn't let selection get past it\n if (previousNodeIsGhostText && $isSentinelNode(selectedNode)) {\n editor.update(\n () => {\n $getNodeByKey(previousNodeKey)?.getPreviousSibling()?.selectEnd();\n },\n { tag: 'historic' },\n );\n return;\n }\n }\n\n const promise = this.__$getGhostText(editor, editorState, prevEditorState);\n promise.then(handleGhostTextResponse).catch(e => console.error(e));\n });\n };\n\n function unmountGhostText() {\n if (ghostTextNodeKey) {\n editor.update(\n () => {\n $clearGhostText();\n },\n { tag: 'historic' },\n );\n }\n }\n\n function $handleTabCommand(e: KeyboardEvent) {\n if (ghostTextNodeKey === null || lastText === null) {\n return false;\n }\n\n const ghostTextNode = $getNodeByKey(ghostTextNodeKey);\n if (!ghostTextNode) {\n return false;\n }\n\n e.preventDefault();\n\n const textNode = $createTextNode(lastText);\n ghostTextNode.replace(textNode);\n textNode.selectEnd();\n $clearGhostText();\n return true;\n }\n\n this.__cleanup = mergeRegister(\n editor.registerNodeTransform(nodeClass, handleGhostTextNodeTransform),\n editor.registerUpdateListener(handleUpdate),\n this.__allowCompletion ? editor.registerCommand(KEY_TAB_COMMAND, $handleTabCommand, COMMAND_PRIORITY_LOW) : noop,\n unmountGhostText,\n );\n }\n\n setExposeText(exposeText?: boolean): void {\n this.__exposeText = exposeText;\n }\n\n setComponentProps(componentProps?: ComponentPropsType): void {\n this.__componentProps = componentProps;\n }\n\n setGetGhostText($getGhostText: GetGhostTextFunction): void {\n this.__$getGhostText = $getGhostText;\n }\n\n setAllowCompletion(allowCompletion?: boolean): void {\n this.__allowCompletion = allowCompletion;\n }\n}\nfunction noop(): void {\n return;\n}\n"],"names":["$createTextNode","$getNodeByKey","$getSelection","$isRangeSelection","$isTextNode","$setSelection","COMMAND_PRIORITY_LOW","KEY_TAB_COMMAND","mergeRegister","$isSentinelNode","GhostTextPluginBase","cleanup","__cleanup","setExposeText","exposeText","__exposeText","setComponentProps","componentProps","__componentProps","setGetGhostText","$getGhostText","__$getGhostText","setAllowCompletion","allowCompletion","__allowCompletion","constructor","editor","id","nodeClass","createNode","__id","ghostTextNodeKey","lastText","undefined","justRemovedGhostText","justAddedGhostText","$clearGhostText","ghostTextNode","isAttached","remove","handleGhostTextNodeTransform","node","key","getKey","handleGhostTextResponse","text","update","selection","selectionCopy","clone","insertNodes","tag","handleUpdate","props","editorState","prevEditorState","read","isCollapsed","selectedNode","getNodes","at","previousNodeKey","getPreviousSibling","previousNodeIsGhostText","anchor","offset","modify","selectEnd","promise","then","catch","e","console","error","unmountGhostText","$handleTabCommand","preventDefault","textNode","replace","registerNodeTransform","registerUpdateListener","registerCommand","noop"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["GhostText.base.ts"],"sourcesContent":["import type { EditorState, Klass, LexicalEditor, LexicalNode, UpdateListener } from '@fluentui-copilot/text-editor';\nimport {\n $createTextNode,\n $getNodeByKey,\n $getSelection,\n $isRangeSelection,\n $isTextNode,\n $setSelection,\n COMMAND_PRIORITY_LOW,\n KEY_TAB_COMMAND,\n mergeRegister,\n} from '@fluentui-copilot/text-editor';\nimport { $isSentinelNode } from '../BasicFunctionality';\n\nexport type GetGhostTextFunction = (\n editor: LexicalEditor,\n editorState: EditorState,\n prevEditorState: EditorState,\n) => Promise<string | undefined>;\n\nexport interface IGhostTextNode<ComponentPropsType> extends LexicalNode {\n __content: string;\n __id: string;\n __allowCommitting?: boolean;\n __componentProps?: ComponentPropsType;\n __exposeText?: boolean;\n}\n\nexport class GhostTextPluginBase<ComponentPropsType> {\n private __id: string;\n private __$getGhostText: GetGhostTextFunction;\n private __componentProps?: ComponentPropsType;\n private __exposeText?: boolean;\n private __allowCompletion?: boolean;\n\n private __cleanup?: () => void;\n\n cleanup(): void {\n this.__cleanup?.();\n }\n\n constructor(\n editor: LexicalEditor,\n id: string,\n $getGhostText: GetGhostTextFunction,\n nodeClass: Klass<IGhostTextNode<ComponentPropsType>>,\n createNode: (\n id: string,\n content: string,\n exposeText?: boolean,\n componentProps?: ComponentPropsType,\n ) => IGhostTextNode<ComponentPropsType>,\n componentProps?: ComponentPropsType,\n // Whether or not the ghost text should count as text inside the input for submitting and character count\n exposeText?: boolean,\n allowCompletion?: boolean,\n ) {\n this.__id = id;\n this.__$getGhostText = $getGhostText;\n this.__componentProps = componentProps;\n this.__exposeText = exposeText;\n this.__allowCompletion = allowCompletion;\n\n let ghostTextNodeKey: string | null = null;\n let lastText: string | undefined = undefined;\n let justRemovedGhostText = false;\n let justAddedGhostText = false;\n\n function $clearGhostText() {\n const ghostTextNode = ghostTextNodeKey !== null ? $getNodeByKey(ghostTextNodeKey) : null;\n ghostTextNodeKey = null;\n lastText = undefined;\n if (ghostTextNode && ghostTextNode.isAttached()) {\n ghostTextNode.remove();\n justRemovedGhostText = true;\n }\n }\n function handleGhostTextNodeTransform(node: IGhostTextNode<ComponentPropsType>) {\n const key = node.getKey();\n\n if (node.__id === id && key !== ghostTextNodeKey) {\n // Only one ghost text\n node.remove();\n $clearGhostText();\n }\n }\n\n const handleGhostTextResponse = (text?: string) => {\n if (text === lastText) {\n return;\n }\n\n editor.update(\n () => {\n $clearGhostText();\n\n const selection = $getSelection();\n if (!text || !selection) {\n return;\n }\n\n const selectionCopy = selection.clone();\n\n const node = createNode(this.__id, text, this.__exposeText, this.__componentProps);\n ghostTextNodeKey = node.getKey();\n lastText = text;\n\n selection.insertNodes([node]);\n $setSelection(selectionCopy);\n justAddedGhostText = true;\n justRemovedGhostText = false;\n },\n { tag: 'historic' },\n );\n };\n\n const handleUpdate: UpdateListener = props => {\n const { editorState, prevEditorState } = props;\n\n // If this update was caused by adding or deleting ghost text, don't recheck the ghost text function until a subsequent update\n if (justRemovedGhostText || justAddedGhostText) {\n justRemovedGhostText = false;\n justAddedGhostText = false;\n return;\n }\n\n editorState.read(() => {\n // We only update the ghost text if the user selection is inside the input\n const selection = $getSelection();\n if (!$getSelection()) {\n return;\n }\n\n if ($isRangeSelection(selection) && selection.isCollapsed()) {\n // All the `$isXNode` functions prefer `null` over `undefined`\n const selectedNode = selection.getNodes()[0] ?? null;\n const previousNodeKey = selectedNode?.getPreviousSibling()?.getKey();\n const previousNodeIsGhostText = previousNodeKey === ghostTextNodeKey;\n // If the ghost text is active and we're navigating past it, act as if the ghost text is not there and move 1 extra character\n if (\n previousNodeIsGhostText &&\n !$isSentinelNode(selectedNode) &&\n $isTextNode(selectedNode) &&\n selection.anchor.offset === 0\n ) {\n editor.update(\n () => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n selection.modify('move', false, 'character');\n }\n $clearGhostText();\n },\n { tag: 'historic' },\n );\n // Defer checking the ghost text until after this update has finished\n return;\n }\n\n // If the ghost text is the last node before the sentinel, we shouldn't let selection get past it\n if (previousNodeIsGhostText && $isSentinelNode(selectedNode)) {\n editor.update(\n () => {\n $getNodeByKey(previousNodeKey)?.getPreviousSibling()?.selectEnd();\n },\n { tag: 'historic' },\n );\n return;\n }\n }\n\n const promise = this.__$getGhostText(editor, editorState, prevEditorState);\n promise.then(handleGhostTextResponse).catch(e => console.error(e));\n });\n };\n\n function unmountGhostText() {\n if (ghostTextNodeKey) {\n editor.update(\n () => {\n $clearGhostText();\n },\n { tag: 'historic' },\n );\n }\n }\n\n function $handleTabCommand(e: KeyboardEvent) {\n if (ghostTextNodeKey === null || lastText === null) {\n return false;\n }\n\n const ghostTextNode = $getNodeByKey(ghostTextNodeKey);\n if (!ghostTextNode) {\n return false;\n }\n\n e.preventDefault();\n\n const textNode = $createTextNode(lastText);\n ghostTextNode.replace(textNode);\n textNode.selectEnd();\n $clearGhostText();\n return true;\n }\n\n this.__cleanup = mergeRegister(\n editor.registerNodeTransform(nodeClass, handleGhostTextNodeTransform),\n editor.registerUpdateListener(handleUpdate),\n this.__allowCompletion ? editor.registerCommand(KEY_TAB_COMMAND, $handleTabCommand, COMMAND_PRIORITY_LOW) : noop,\n unmountGhostText,\n );\n }\n\n setExposeText(exposeText?: boolean): void {\n this.__exposeText = exposeText;\n }\n\n setComponentProps(componentProps?: ComponentPropsType): void {\n this.__componentProps = componentProps;\n }\n\n setGetGhostText($getGhostText: GetGhostTextFunction): void {\n this.__$getGhostText = $getGhostText;\n }\n\n setAllowCompletion(allowCompletion?: boolean): void {\n this.__allowCompletion = allowCompletion;\n }\n}\nfunction noop(): void {\n return;\n}\n"],"names":["$createTextNode","$getNodeByKey","$getSelection","$isRangeSelection","$isTextNode","$setSelection","COMMAND_PRIORITY_LOW","KEY_TAB_COMMAND","mergeRegister","$isSentinelNode","GhostTextPluginBase","cleanup","__cleanup","setExposeText","exposeText","__exposeText","setComponentProps","componentProps","__componentProps","setGetGhostText","$getGhostText","__$getGhostText","setAllowCompletion","allowCompletion","__allowCompletion","constructor","editor","id","nodeClass","createNode","__id","ghostTextNodeKey","lastText","undefined","justRemovedGhostText","justAddedGhostText","$clearGhostText","ghostTextNode","isAttached","remove","handleGhostTextNodeTransform","node","key","getKey","handleGhostTextResponse","text","update","selection","selectionCopy","clone","insertNodes","tag","handleUpdate","props","editorState","prevEditorState","read","isCollapsed","selectedNode","getNodes","previousNodeKey","getPreviousSibling","previousNodeIsGhostText","anchor","offset","modify","selectEnd","promise","then","catch","e","console","error","unmountGhostText","$handleTabCommand","preventDefault","textNode","replace","registerNodeTransform","registerUpdateListener","registerCommand","noop"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -101,9 +101,9 @@ class GhostTextPluginBase {
101
101
  }
102
102
  if ((0, _texteditor.$isRangeSelection)(selection) && selection.isCollapsed()) {
103
103
  var _selectedNode_getPreviousSibling;
104
- var _selection_getNodes_at;
104
+ var _selection_getNodes_;
105
105
  // All the `$isXNode` functions prefer `null` over `undefined`
106
- const selectedNode = (_selection_getNodes_at = selection.getNodes().at(0)) !== null && _selection_getNodes_at !== void 0 ? _selection_getNodes_at : null;
106
+ const selectedNode = (_selection_getNodes_ = selection.getNodes()[0]) !== null && _selection_getNodes_ !== void 0 ? _selection_getNodes_ : null;
107
107
  const previousNodeKey = selectedNode === null || selectedNode === void 0 ? void 0 : (_selectedNode_getPreviousSibling = selectedNode.getPreviousSibling()) === null || _selectedNode_getPreviousSibling === void 0 ? void 0 : _selectedNode_getPreviousSibling.getKey();
108
108
  const previousNodeIsGhostText = previousNodeKey === ghostTextNodeKey;
109
109
  // If the ghost text is active and we're navigating past it, act as if the ghost text is not there and move 1 extra character
@@ -1 +1 @@
1
- {"version":3,"sources":["GhostText.base.ts"],"sourcesContent":["import type { EditorState, Klass, LexicalEditor, LexicalNode, UpdateListener } from '@fluentui-copilot/text-editor';\nimport {\n $createTextNode,\n $getNodeByKey,\n $getSelection,\n $isRangeSelection,\n $isTextNode,\n $setSelection,\n COMMAND_PRIORITY_LOW,\n KEY_TAB_COMMAND,\n mergeRegister,\n} from '@fluentui-copilot/text-editor';\nimport { $isSentinelNode } from '../BasicFunctionality';\n\nexport type GetGhostTextFunction = (\n editor: LexicalEditor,\n editorState: EditorState,\n prevEditorState: EditorState,\n) => Promise<string | undefined>;\n\nexport interface IGhostTextNode<ComponentPropsType> extends LexicalNode {\n __content: string;\n __id: string;\n __allowCommitting?: boolean;\n __componentProps?: ComponentPropsType;\n __exposeText?: boolean;\n}\n\nexport class GhostTextPluginBase<ComponentPropsType> {\n private __id: string;\n private __$getGhostText: GetGhostTextFunction;\n private __componentProps?: ComponentPropsType;\n private __exposeText?: boolean;\n private __allowCompletion?: boolean;\n\n private __cleanup?: () => void;\n\n cleanup(): void {\n this.__cleanup?.();\n }\n\n constructor(\n editor: LexicalEditor,\n id: string,\n $getGhostText: GetGhostTextFunction,\n nodeClass: Klass<IGhostTextNode<ComponentPropsType>>,\n createNode: (\n id: string,\n content: string,\n exposeText?: boolean,\n componentProps?: ComponentPropsType,\n ) => IGhostTextNode<ComponentPropsType>,\n componentProps?: ComponentPropsType,\n // Whether or not the ghost text should count as text inside the input for submitting and character count\n exposeText?: boolean,\n allowCompletion?: boolean,\n ) {\n this.__id = id;\n this.__$getGhostText = $getGhostText;\n this.__componentProps = componentProps;\n this.__exposeText = exposeText;\n this.__allowCompletion = allowCompletion;\n\n let ghostTextNodeKey: string | null = null;\n let lastText: string | undefined = undefined;\n let justRemovedGhostText = false;\n let justAddedGhostText = false;\n\n function $clearGhostText() {\n const ghostTextNode = ghostTextNodeKey !== null ? $getNodeByKey(ghostTextNodeKey) : null;\n ghostTextNodeKey = null;\n lastText = undefined;\n if (ghostTextNode && ghostTextNode.isAttached()) {\n ghostTextNode.remove();\n justRemovedGhostText = true;\n }\n }\n function handleGhostTextNodeTransform(node: IGhostTextNode<ComponentPropsType>) {\n const key = node.getKey();\n\n if (node.__id === id && key !== ghostTextNodeKey) {\n // Only one ghost text\n node.remove();\n $clearGhostText();\n }\n }\n\n const handleGhostTextResponse = (text?: string) => {\n if (text === lastText) {\n return;\n }\n\n editor.update(\n () => {\n $clearGhostText();\n\n const selection = $getSelection();\n if (!text || !selection) {\n return;\n }\n\n const selectionCopy = selection.clone();\n\n const node = createNode(this.__id, text, this.__exposeText, this.__componentProps);\n ghostTextNodeKey = node.getKey();\n lastText = text;\n\n selection.insertNodes([node]);\n $setSelection(selectionCopy);\n justAddedGhostText = true;\n justRemovedGhostText = false;\n },\n { tag: 'historic' },\n );\n };\n\n const handleUpdate: UpdateListener = props => {\n const { editorState, prevEditorState } = props;\n\n // If this update was caused by adding or deleting ghost text, don't recheck the ghost text function until a subsequent update\n if (justRemovedGhostText || justAddedGhostText) {\n justRemovedGhostText = false;\n justAddedGhostText = false;\n return;\n }\n\n editorState.read(() => {\n // We only update the ghost text if the user selection is inside the input\n const selection = $getSelection();\n if (!$getSelection()) {\n return;\n }\n\n if ($isRangeSelection(selection) && selection.isCollapsed()) {\n // All the `$isXNode` functions prefer `null` over `undefined`\n const selectedNode = selection.getNodes().at(0) ?? null;\n const previousNodeKey = selectedNode?.getPreviousSibling()?.getKey();\n const previousNodeIsGhostText = previousNodeKey === ghostTextNodeKey;\n // If the ghost text is active and we're navigating past it, act as if the ghost text is not there and move 1 extra character\n if (\n previousNodeIsGhostText &&\n !$isSentinelNode(selectedNode) &&\n $isTextNode(selectedNode) &&\n selection.anchor.offset === 0\n ) {\n editor.update(\n () => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n selection.modify('move', false, 'character');\n }\n $clearGhostText();\n },\n { tag: 'historic' },\n );\n // Defer checking the ghost text until after this update has finished\n return;\n }\n\n // If the ghost text is the last node before the sentinel, we shouldn't let selection get past it\n if (previousNodeIsGhostText && $isSentinelNode(selectedNode)) {\n editor.update(\n () => {\n $getNodeByKey(previousNodeKey)?.getPreviousSibling()?.selectEnd();\n },\n { tag: 'historic' },\n );\n return;\n }\n }\n\n const promise = this.__$getGhostText(editor, editorState, prevEditorState);\n promise.then(handleGhostTextResponse).catch(e => console.error(e));\n });\n };\n\n function unmountGhostText() {\n if (ghostTextNodeKey) {\n editor.update(\n () => {\n $clearGhostText();\n },\n { tag: 'historic' },\n );\n }\n }\n\n function $handleTabCommand(e: KeyboardEvent) {\n if (ghostTextNodeKey === null || lastText === null) {\n return false;\n }\n\n const ghostTextNode = $getNodeByKey(ghostTextNodeKey);\n if (!ghostTextNode) {\n return false;\n }\n\n e.preventDefault();\n\n const textNode = $createTextNode(lastText);\n ghostTextNode.replace(textNode);\n textNode.selectEnd();\n $clearGhostText();\n return true;\n }\n\n this.__cleanup = mergeRegister(\n editor.registerNodeTransform(nodeClass, handleGhostTextNodeTransform),\n editor.registerUpdateListener(handleUpdate),\n this.__allowCompletion ? editor.registerCommand(KEY_TAB_COMMAND, $handleTabCommand, COMMAND_PRIORITY_LOW) : noop,\n unmountGhostText,\n );\n }\n\n setExposeText(exposeText?: boolean): void {\n this.__exposeText = exposeText;\n }\n\n setComponentProps(componentProps?: ComponentPropsType): void {\n this.__componentProps = componentProps;\n }\n\n setGetGhostText($getGhostText: GetGhostTextFunction): void {\n this.__$getGhostText = $getGhostText;\n }\n\n setAllowCompletion(allowCompletion?: boolean): void {\n this.__allowCompletion = allowCompletion;\n }\n}\nfunction noop(): void {\n return;\n}\n"],"names":["GhostTextPluginBase","cleanup","_this___cleanup","_this","__cleanup","call","setExposeText","exposeText","__exposeText","setComponentProps","componentProps","__componentProps","setGetGhostText","$getGhostText","__$getGhostText","setAllowCompletion","allowCompletion","__allowCompletion","constructor","editor","id","nodeClass","createNode","_define_property","__id","ghostTextNodeKey","lastText","undefined","justRemovedGhostText","justAddedGhostText","$clearGhostText","ghostTextNode","$getNodeByKey","isAttached","remove","handleGhostTextNodeTransform","node","key","getKey","handleGhostTextResponse","text","update","selection","$getSelection","selectionCopy","clone","insertNodes","$setSelection","tag","handleUpdate","props","editorState","prevEditorState","read","$isRangeSelection","isCollapsed","selectedNode","getNodes","at","previousNodeKey","getPreviousSibling","previousNodeIsGhostText","$isSentinelNode","$isTextNode","anchor","offset","modify","selectEnd","promise","then","catch","e","console","error","unmountGhostText","$handleTabCommand","preventDefault","textNode","$createTextNode","replace","mergeRegister","registerNodeTransform","registerUpdateListener","registerCommand","KEY_TAB_COMMAND","COMMAND_PRIORITY_LOW","noop"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["GhostText.base.ts"],"sourcesContent":["import type { EditorState, Klass, LexicalEditor, LexicalNode, UpdateListener } from '@fluentui-copilot/text-editor';\nimport {\n $createTextNode,\n $getNodeByKey,\n $getSelection,\n $isRangeSelection,\n $isTextNode,\n $setSelection,\n COMMAND_PRIORITY_LOW,\n KEY_TAB_COMMAND,\n mergeRegister,\n} from '@fluentui-copilot/text-editor';\nimport { $isSentinelNode } from '../BasicFunctionality';\n\nexport type GetGhostTextFunction = (\n editor: LexicalEditor,\n editorState: EditorState,\n prevEditorState: EditorState,\n) => Promise<string | undefined>;\n\nexport interface IGhostTextNode<ComponentPropsType> extends LexicalNode {\n __content: string;\n __id: string;\n __allowCommitting?: boolean;\n __componentProps?: ComponentPropsType;\n __exposeText?: boolean;\n}\n\nexport class GhostTextPluginBase<ComponentPropsType> {\n private __id: string;\n private __$getGhostText: GetGhostTextFunction;\n private __componentProps?: ComponentPropsType;\n private __exposeText?: boolean;\n private __allowCompletion?: boolean;\n\n private __cleanup?: () => void;\n\n cleanup(): void {\n this.__cleanup?.();\n }\n\n constructor(\n editor: LexicalEditor,\n id: string,\n $getGhostText: GetGhostTextFunction,\n nodeClass: Klass<IGhostTextNode<ComponentPropsType>>,\n createNode: (\n id: string,\n content: string,\n exposeText?: boolean,\n componentProps?: ComponentPropsType,\n ) => IGhostTextNode<ComponentPropsType>,\n componentProps?: ComponentPropsType,\n // Whether or not the ghost text should count as text inside the input for submitting and character count\n exposeText?: boolean,\n allowCompletion?: boolean,\n ) {\n this.__id = id;\n this.__$getGhostText = $getGhostText;\n this.__componentProps = componentProps;\n this.__exposeText = exposeText;\n this.__allowCompletion = allowCompletion;\n\n let ghostTextNodeKey: string | null = null;\n let lastText: string | undefined = undefined;\n let justRemovedGhostText = false;\n let justAddedGhostText = false;\n\n function $clearGhostText() {\n const ghostTextNode = ghostTextNodeKey !== null ? $getNodeByKey(ghostTextNodeKey) : null;\n ghostTextNodeKey = null;\n lastText = undefined;\n if (ghostTextNode && ghostTextNode.isAttached()) {\n ghostTextNode.remove();\n justRemovedGhostText = true;\n }\n }\n function handleGhostTextNodeTransform(node: IGhostTextNode<ComponentPropsType>) {\n const key = node.getKey();\n\n if (node.__id === id && key !== ghostTextNodeKey) {\n // Only one ghost text\n node.remove();\n $clearGhostText();\n }\n }\n\n const handleGhostTextResponse = (text?: string) => {\n if (text === lastText) {\n return;\n }\n\n editor.update(\n () => {\n $clearGhostText();\n\n const selection = $getSelection();\n if (!text || !selection) {\n return;\n }\n\n const selectionCopy = selection.clone();\n\n const node = createNode(this.__id, text, this.__exposeText, this.__componentProps);\n ghostTextNodeKey = node.getKey();\n lastText = text;\n\n selection.insertNodes([node]);\n $setSelection(selectionCopy);\n justAddedGhostText = true;\n justRemovedGhostText = false;\n },\n { tag: 'historic' },\n );\n };\n\n const handleUpdate: UpdateListener = props => {\n const { editorState, prevEditorState } = props;\n\n // If this update was caused by adding or deleting ghost text, don't recheck the ghost text function until a subsequent update\n if (justRemovedGhostText || justAddedGhostText) {\n justRemovedGhostText = false;\n justAddedGhostText = false;\n return;\n }\n\n editorState.read(() => {\n // We only update the ghost text if the user selection is inside the input\n const selection = $getSelection();\n if (!$getSelection()) {\n return;\n }\n\n if ($isRangeSelection(selection) && selection.isCollapsed()) {\n // All the `$isXNode` functions prefer `null` over `undefined`\n const selectedNode = selection.getNodes()[0] ?? null;\n const previousNodeKey = selectedNode?.getPreviousSibling()?.getKey();\n const previousNodeIsGhostText = previousNodeKey === ghostTextNodeKey;\n // If the ghost text is active and we're navigating past it, act as if the ghost text is not there and move 1 extra character\n if (\n previousNodeIsGhostText &&\n !$isSentinelNode(selectedNode) &&\n $isTextNode(selectedNode) &&\n selection.anchor.offset === 0\n ) {\n editor.update(\n () => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n selection.modify('move', false, 'character');\n }\n $clearGhostText();\n },\n { tag: 'historic' },\n );\n // Defer checking the ghost text until after this update has finished\n return;\n }\n\n // If the ghost text is the last node before the sentinel, we shouldn't let selection get past it\n if (previousNodeIsGhostText && $isSentinelNode(selectedNode)) {\n editor.update(\n () => {\n $getNodeByKey(previousNodeKey)?.getPreviousSibling()?.selectEnd();\n },\n { tag: 'historic' },\n );\n return;\n }\n }\n\n const promise = this.__$getGhostText(editor, editorState, prevEditorState);\n promise.then(handleGhostTextResponse).catch(e => console.error(e));\n });\n };\n\n function unmountGhostText() {\n if (ghostTextNodeKey) {\n editor.update(\n () => {\n $clearGhostText();\n },\n { tag: 'historic' },\n );\n }\n }\n\n function $handleTabCommand(e: KeyboardEvent) {\n if (ghostTextNodeKey === null || lastText === null) {\n return false;\n }\n\n const ghostTextNode = $getNodeByKey(ghostTextNodeKey);\n if (!ghostTextNode) {\n return false;\n }\n\n e.preventDefault();\n\n const textNode = $createTextNode(lastText);\n ghostTextNode.replace(textNode);\n textNode.selectEnd();\n $clearGhostText();\n return true;\n }\n\n this.__cleanup = mergeRegister(\n editor.registerNodeTransform(nodeClass, handleGhostTextNodeTransform),\n editor.registerUpdateListener(handleUpdate),\n this.__allowCompletion ? editor.registerCommand(KEY_TAB_COMMAND, $handleTabCommand, COMMAND_PRIORITY_LOW) : noop,\n unmountGhostText,\n );\n }\n\n setExposeText(exposeText?: boolean): void {\n this.__exposeText = exposeText;\n }\n\n setComponentProps(componentProps?: ComponentPropsType): void {\n this.__componentProps = componentProps;\n }\n\n setGetGhostText($getGhostText: GetGhostTextFunction): void {\n this.__$getGhostText = $getGhostText;\n }\n\n setAllowCompletion(allowCompletion?: boolean): void {\n this.__allowCompletion = allowCompletion;\n }\n}\nfunction noop(): void {\n return;\n}\n"],"names":["GhostTextPluginBase","cleanup","_this___cleanup","_this","__cleanup","call","setExposeText","exposeText","__exposeText","setComponentProps","componentProps","__componentProps","setGetGhostText","$getGhostText","__$getGhostText","setAllowCompletion","allowCompletion","__allowCompletion","constructor","editor","id","nodeClass","createNode","_define_property","__id","ghostTextNodeKey","lastText","undefined","justRemovedGhostText","justAddedGhostText","$clearGhostText","ghostTextNode","$getNodeByKey","isAttached","remove","handleGhostTextNodeTransform","node","key","getKey","handleGhostTextResponse","text","update","selection","$getSelection","selectionCopy","clone","insertNodes","$setSelection","tag","handleUpdate","props","editorState","prevEditorState","read","$isRangeSelection","isCollapsed","selectedNode","getNodes","previousNodeKey","getPreviousSibling","previousNodeIsGhostText","$isSentinelNode","$isTextNode","anchor","offset","modify","selectEnd","promise","then","catch","e","console","error","unmountGhostText","$handleTabCommand","preventDefault","textNode","$createTextNode","replace","mergeRegister","registerNodeTransform","registerUpdateListener","registerCommand","KEY_TAB_COMMAND","COMMAND_PRIORITY_LOW","noop"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluentui-copilot/chat-input-plugins",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "A Fluent AI package for non-react specific chat input plugins.",
5
5
  "main": "lib-commonjs/index.js",
6
6
  "module": "lib/index.js",
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "license": "MIT",
14
14
  "dependencies": {
15
- "@fluentui-copilot/text-editor": "^0.3.2",
15
+ "@fluentui-copilot/text-editor": "^0.3.3",
16
16
  "@swc/helpers": "^0.5.1"
17
17
  },
18
18
  "beachball": {