@fluentui-copilot/chat-input-plugins 0.4.1 → 0.4.2-hotfix.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 (50) hide show
  1. package/CHANGELOG.json +60 -0
  2. package/CHANGELOG.md +19 -1
  3. package/dist/index.d.ts +1 -1
  4. package/lib/BasicFunctionality/BasicFunctionality.base.js +94 -91
  5. package/lib/BasicFunctionality/BasicFunctionality.base.js.map +1 -1
  6. package/lib/BasicFunctionality/SentinelNode.js +29 -30
  7. package/lib/BasicFunctionality/SentinelNodeHandlers.js +73 -78
  8. package/lib/BasicFunctionality/index.js +0 -1
  9. package/lib/ChatInputEntity/ChatInputEntityPlugin.base.js +109 -114
  10. package/lib/ChatInputEntity/ChatInputEntityPlugin.types.js +1 -2
  11. package/lib/ChatInputEntity/index.js +0 -1
  12. package/lib/GhostText/GhostText.base.js +142 -145
  13. package/lib/GhostText/index.js +0 -1
  14. package/lib/ImperativeControl/ImperativeControl.base.js +82 -83
  15. package/lib/ImperativeControl/index.js +0 -1
  16. package/lib/ManualGhostText/ManualGhostText.base.js +68 -67
  17. package/lib/ManualGhostText/index.js +0 -1
  18. package/lib/PasteUnfurling/PasteUnfurling.base.js +52 -57
  19. package/lib/PasteUnfurling/PasteUnfurling.types.js +1 -2
  20. package/lib/PasteUnfurling/PasteUnfurlingTestUtils.js +138 -139
  21. package/lib/PasteUnfurling/index.js +0 -1
  22. package/lib/index.js +0 -1
  23. package/lib-commonjs/BasicFunctionality/BasicFunctionality.base.js +7 -5
  24. package/lib-commonjs/BasicFunctionality/BasicFunctionality.base.js.map +1 -1
  25. package/lib-commonjs/BasicFunctionality/SentinelNode.js +1 -1
  26. package/lib-commonjs/BasicFunctionality/SentinelNode.js.map +1 -1
  27. package/lib-commonjs/BasicFunctionality/SentinelNodeHandlers.js +3 -5
  28. package/lib-commonjs/BasicFunctionality/SentinelNodeHandlers.js.map +1 -1
  29. package/lib-commonjs/BasicFunctionality/index.js +0 -1
  30. package/lib-commonjs/ChatInputEntity/ChatInputEntityPlugin.base.js +3 -5
  31. package/lib-commonjs/ChatInputEntity/ChatInputEntityPlugin.base.js.map +1 -1
  32. package/lib-commonjs/ChatInputEntity/ChatInputEntityPlugin.types.js +0 -1
  33. package/lib-commonjs/ChatInputEntity/index.js +0 -1
  34. package/lib-commonjs/GhostText/GhostText.base.js +2 -3
  35. package/lib-commonjs/GhostText/GhostText.base.js.map +1 -1
  36. package/lib-commonjs/GhostText/index.js +0 -1
  37. package/lib-commonjs/ImperativeControl/ImperativeControl.base.js +1 -1
  38. package/lib-commonjs/ImperativeControl/ImperativeControl.base.js.map +1 -1
  39. package/lib-commonjs/ImperativeControl/index.js +0 -1
  40. package/lib-commonjs/ManualGhostText/ManualGhostText.base.js +1 -1
  41. package/lib-commonjs/ManualGhostText/ManualGhostText.base.js.map +1 -1
  42. package/lib-commonjs/ManualGhostText/index.js +0 -1
  43. package/lib-commonjs/PasteUnfurling/PasteUnfurling.base.js +1 -1
  44. package/lib-commonjs/PasteUnfurling/PasteUnfurling.base.js.map +1 -1
  45. package/lib-commonjs/PasteUnfurling/PasteUnfurling.types.js +0 -1
  46. package/lib-commonjs/PasteUnfurling/PasteUnfurlingTestUtils.js +1 -1
  47. package/lib-commonjs/PasteUnfurling/PasteUnfurlingTestUtils.js.map +1 -1
  48. package/lib-commonjs/PasteUnfurling/index.js +0 -1
  49. package/lib-commonjs/index.js +0 -1
  50. package/package.json +3 -7
