'use client';
import React, { useState, useEffect, useRef } from 'react';
import type { Meta, StoryObj } from "@storybook/react";
import { getPublicClient } from "../api";
const client = getPublicClient('f5d86791-d513-48de-8fd2-b6dbdd4abe9b');
const DEFAULT_PROMPT = `Your job is to predict the next 5-10 words. Never break your role. Write only the text that follows, NOTHING ELSE (this is very important). You must attempt to predict the next words no matter what based on the current text input. Do NOT write anything else or apologize. No more than 5-10 words. Current text: {{inputText}}`;
export const AutocompleteTextField = ({
prompt = DEFAULT_PROMPT,
placeholder = "",
}: any) => {
const [text, setText] = React.useState('');
const [dirtyCount, setDirtyCount] = React.useState(0);
const [prediction, setPrediction] = React.useState('');
const inputRef = React.useRef(null) as any;
const [isFocused, setIsFocused] = useState(false);
const timeoutRef = useRef(null) as any;
// Event handler for focus
const handleFocus = () => {
setIsFocused(true);
};
// Event handler for blur
const handleBlur = () => {
setIsFocused(false);
};
useEffect(() => {
if (!inputRef.current) {
return;
}
const currentElement = inputRef.current as HTMLElement;
// Attach the event listeners
currentElement.addEventListener('focus', handleFocus);
currentElement.addEventListener('blur', handleBlur);
// Cleanup function to remove event listeners
return () => {
currentElement.removeEventListener('focus', handleFocus);
currentElement.removeEventListener('blur', handleBlur);
};
}, []); // Empty dependency array ensures this effect runs only once
React.useEffect(() => {
if (dirtyCount > 0) {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
if (text !== '') {
timeoutRef.current = setTimeout(() => {
getPredictions(text);
setDirtyCount(0);
}, 500);
}
}
}, [dirtyCount, text]);
const handleInput = (e: any) => {
e.preventDefault();
console.log(e.target.innerHTML);
setText(() => {
let newText = e.target.innerHTML;
newText = newText.replace(/(
){2,}/gi, '
');
newText = newText.replace(/
/gi, '\n');
newText = newText.replace(/ /gi, ' ');
const lastChar = newText[newText.length - 1] === ' ' ? ' ' : newText[newText.length - 1];
if (lastChar === prediction[0]) {
setPrediction((prevPrediction) => {
const newPrediction = prevPrediction.slice(1);
return newPrediction;
});
} else {
setDirtyCount((prevCount) => prevCount + 1);
setPrediction('');
}
return newText;
});
};
const handleKeyDown = (e: any) => {
if (e.key === 'Tab' && prediction) {
e.preventDefault();
// Append prediction and reset prediction state
const newText = text + prediction;
setText(newText);
setPrediction('');
const html = newText.split('\n').join('
');
inputRef.current.innerHTML = html; // Update contentEditable text
const range = document.createRange();
const sel = window.getSelection() as any;
range.selectNodeContents(inputRef.current); // Select the entire content of the div
range.collapse(false); // false collapses the range to the end, true to the start
sel.removeAllRanges(); // Remove any existing selections
sel.addRange(range); // Add the new range
} else if (e.key === 'Escape') {
setPrediction('');
}
};
const getPredictions = async (inputText: string) => {
if (!client) {
console.error("OpenAI client is not defined.");
return;
}
try {
const response = await client.getCompletion({
model: 'gpt-3.5-turbo',
messages: [{
role: 'system',
content: prompt.replace("{{inputText}}", inputText),
}],
});
if (response && response.choices && response.choices.length > 0) {
const predictedText = response.choices[0].message.content;
console.log("Predicted text:", predictedText);
setPrediction(predictedText);
}
} catch (error) {
console.error("Failed to fetch predictions:", error);
}
};
return (