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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.json +31 -1
  2. package/CHANGELOG.md +20 -2
  3. package/lib/BasicFunctionality/BasicFunctionality.base.js +90 -96
  4. package/lib/BasicFunctionality/BasicFunctionality.base.js.map +1 -1
  5. package/lib/BasicFunctionality/SentinelNode.js +29 -30
  6. package/lib/BasicFunctionality/SentinelNode.js.map +1 -1
  7. package/lib/BasicFunctionality/SentinelNodeHandlers.js +73 -78
  8. package/lib/BasicFunctionality/SentinelNodeHandlers.js.map +1 -1
  9. package/lib/BasicFunctionality/index.js +0 -1
  10. package/lib/ChatInputEntity/ChatInputEntityPlugin.base.js +109 -114
  11. package/lib/ChatInputEntity/ChatInputEntityPlugin.base.js.map +1 -1
  12. package/lib/ChatInputEntity/ChatInputEntityPlugin.types.js +1 -2
  13. package/lib/ChatInputEntity/index.js +0 -1
  14. package/lib/GhostText/GhostText.base.js +142 -145
  15. package/lib/GhostText/GhostText.base.js.map +1 -1
  16. package/lib/GhostText/index.js +0 -1
  17. package/lib/ImperativeControl/ImperativeControl.base.js +82 -83
  18. package/lib/ImperativeControl/ImperativeControl.base.js.map +1 -1
  19. package/lib/ImperativeControl/index.js +0 -1
  20. package/lib/ManualGhostText/ManualGhostText.base.js +68 -67
  21. package/lib/ManualGhostText/index.js +0 -1
  22. package/lib/PasteUnfurling/PasteUnfurling.base.js +52 -57
  23. package/lib/PasteUnfurling/PasteUnfurling.types.js +1 -2
  24. package/lib/PasteUnfurling/PasteUnfurlingTestUtils.js +138 -139
  25. package/lib/PasteUnfurling/PasteUnfurlingTestUtils.js.map +1 -1
  26. package/lib/PasteUnfurling/index.js +0 -1
  27. package/lib/index.js +0 -1
  28. package/lib-commonjs/BasicFunctionality/BasicFunctionality.base.js +2 -3
  29. package/lib-commonjs/BasicFunctionality/BasicFunctionality.base.js.map +1 -1
  30. package/lib-commonjs/BasicFunctionality/SentinelNode.js +1 -1
  31. package/lib-commonjs/BasicFunctionality/SentinelNode.js.map +1 -1
  32. package/lib-commonjs/BasicFunctionality/SentinelNodeHandlers.js +3 -5
  33. package/lib-commonjs/BasicFunctionality/SentinelNodeHandlers.js.map +1 -1
  34. package/lib-commonjs/BasicFunctionality/index.js +0 -1
  35. package/lib-commonjs/ChatInputEntity/ChatInputEntityPlugin.base.js +3 -5
  36. package/lib-commonjs/ChatInputEntity/ChatInputEntityPlugin.base.js.map +1 -1
  37. package/lib-commonjs/ChatInputEntity/ChatInputEntityPlugin.types.js +0 -1
  38. package/lib-commonjs/ChatInputEntity/index.js +0 -1
  39. package/lib-commonjs/GhostText/GhostText.base.js +2 -3
  40. package/lib-commonjs/GhostText/GhostText.base.js.map +1 -1
  41. package/lib-commonjs/GhostText/index.js +0 -1
  42. package/lib-commonjs/ImperativeControl/ImperativeControl.base.js +1 -1
  43. package/lib-commonjs/ImperativeControl/ImperativeControl.base.js.map +1 -1
  44. package/lib-commonjs/ImperativeControl/index.js +0 -1
  45. package/lib-commonjs/ManualGhostText/ManualGhostText.base.js +1 -1
  46. package/lib-commonjs/ManualGhostText/ManualGhostText.base.js.map +1 -1
  47. package/lib-commonjs/ManualGhostText/index.js +0 -1
  48. package/lib-commonjs/PasteUnfurling/PasteUnfurling.base.js +1 -1
  49. package/lib-commonjs/PasteUnfurling/PasteUnfurling.base.js.map +1 -1
  50. package/lib-commonjs/PasteUnfurling/PasteUnfurling.types.js +0 -1
  51. package/lib-commonjs/PasteUnfurling/PasteUnfurlingTestUtils.js +1 -1
  52. package/lib-commonjs/PasteUnfurling/PasteUnfurlingTestUtils.js.map +1 -1
  53. package/lib-commonjs/PasteUnfurling/index.js +0 -1
  54. package/lib-commonjs/index.js +0 -1
  55. package/package.json +2 -2
