import React from "react"; import { Editor } from "slate"; import { ReactEditor } from "slate-react"; import { getFullEditorTextWithNewlines } from "../../lib/get-text-around-cursor"; import { replaceEditorText } from "../../lib/slatejs-edits/replace-text"; import { HTMLCopilotTextAreaElement } from "../../types"; import { CustomEditor } from "../../types/base/custom-editor"; export function usePopulateCopilotTextareaRef( editor: Editor, ref: React.Ref, ) { React.useImperativeHandle(ref, () => { class Combined { constructor( private customMethods: CustomMethods, private editorHtmlElement: HTMLElement, ) {} [key: string]: any; get(target: any, propKey: string): any { if (this.isKeyOfCustomMethods(propKey)) { const value = this.customMethods[propKey]; if (typeof value === "function") { return value.bind(this.customMethods); } return value; } else if (this.isKeyOfHTMLElement(propKey)) { const value = this.editorHtmlElement[propKey]; if (typeof value === "function") { return value.bind(this.editorHtmlElement); } return value; } } set(target: any, propKey: string, value: any): boolean { if (this.isKeyOfCustomMethods(propKey)) { (this.customMethods as any)[propKey] = value; } else if (this.isKeyOfHTMLElement(propKey)) { (this.editorHtmlElement as any)[propKey] = value; } else { // Default behavior (optional) target[propKey] = value; } return true; } private isKeyOfCustomMethods(key: string): key is keyof CustomMethods { return key in this.customMethods; } private isKeyOfHTMLElement(key: string): key is keyof HTMLElement { return key in this.editorHtmlElement; } } const handler = { get(target: any, propKey: keyof CustomMethods | keyof HTMLElement) { return target.get(target, propKey); }, set( target: any, propKey: keyof CustomMethods | keyof HTMLElement, value: any, ) { return target.set(target, propKey, value); }, }; class CustomMethods { constructor(private editor: CustomEditor) {} focus() { ReactEditor.focus(this.editor); } blur() { ReactEditor.blur(this.editor); } get value() { return getFullEditorTextWithNewlines(this.editor); } set value(value: string) { replaceEditorText(this.editor, value); } } const editorHtmlElement = ReactEditor.toDOMNode(editor, editor); const customMethods = new CustomMethods(editor); const combined = new Combined(customMethods, editorHtmlElement); return new Proxy(combined, handler); }, [editor]); }