package/CHANGELOG.json CHANGED
@@ -1,6 +1,66 @@
1
1
  {
2
2
  "name": "@fluentui-copilot/chat-input-plugins",
3
3
  "entries": [
4
+ {
5
+ "date": "Tue, 12 Aug 2025 16:09:21 GMT",
6
+ "tag": "@fluentui-copilot/chat-input-plugins_v0.4.2-hotfix.2",
7
+ "version": "0.4.2-hotfix.2",
8
+ "comments": {
9
+ "prerelease": [
10
+ {
11
+ "author": "hochelmartin@gmail.com",
12
+ "package": "@fluentui-copilot/chat-input-plugins",
13
+ "commit": "3e4ebe676646c4c4346dbbab83511f963ffefd85",
14
+ "comment": "release: prepare hotfix 0.26.2-hotfix.1"
15
+ }
16
+ ]
17
+ }
18
+ },
19
+ {
20
+ "date": "Mon, 19 May 2025 18:04:26 GMT",
21
+ "tag": "@fluentui-copilot/chat-input-plugins_v0.4.2",
22
+ "version": "0.4.2",
23
+ "comments": {
24
+ "none": [
25
+ {
26
+ "author": "hochelmartin@gmail.com",
27
+ "package": "@fluentui-copilot/chat-input-plugins",
28
+ "commit": "442954951d0eca92de20ecb0ff0fa9492431b62d",
29
+ "comment": "fix: exclude story files from production build"
30
+ }
31
+ ]
32
+ }
33
+ },
34
+ {
35
+ "date": "Wed, 30 Apr 2025 01:47:47 GMT",
36
+ "tag": "@fluentui-copilot/chat-input-plugins_v0.4.2",
37
+ "version": "0.4.2",
38
+ "comments": {
39
+ "none": [
40
+ {
41
+ "author": "tristan.watanabe@gmail.com",
42
+ "package": "@fluentui-copilot/chat-input-plugins",
43
+ "commit": "1391e0a7243d050db30fcc27547fd3e91df0162c",
44
+ "comment": "chore: update tsconfig to remove allowSyntheticDefaultImports to enforce named imports."
45
+ }
46
+ ]
47
+ }
48
+ },
49
+ {
50
+ "date": "Fri, 07 Feb 2025 02:02:08 GMT",
51
+ "tag": "@fluentui-copilot/chat-input-plugins_v0.4.2",
52
+ "version": "0.4.2",
53
+ "comments": {
54
+ "patch": [
55
+ {
56
+ "author": "owcampbe@microsoft.com",
57
+ "package": "@fluentui-copilot/chat-input-plugins",
58
+ "commit": "7f530f0f6d24d12c634a1247655aeaa92ddb7561",
59
+ "comment": "feat: Allow disabling the SentinelNode."
60
+ }
61
+ ]
62
+ }
63
+ },
4
64
  {
5
65
  "date": "Wed, 18 Dec 2024 08:55:41 GMT",
6
66
  "tag": "@fluentui-copilot/chat-input-plugins_v0.3.4",
package/CHANGELOG.md CHANGED
@@ -1,9 +1,27 @@
1
1
  # Change Log - @fluentui-copilot/chat-input-plugins
2
2
 
3
- This log was last generated on Wed, 18 Dec 2024 08:55:41 GMT and should not be manually modified.
3
+ This log was last generated on Tue, 12 Aug 2025 16:09:21 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## [0.4.2-hotfix.2](https://github.com/microsoft/fluentai/tree/@fluentui-copilot/chat-input-plugins_v0.4.2-hotfix.2)
8
+
9
+ Tue, 12 Aug 2025 16:09:21 GMT
10
+ [Compare changes](https://github.com/microsoft/fluentai/compare/@fluentui-copilot/chat-input-plugins_v0.4.2..@fluentui-copilot/chat-input-plugins_v0.4.2-hotfix.2)
11
+
12
+ ### Changes
13
+
14
+ - release: prepare hotfix 0.26.2-hotfix.1 ([PR #3284](https://github.com/microsoft/fluentai/pull/3284) by hochelmartin@gmail.com)
15
+
16
+ ## [0.4.2](https://github.com/microsoft/fluentai/tree/@fluentui-copilot/chat-input-plugins_v0.4.2)
17
+
18
+ Fri, 07 Feb 2025 02:02:08 GMT
19
+ [Compare changes](https://github.com/microsoft/fluentai/compare/@fluentui-copilot/chat-input-plugins_v0.3.4..@fluentui-copilot/chat-input-plugins_v0.4.2)
20
+
21
+ ### Patches
22
+
23
+ - feat: Allow disabling the SentinelNode. ([PR #2567](https://github.com/microsoft/fluentai/pull/2567) by owcampbe@microsoft.com)
24
+
7
25
  ## [0.3.4](https://github.com/microsoft/fluentai/tree/@fluentui-copilot/chat-input-plugins_v0.3.4)
8
26
 
9
27
  Wed, 18 Dec 2024 08:55:41 GMT
package/dist/index.d.ts CHANGED
@@ -18,7 +18,7 @@ export declare class BasicFunctionalityBase implements IBasicFunctionalityBase {
18
18
  private __baseHandlersCleanup?;
19
19
  private __pasteHandlerCleanup?;
20
20
  private __enterHandler;
21
- constructor(editor: LexicalEditor);
21
+ constructor(editor: LexicalEditor, isSentinelNodeEnabled?: boolean);
22
22
  insertDefaultValue(defaultValue: string): void;
23
23
  activateContentCallbacks(onContentChange?: ((value: string) => void) | undefined, onCountChanged?: ((count: number) => void) | undefined): void;
24
24
  deactivateContentCallbacks(): void;
@@ -4,102 +4,105 @@ import { $createTextNode, $getRoot, $getSelection, $insertNodes, $isRangeSelecti
4
4
  import { SENTINEL_VALUE } from './SentinelNode';
5
5
  import { registerSentinelNodeHandlers } from './SentinelNodeHandlers';
6
6
  function isClipboardEvent(event) {
7
- return event.type === 'paste';
7
+ return event.type === 'paste';
8
8
  }
9
9
  export class BasicFunctionalityBase {
10
- __enterHandler(event) {
11
- const selection = $getSelection();
12
- if (!$isRangeSelection(selection)) {
13
- return false;
10
+ __enterHandler(event) {
11
+ const selection = $getSelection();
12
+ if (!$isRangeSelection(selection)) {
13
+ return false;
14
+ }
15
+ if (event === null) {
16
+ return false;
17
+ }
18
+ event.preventDefault();
19
+ if (event.shiftKey) {
20
+ return this.__editor.dispatchCommand(INSERT_PARAGRAPH_COMMAND, undefined);
21
+ }
22
+ // Mark event handled to override default behavior
23
+ return true;
14
24
  }
15
- if (event === null) {
16
- return false;
25
+ insertDefaultValue(defaultValue) {
26
+ if (defaultValue) {
27
+ this.__editor.update(()=>{
28
+ $insertNodes([
29
+ $createTextNode(defaultValue)
30
+ ]);
31
+ });
32
+ }
17
33
  }
18
- event.preventDefault();
19
- if (event.shiftKey) {
20
- return this.__editor.dispatchCommand(INSERT_PARAGRAPH_COMMAND, undefined);
34
+ activateContentCallbacks(onContentChange, onCountChanged) {
35
+ this.deactivateContentCallbacks();
36
+ this.__contentChangeCleanup = this.__editor.registerTextContentListener((text)=>{
37
+ // Remove the sentinel node
38
+ const processed = text.replace(SENTINEL_VALUE, '');
39
+ onContentChange === null || onContentChange === void 0 ? void 0 : onContentChange(processed);
40
+ onCountChanged === null || onCountChanged === void 0 ? void 0 : onCountChanged(processed.length);
41
+ });
21
42
  }
22
- // Mark event handled to override default behavior
23
- return true;
24
- }
25
- insertDefaultValue(defaultValue) {
26
- if (defaultValue) {
27
- this.__editor.update(() => {
28
- $insertNodes([$createTextNode(defaultValue)]);
29
- });
43
+ deactivateContentCallbacks() {
44
+ var _this___contentChangeCleanup, _this;
45
+ (_this___contentChangeCleanup = (_this = this).__contentChangeCleanup) === null || _this___contentChangeCleanup === void 0 ? void 0 : _this___contentChangeCleanup.call(_this);
46
+ this.__contentChangeCleanup = undefined;
30
47
  }
31
- }
32
- activateContentCallbacks(onContentChange, onCountChanged) {
33
- this.deactivateContentCallbacks();
34
- this.__contentChangeCleanup = this.__editor.registerTextContentListener(text => {
35
- // Remove the sentinel node
36
- const processed = text.replace(SENTINEL_VALUE, '');
37
- onContentChange === null || onContentChange === void 0 ? void 0 : onContentChange(processed);
38
- onCountChanged === null || onCountChanged === void 0 ? void 0 : onCountChanged(processed.length);
39
- });
40
- }
41
- deactivateContentCallbacks() {
42
- var _this___contentChangeCleanup, _this;
43
- (_this___contentChangeCleanup = (_this = this).__contentChangeCleanup) === null || _this___contentChangeCleanup === void 0 ? void 0 : _this___contentChangeCleanup.call(_this);
44
- this.__contentChangeCleanup = undefined;
45
- }
46
- activatePasteCallback(onPaste) {
47
- this.__pasteHandlerCleanup = this.__editor.registerCommand(PASTE_COMMAND, event => {
48
- if (!isClipboardEvent(event)) {
49
- return false;
50
- }
51
- onPaste(event);
52
- if (event.defaultPrevented) {
53
- return true;
54
- }
55
- return false;
56
- }, COMMAND_PRIORITY_HIGH);
57
- }
58
- deactivatePasteCallback() {
59
- var _this___pasteHandlerCleanup, _this;
60
- (_this___pasteHandlerCleanup = (_this = this).__pasteHandlerCleanup) === null || _this___pasteHandlerCleanup === void 0 ? void 0 : _this___pasteHandlerCleanup.call(_this);
61
- this.__pasteHandlerCleanup = undefined;
62
- }
63
- activateTrimWhitespace() {
64
- this.deactivateTrimWhitespace();
65
- this.__trimWhitespaceCleanup = this.__editor.registerTextContentListener(text => {
66
- if (text.trim() === '') {
67
- this.__editor.update(() => {
68
- $getRoot().getAllTextNodes().forEach(node => {
69
- node.remove();
70
- });
71
- },
72
- // Don't allow undoing this action
73
- {
74
- tag: 'historic'
48
+ activatePasteCallback(onPaste) {
49
+ this.__pasteHandlerCleanup = this.__editor.registerCommand(PASTE_COMMAND, (event)=>{
50
+ if (!isClipboardEvent(event)) {
51
+ return false;
52
+ }
53
+ onPaste(event);
54
+ if (event.defaultPrevented) {
55
+ return true;
56
+ }
57
+ return false;
58
+ }, COMMAND_PRIORITY_HIGH);
59
+ }
60
+ deactivatePasteCallback() {
61
+ var _this___pasteHandlerCleanup, _this;
62
+ (_this___pasteHandlerCleanup = (_this = this).__pasteHandlerCleanup) === null || _this___pasteHandlerCleanup === void 0 ? void 0 : _this___pasteHandlerCleanup.call(_this);
63
+ this.__pasteHandlerCleanup = undefined;
64
+ }
65
+ activateTrimWhitespace() {
66
+ this.deactivateTrimWhitespace();
67
+ this.__trimWhitespaceCleanup = this.__editor.registerTextContentListener((text)=>{
68
+ if (text.trim() === '') {
69
+ this.__editor.update(()=>{
70
+ $getRoot().getAllTextNodes().forEach((node)=>{
71
+ node.remove();
72
+ });
73
+ }, // Don't allow undoing this action
74
+ {
75
+ tag: 'historic'
76
+ });
77
+ }
75
78
  });
76
- }
77
- });
78
- }
79
- deactivateTrimWhitespace() {
80
- var _this___trimWhitespaceCleanup, _this;
81
- (_this___trimWhitespaceCleanup = (_this = this).__trimWhitespaceCleanup) === null || _this___trimWhitespaceCleanup === void 0 ? void 0 : _this___trimWhitespaceCleanup.call(_this);
82
- this.__trimWhitespaceCleanup = undefined;
83
- }
84
- setIsDisabled(isDisabled) {
85
- this.__editor.setEditable(!isDisabled);
86
- }
87
- cleanup() {
88
- var _this___baseHandlersCleanup, _this;
89
- this.deactivateContentCallbacks();
90
- this.deactivateTrimWhitespace();
91
- this.deactivatePasteCallback();
92
- (_this___baseHandlersCleanup = (_this = this).__baseHandlersCleanup) === null || _this___baseHandlersCleanup === void 0 ? void 0 : _this___baseHandlersCleanup.call(_this);
93
- this.__baseHandlersCleanup = undefined;
94
- }
95
- constructor(editor) {
96
- _define_property(this, "__editor", void 0);
97
- _define_property(this, "__contentChangeCleanup", void 0);
98
- _define_property(this, "__trimWhitespaceCleanup", void 0);
99
- _define_property(this, "__baseHandlersCleanup", void 0);
100
- _define_property(this, "__pasteHandlerCleanup", void 0);
101
- this.__editor = editor;
102
- this.__baseHandlersCleanup = mergeRegister(this.__editor.registerCommand(KEY_ENTER_COMMAND, this.__enterHandler.bind(this), COMMAND_PRIORITY_HIGH), registerSentinelNodeHandlers(editor));
103
- }
79
+ }
80
+ deactivateTrimWhitespace() {
81
+ var _this___trimWhitespaceCleanup, _this;
82
+ (_this___trimWhitespaceCleanup = (_this = this).__trimWhitespaceCleanup) === null || _this___trimWhitespaceCleanup === void 0 ? void 0 : _this___trimWhitespaceCleanup.call(_this);
83
+ this.__trimWhitespaceCleanup = undefined;
84
+ }
85
+ setIsDisabled(isDisabled) {
86
+ this.__editor.setEditable(!isDisabled);
87
+ }
88
+ cleanup() {
89
+ var _this___baseHandlersCleanup, _this;
90
+ this.deactivateContentCallbacks();
91
+ this.deactivateTrimWhitespace();
92
+ this.deactivatePasteCallback();
93
+ (_this___baseHandlersCleanup = (_this = this).__baseHandlersCleanup) === null || _this___baseHandlersCleanup === void 0 ? void 0 : _this___baseHandlersCleanup.call(_this);
94
+ this.__baseHandlersCleanup = undefined;
95
+ }
96
+ constructor(editor, isSentinelNodeEnabled = true){
97
+ _define_property(this, "__editor", void 0);
98
+ _define_property(this, "__contentChangeCleanup", void 0);
99
+ _define_property(this, "__trimWhitespaceCleanup", void 0);
100
+ _define_property(this, "__baseHandlersCleanup", void 0);
101
+ _define_property(this, "__pasteHandlerCleanup", void 0);
102
+ this.__editor = editor;
103
+ this.__baseHandlersCleanup = mergeRegister(this.__editor.registerCommand(KEY_ENTER_COMMAND, this.__enterHandler.bind(this), COMMAND_PRIORITY_HIGH), isSentinelNodeEnabled ? registerSentinelNodeHandlers(editor) : noop);
104
+ }
105
+ }
106
+ function noop() {
107
+ return;
104
108
  }
105
- //# sourceMappingURL=BasicFunctionality.base.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["BasicFunctionality.base.ts"],"sourcesContent":["import type { LexicalEditor } from '@fluentui-copilot/text-editor';\nimport { COMMAND_PRIORITY_HIGH } from '@fluentui-copilot/text-editor';\nimport {\n $createTextNode,\n $getRoot,\n $getSelection,\n $insertNodes,\n $isRangeSelection,\n INSERT_PARAGRAPH_COMMAND,\n KEY_ENTER_COMMAND,\n PASTE_COMMAND,\n mergeRegister,\n} from '@fluentui-copilot/text-editor';\nimport { SENTINEL_VALUE } from './SentinelNode';\nimport { registerSentinelNodeHandlers } from './SentinelNodeHandlers';\n\nfunction isClipboardEvent(event: ClipboardEvent | KeyboardEvent | InputEvent): event is ClipboardEvent {\n return event.type === 'paste';\n}\n\nexport interface IBasicFunctionalityBase {\n insertDefaultValue: (defaultValue: string) => void;\n setIsDisabled: (isDisabled: boolean) => void;\n activateContentCallbacks(onContentChange?: (value: string) => void, onCountChanged?: (count: number) => void): void;\n deactivateContentCallbacks(): void;\n activateTrimWhitespace(): void;\n deactivateTrimWhitespace(): void;\n activatePasteCallback(onPaste: (event: ClipboardEvent) => void): void;\n deactivatePasteCallback(): void;\n cleanup(): void;\n}\n\nexport class BasicFunctionalityBase implements IBasicFunctionalityBase {\n private __editor: LexicalEditor;\n private __contentChangeCleanup?: () => void;\n private __trimWhitespaceCleanup?: () => void;\n private __baseHandlersCleanup?: () => void;\n private __pasteHandlerCleanup?: () => void;\n\n private __enterHandler(event: KeyboardEvent) {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) {\n return false;\n }\n\n if (event === null) {\n return false;\n }\n\n event.preventDefault();\n\n if (event.shiftKey) {\n return this.__editor.dispatchCommand(INSERT_PARAGRAPH_COMMAND, undefined);\n }\n\n // Mark event handled to override default behavior\n return true;\n }\n\n constructor(editor: LexicalEditor) {\n this.__editor = editor;\n\n this.__baseHandlersCleanup = mergeRegister(\n this.__editor.registerCommand(KEY_ENTER_COMMAND, this.__enterHandler.bind(this), COMMAND_PRIORITY_HIGH),\n registerSentinelNodeHandlers(editor),\n );\n }\n\n insertDefaultValue(defaultValue: string) {\n if (defaultValue) {\n this.__editor.update(() => {\n $insertNodes([$createTextNode(defaultValue)]);\n });\n }\n }\n\n activateContentCallbacks(\n onContentChange?: ((value: string) => void) | undefined,\n onCountChanged?: ((count: number) => void) | undefined,\n ) {\n this.deactivateContentCallbacks();\n this.__contentChangeCleanup = this.__editor.registerTextContentListener(text => {\n // Remove the sentinel node\n const processed = text.replace(SENTINEL_VALUE, '');\n onContentChange?.(processed);\n onCountChanged?.(processed.length);\n });\n }\n\n deactivateContentCallbacks() {\n this.__contentChangeCleanup?.();\n this.__contentChangeCleanup = undefined;\n }\n\n activatePasteCallback(onPaste: (event: ClipboardEvent) => void) {\n this.__pasteHandlerCleanup = this.__editor.registerCommand(\n PASTE_COMMAND,\n (event: ClipboardEvent | KeyboardEvent | InputEvent) => {\n if (!isClipboardEvent(event)) {\n return false;\n }\n\n onPaste(event);\n\n if (event.defaultPrevented) {\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH,\n );\n }\n\n deactivatePasteCallback() {\n this.__pasteHandlerCleanup?.();\n this.__pasteHandlerCleanup = undefined;\n }\n\n activateTrimWhitespace() {\n this.deactivateTrimWhitespace();\n this.__trimWhitespaceCleanup = this.__editor.registerTextContentListener(text => {\n if (text.trim() === '') {\n this.__editor.update(\n () => {\n $getRoot()\n .getAllTextNodes()\n .forEach(node => {\n node.remove();\n });\n },\n // Don't allow undoing this action\n { tag: 'historic' },\n );\n }\n });\n }\n\n deactivateTrimWhitespace() {\n this.__trimWhitespaceCleanup?.();\n this.__trimWhitespaceCleanup = undefined;\n }\n\n setIsDisabled(isDisabled: boolean) {\n this.__editor.setEditable(!isDisabled);\n }\n\n cleanup() {\n this.deactivateContentCallbacks();\n this.deactivateTrimWhitespace();\n this.deactivatePasteCallback();\n this.__baseHandlersCleanup?.();\n this.__baseHandlersCleanup = undefined;\n }\n}\n"],"names":["COMMAND_PRIORITY_HIGH","$createTextNode","$getRoot","$getSelection","$insertNodes","$isRangeSelection","INSERT_PARAGRAPH_COMMAND","KEY_ENTER_COMMAND","PASTE_COMMAND","mergeRegister","SENTINEL_VALUE","registerSentinelNodeHandlers","isClipboardEvent","event","type","BasicFunctionalityBase","__enterHandler","selection","preventDefault","shiftKey","__editor","dispatchCommand","undefined","insertDefaultValue","defaultValue","update","activateContentCallbacks","onContentChange","onCountChanged","deactivateContentCallbacks","__contentChangeCleanup","registerTextContentListener","text","processed","replace","length","activatePasteCallback","onPaste","__pasteHandlerCleanup","registerCommand","defaultPrevented","deactivatePasteCallback","activateTrimWhitespace","deactivateTrimWhitespace","__trimWhitespaceCleanup","trim","getAllTextNodes","forEach","node","remove","tag","setIsDisabled","isDisabled","setEditable","cleanup","__baseHandlersCleanup","constructor","editor","bind"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["BasicFunctionality.base.ts"],"sourcesContent":["import type { LexicalEditor } from '@fluentui-copilot/text-editor';\nimport { COMMAND_PRIORITY_HIGH } from '@fluentui-copilot/text-editor';\nimport {\n $createTextNode,\n $getRoot,\n $getSelection,\n $insertNodes,\n $isRangeSelection,\n INSERT_PARAGRAPH_COMMAND,\n KEY_ENTER_COMMAND,\n PASTE_COMMAND,\n mergeRegister,\n} from '@fluentui-copilot/text-editor';\nimport { SENTINEL_VALUE } from './SentinelNode';\nimport { registerSentinelNodeHandlers } from './SentinelNodeHandlers';\n\nfunction isClipboardEvent(event: ClipboardEvent | KeyboardEvent | InputEvent): event is ClipboardEvent {\n return event.type === 'paste';\n}\n\nexport interface IBasicFunctionalityBase {\n insertDefaultValue: (defaultValue: string) => void;\n setIsDisabled: (isDisabled: boolean) => void;\n activateContentCallbacks(onContentChange?: (value: string) => void, onCountChanged?: (count: number) => void): void;\n deactivateContentCallbacks(): void;\n activateTrimWhitespace(): void;\n deactivateTrimWhitespace(): void;\n activatePasteCallback(onPaste: (event: ClipboardEvent) => void): void;\n deactivatePasteCallback(): void;\n cleanup(): void;\n}\n\nexport class BasicFunctionalityBase implements IBasicFunctionalityBase {\n private __editor: LexicalEditor;\n private __contentChangeCleanup?: () => void;\n private __trimWhitespaceCleanup?: () => void;\n private __baseHandlersCleanup?: () => void;\n private __pasteHandlerCleanup?: () => void;\n\n private __enterHandler(event: KeyboardEvent) {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) {\n return false;\n }\n\n if (event === null) {\n return false;\n }\n\n event.preventDefault();\n\n if (event.shiftKey) {\n return this.__editor.dispatchCommand(INSERT_PARAGRAPH_COMMAND, undefined);\n }\n\n // Mark event handled to override default behavior\n return true;\n }\n\n constructor(editor: LexicalEditor, isSentinelNodeEnabled = true) {\n this.__editor = editor;\n\n this.__baseHandlersCleanup = mergeRegister(\n this.__editor.registerCommand(KEY_ENTER_COMMAND, this.__enterHandler.bind(this), COMMAND_PRIORITY_HIGH),\n isSentinelNodeEnabled ? registerSentinelNodeHandlers(editor) : noop,\n );\n }\n\n insertDefaultValue(defaultValue: string) {\n if (defaultValue) {\n this.__editor.update(() => {\n $insertNodes([$createTextNode(defaultValue)]);\n });\n }\n }\n\n activateContentCallbacks(\n onContentChange?: ((value: string) => void) | undefined,\n onCountChanged?: ((count: number) => void) | undefined,\n ) {\n this.deactivateContentCallbacks();\n this.__contentChangeCleanup = this.__editor.registerTextContentListener(text => {\n // Remove the sentinel node\n const processed = text.replace(SENTINEL_VALUE, '');\n onContentChange?.(processed);\n onCountChanged?.(processed.length);\n });\n }\n\n deactivateContentCallbacks() {\n this.__contentChangeCleanup?.();\n this.__contentChangeCleanup = undefined;\n }\n\n activatePasteCallback(onPaste: (event: ClipboardEvent) => void) {\n this.__pasteHandlerCleanup = this.__editor.registerCommand(\n PASTE_COMMAND,\n (event: ClipboardEvent | KeyboardEvent | InputEvent) => {\n if (!isClipboardEvent(event)) {\n return false;\n }\n\n onPaste(event);\n\n if (event.defaultPrevented) {\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH,\n );\n }\n\n deactivatePasteCallback() {\n this.__pasteHandlerCleanup?.();\n this.__pasteHandlerCleanup = undefined;\n }\n\n activateTrimWhitespace() {\n this.deactivateTrimWhitespace();\n this.__trimWhitespaceCleanup = this.__editor.registerTextContentListener(text => {\n if (text.trim() === '') {\n this.__editor.update(\n () => {\n $getRoot()\n .getAllTextNodes()\n .forEach(node => {\n node.remove();\n });\n },\n // Don't allow undoing this action\n { tag: 'historic' },\n );\n }\n });\n }\n\n deactivateTrimWhitespace() {\n this.__trimWhitespaceCleanup?.();\n this.__trimWhitespaceCleanup = undefined;\n }\n\n setIsDisabled(isDisabled: boolean) {\n this.__editor.setEditable(!isDisabled);\n }\n\n cleanup() {\n this.deactivateContentCallbacks();\n this.deactivateTrimWhitespace();\n this.deactivatePasteCallback();\n this.__baseHandlersCleanup?.();\n this.__baseHandlersCleanup = undefined;\n }\n}\n\nfunction noop() {\n return;\n}\n"],"names":["COMMAND_PRIORITY_HIGH","$createTextNode","$getRoot","$getSelection","$insertNodes","$isRangeSelection","INSERT_PARAGRAPH_COMMAND","KEY_ENTER_COMMAND","PASTE_COMMAND","mergeRegister","SENTINEL_VALUE","registerSentinelNodeHandlers","isClipboardEvent","event","type","BasicFunctionalityBase","__enterHandler","selection","preventDefault","shiftKey","__editor","dispatchCommand","undefined","insertDefaultValue","defaultValue","update","activateContentCallbacks","onContentChange","onCountChanged","deactivateContentCallbacks","__contentChangeCleanup","registerTextContentListener","text","processed","replace","length","activatePasteCallback","onPaste","__pasteHandlerCleanup","registerCommand","defaultPrevented","deactivatePasteCallback","activateTrimWhitespace","deactivateTrimWhitespace","__trimWhitespaceCleanup","trim","getAllTextNodes","forEach","node","remove","tag","setIsDisabled","isDisabled","setEditable","cleanup","__baseHandlersCleanup","constructor","editor","isSentinelNodeEnabled","bind","noop"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -5,38 +5,37 @@ import { TextNode } from '@fluentui-copilot/text-editor';
5
5
  // These two characters together are a no-op and should not be present together in any legitimate user input.
6
6
  export const SENTINEL_VALUE = '\u200b\u200c';
7
7
  export class SentinelNode extends TextNode {
8
- static getType() {
9
- return 'sentinel';
10
- }
11
- static clone(node) {
12
- return new SentinelNode(node.__key);
13
- }
14
- createDOM(config) {
15
- const element = super.createDOM(config);
16
- element.ariaHidden = 'true';
17
- return element;
18
- }
19
- isToken() {
20
- return true;
21
- }
22
- exportJSON() {
23
- return {
24
- ...super.exportJSON(),
25
- type: 'sentinel',
26
- version: 1
27
- };
28
- }
29
- static importJSON(serializedNode) {
30
- return $createSentinelNode();
31
- }
32
- constructor(key) {
33
- super(SENTINEL_VALUE, key);
34
- }
8
+ static getType() {
9
+ return 'sentinel';
10
+ }
11
+ static clone(node) {
12
+ return new SentinelNode(node.__key);
13
+ }
14
+ createDOM(config) {
15
+ const element = super.createDOM(config);
16
+ element.ariaHidden = 'true';
17
+ return element;
18
+ }
19
+ isToken() {
20
+ return true;
21
+ }
22
+ exportJSON() {
23
+ return {
24
+ ...super.exportJSON(),
25
+ type: 'sentinel',
26
+ version: 1
27
+ };
28
+ }
29
+ static importJSON(serializedNode) {
30
+ return $createSentinelNode();
31
+ }
32
+ constructor(key){
33
+ super(SENTINEL_VALUE, key);
34
+ }
35
35
  }
36
36
  export function $createSentinelNode(key) {
37
- return new SentinelNode(key);
37
+ return new SentinelNode(key);
38
38
  }
39
39
  export function $isSentinelNode(node) {
40
- return node instanceof SentinelNode;
40
+ return node instanceof SentinelNode;
41
41
  }
42
- //# sourceMappingURL=SentinelNode.js.map
@@ -1,84 +1,79 @@
1
1
  import { $getLeafNodes, $getNodeByKey, $getRoot, $getSelection, $isRangeSelection, $normalizeSelection__EXPERIMENTAL, $setSelection, mergeRegister } from '@fluentui-copilot/text-editor';
2
2
  import { $isSentinelNode, $createSentinelNode, SentinelNode } from './SentinelNode';
3
3
  export function registerSentinelNodeHandlers(editor) {
4
- // Add a sentinel node at the end of the input when there is content.
5
- // This sentinel node fixes a number of issues.
6
- // In Safari, Lexical's behaviour of adding <br /> tags to the end of the input when it ends
7
- // in a decorator node causes cursor location issues: https://github.com/facebook/lexical/issues/4487
8
- // Otherwise, when a decorator node is the last node in the input, the cursor can't move past it.
9
- // Adding an invisible text node that doesn't contribute to the content and can't be selected to the end of the input
10
- // mitigates these issues.
11
- const sentinelNodeUpdateHandler = ({
12
- editorState
13
- }) => {
14
- editorState.read(() => {
15
- const leaves = $getLeafNodes($getRoot());
16
- if (leaves.length === 0) {
17
- return;
18
- }
19
- const lastNode = leaves[leaves.length - 1];
20
- const lastNodeKey = lastNode.getKey();
21
- // If the last node isn't a sentinel, add one
22
- if (!$isSentinelNode(lastNode)) {
23
- editor.update(() => {
24
- var
25
- // We find the node by its key again in case the node was removed before this update runs
26
- _$getNodeByKey;
27
- (_$getNodeByKey = $getNodeByKey(lastNodeKey)) === null || _$getNodeByKey === void 0 ? void 0 : _$getNodeByKey.insertAfter($createSentinelNode());
28
- },
29
- // historic tag prevents every sentinel node addition from being added to LexicalHistoryPlugin undo stack
30
- {
31
- discrete: true,
32
- tag: 'historic'
33
- });
34
- return;
35
- }
36
- // If the sentinel node is not selected, we're done
37
- const previous = lastNode.getPreviousSibling();
38
- if (!previous || !lastNode.isSelected()) {
39
- return;
40
- }
41
- const selection = $getSelection();
42
- if (!$isRangeSelection(selection)) {
43
- return;
44
- }
45
- // If the cursor is inside the sentinel node, move it out (next to the beginning)
46
- // We allow selection on the boundary of the sentinel in case the adjacent node is a decorator node
47
- // where selection is ill-defined.
48
- if (selection.isCollapsed() && selection.anchor.offset > 0) {
49
- editor.update(() => {
50
- var _$getNodeByKey;
51
- (_$getNodeByKey = $getNodeByKey(lastNodeKey)) === null || _$getNodeByKey === void 0 ? void 0 : _$getNodeByKey.selectStart();
52
- });
53
- return;
54
- }
55
- // If the selection is a range which includes the sentinel, modify the range to exclude it
56
- if (!selection.isCollapsed()) {
57
- let selectionChanged = false;
58
- const newSelection = selection.clone();
59
- if (newSelection.anchor.getNode() === lastNode && newSelection.anchor.offset > 0) {
60
- newSelection.anchor.set(lastNodeKey, 0, 'text');
61
- selectionChanged = true;
62
- }
63
- if (newSelection.focus.getNode() === lastNode && newSelection.focus.offset > 0) {
64
- newSelection.focus.set(lastNodeKey, 0, 'text');
65
- selectionChanged = true;
66
- }
67
- if (selectionChanged) {
68
- editor.update(() => {
69
- if ($getNodeByKey(lastNodeKey) !== null) {
70
- $setSelection($normalizeSelection__EXPERIMENTAL(newSelection));
4
+ // Add a sentinel node at the end of the input when there is content.
5
+ // This sentinel node fixes a number of issues.
6
+ // In Safari, Lexical's behaviour of adding <br /> tags to the end of the input when it ends
7
+ // in a decorator node causes cursor location issues: https://github.com/facebook/lexical/issues/4487
8
+ // Otherwise, when a decorator node is the last node in the input, the cursor can't move past it.
9
+ // Adding an invisible text node that doesn't contribute to the content and can't be selected to the end of the input
10
+ // mitigates these issues.
11
+ const sentinelNodeUpdateHandler = ({ editorState })=>{
12
+ editorState.read(()=>{
13
+ const leaves = $getLeafNodes($getRoot());
14
+ if (leaves.length === 0) {
15
+ return;
16
+ }
17
+ const lastNode = leaves[leaves.length - 1];
18
+ const lastNodeKey = lastNode.getKey();
19
+ // If the last node isn't a sentinel, add one
20
+ if (!$isSentinelNode(lastNode)) {
21
+ editor.update(()=>{
22
+ var // We find the node by its key again in case the node was removed before this update runs
23
+ _$getNodeByKey;
24
+ (_$getNodeByKey = $getNodeByKey(lastNodeKey)) === null || _$getNodeByKey === void 0 ? void 0 : _$getNodeByKey.insertAfter($createSentinelNode());
25
+ }, // historic tag prevents every sentinel node addition from being added to LexicalHistoryPlugin undo stack
26
+ {
27
+ discrete: true,
28
+ tag: 'historic'
29
+ });
30
+ return;
71
31
  }
72
- });
32
+ // If the sentinel node is not selected, we're done
33
+ const previous = lastNode.getPreviousSibling();
34
+ if (!previous || !lastNode.isSelected()) {
35
+ return;
36
+ }
37
+ const selection = $getSelection();
38
+ if (!$isRangeSelection(selection)) {
39
+ return;
40
+ }
41
+ // If the cursor is inside the sentinel node, move it out (next to the beginning)
42
+ // We allow selection on the boundary of the sentinel in case the adjacent node is a decorator node
43
+ // where selection is ill-defined.
44
+ if (selection.isCollapsed() && selection.anchor.offset > 0) {
45
+ editor.update(()=>{
46
+ var _$getNodeByKey;
47
+ (_$getNodeByKey = $getNodeByKey(lastNodeKey)) === null || _$getNodeByKey === void 0 ? void 0 : _$getNodeByKey.selectStart();
48
+ });
49
+ return;
50
+ }
51
+ // If the selection is a range which includes the sentinel, modify the range to exclude it
52
+ if (!selection.isCollapsed()) {
53
+ let selectionChanged = false;
54
+ const newSelection = selection.clone();
55
+ if (newSelection.anchor.getNode() === lastNode && newSelection.anchor.offset > 0) {
56
+ newSelection.anchor.set(lastNodeKey, 0, 'text');
57
+ selectionChanged = true;
58
+ }
59
+ if (newSelection.focus.getNode() === lastNode && newSelection.focus.offset > 0) {
60
+ newSelection.focus.set(lastNodeKey, 0, 'text');
61
+ selectionChanged = true;
62
+ }
63
+ if (selectionChanged) {
64
+ editor.update(()=>{
65
+ if ($getNodeByKey(lastNodeKey) !== null) {
66
+ $setSelection($normalizeSelection__EXPERIMENTAL(newSelection));
67
+ }
68
+ });
69
+ }
70
+ }
71
+ });
72
+ };
73
+ return mergeRegister(editor.registerUpdateListener(sentinelNodeUpdateHandler), editor.registerNodeTransform(SentinelNode, (node)=>{
74
+ if (!node.getPreviousSibling() || node.getNextSibling()) {
75
+ node.remove();
76
+ return;
73
77
  }
74
- }
75
- });
76
- };
77
- return mergeRegister(editor.registerUpdateListener(sentinelNodeUpdateHandler), editor.registerNodeTransform(SentinelNode, node => {
78
- if (!node.getPreviousSibling() || node.getNextSibling()) {
79
- node.remove();
80
- return;
81
- }
82
- }));
78
+ }));
83
79
  }
84
- //# sourceMappingURL=SentinelNodeHandlers.js.map
@@ -1,3 +1,2 @@
1
1
  export { BasicFunctionalityBase } from './BasicFunctionality.base';
2
2
  export { $createSentinelNode, $isSentinelNode, SENTINEL_VALUE, SentinelNode } from './SentinelNode';
3
- //# sourceMappingURL=index.js.map