@@ -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() {\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) {\n this.__exposeText = exposeText;\n }\n\n setComponentProps(componentProps?: ComponentPropsType) {\n this.__componentProps = componentProps;\n }\n\n setGetGhostText($getGhostText: GetGhostTextFunction) {\n this.__$getGhostText = $getGhostText;\n }\n\n setAllowCompletion(allowCompletion?: boolean) {\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().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,2 +1 @@
1
1
  export { GhostTextPluginBase } from './GhostText.base';
2
- //# sourceMappingURL=index.js.map
@@ -2,87 +2,86 @@ import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
2
  import { $createParagraphNode, $createRangeSelection, $createTextNode, $getLeafNodes, $getRoot, $getSelection, $isTextNode, $normalizeSelection__EXPERIMENTAL, $setSelection } from '@fluentui-copilot/text-editor';
3
3
  import { SENTINEL_VALUE, $isSentinelNode } from '../BasicFunctionality';
4
4
  export class ImperativeControlBase {
5
- moveCursor(location) {
6
- this.__editor.update(() => {
7
- const children = $getLeafNodes($getRoot());
8
- let baseOffset = 0;
9
- let currentNode = children.shift();
10
- while (baseOffset < location && currentNode) {
11
- const nodeLength = $isTextNode(currentNode) && !currentNode.isToken() ? currentNode.getTextContent().length : 1;
12
- if (baseOffset + nodeLength >= location) {
13
- const elementType = $isTextNode(currentNode) ? 'text' : 'element';
14
- const localOffset = location - baseOffset;
15
- const nodeKey = currentNode.getKey();
16
- const selection = $createRangeSelection();
17
- selection.anchor.set(nodeKey, localOffset, elementType);
18
- selection.focus.set(nodeKey, localOffset, elementType);
19
- $setSelection($normalizeSelection__EXPERIMENTAL(selection));
20
- return;
21
- }
22
- baseOffset += nodeLength;
23
- currentNode = children.shift();
24
- }
25
- if (location > baseOffset) {
26
- $getRoot().selectEnd();
27
- }
28
- });
29
- }
30
- setInputText(inputText) {
31
- this.__editor.update(() => {
32
- const root = $getRoot();
33
- root.clear();
34
- if (inputText !== '') {
35
- const newParagraph = $createParagraphNode();
36
- const newText = $createTextNode(inputText);
37
- newParagraph.append(newText);
38
- root.append(newParagraph);
39
- root.selectEnd();
40
- }
41
- });
42
- }
43
- appendText(text) {
44
- this.__editor.update(() => {
45
- $getRoot().selectEnd().insertText(text);
46
- });
47
- }
48
- prependText(text) {
49
- this.__editor.update(() => {
50
- $getRoot().selectStart().insertText(text);
51
- });
52
- }
53
- insertTextAtCursor(text) {
54
- this.__editor.update(() => {
55
- var _$getSelection;
56
- const selection = (_$getSelection = $getSelection()) !== null && _$getSelection !== void 0 ? _$getSelection : $getRoot().selectEnd();
57
- selection.insertText(text);
58
- });
59
- }
60
- getInputText(transform) {
61
- return this.__editor.getEditorState().read(() => {
62
- if (!transform) {
63
- return $getRoot().getTextContent().replace(SENTINEL_VALUE, '');
64
- }
65
- const children = $getLeafNodes($getRoot());
66
- const transformedNodeTexts = [];
67
- for (const currentNode of children) {
68
- if (!$isSentinelNode(currentNode)) {
69
- transformedNodeTexts.push(transform(currentNode));
70
- }
71
- }
72
- return transformedNodeTexts.join('');
73
- });
74
- }
75
- scrollToBottom() {
76
- var _this___editor_getRootElement;
77
- (_this___editor_getRootElement = this.__editor.getRootElement()) === null || _this___editor_getRootElement === void 0 ? void 0 : _this___editor_getRootElement.scrollIntoView({
78
- behavior: 'smooth',
79
- block: 'end'
80
- });
81
- return;
82
- }
83
- constructor(editor) {
84
- _define_property(this, "__editor", void 0);
85
- this.__editor = editor;
86
- }
5
+ moveCursor(location) {
6
+ this.__editor.update(()=>{
7
+ const children = $getLeafNodes($getRoot());
8
+ let baseOffset = 0;
9
+ let currentNode = children.shift();
10
+ while(baseOffset < location && currentNode){
11
+ const nodeLength = $isTextNode(currentNode) && !currentNode.isToken() ? currentNode.getTextContent().length : 1;
12
+ if (baseOffset + nodeLength >= location) {
13
+ const elementType = $isTextNode(currentNode) ? 'text' : 'element';
14
+ const localOffset = location - baseOffset;
15
+ const nodeKey = currentNode.getKey();
16
+ const selection = $createRangeSelection();
17
+ selection.anchor.set(nodeKey, localOffset, elementType);
18
+ selection.focus.set(nodeKey, localOffset, elementType);
19
+ $setSelection($normalizeSelection__EXPERIMENTAL(selection));
20
+ return;
21
+ }
22
+ baseOffset += nodeLength;
23
+ currentNode = children.shift();
24
+ }
25
+ if (location > baseOffset) {
26
+ $getRoot().selectEnd();
27
+ }
28
+ });
29
+ }
30
+ setInputText(inputText) {
31
+ this.__editor.update(()=>{
32
+ const root = $getRoot();
33
+ root.clear();
34
+ if (inputText !== '') {
35
+ const newParagraph = $createParagraphNode();
36
+ const newText = $createTextNode(inputText);
37
+ newParagraph.append(newText);
38
+ root.append(newParagraph);
39
+ root.selectEnd();
40
+ }
41
+ });
42
+ }
43
+ appendText(text) {
44
+ this.__editor.update(()=>{
45
+ $getRoot().selectEnd().insertText(text);
46
+ });
47
+ }
48
+ prependText(text) {
49
+ this.__editor.update(()=>{
50
+ $getRoot().selectStart().insertText(text);
51
+ });
52
+ }
53
+ insertTextAtCursor(text) {
54
+ this.__editor.update(()=>{
55
+ var _$getSelection;
56
+ const selection = (_$getSelection = $getSelection()) !== null && _$getSelection !== void 0 ? _$getSelection : $getRoot().selectEnd();
57
+ selection.insertText(text);
58
+ });
59
+ }
60
+ getInputText(transform) {
61
+ return this.__editor.getEditorState().read(()=>{
62
+ if (!transform) {
63
+ return $getRoot().getTextContent().replace(SENTINEL_VALUE, '');
64
+ }
65
+ const children = $getLeafNodes($getRoot());
66
+ const transformedNodeTexts = [];
67
+ for (const currentNode of children){
68
+ if (!$isSentinelNode(currentNode)) {
69
+ transformedNodeTexts.push(transform(currentNode));
70
+ }
71
+ }
72
+ return transformedNodeTexts.join('');
73
+ });
74
+ }
75
+ scrollToBottom() {
76
+ var _this___editor_getRootElement;
77
+ (_this___editor_getRootElement = this.__editor.getRootElement()) === null || _this___editor_getRootElement === void 0 ? void 0 : _this___editor_getRootElement.scrollIntoView({
78
+ behavior: 'smooth',
79
+ block: 'end'
80
+ });
81
+ return;
82
+ }
83
+ constructor(editor){
84
+ _define_property(this, "__editor", void 0);
85
+ this.__editor = editor;
86
+ }
87
87
  }
88
- //# sourceMappingURL=ImperativeControl.base.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["ImperativeControl.base.ts"],"sourcesContent":["import type { LexicalEditor, LexicalNode } from '@fluentui-copilot/text-editor';\nimport {\n $createParagraphNode,\n $createRangeSelection,\n $createTextNode,\n $getLeafNodes,\n $getRoot,\n $getSelection,\n $isTextNode,\n $normalizeSelection__EXPERIMENTAL,\n $setSelection,\n} from '@fluentui-copilot/text-editor';\nimport { SENTINEL_VALUE, $isSentinelNode } from '../BasicFunctionality';\n\nexport interface IImperativeControlBase {\n setInputText: (inputText: string) => void;\n appendText: (text: string) => void;\n prependText: (text: string) => void;\n insertTextAtCursor: (text: string) => void;\n /**\n * @param transform will be called for each Lexical node in the input. This enables custom string representation for each node.\n */\n getInputText: (transform?: (node: LexicalNode) => string) => string;\n scrollToBottom: () => void;\n moveCursor: (location: number) => void;\n}\n\nexport class ImperativeControlBase implements IImperativeControlBase {\n private __editor: LexicalEditor;\n\n constructor(editor: LexicalEditor) {\n this.__editor = editor;\n }\n\n moveCursor(location: number): void {\n this.__editor.update(() => {\n const children = $getLeafNodes($getRoot());\n\n let baseOffset = 0;\n let currentNode = children.shift();\n while (baseOffset < location && currentNode) {\n const nodeLength =\n $isTextNode(currentNode) && !currentNode.isToken()\n ? currentNode.getTextContent().length\n : // Token text nodes and non-text nodes are considered to be a single entry in the input\n 1;\n\n if (baseOffset + nodeLength >= location) {\n const elementType = $isTextNode(currentNode) ? 'text' : 'element';\n const localOffset = location - baseOffset;\n const nodeKey = currentNode.getKey();\n\n const selection = $createRangeSelection();\n selection.anchor.set(nodeKey, localOffset, elementType);\n selection.focus.set(nodeKey, localOffset, elementType);\n\n $setSelection($normalizeSelection__EXPERIMENTAL(selection));\n return;\n }\n\n baseOffset += nodeLength;\n currentNode = children.shift();\n }\n\n if (location > baseOffset) {\n $getRoot().selectEnd();\n }\n });\n }\n setInputText(inputText: string) {\n this.__editor.update(() => {\n const root = $getRoot();\n root.clear();\n if (inputText !== '') {\n const newParagraph = $createParagraphNode();\n const newText = $createTextNode(inputText);\n\n newParagraph.append(newText);\n root.append(newParagraph);\n root.selectEnd();\n }\n });\n }\n appendText(text: string) {\n this.__editor.update(() => {\n $getRoot().selectEnd().insertText(text);\n });\n }\n prependText(text: string) {\n this.__editor.update(() => {\n $getRoot().selectStart().insertText(text);\n });\n }\n insertTextAtCursor(text: string) {\n this.__editor.update(() => {\n const selection = $getSelection() ?? $getRoot().selectEnd();\n selection.insertText(text);\n });\n }\n getInputText(transform?: (node: LexicalNode) => string) {\n return this.__editor.getEditorState().read(() => {\n if (!transform) {\n return $getRoot().getTextContent().replace(SENTINEL_VALUE, '');\n }\n const children = $getLeafNodes($getRoot());\n const transformedNodeTexts: string[] = [];\n\n for (const currentNode of children) {\n if (!$isSentinelNode(currentNode)) {\n transformedNodeTexts.push(transform(currentNode));\n }\n }\n\n return transformedNodeTexts.join('');\n });\n }\n scrollToBottom() {\n this.__editor.getRootElement()?.scrollIntoView({ behavior: 'smooth', block: 'end' });\n return;\n }\n}\n"],"names":["$createParagraphNode","$createRangeSelection","$createTextNode","$getLeafNodes","$getRoot","$getSelection","$isTextNode","$normalizeSelection__EXPERIMENTAL","$setSelection","SENTINEL_VALUE","$isSentinelNode","ImperativeControlBase","moveCursor","location","__editor","update","children","baseOffset","currentNode","shift","nodeLength","isToken","getTextContent","length","elementType","localOffset","nodeKey","getKey","selection","anchor","set","focus","selectEnd","setInputText","inputText","root","clear","newParagraph","newText","append","appendText","text","insertText","prependText","selectStart","insertTextAtCursor","getInputText","transform","getEditorState","read","replace","transformedNodeTexts","push","join","scrollToBottom","getRootElement","scrollIntoView","behavior","block","constructor","editor"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["ImperativeControl.base.ts"],"sourcesContent":["import type { LexicalEditor, LexicalNode } from '@fluentui-copilot/text-editor';\nimport {\n $createParagraphNode,\n $createRangeSelection,\n $createTextNode,\n $getLeafNodes,\n $getRoot,\n $getSelection,\n $isTextNode,\n $normalizeSelection__EXPERIMENTAL,\n $setSelection,\n} from '@fluentui-copilot/text-editor';\nimport { SENTINEL_VALUE, $isSentinelNode } from '../BasicFunctionality';\n\nexport interface IImperativeControlBase {\n setInputText: (inputText: string) => void;\n appendText: (text: string) => void;\n prependText: (text: string) => void;\n insertTextAtCursor: (text: string) => void;\n /**\n * @param transform will be called for each Lexical node in the input. This enables custom string representation for each node.\n */\n getInputText: (transform?: (node: LexicalNode) => string) => string;\n scrollToBottom: () => void;\n moveCursor: (location: number) => void;\n}\n\nexport class ImperativeControlBase implements IImperativeControlBase {\n private __editor: LexicalEditor;\n\n constructor(editor: LexicalEditor) {\n this.__editor = editor;\n }\n\n moveCursor(location: number): void {\n this.__editor.update(() => {\n const children = $getLeafNodes($getRoot());\n\n let baseOffset = 0;\n let currentNode = children.shift();\n while (baseOffset < location && currentNode) {\n const nodeLength =\n $isTextNode(currentNode) && !currentNode.isToken()\n ? currentNode.getTextContent().length\n : // Token text nodes and non-text nodes are considered to be a single entry in the input\n 1;\n\n if (baseOffset + nodeLength >= location) {\n const elementType = $isTextNode(currentNode) ? 'text' : 'element';\n const localOffset = location - baseOffset;\n const nodeKey = currentNode.getKey();\n\n const selection = $createRangeSelection();\n selection.anchor.set(nodeKey, localOffset, elementType);\n selection.focus.set(nodeKey, localOffset, elementType);\n\n $setSelection($normalizeSelection__EXPERIMENTAL(selection));\n return;\n }\n\n baseOffset += nodeLength;\n currentNode = children.shift();\n }\n\n if (location > baseOffset) {\n $getRoot().selectEnd();\n }\n });\n }\n setInputText(inputText: string): void {\n this.__editor.update(() => {\n const root = $getRoot();\n root.clear();\n if (inputText !== '') {\n const newParagraph = $createParagraphNode();\n const newText = $createTextNode(inputText);\n\n newParagraph.append(newText);\n root.append(newParagraph);\n root.selectEnd();\n }\n });\n }\n appendText(text: string): void {\n this.__editor.update(() => {\n $getRoot().selectEnd().insertText(text);\n });\n }\n prependText(text: string): void {\n this.__editor.update(() => {\n $getRoot().selectStart().insertText(text);\n });\n }\n insertTextAtCursor(text: string): void {\n this.__editor.update(() => {\n const selection = $getSelection() ?? $getRoot().selectEnd();\n selection.insertText(text);\n });\n }\n getInputText(transform?: (node: LexicalNode) => string): string {\n return this.__editor.getEditorState().read(() => {\n if (!transform) {\n return $getRoot().getTextContent().replace(SENTINEL_VALUE, '');\n }\n const children = $getLeafNodes($getRoot());\n const transformedNodeTexts: string[] = [];\n\n for (const currentNode of children) {\n if (!$isSentinelNode(currentNode)) {\n transformedNodeTexts.push(transform(currentNode));\n }\n }\n\n return transformedNodeTexts.join('');\n });\n }\n scrollToBottom(): void {\n this.__editor.getRootElement()?.scrollIntoView({ behavior: 'smooth', block: 'end' });\n return;\n }\n}\n"],"names":["$createParagraphNode","$createRangeSelection","$createTextNode","$getLeafNodes","$getRoot","$getSelection","$isTextNode","$normalizeSelection__EXPERIMENTAL","$setSelection","SENTINEL_VALUE","$isSentinelNode","ImperativeControlBase","moveCursor","location","__editor","update","children","baseOffset","currentNode","shift","nodeLength","isToken","getTextContent","length","elementType","localOffset","nodeKey","getKey","selection","anchor","set","focus","selectEnd","setInputText","inputText","root","clear","newParagraph","newText","append","appendText","text","insertText","prependText","selectStart","insertTextAtCursor","getInputText","transform","getEditorState","read","replace","transformedNodeTexts","push","join","scrollToBottom","getRootElement","scrollIntoView","behavior","block","constructor","editor"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -1,2 +1 @@
1
1
  export { ImperativeControlBase } from './ImperativeControl.base';
2
- //# sourceMappingURL=index.js.map
@@ -1,77 +1,78 @@
1
1
  import { _ as _define_property } from "@swc/helpers/_/_define_property";
2
2
  import { $createTextNode, $getNodeByKey, $insertNodes } from '@fluentui-copilot/text-editor';
3
3
  export class ManualGhostTextBase {
4
- getGhostText() {
5
- return this.__editor.getEditorState().read(() => {
6
- if (this.__nodeKey) {
7
- const node = $getNodeByKey(this.__nodeKey);
8
- if (this.__$isNodeType(node)) {
9
- return node.__content;
10
- }
11
- }
12
- });
13
- }
14
- setGhostText(text, exposeText, componentProps, discrete) {
15
- this.__editor.update(() => {
16
- if (this.__nodeKey) {
17
- const node = $getNodeByKey(this.__nodeKey);
18
- if (this.__$isNodeType(node)) {
19
- node.getWritable().__content = text;
20
- return;
21
- }
22
- }
23
- const node = this.__$createNode(this.__id, text, exposeText, componentProps);
24
- this.__nodeKey = node.getKey();
25
- $insertNodes([node]);
26
- node.selectStart();
27
- }, {
28
- tag: 'historic',
29
- discrete: discrete ? true : undefined
30
- });
31
- }
32
- commitGhostText(finalText, discrete) {
33
- if (this.__nodeKey) {
34
- this.__editor.update(() => {
4
+ getGhostText() {
5
+ return this.__editor.getEditorState().read(()=>{
6
+ if (this.__nodeKey) {
7
+ const node = $getNodeByKey(this.__nodeKey);
8
+ if (this.__$isNodeType(node)) {
9
+ return node.__content;
10
+ }
11
+ }
12
+ });
13
+ }
14
+ setGhostText(text, exposeText, componentProps, discrete) {
15
+ this.__editor.update(()=>{
16
+ if (this.__nodeKey) {
17
+ const node = $getNodeByKey(this.__nodeKey);
18
+ if (this.__$isNodeType(node)) {
19
+ node.getWritable().__content = text;
20
+ return;
21
+ }
22
+ }
23
+ const node = this.__$createNode(this.__id, text, exposeText, componentProps);
24
+ this.__nodeKey = node.getKey();
25
+ $insertNodes([
26
+ node
27
+ ]);
28
+ node.selectStart();
29
+ }, {
30
+ tag: 'historic',
31
+ discrete: discrete ? true : undefined
32
+ });
33
+ }
34
+ commitGhostText(finalText, discrete) {
35
35
  if (this.__nodeKey) {
36
- const node = $getNodeByKey(this.__nodeKey);
37
- if (this.__$isNodeType(node)) {
38
- const textNode = $createTextNode(finalText);
39
- node.replace(textNode);
40
- textNode.selectEnd();
41
- }
36
+ this.__editor.update(()=>{
37
+ if (this.__nodeKey) {
38
+ const node = $getNodeByKey(this.__nodeKey);
39
+ if (this.__$isNodeType(node)) {
40
+ const textNode = $createTextNode(finalText);
41
+ node.replace(textNode);
42
+ textNode.selectEnd();
43
+ }
44
+ }
45
+ }, {
46
+ discrete: discrete ? true : undefined
47
+ });
48
+ this.__nodeKey = undefined;
42
49
  }
43
- }, {
44
- discrete: discrete ? true : undefined
45
- });
46
- this.__nodeKey = undefined;
47
50
  }
48
- }
49
- cancelGhostText(discrete) {
50
- if (this.__nodeKey) {
51
- this.__editor.update(() => {
51
+ cancelGhostText(discrete) {
52
52
  if (this.__nodeKey) {
53
- const node = $getNodeByKey(this.__nodeKey);
54
- if (this.__$isNodeType(node)) {
55
- node.remove();
56
- }
53
+ this.__editor.update(()=>{
54
+ if (this.__nodeKey) {
55
+ const node = $getNodeByKey(this.__nodeKey);
56
+ if (this.__$isNodeType(node)) {
57
+ node.remove();
58
+ }
59
+ }
60
+ }, {
61
+ tag: 'historic',
62
+ discrete: discrete ? true : undefined
63
+ });
64
+ this.__nodeKey = undefined;
57
65
  }
58
- }, {
59
- tag: 'historic',
60
- discrete: discrete ? true : undefined
61
- });
62
- this.__nodeKey = undefined;
63
66
  }
64
- }
65
- constructor(editor, id, $isNodeType, $createNode) {
66
- _define_property(this, "__editor", void 0);
67
- _define_property(this, "__nodeKey", void 0);
68
- _define_property(this, "__id", void 0);
69
- _define_property(this, "__$isNodeType", void 0);
70
- _define_property(this, "__$createNode", void 0);
71
- this.__editor = editor;
72
- this.__id = id;
73
- this.__$isNodeType = $isNodeType;
74
- this.__$createNode = $createNode;
75
- }
67
+ constructor(editor, id, $isNodeType, $createNode){
68
+ _define_property(this, "__editor", void 0);
69
+ _define_property(this, "__nodeKey", void 0);
70
+ _define_property(this, "__id", void 0);
71
+ _define_property(this, "__$isNodeType", void 0);
72
+ _define_property(this, "__$createNode", void 0);
73
+ this.__editor = editor;
74
+ this.__id = id;
75
+ this.__$isNodeType = $isNodeType;
76
+ this.__$createNode = $createNode;
77
+ }
76
78
  }
77
- //# sourceMappingURL=ManualGhostText.base.js.map
@@ -1,2 +1 @@
1
1
  export { ManualGhostTextBase } from './ManualGhostText.base';
2
- //# sourceMappingURL=index.js.map
@@ -1,65 +1,60 @@
1
1
  import { COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_LOW, PASTE_COMMAND, $insertNodes, $createTextNode } from '@fluentui-copilot/text-editor';
2
2
  function unhandledPart(part) {
3
- throw new Error(`Unhandled part: ${part}`);
3
+ throw new Error(`Unhandled part: ${part}`);
4
4
  }
5
5
  export function registerPasteUnfurlingPlugin(editor, props) {
6
- const {
7
- entityPluginId,
8
- transforms,
9
- $createEntityNode
10
- } = props;
11
- function insertParts(parts) {
12
- editor.update(() => {
13
- const nodes = parts.map(part => {
14
- switch (part.type) {
15
- case 'entity':
16
- return $createEntityNode(entityPluginId, part.value.text, part.value.data, part.value.entityProps);
17
- case 'text':
18
- return $createTextNode(part.value);
19
- }
20
- return unhandledPart(part);
21
- });
22
- $insertNodes(nodes);
23
- });
24
- }
25
- function handlePaste(event) {
26
- const transformPromises = [];
27
- for (const transform of transforms) {
28
- transformPromises.push(Promise.resolve(transform(event, editor)));
6
+ const { entityPluginId, transforms, $createEntityNode } = props;
7
+ function insertParts(parts) {
8
+ editor.update(()=>{
9
+ const nodes = parts.map((part)=>{
10
+ switch(part.type){
11
+ case 'entity':
12
+ return $createEntityNode(entityPluginId, part.value.text, part.value.data, part.value.entityProps);
13
+ case 'text':
14
+ return $createTextNode(part.value);
15
+ }
16
+ return unhandledPart(part);
17
+ });
18
+ $insertNodes(nodes);
19
+ });
29
20
  }
30
- Promise.allSettled(transformPromises).then(results => {
31
- let handledPaste = false;
32
- for (const result of results) {
33
- if (result.status === 'fulfilled') {
34
- const transformResult = result.value;
35
- if (transformResult.transformedParts) {
36
- insertParts(transformResult.transformedParts);
37
- }
38
- if (transformResult.handled) {
39
- handledPaste = true;
40
- break;
41
- }
21
+ function handlePaste(event) {
22
+ const transformPromises = [];
23
+ for (const transform of transforms){
24
+ transformPromises.push(Promise.resolve(transform(event, editor)));
42
25
  }
43
- }
44
- if (!handledPaste) {
45
- var _commandsMap_get;
46
- const commandsMap = editor._commands;
47
- const defaultEditorListeners = (_commandsMap_get = commandsMap.get(PASTE_COMMAND)) === null || _commandsMap_get === void 0 ? void 0 : _commandsMap_get[COMMAND_PRIORITY_EDITOR];
48
- if (defaultEditorListeners) {
49
- // After the promises have resolved, we're not guaranteed to be in the same update state as the original command
50
- editor.update(() => {
51
- for (const listener of defaultEditorListeners) {
52
- const defaultHandled = listener(event, editor);
53
- if (defaultHandled) {
54
- break;
55
- }
26
+ Promise.allSettled(transformPromises).then((results)=>{
27
+ let handledPaste = false;
28
+ for (const result of results){
29
+ if (result.status === 'fulfilled') {
30
+ const transformResult = result.value;
31
+ if (transformResult.transformedParts) {
32
+ insertParts(transformResult.transformedParts);
33
+ }
34
+ if (transformResult.handled) {
35
+ handledPaste = true;
36
+ break;
37
+ }
38
+ }
56
39
  }
57
- });
58
- }
59
- }
60
- });
61
- return true;
62
- }
63
- return editor.registerCommand(PASTE_COMMAND, handlePaste, COMMAND_PRIORITY_LOW);
40
+ if (!handledPaste) {
41
+ var _commandsMap_get;
42
+ const commandsMap = editor._commands;
43
+ const defaultEditorListeners = (_commandsMap_get = commandsMap.get(PASTE_COMMAND)) === null || _commandsMap_get === void 0 ? void 0 : _commandsMap_get[COMMAND_PRIORITY_EDITOR];
44
+ if (defaultEditorListeners) {
45
+ // After the promises have resolved, we're not guaranteed to be in the same update state as the original command
46
+ editor.update(()=>{
47
+ for (const listener of defaultEditorListeners){
48
+ const defaultHandled = listener(event, editor);
49
+ if (defaultHandled) {
50
+ break;
51
+ }
52
+ }
53
+ });
54
+ }
55
+ }
56
+ });
57
+ return true;
58
+ }
59
+ return editor.registerCommand(PASTE_COMMAND, handlePaste, COMMAND_PRIORITY_LOW);
64
60
  }
65
- //# sourceMappingURL=PasteUnfurling.base.js.map
@@ -1,2 +1 @@
1
- export {};
2
- //# sourceMappingURL=PasteUnfurling.types.js.map
1
+ export { };