@copilotkit/react-textarea 0.18.0 → 0.19.0-alpha.1
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/.turbo/turbo-build.log +303 -189
- package/CHANGELOG.md +19 -0
- package/dist/chunk-2NURR2DX.mjs +47 -0
- package/dist/chunk-2NURR2DX.mjs.map +1 -0
- package/dist/chunk-3YJ63D5D.mjs +106 -0
- package/dist/chunk-3YJ63D5D.mjs.map +1 -0
- package/dist/chunk-4S5ZJH3I.mjs +18 -0
- package/dist/chunk-4S5ZJH3I.mjs.map +1 -0
- package/dist/chunk-55EGOC5T.mjs +87 -0
- package/dist/chunk-55EGOC5T.mjs.map +1 -0
- package/dist/{chunk-3A2CNIG5.mjs → chunk-5ARCOTW3.mjs} +8 -5
- package/dist/chunk-5ARCOTW3.mjs.map +1 -0
- package/dist/chunk-5EJ5XOGP.mjs +22 -0
- package/dist/chunk-5EJ5XOGP.mjs.map +1 -0
- package/dist/chunk-5FO6ISW4.mjs +3 -0
- package/dist/{chunk-5GGCWNTT.mjs → chunk-5SL5L4VS.mjs} +67 -29
- package/dist/chunk-5SL5L4VS.mjs.map +1 -0
- package/dist/{chunk-JWN2VEE3.mjs → chunk-A2RRLD23.mjs} +13 -12
- package/dist/chunk-A2RRLD23.mjs.map +1 -0
- package/dist/chunk-CDB7HFCY.mjs +65 -0
- package/dist/chunk-CDB7HFCY.mjs.map +1 -0
- package/dist/{chunk-MFJNLKRC.mjs → chunk-D7SEV5PR.mjs} +4 -3
- package/dist/chunk-D7SEV5PR.mjs.map +1 -0
- package/dist/chunk-HAFHLU4N.mjs +55 -0
- package/dist/chunk-HAFHLU4N.mjs.map +1 -0
- package/dist/chunk-ITZHK3YV.mjs +477 -0
- package/dist/chunk-ITZHK3YV.mjs.map +1 -0
- package/dist/{chunk-3UQM3NLM.mjs → chunk-IXJ2HCOA.mjs} +42 -7
- package/dist/chunk-IXJ2HCOA.mjs.map +1 -0
- package/dist/{chunk-UW3ITU2Y.mjs → chunk-JAFCXEPU.mjs} +1 -1
- package/dist/chunk-JAFCXEPU.mjs.map +1 -0
- package/dist/chunk-KDFCAQGV.mjs +44 -0
- package/dist/chunk-KDFCAQGV.mjs.map +1 -0
- package/dist/chunk-L7VVZH4Q.mjs +3 -0
- package/dist/chunk-ND5PXTAW.mjs +17 -0
- package/dist/chunk-ND5PXTAW.mjs.map +1 -0
- package/dist/chunk-O5OWT5GE.mjs +114 -0
- package/dist/chunk-O5OWT5GE.mjs.map +1 -0
- package/dist/chunk-OD7ZMOVE.mjs +45 -0
- package/dist/chunk-OD7ZMOVE.mjs.map +1 -0
- package/dist/chunk-OM5WQQOU.mjs +47 -0
- package/dist/chunk-OM5WQQOU.mjs.map +1 -0
- package/dist/chunk-QL2GYGG5.mjs +19 -0
- package/dist/chunk-QL2GYGG5.mjs.map +1 -0
- package/dist/chunk-RPDVSCLO.mjs +107 -0
- package/dist/chunk-RPDVSCLO.mjs.map +1 -0
- package/dist/{chunk-HZGSG7ST.mjs → chunk-UHD44NC5.mjs} +10 -5
- package/dist/chunk-UHD44NC5.mjs.map +1 -0
- package/dist/chunk-VBIJPE3H.mjs +108 -0
- package/dist/chunk-VBIJPE3H.mjs.map +1 -0
- package/dist/chunk-XDT7BF3V.mjs +81 -0
- package/dist/chunk-XDT7BF3V.mjs.map +1 -0
- package/dist/chunk-XHUMROEY.mjs +91 -0
- package/dist/chunk-XHUMROEY.mjs.map +1 -0
- package/dist/{chunk-LWVCQYWV.mjs → chunk-YQU7WG7T.mjs} +2 -2
- package/dist/chunk-YTOPHPSG.mjs +45 -0
- package/dist/chunk-YTOPHPSG.mjs.map +1 -0
- package/dist/chunk-YW3REYX6.mjs +23 -0
- package/dist/chunk-YW3REYX6.mjs.map +1 -0
- package/dist/components/base-copilot-textarea/base-copilot-textarea.d.ts +3 -5
- package/dist/components/base-copilot-textarea/base-copilot-textarea.mjs +21 -7
- package/dist/components/base-copilot-textarea/track-cursor-moved-since-last-text-change.d.ts +6 -0
- package/dist/components/base-copilot-textarea/track-cursor-moved-since-last-text-change.mjs +5 -0
- package/dist/components/copilot-textarea/copilot-textarea.d.ts +13 -10
- package/dist/components/copilot-textarea/copilot-textarea.mjs +31 -12
- package/dist/components/hovering-toolbar/hovering-editor-provider.d.ts +13 -0
- package/dist/components/hovering-toolbar/hovering-editor-provider.mjs +4 -0
- package/dist/components/hovering-toolbar/hovering-toolbar-components.d.ts +18 -0
- package/dist/components/hovering-toolbar/hovering-toolbar-components.mjs +4 -0
- package/dist/components/hovering-toolbar/hovering-toolbar.d.ts +8 -0
- package/dist/components/hovering-toolbar/hovering-toolbar.mjs +17 -0
- package/dist/components/hovering-toolbar/hovering-toolbar.mjs.map +1 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box.d.ts +12 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box.mjs +12 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box.mjs.map +1 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/index.d.ts +3 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/index.mjs +13 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/index.mjs.map +1 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/mode-pre-suggestion.d.ts +16 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/mode-pre-suggestion.mjs +5 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/mode-pre-suggestion.mjs.map +1 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/mode-suggestion-appearing.d.ts +37 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/mode-suggestion-appearing.mjs +10 -0
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/mode-suggestion-appearing.mjs.map +1 -0
- package/dist/components/index.d.ts +9 -4
- package/dist/components/index.mjs +31 -12
- package/dist/components/manual-ui/chip-with-icon.d.ts +10 -0
- package/dist/components/manual-ui/chip-with-icon.mjs +29 -0
- package/dist/components/manual-ui/chip-with-icon.mjs.map +1 -0
- package/dist/components/source-search-box/source-search-box.d.ts +17 -0
- package/dist/components/source-search-box/source-search-box.mjs +10 -0
- package/dist/components/source-search-box/source-search-box.mjs.map +1 -0
- package/dist/components/ui/button.d.ts +14 -0
- package/dist/components/ui/button.mjs +5 -0
- package/dist/components/ui/button.mjs.map +1 -0
- package/dist/components/ui/card.d.ts +10 -0
- package/dist/components/ui/card.mjs +63 -0
- package/dist/components/ui/card.mjs.map +1 -0
- package/dist/components/ui/command.d.ts +48 -0
- package/dist/components/ui/command.mjs +6 -0
- package/dist/components/ui/command.mjs.map +1 -0
- package/dist/components/ui/dialog.d.ts +18 -0
- package/dist/components/ui/dialog.mjs +5 -0
- package/dist/components/ui/dialog.mjs.map +1 -0
- package/dist/components/ui/label.d.ts +8 -0
- package/dist/components/ui/label.mjs +5 -0
- package/dist/components/ui/label.mjs.map +1 -0
- package/dist/components/ui/separator.d.ts +6 -0
- package/dist/components/ui/separator.mjs +26 -0
- package/dist/components/ui/separator.mjs.map +1 -0
- package/dist/components/ui/textarea.d.ts +7 -0
- package/dist/components/ui/textarea.mjs +22 -0
- package/dist/components/ui/textarea.mjs.map +1 -0
- package/dist/hooks/base-copilot-textarea-implementation/use-autosuggestions.mjs +2 -2
- package/dist/hooks/base-copilot-textarea-implementation/use-populate-copilot-textarea-ref.d.ts +2 -2
- package/dist/hooks/base-copilot-textarea-implementation/use-populate-copilot-textarea-ref.mjs +2 -2
- package/dist/hooks/make-autosuggestions-function/use-make-standard-autosuggestions-function.d.ts +5 -7
- package/dist/hooks/make-autosuggestions-function/use-make-standard-autosuggestions-function.mjs +2 -1
- package/dist/hooks/make-autosuggestions-function/use-make-standard-insertion-function.d.ts +23 -0
- package/dist/hooks/make-autosuggestions-function/use-make-standard-insertion-function.mjs +5 -0
- package/dist/hooks/make-autosuggestions-function/use-make-standard-insertion-function.mjs.map +1 -0
- package/dist/hooks/misc/use-autosize-textarea.d.ts +5 -0
- package/dist/hooks/misc/use-autosize-textarea.mjs +4 -0
- package/dist/hooks/misc/use-autosize-textarea.mjs.map +1 -0
- package/dist/index.css +674 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.mjs +31 -12
- package/dist/lib/editor-to-text.mjs +1 -42
- package/dist/lib/editor-to-text.mjs.map +1 -1
- package/dist/lib/get-text-around-cursor.d.ts +10 -3
- package/dist/lib/get-text-around-cursor.mjs +1 -1
- package/dist/lib/retry.d.ts +3 -0
- package/dist/lib/retry.mjs +4 -0
- package/dist/lib/retry.mjs.map +1 -0
- package/dist/types/autosuggestions-config/autosuggestions-config-user-specified.d.ts +25 -0
- package/dist/types/autosuggestions-config/autosuggestions-config-user-specified.mjs +3 -0
- package/dist/types/autosuggestions-config/autosuggestions-config-user-specified.mjs.map +1 -0
- package/dist/types/autosuggestions-config/autosuggestions-config.d.ts +20 -0
- package/dist/types/autosuggestions-config/autosuggestions-config.mjs +10 -0
- package/dist/types/autosuggestions-config/autosuggestions-config.mjs.map +1 -0
- package/dist/types/autosuggestions-config/editing-api-config.d.ts +17 -0
- package/dist/types/autosuggestions-config/editing-api-config.mjs +5 -0
- package/dist/types/autosuggestions-config/editing-api-config.mjs.map +1 -0
- package/dist/types/autosuggestions-config/index.d.ts +10 -0
- package/dist/types/autosuggestions-config/index.mjs +11 -0
- package/dist/types/autosuggestions-config/index.mjs.map +1 -0
- package/dist/types/autosuggestions-config/insertions-api-config.d.ts +17 -0
- package/dist/types/autosuggestions-config/insertions-api-config.mjs +5 -0
- package/dist/types/autosuggestions-config/insertions-api-config.mjs.map +1 -0
- package/dist/types/{standard-autosuggestions → autosuggestions-config/subtypes}/chatlike-api-endpoint.d.ts +7 -4
- package/dist/types/autosuggestions-config/subtypes/chatlike-api-endpoint.mjs +4 -0
- package/dist/types/autosuggestions-config/subtypes/chatlike-api-endpoint.mjs.map +1 -0
- package/dist/types/autosuggestions-config/subtypes/make-system-prompt.d.ts +3 -0
- package/dist/types/autosuggestions-config/subtypes/make-system-prompt.mjs +3 -0
- package/dist/types/autosuggestions-config/subtypes/make-system-prompt.mjs.map +1 -0
- package/dist/types/autosuggestions-config/subtypes/minimal-chat-gpt-message.mjs.map +1 -0
- package/dist/types/autosuggestions-config/suggestions-api-config.d.ts +17 -0
- package/dist/types/autosuggestions-config/suggestions-api-config.mjs +5 -0
- package/dist/types/autosuggestions-config/suggestions-api-config.mjs.map +1 -0
- package/dist/types/base/autosuggestions-bare-function.d.ts +16 -2
- package/dist/types/base/base-autosuggestions-config.d.ts +5 -1
- package/dist/types/base/base-autosuggestions-config.mjs +1 -1
- package/dist/types/base/base-copilot-textarea-props.d.ts +3 -1
- package/dist/types/base/editor-autocomplete-state.mjs +1 -1
- package/dist/types/base/index.mjs +1 -1
- package/dist/types/index.d.ts +8 -3
- package/dist/types/index.mjs +7 -4
- package/package.json +19 -5
- package/src/components/base-copilot-textarea/base-copilot-textarea.tsx +64 -13
- package/src/components/base-copilot-textarea/track-cursor-moved-since-last-text-change.tsx +61 -0
- package/src/components/copilot-textarea/copilot-textarea.tsx +29 -17
- package/src/components/hovering-toolbar/hovering-editor-provider.tsx +29 -0
- package/src/components/hovering-toolbar/hovering-toolbar-components.tsx +115 -0
- package/src/components/hovering-toolbar/hovering-toolbar.tsx +156 -0
- package/src/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box.tsx +73 -0
- package/src/components/hovering-toolbar/text-insertion-prompt-box/index.ts +2 -0
- package/src/components/hovering-toolbar/text-insertion-prompt-box/mode-pre-suggestion.tsx +83 -0
- package/src/components/hovering-toolbar/text-insertion-prompt-box/mode-suggestion-appearing.tsx +410 -0
- package/src/components/manual-ui/chip-with-icon.tsx +28 -0
- package/src/components/source-search-box/source-search-box.tsx +133 -0
- package/src/components/ui/button.tsx +56 -0
- package/src/components/ui/card.tsx +86 -0
- package/src/components/ui/command.tsx +155 -0
- package/src/components/ui/dialog.tsx +123 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/separator.tsx +31 -0
- package/src/components/ui/textarea.tsx +24 -0
- package/src/hooks/base-copilot-textarea-implementation/use-autosuggestions.ts +10 -3
- package/src/hooks/make-autosuggestions-function/use-make-standard-autosuggestions-function.tsx +29 -44
- package/src/hooks/make-autosuggestions-function/use-make-standard-insertion-function.tsx +150 -0
- package/src/hooks/misc/use-autosize-textarea.tsx +21 -0
- package/src/lib/get-text-around-cursor.ts +71 -6
- package/src/lib/retry.tsx +23 -0
- package/src/styles.css +2 -0
- package/src/types/autosuggestions-config/autosuggestions-config-user-specified.tsx +27 -0
- package/src/types/autosuggestions-config/autosuggestions-config.tsx +43 -0
- package/src/types/autosuggestions-config/editing-api-config.tsx +102 -0
- package/src/types/autosuggestions-config/index.ts +11 -0
- package/src/types/autosuggestions-config/insertions-api-config.tsx +95 -0
- package/src/types/{standard-autosuggestions → autosuggestions-config/subtypes}/chatlike-api-endpoint.tsx +19 -7
- package/src/types/autosuggestions-config/subtypes/make-system-prompt.ts +4 -0
- package/src/types/{standard-autosuggestions/autosuggestions-config.tsx → autosuggestions-config/suggestions-api-config.tsx} +12 -23
- package/src/types/base/autosuggestions-bare-function.ts +24 -2
- package/src/types/base/base-autosuggestions-config.tsx +7 -2
- package/src/types/base/base-copilot-textarea-props.tsx +3 -1
- package/src/types/base/editor-autocomplete-state.ts +1 -0
- package/src/types/index.ts +1 -1
- package/tailwind.config.js +2 -0
- package/dist/chunk-3A2CNIG5.mjs.map +0 -1
- package/dist/chunk-3UQM3NLM.mjs.map +0 -1
- package/dist/chunk-5GGCWNTT.mjs.map +0 -1
- package/dist/chunk-BLRD23HM.mjs +0 -32
- package/dist/chunk-BLRD23HM.mjs.map +0 -1
- package/dist/chunk-BTAUKCBN.mjs +0 -60
- package/dist/chunk-BTAUKCBN.mjs.map +0 -1
- package/dist/chunk-HZGSG7ST.mjs.map +0 -1
- package/dist/chunk-JWN2VEE3.mjs.map +0 -1
- package/dist/chunk-MFJNLKRC.mjs.map +0 -1
- package/dist/chunk-SL4J5HMW.mjs +0 -3
- package/dist/chunk-UW3ITU2Y.mjs.map +0 -1
- package/dist/types/standard-autosuggestions/autosuggestions-config.d.ts +0 -19
- package/dist/types/standard-autosuggestions/autosuggestions-config.mjs +0 -6
- package/dist/types/standard-autosuggestions/chatlike-api-endpoint.mjs +0 -4
- package/dist/types/standard-autosuggestions/index.d.ts +0 -4
- package/dist/types/standard-autosuggestions/index.mjs +0 -8
- package/src/types/standard-autosuggestions/index.ts +0 -14
- /package/dist/{chunk-SL4J5HMW.mjs.map → chunk-5FO6ISW4.mjs.map} +0 -0
- /package/dist/{types/standard-autosuggestions/autosuggestions-config.mjs.map → chunk-L7VVZH4Q.mjs.map} +0 -0
- /package/dist/{chunk-LWVCQYWV.mjs.map → chunk-YQU7WG7T.mjs.map} +0 -0
- /package/dist/{types/standard-autosuggestions/chatlike-api-endpoint.mjs.map → components/base-copilot-textarea/track-cursor-moved-since-last-text-change.mjs.map} +0 -0
- /package/dist/{types/standard-autosuggestions/index.mjs.map → components/hovering-toolbar/hovering-editor-provider.mjs.map} +0 -0
- /package/dist/{types/standard-autosuggestions/minimal-chat-gpt-message.mjs.map → components/hovering-toolbar/hovering-toolbar-components.mjs.map} +0 -0
- /package/dist/types/{standard-autosuggestions → autosuggestions-config/subtypes}/minimal-chat-gpt-message.d.ts +0 -0
- /package/dist/types/{standard-autosuggestions → autosuggestions-config/subtypes}/minimal-chat-gpt-message.mjs +0 -0
- /package/src/types/{standard-autosuggestions → autosuggestions-config/subtypes}/minimal-chat-gpt-message.tsx +0 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { css } from "@emotion/css";
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { BaseSelection, Editor, Range, Location, Transforms } from "slate";
|
|
4
|
+
import { useSlate, useSlateSelection } from "slate-react";
|
|
5
|
+
import { HoveringInsertionPromptBox } from "./text-insertion-prompt-box";
|
|
6
|
+
import { Button, Icon, Menu, Portal } from "./hovering-toolbar-components";
|
|
7
|
+
import { useHoveringEditorContext } from "./hovering-editor-provider";
|
|
8
|
+
import {
|
|
9
|
+
getFullEditorTextWithNewlines,
|
|
10
|
+
getTextAroundSelection,
|
|
11
|
+
} from "../../lib/get-text-around-cursor";
|
|
12
|
+
import {
|
|
13
|
+
EditingEditorState,
|
|
14
|
+
InsertionEditorApiConfig,
|
|
15
|
+
} from "../../types/base/autosuggestions-bare-function";
|
|
16
|
+
|
|
17
|
+
export interface HoveringToolbarProps {
|
|
18
|
+
apiConfig: InsertionEditorApiConfig;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const HoveringToolbar: (
|
|
22
|
+
props: HoveringToolbarProps
|
|
23
|
+
) => JSX.Element | null = (props) => {
|
|
24
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
25
|
+
const editor = useSlate();
|
|
26
|
+
const selection = useSlateSelection();
|
|
27
|
+
const { isDisplayed, setIsDisplayed } = useHoveringEditorContext();
|
|
28
|
+
|
|
29
|
+
// only render on client
|
|
30
|
+
const [isClient, setIsClient] = useState(false);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
setIsClient(true);
|
|
33
|
+
}, []);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const el = ref.current;
|
|
37
|
+
const { selection } = editor;
|
|
38
|
+
|
|
39
|
+
if (!el) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!selection) {
|
|
44
|
+
el.removeAttribute("style");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const domSelection = window.getSelection();
|
|
49
|
+
if (!domSelection) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const domRange = domSelection.getRangeAt(0);
|
|
54
|
+
const rect = domRange.getBoundingClientRect();
|
|
55
|
+
|
|
56
|
+
// We use window = (0,0,0,0) as a signal that the selection is not in the original copilot-textarea,
|
|
57
|
+
// but inside the hovering window.
|
|
58
|
+
//
|
|
59
|
+
// in such case, we simply do nothing.
|
|
60
|
+
if (
|
|
61
|
+
rect.top === 0 &&
|
|
62
|
+
rect.left === 0 &&
|
|
63
|
+
rect.width === 0 &&
|
|
64
|
+
rect.height === 0
|
|
65
|
+
) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const minGapFromEdge = 60;
|
|
70
|
+
const verticalOffsetFromCorner = 35;
|
|
71
|
+
const horizontalOffsetFromCorner = 15;
|
|
72
|
+
let top =
|
|
73
|
+
rect.top + window.scrollY - el.offsetHeight + verticalOffsetFromCorner;
|
|
74
|
+
// make sure top is in the viewport and not too close to the edge
|
|
75
|
+
if (top < minGapFromEdge) {
|
|
76
|
+
top = rect.bottom + window.scrollY + minGapFromEdge;
|
|
77
|
+
} else if (top + el.offsetHeight > window.innerHeight - minGapFromEdge) {
|
|
78
|
+
top = rect.top + window.scrollY - el.offsetHeight - minGapFromEdge;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let left =
|
|
82
|
+
rect.left +
|
|
83
|
+
window.scrollX -
|
|
84
|
+
el.offsetWidth / 2 +
|
|
85
|
+
rect.width / 2 +
|
|
86
|
+
horizontalOffsetFromCorner;
|
|
87
|
+
// make sure left is in the viewport and not too close to the edge
|
|
88
|
+
if (left < minGapFromEdge) {
|
|
89
|
+
left = minGapFromEdge;
|
|
90
|
+
} else if (left + el.offsetWidth > window.innerWidth - minGapFromEdge) {
|
|
91
|
+
left = window.innerWidth - el.offsetWidth - minGapFromEdge;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
el.style.opacity = "1";
|
|
95
|
+
el.style.top = `${top}px`;
|
|
96
|
+
el.style.left = `${left}px`;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
101
|
+
if (ref.current && !ref.current.contains(event.target as Node)) {
|
|
102
|
+
setIsDisplayed(false);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
107
|
+
return () => {
|
|
108
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
109
|
+
};
|
|
110
|
+
}, [ref, setIsDisplayed]);
|
|
111
|
+
|
|
112
|
+
if (!isClient) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<Portal>
|
|
118
|
+
<Menu
|
|
119
|
+
ref={ref}
|
|
120
|
+
className="p-2 absolute z-10 top-[-10000px] left-[-10000px] mt-[-6px] opacity-0 transition-opacity duration-700"
|
|
121
|
+
>
|
|
122
|
+
{isDisplayed && selection && (
|
|
123
|
+
<HoveringInsertionPromptBox
|
|
124
|
+
editorState={editorState(editor, selection)}
|
|
125
|
+
apiConfig={props.apiConfig}
|
|
126
|
+
closeWindow={() => {
|
|
127
|
+
setIsDisplayed(false);
|
|
128
|
+
}}
|
|
129
|
+
performInsertion={(insertedText) => {
|
|
130
|
+
console.log("inserted text", insertedText);
|
|
131
|
+
// replace the selection with the inserted text
|
|
132
|
+
Transforms.delete(editor, { at: selection });
|
|
133
|
+
Transforms.insertText(editor, insertedText, {
|
|
134
|
+
at: selection,
|
|
135
|
+
});
|
|
136
|
+
setIsDisplayed(false);
|
|
137
|
+
}}
|
|
138
|
+
/>
|
|
139
|
+
)}
|
|
140
|
+
</Menu>
|
|
141
|
+
</Portal>
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
function editorState(editor: Editor, selection: Location): EditingEditorState {
|
|
146
|
+
const textAroundCursor = getTextAroundSelection(editor);
|
|
147
|
+
if (textAroundCursor) {
|
|
148
|
+
return textAroundCursor;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
textBeforeCursor: getFullEditorTextWithNewlines(editor),
|
|
153
|
+
textAfterCursor: "",
|
|
154
|
+
selectedText: "",
|
|
155
|
+
};
|
|
156
|
+
}
|
package/src/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box.tsx
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, { useCallback, useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
State_SuggestionAppearing,
|
|
4
|
+
SuggestionAppearing,
|
|
5
|
+
} from "./mode-suggestion-appearing";
|
|
6
|
+
import { PreSuggestion, State_PreSuggestion } from "./mode-pre-suggestion";
|
|
7
|
+
import {
|
|
8
|
+
EditingEditorState,
|
|
9
|
+
InsertionEditorApiConfig,
|
|
10
|
+
} from "../../../types/base/autosuggestions-bare-function";
|
|
11
|
+
|
|
12
|
+
type InsertionPromptState = State_PreSuggestion | State_SuggestionAppearing;
|
|
13
|
+
|
|
14
|
+
export interface Props {
|
|
15
|
+
editorState: EditingEditorState;
|
|
16
|
+
apiConfig: InsertionEditorApiConfig;
|
|
17
|
+
performInsertion: (insertedText: string) => void;
|
|
18
|
+
closeWindow: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const HoveringInsertionPromptBox: React.FC<Props> = (props) => {
|
|
22
|
+
const [insertionPrompt, setInsertionPrompt] = useState<string>("");
|
|
23
|
+
const [mode, setMode] = useState<InsertionPromptState>({
|
|
24
|
+
type: "pre-suggestion",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const handleGeneratedText = useCallback(
|
|
28
|
+
(generatingText: ReadableStream<string>) => {
|
|
29
|
+
setMode({
|
|
30
|
+
type: "suggestion-appearing",
|
|
31
|
+
initialSuggestion: {
|
|
32
|
+
editorState: props.editorState,
|
|
33
|
+
adjustmentPrompt: insertionPrompt,
|
|
34
|
+
generatingSuggestion: generatingText,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
[setMode, insertionPrompt]
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const goBack = () => {
|
|
42
|
+
setMode({ type: "pre-suggestion" });
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
className="flex flex-col justify-center items-center space-y-4 rounded-md border shadow-lg p-4 border-gray- bg-white"
|
|
48
|
+
style={{ width: "30rem" }}
|
|
49
|
+
>
|
|
50
|
+
{mode.type === "pre-suggestion" ? (
|
|
51
|
+
<PreSuggestion
|
|
52
|
+
{...props}
|
|
53
|
+
insertionOrEditingFunction={
|
|
54
|
+
props.apiConfig.insertionOrEditingFunction
|
|
55
|
+
}
|
|
56
|
+
insertionOrEditingPrompt={insertionPrompt}
|
|
57
|
+
setInsertionOrEditingPrompt={setInsertionPrompt}
|
|
58
|
+
onGeneratedText={handleGeneratedText}
|
|
59
|
+
/>
|
|
60
|
+
) : (
|
|
61
|
+
<SuggestionAppearing
|
|
62
|
+
{...props}
|
|
63
|
+
state={mode}
|
|
64
|
+
goBack={goBack}
|
|
65
|
+
insertionOrEditingFunction={
|
|
66
|
+
props.apiConfig.insertionOrEditingFunction
|
|
67
|
+
}
|
|
68
|
+
onGeneratedText={handleGeneratedText}
|
|
69
|
+
/>
|
|
70
|
+
)}
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import useAutosizeTextArea from "../../../hooks/misc/use-autosize-textarea";
|
|
2
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
3
|
+
import {
|
|
4
|
+
EditingEditorState,
|
|
5
|
+
Generator_InsertionOrEditingSuggestion,
|
|
6
|
+
} from "../../../types/base/autosuggestions-bare-function";
|
|
7
|
+
|
|
8
|
+
export type State_PreSuggestion = {
|
|
9
|
+
type: "pre-suggestion";
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export interface PreSuggestionProps {
|
|
13
|
+
editorState: EditingEditorState;
|
|
14
|
+
insertionOrEditingFunction: Generator_InsertionOrEditingSuggestion;
|
|
15
|
+
onGeneratedText: (generatedText: ReadableStream<string>) => void;
|
|
16
|
+
|
|
17
|
+
insertionOrEditingPrompt: string;
|
|
18
|
+
setInsertionOrEditingPrompt: (value: string) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const PreSuggestion: React.FC<PreSuggestionProps> = ({
|
|
22
|
+
editorState,
|
|
23
|
+
insertionOrEditingFunction: insertionSuggestion,
|
|
24
|
+
onGeneratedText,
|
|
25
|
+
insertionOrEditingPrompt: insertionPrompt,
|
|
26
|
+
setInsertionOrEditingPrompt: setInsertionPrompt,
|
|
27
|
+
}) => {
|
|
28
|
+
const [loading, setLoading] = useState(false);
|
|
29
|
+
|
|
30
|
+
const promptTextAreaRef = useRef<HTMLTextAreaElement>(null);
|
|
31
|
+
useAutosizeTextArea(promptTextAreaRef, insertionPrompt);
|
|
32
|
+
|
|
33
|
+
// initially focus on the prompt text area
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
promptTextAreaRef.current?.focus();
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
const generateText = async (abortSignal?: AbortSignal) => {
|
|
39
|
+
// don't generate text if the prompt is empty
|
|
40
|
+
if (!insertionPrompt.trim()) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
setLoading(true);
|
|
45
|
+
const insertionSuggestionTextStream = await insertionSuggestion(
|
|
46
|
+
editorState,
|
|
47
|
+
insertionPrompt,
|
|
48
|
+
abortSignal || new AbortController().signal
|
|
49
|
+
);
|
|
50
|
+
onGeneratedText(insertionSuggestionTextStream);
|
|
51
|
+
|
|
52
|
+
setLoading(false);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<div className="flex flex-col justify-center items-start gap-2">
|
|
57
|
+
<textarea
|
|
58
|
+
ref={promptTextAreaRef}
|
|
59
|
+
value={insertionPrompt}
|
|
60
|
+
onChange={(e) => setInsertionPrompt(e.target.value)}
|
|
61
|
+
onKeyDown={(e) => {
|
|
62
|
+
if (e.key === "Enter" && e.shiftKey) {
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
setInsertionPrompt(insertionPrompt + "\n");
|
|
65
|
+
} else if (e.key === "Enter") {
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
generateText();
|
|
68
|
+
}
|
|
69
|
+
}}
|
|
70
|
+
placeholder="Describe the text you'd like to insert..."
|
|
71
|
+
className="w-full bg-slate-100 h-auto text-sm p-2 rounded-md resize-none overflow-visible focus:outline-none focus:ring-0 focus:border-none"
|
|
72
|
+
rows={1}
|
|
73
|
+
/>
|
|
74
|
+
<button
|
|
75
|
+
disabled={loading || !insertionPrompt.trim()}
|
|
76
|
+
onClick={() => generateText()}
|
|
77
|
+
className="w-full py-2 px-4 rounded-md text-white bg-blue-500 hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
|
78
|
+
>
|
|
79
|
+
{loading ? "Loading..." : "Generate Text"}
|
|
80
|
+
</button>
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
};
|