@foundationui/smart-input
Advanced tools
Comparing version 1.0.9 to 1.0.10
@@ -8,3 +8,3 @@ import React, { MutableRefObject } from 'react'; | ||
renderText: (props: any) => React.ReactElement; | ||
renderSuggestion: (props: any) => React.ReactElement; | ||
renderCompletion: (props: any) => React.ReactElement; | ||
renderPlaceholder?: (props: any) => React.ReactElement; | ||
@@ -21,5 +21,5 @@ modelId?: string; | ||
className?: string; | ||
mockSuggestion?: (text: string) => string; | ||
mockCompletion?: (text: string) => string; | ||
} | ||
export declare function SmartInput(props: SmartInputProps): JSX.Element; | ||
export declare function SmartInputDev(props: SmartInputProps): JSX.Element; | ||
type CustomElement = { | ||
@@ -26,0 +26,0 @@ type: 'text' | 'completion' | undefined; |
@@ -37,3 +37,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SmartInput = void 0; | ||
exports.SmartInputDev = void 0; | ||
var react_1 = __importStar(require("react")); | ||
@@ -44,26 +44,26 @@ var slate_1 = require("slate"); | ||
var SmartInputFetcher_1 = require("./SmartInputFetcher"); | ||
function SmartInput(props) { | ||
function SmartInputDev(props) { | ||
var editor = react_1.default.useMemo(function () { return (0, slate_history_1.withHistory)((0, slate_react_1.withReact)((0, slate_1.createEditor)())); }, []); | ||
var _a = react_1.default.useState(''), completion = _a[0], setCompletion = _a[1]; | ||
var acceptSuggestion = function () { | ||
acceptCompletion(editor, completion); | ||
setCompletion(''); | ||
var _a = react_1.default.useState(null), completion = _a[0], setCompletion = _a[1]; | ||
var fetcher = react_1.default.useState(new SmartInputFetcher_1.SmartInputFetcher(function (text, completion) { | ||
addCompletion(completion); | ||
}, props.modelId, props.modelId ? props.mockCompletion : function () { return ' -- sample completion --'; }))[0]; | ||
var acceptCompletion = function () { | ||
EditorHelper.acceptCompletion(editor, fetcher, completion); | ||
setCompletion(null); | ||
}; | ||
var addSuggestion = function (completion) { | ||
var addCompletion = function (completion) { | ||
if (props.value) { | ||
addCompletion(editor, completion); | ||
EditorHelper.addCompletion(editor, fetcher, completion); | ||
setCompletion(completion); | ||
} | ||
}; | ||
var clearSuggestion = function () { | ||
removeCompletion(editor); | ||
setCompletion(''); | ||
var clearCompletion = function () { | ||
EditorHelper.removeCompletion(editor); | ||
setCompletion(null); | ||
}; | ||
var fetcher = react_1.default.useState(new SmartInputFetcher_1.SmartInputFetcher(function (text, suggestion) { | ||
addSuggestion(suggestion); | ||
}, props.modelId, props.modelId ? props.mockSuggestion : function () { return ' -- sample suggestion --'; }))[0]; | ||
fetcher.addSuggestion = function (text, suggestion) { | ||
fetcher.addCompletion = function (text, completion) { | ||
var currText = props.value; | ||
if (suggestion && (text + suggestion).startsWith(currText)) { | ||
addSuggestion(suggestion); | ||
if (completion && (text + completion).startsWith(currText)) { | ||
addCompletion(completion); | ||
} | ||
@@ -97,7 +97,7 @@ }; | ||
case 'completion': | ||
return props.renderSuggestion(__assign(__assign({}, p), { contentEditable: 'false', suppressContentEditableWarning: true })); | ||
return props.renderCompletion(__assign(__assign({}, p), { contentEditable: 'false', suppressContentEditableWarning: true })); | ||
default: | ||
return react_1.default.createElement(slate_react_1.DefaultElement, __assign({}, p)); | ||
} | ||
}, [props.renderText, props.renderSuggestion]); | ||
}, [props.renderText, props.renderCompletion]); | ||
var renderPlaceholder = react_1.default.useCallback(function (p) { | ||
@@ -107,8 +107,10 @@ return props.renderPlaceholder(__assign(__assign(__assign({}, p), (p.attributes || {})), { style: __assign({ position: 'absolute', pointerEvents: 'none', width: '100%', maxWidth: '100%', userSelect: 'none', textDecoration: 'none' }, (p.style || {})) })); | ||
return (react_1.default.createElement(slate_react_1.Slate, { editor: editor, value: initialValue, onChange: function (value) { | ||
var text = serialize(value.filter(function (n) { return n.type !== 'completion'; })); | ||
fetcher.fetch(text, props.context || {}); | ||
var _a; | ||
var text = EditorHelper.serialize(value.filter(function (n) { return n.type !== 'completion'; })); | ||
(_a = fetcher.fetchCompletion(text, props.context || {})) === null || _a === void 0 ? void 0 : _a.catch(function (e) { return console.error(e); }); | ||
fetcher.sendEvents(text, props.context || {}); | ||
props.onChange(text); | ||
} }, | ||
react_1.default.createElement(slate_react_1.Editable, { placeholder: props.placeholder, className: props.className, style: __assign(__assign({}, (props.style || {})), { whiteSpace: props.multiline ? undefined : 'pre' }), onPaste: function (event) { | ||
clearSuggestion(); | ||
clearCompletion(); | ||
event.preventDefault(); | ||
@@ -123,4 +125,4 @@ var value = event.clipboardData.getData('Text'); | ||
}, renderPlaceholder: props.renderPlaceholder ? renderPlaceholder : undefined, renderElement: renderElement, onBlur: function (e) { | ||
clearSuggestion(); | ||
fetcher.pendingCompletion = null; | ||
clearCompletion(); | ||
fetcher.currentCompletion = null; | ||
if (props.onBlur) { | ||
@@ -142,23 +144,24 @@ props.onBlur(e); | ||
}, onKeyDown: function (event) { | ||
var hasCompletion = completion.trim().length > 0; | ||
var _a, _b, _c; | ||
var hasCompletion = Boolean((_b = (_a = completion === null || completion === void 0 ? void 0 : completion.completion) === null || _a === void 0 ? void 0 : _a.trim()) === null || _b === void 0 ? void 0 : _b.length); | ||
if (event.key === 'Tab' && hasCompletion) { | ||
event.preventDefault(); | ||
acceptSuggestion(); | ||
fetcher.pendingCompletion = null; | ||
acceptCompletion(); | ||
fetcher.currentCompletion = null; | ||
} | ||
else if (event.key === 'ArrowRight' && hasCompletion) { | ||
event.preventDefault(); | ||
acceptSuggestion(); | ||
fetcher.pendingCompletion = null; | ||
acceptCompletion(); | ||
fetcher.currentCompletion = null; | ||
} | ||
else if (event.key === 'ArrowLeft' && hasCompletion) { | ||
clearSuggestion(); | ||
fetcher.pendingCompletion = null; | ||
clearCompletion(); | ||
fetcher.currentCompletion = null; | ||
} | ||
else if ((event.key === 'ArrowDown' || event.key === 'ArrowUp') && hasCompletion) { | ||
clearSuggestion(); | ||
clearCompletion(); | ||
} | ||
else if (event.key === 'Backspace') { | ||
fetcher.pendingCompletion = null; | ||
clearSuggestion(); | ||
fetcher.currentCompletion = null; | ||
clearCompletion(); | ||
} | ||
@@ -168,3 +171,3 @@ else if (event.key === 'Enter' && !event.metaKey) { | ||
if (props.multiline) { | ||
clearSuggestion(); | ||
clearCompletion(); | ||
editor.insertText('\n'); | ||
@@ -174,9 +177,13 @@ } | ||
else if (event.key !== 'Shift') { | ||
if (completion && !event.metaKey && completion.startsWith(event.key) && event.key.length === 1) { | ||
updateCompletion(editor, completion.substring(1)); | ||
setCompletion(completion.substring(1)); | ||
if (completion && | ||
!event.metaKey && | ||
((_c = completion.completion) === null || _c === void 0 ? void 0 : _c.startsWith(event.key)) && | ||
event.key.length === 1) { | ||
var newCompletionText = completion.completion.substring(1); | ||
EditorHelper.updateCompletion(editor, newCompletionText); | ||
setCompletion(__assign(__assign({}, completion), { completion: newCompletionText })); | ||
} | ||
else { | ||
fetcher.pendingCompletion = null; | ||
clearSuggestion(); | ||
fetcher.currentCompletion = null; | ||
clearCompletion(); | ||
} | ||
@@ -189,60 +196,64 @@ } | ||
} | ||
exports.SmartInput = SmartInput; | ||
function isCompletionActive(editor) { | ||
var completion = editor.children.find(function (n) { return n.type === 'completion'; }); | ||
return !!completion; | ||
} | ||
function isCursorAtEndOfDocument(editor) { | ||
var sel = editor.selection; | ||
if (!sel) { | ||
return false; | ||
} | ||
var node = sel.anchor.path[0]; | ||
var offset = sel.anchor.offset; | ||
if (node !== editor.children.length - 1) { | ||
return false; | ||
} | ||
return offset === slate_1.Node.string(editor.children[node]).length; | ||
} | ||
function acceptCompletion(editor, completion) { | ||
var isActive = isCompletionActive(editor); | ||
if (isActive) { | ||
removeCompletion(editor); | ||
editor.insertText(completion); | ||
} | ||
} | ||
function addCompletion(editor, completion) { | ||
var isActive = isCompletionActive(editor); | ||
var isCursorEnd = isCursorAtEndOfDocument(editor); | ||
if (!isActive && isCursorEnd) { | ||
slate_1.Transforms.insertNodes(editor, { | ||
type: 'completion', | ||
children: [{ text: completion }], | ||
}, { | ||
at: [editor.children.length], | ||
}); | ||
} | ||
} | ||
function removeCompletion(editor) { | ||
var isActive = isCompletionActive(editor); | ||
if (isActive) { | ||
slate_1.Transforms.removeNodes(editor, { | ||
at: [editor.children.length - 1], | ||
}); | ||
} | ||
} | ||
function updateCompletion(editor, newCompletion) { | ||
var isActive = isCompletionActive(editor); | ||
if (isActive && newCompletion.length > 0) { | ||
slate_1.Transforms.delete(editor, { | ||
at: { | ||
anchor: { path: [editor.children.length - 1, 0], offset: 0 }, | ||
focus: { path: [editor.children.length - 1, 0], offset: 1 }, | ||
}, | ||
}); | ||
} | ||
} | ||
var serialize = function (nodes) { | ||
return nodes.map(function (n) { return slate_1.Node.string(n); }).join('\n'); | ||
exports.SmartInputDev = SmartInputDev; | ||
var EditorHelper = { | ||
isCompletionActive: function (editor) { | ||
var completion = editor.children.find(function (n) { return n.type === 'completion'; }); | ||
return !!completion; | ||
}, | ||
isCursorAtEndOfDocument: function (editor) { | ||
var sel = editor.selection; | ||
if (!sel) { | ||
return false; | ||
} | ||
var node = sel.anchor.path[0]; | ||
var offset = sel.anchor.offset; | ||
if (node !== editor.children.length - 1) { | ||
return false; | ||
} | ||
return offset === slate_1.Node.string(editor.children[node]).length; | ||
}, | ||
acceptCompletion: function (editor, fetcher, completion) { | ||
var isActive = EditorHelper.isCompletionActive(editor); | ||
if (isActive && (completion === null || completion === void 0 ? void 0 : completion.completion)) { | ||
EditorHelper.removeCompletion(editor); | ||
editor.insertText(completion.completion); | ||
fetcher.updateCompletion(completion.sid, { accepted: true }); | ||
} | ||
}, | ||
addCompletion: function (editor, fetcher, completion) { | ||
var isActive = EditorHelper.isCompletionActive(editor); | ||
var isCursorEnd = EditorHelper.isCursorAtEndOfDocument(editor); | ||
if (!isActive && isCursorEnd && (completion === null || completion === void 0 ? void 0 : completion.completion)) { | ||
slate_1.Transforms.insertNodes(editor, { | ||
type: 'completion', | ||
children: [{ text: completion.completion }], | ||
}, { | ||
at: [editor.children.length], | ||
}); | ||
fetcher.updateCompletion(completion.sid, { seen: true }); | ||
} | ||
}, | ||
removeCompletion: function (editor) { | ||
var isActive = EditorHelper.isCompletionActive(editor); | ||
if (isActive) { | ||
slate_1.Transforms.removeNodes(editor, { | ||
at: [editor.children.length - 1], | ||
}); | ||
} | ||
}, | ||
updateCompletion: function (editor, newCompletion) { | ||
var isActive = EditorHelper.isCompletionActive(editor); | ||
if (isActive && newCompletion.length > 0) { | ||
slate_1.Transforms.delete(editor, { | ||
at: { | ||
anchor: { path: [editor.children.length - 1, 0], offset: 0 }, | ||
focus: { path: [editor.children.length - 1, 0], offset: 1 }, | ||
}, | ||
}); | ||
} | ||
}, | ||
serialize: function (nodes) { | ||
return nodes.map(function (n) { return slate_1.Node.string(n); }).join('\n'); | ||
}, | ||
}; | ||
//# sourceMappingURL=SmartInput.js.map |
@@ -0,13 +1,24 @@ | ||
/// <reference types="lodash" /> | ||
import { ICompletionResponse } from './ICompletionResponse'; | ||
export declare class SmartInputFetcher { | ||
addSuggestion: (text: string, suggestion: string) => void; | ||
addCompletion: (text: string, completion: ICompletionResponse) => void; | ||
modelId?: string | undefined; | ||
mockSuggestion?: ((text: string) => any) | undefined; | ||
mockCompletion?: ((text: string) => string | null) | undefined; | ||
sequenceId: number; | ||
pendingCompletion: { | ||
sessionId: string; | ||
fetchCache: Record<string, ICompletionResponse | null>; | ||
alreadySeen: Set<string>; | ||
alreadyAccepted: Set<string>; | ||
currentCompletion: { | ||
sequenceId: number; | ||
text: string; | ||
suggestion?: string; | ||
completion?: string | null; | ||
} | null; | ||
constructor(addSuggestion: (text: string, suggestion: string) => void, modelId?: string | undefined, mockSuggestion?: ((text: string) => any) | undefined); | ||
fetch: (...args: any[]) => void; | ||
constructor(addCompletion: (text: string, completion: ICompletionResponse) => void, modelId?: string | undefined, mockCompletion?: ((text: string) => string | null) | undefined); | ||
fetchCompletion: import("lodash").DebouncedFunc<(text: string, context: any) => Promise<ICompletionResponse | null>>; | ||
updateCompletion(completionSid: string, arg: { | ||
seen?: boolean; | ||
accepted?: boolean; | ||
}): void; | ||
sendEvents: import("lodash").DebouncedFunc<(text: string, context: any) => void>; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SmartInputFetcher = void 0; | ||
var lodash_debounce_1 = __importDefault(require("lodash.debounce")); | ||
var lodash_throttle_1 = __importDefault(require("lodash.throttle")); | ||
var ulid_1 = require("ulid"); | ||
var SmartInputFetcher = (function () { | ||
function SmartInputFetcher(addSuggestion, modelId, mockSuggestion) { | ||
function SmartInputFetcher(addCompletion, modelId, mockCompletion) { | ||
var _this = this; | ||
this.addSuggestion = addSuggestion; | ||
this.addCompletion = addCompletion; | ||
this.modelId = modelId; | ||
this.mockSuggestion = mockSuggestion; | ||
this.mockCompletion = mockCompletion; | ||
this.sequenceId = 0; | ||
this.pendingCompletion = null; | ||
this.fetch = debounce(function (text, context) { | ||
var _a; | ||
if (text.length === 0) { | ||
return; | ||
} | ||
var seqId = ++_this.sequenceId; | ||
if ((_a = _this.pendingCompletion) === null || _a === void 0 ? void 0 : _a.suggestion) { | ||
var currExpectedText = _this.pendingCompletion.text + _this.pendingCompletion.suggestion; | ||
if (currExpectedText.startsWith(text)) { | ||
return; | ||
} | ||
} | ||
_this.pendingCompletion = { text: text, sequenceId: seqId }; | ||
if (_this.mockSuggestion) { | ||
var suggestion_1 = _this.mockSuggestion(text); | ||
if (suggestion_1) { | ||
setTimeout(function () { | ||
var _a; | ||
if (((_a = _this.pendingCompletion) === null || _a === void 0 ? void 0 : _a.sequenceId) === seqId) { | ||
_this.addSuggestion(text, suggestion_1); | ||
_this.pendingCompletion.suggestion = suggestion_1; | ||
this.sessionId = (0, ulid_1.ulid)(); | ||
this.fetchCache = {}; | ||
this.alreadySeen = new Set(); | ||
this.alreadyAccepted = new Set(); | ||
this.currentCompletion = null; | ||
this.fetchCompletion = (0, lodash_debounce_1.default)(function (text, context) { return __awaiter(_this, void 0, void 0, function () { | ||
var seqId, currExpectedText, cachedVal, completion_1, res, data; | ||
var _this = this; | ||
var _a, _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
if (text.length === 0) { | ||
return [2, null]; | ||
} | ||
}, getRandomInt(200, 1000)); | ||
seqId = ++this.sequenceId; | ||
if ((_a = this.currentCompletion) === null || _a === void 0 ? void 0 : _a.completion) { | ||
currExpectedText = this.currentCompletion.text + this.currentCompletion.completion; | ||
if (currExpectedText.startsWith(text)) { | ||
return [2, null]; | ||
} | ||
} | ||
this.currentCompletion = { text: text, sequenceId: seqId }; | ||
cachedVal = this.fetchCache[text]; | ||
if (cachedVal) { | ||
this.addCompletion(text, cachedVal); | ||
this.currentCompletion.completion = cachedVal.completion; | ||
return [2, cachedVal]; | ||
} | ||
if (!this.mockCompletion) return [3, 3]; | ||
completion_1 = this.mockCompletion(text); | ||
if (!completion_1) return [3, 2]; | ||
return [4, new Promise(function (resolve) { | ||
setTimeout(function () { | ||
var _a; | ||
var c = { input: text, sid: (0, ulid_1.ulid)(), completion: completion_1 }; | ||
_this.fetchCache[text] = c; | ||
if (((_a = _this.currentCompletion) === null || _a === void 0 ? void 0 : _a.sequenceId) === seqId) { | ||
_this.addCompletion(text, c); | ||
_this.currentCompletion.completion = completion_1; | ||
} | ||
resolve(c); | ||
}, getRandomInt(200, 1000)); | ||
})]; | ||
case 1: return [2, _c.sent()]; | ||
case 2: return [2, { input: text, sid: (0, ulid_1.ulid)(), completion: null }]; | ||
case 3: return [4, fetch('https://api.foundation-ui.com/completions', { | ||
method: 'POST', | ||
mode: 'cors', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
Authorization: "Bearer ".concat(this.modelId), | ||
}, | ||
body: JSON.stringify({ | ||
model: this.modelId, | ||
input: text, | ||
session: this.sessionId, | ||
context: context, | ||
}), | ||
})]; | ||
case 4: | ||
res = _c.sent(); | ||
if (res.status !== 200) { | ||
console.error("Couldn't fetch completions"); | ||
return [2, null]; | ||
} | ||
return [4, res.json()]; | ||
case 5: | ||
data = (_c.sent()); | ||
this.fetchCache[text] = data; | ||
if (((_b = this.currentCompletion) === null || _b === void 0 ? void 0 : _b.sequenceId) === seqId) { | ||
this.addCompletion(text, data); | ||
this.currentCompletion.completion = data.completion; | ||
} | ||
return [2, data]; | ||
} | ||
return; | ||
} | ||
fetch('https://api.lydian.company/app/events', { | ||
}); | ||
}); }, 200); | ||
this.sendEvents = (0, lodash_throttle_1.default)(function (text, context) { | ||
fetch('https://api.foundation-ui.com/events', { | ||
method: 'POST', | ||
@@ -47,3 +141,3 @@ mode: 'cors', | ||
model: _this.modelId, | ||
session: '' + Date.now(), | ||
session: _this.sessionId, | ||
input: text, | ||
@@ -55,18 +149,43 @@ context: context, | ||
if (res.status !== 200) { | ||
console.error("Couldn't fetch suggestions"); | ||
return; | ||
console.error('Error sending events'); | ||
} | ||
return res.json(); | ||
}) | ||
.then(function (data) { | ||
var _a; | ||
var suggestion = (data === null || data === void 0 ? void 0 : data.suggestion) || ''; | ||
if (suggestion && ((_a = _this.pendingCompletion) === null || _a === void 0 ? void 0 : _a.sequenceId) === seqId) { | ||
_this.addSuggestion(text, suggestion); | ||
_this.pendingCompletion.suggestion = suggestion; | ||
} | ||
}) | ||
.catch(function (e) { return console.error(e); }); | ||
}, 200); | ||
}, 1000, { trailing: true }); | ||
} | ||
SmartInputFetcher.prototype.updateCompletion = function (completionSid, arg) { | ||
var _this = this; | ||
if (this.mockCompletion) { | ||
return; | ||
} | ||
var shouldUpdate = (arg.seen && !this.alreadySeen.has(completionSid)) || (arg.accepted && !this.alreadyAccepted.has(completionSid)); | ||
if (!shouldUpdate) { | ||
return; | ||
} | ||
fetch('https://api.foundation-ui.com/completions', { | ||
method: 'PUT', | ||
mode: 'cors', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
Authorization: "Bearer ".concat(this.modelId), | ||
}, | ||
body: JSON.stringify({ | ||
completionSid: completionSid, | ||
seen: arg.seen, | ||
accepted: arg.accepted, | ||
}), | ||
}) | ||
.then(function (res) { | ||
if (res.status !== 200) { | ||
console.error("Couldn't update completion"); | ||
} | ||
if (arg.seen) { | ||
_this.alreadySeen.add(completionSid); | ||
} | ||
if (arg.accepted) { | ||
_this.alreadyAccepted.add(completionSid); | ||
} | ||
}) | ||
.catch(function (e) { return console.error(e); }); | ||
}; | ||
return SmartInputFetcher; | ||
@@ -80,15 +199,2 @@ }()); | ||
} | ||
var debounce = function (callback, wait) { | ||
var timeoutId = null; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
window.clearTimeout(timeoutId); | ||
timeoutId = window.setTimeout(function () { | ||
callback.apply(null, args); | ||
}, wait); | ||
}; | ||
}; | ||
//# sourceMappingURL=SmartInputFetcher.js.map |
@@ -8,3 +8,3 @@ import React, { MutableRefObject } from 'react'; | ||
renderText: (props: any) => React.ReactElement; | ||
renderSuggestion: (props: any) => React.ReactElement; | ||
renderCompletion: (props: any) => React.ReactElement; | ||
renderPlaceholder?: (props: any) => React.ReactElement; | ||
@@ -21,5 +21,5 @@ modelId?: string; | ||
className?: string; | ||
mockSuggestion?: (text: string) => string; | ||
mockCompletion?: (text: string) => string; | ||
} | ||
export declare function SmartInput(props: SmartInputProps): JSX.Element; | ||
export declare function SmartInputDev(props: SmartInputProps): JSX.Element; | ||
type CustomElement = { | ||
@@ -26,0 +26,0 @@ type: 'text' | 'completion' | undefined; |
@@ -17,26 +17,26 @@ var __assign = (this && this.__assign) || function () { | ||
import { SmartInputFetcher } from './SmartInputFetcher'; | ||
export function SmartInput(props) { | ||
export function SmartInputDev(props) { | ||
var editor = React.useMemo(function () { return withHistory(withReact(createEditor())); }, []); | ||
var _a = React.useState(''), completion = _a[0], setCompletion = _a[1]; | ||
var acceptSuggestion = function () { | ||
acceptCompletion(editor, completion); | ||
setCompletion(''); | ||
var _a = React.useState(null), completion = _a[0], setCompletion = _a[1]; | ||
var fetcher = React.useState(new SmartInputFetcher(function (text, completion) { | ||
addCompletion(completion); | ||
}, props.modelId, props.modelId ? props.mockCompletion : function () { return ' -- sample completion --'; }))[0]; | ||
var acceptCompletion = function () { | ||
EditorHelper.acceptCompletion(editor, fetcher, completion); | ||
setCompletion(null); | ||
}; | ||
var addSuggestion = function (completion) { | ||
var addCompletion = function (completion) { | ||
if (props.value) { | ||
addCompletion(editor, completion); | ||
EditorHelper.addCompletion(editor, fetcher, completion); | ||
setCompletion(completion); | ||
} | ||
}; | ||
var clearSuggestion = function () { | ||
removeCompletion(editor); | ||
setCompletion(''); | ||
var clearCompletion = function () { | ||
EditorHelper.removeCompletion(editor); | ||
setCompletion(null); | ||
}; | ||
var fetcher = React.useState(new SmartInputFetcher(function (text, suggestion) { | ||
addSuggestion(suggestion); | ||
}, props.modelId, props.modelId ? props.mockSuggestion : function () { return ' -- sample suggestion --'; }))[0]; | ||
fetcher.addSuggestion = function (text, suggestion) { | ||
fetcher.addCompletion = function (text, completion) { | ||
var currText = props.value; | ||
if (suggestion && (text + suggestion).startsWith(currText)) { | ||
addSuggestion(suggestion); | ||
if (completion && (text + completion).startsWith(currText)) { | ||
addCompletion(completion); | ||
} | ||
@@ -70,7 +70,7 @@ }; | ||
case 'completion': | ||
return props.renderSuggestion(__assign(__assign({}, p), { contentEditable: 'false', suppressContentEditableWarning: true })); | ||
return props.renderCompletion(__assign(__assign({}, p), { contentEditable: 'false', suppressContentEditableWarning: true })); | ||
default: | ||
return React.createElement(DefaultElement, __assign({}, p)); | ||
} | ||
}, [props.renderText, props.renderSuggestion]); | ||
}, [props.renderText, props.renderCompletion]); | ||
var renderPlaceholder = React.useCallback(function (p) { | ||
@@ -80,8 +80,10 @@ return props.renderPlaceholder(__assign(__assign(__assign({}, p), (p.attributes || {})), { style: __assign({ position: 'absolute', pointerEvents: 'none', width: '100%', maxWidth: '100%', userSelect: 'none', textDecoration: 'none' }, (p.style || {})) })); | ||
return (React.createElement(Slate, { editor: editor, value: initialValue, onChange: function (value) { | ||
var text = serialize(value.filter(function (n) { return n.type !== 'completion'; })); | ||
fetcher.fetch(text, props.context || {}); | ||
var _a; | ||
var text = EditorHelper.serialize(value.filter(function (n) { return n.type !== 'completion'; })); | ||
(_a = fetcher.fetchCompletion(text, props.context || {})) === null || _a === void 0 ? void 0 : _a.catch(function (e) { return console.error(e); }); | ||
fetcher.sendEvents(text, props.context || {}); | ||
props.onChange(text); | ||
} }, | ||
React.createElement(Editable, { placeholder: props.placeholder, className: props.className, style: __assign(__assign({}, (props.style || {})), { whiteSpace: props.multiline ? undefined : 'pre' }), onPaste: function (event) { | ||
clearSuggestion(); | ||
clearCompletion(); | ||
event.preventDefault(); | ||
@@ -96,4 +98,4 @@ var value = event.clipboardData.getData('Text'); | ||
}, renderPlaceholder: props.renderPlaceholder ? renderPlaceholder : undefined, renderElement: renderElement, onBlur: function (e) { | ||
clearSuggestion(); | ||
fetcher.pendingCompletion = null; | ||
clearCompletion(); | ||
fetcher.currentCompletion = null; | ||
if (props.onBlur) { | ||
@@ -115,23 +117,24 @@ props.onBlur(e); | ||
}, onKeyDown: function (event) { | ||
var hasCompletion = completion.trim().length > 0; | ||
var _a, _b, _c; | ||
var hasCompletion = Boolean((_b = (_a = completion === null || completion === void 0 ? void 0 : completion.completion) === null || _a === void 0 ? void 0 : _a.trim()) === null || _b === void 0 ? void 0 : _b.length); | ||
if (event.key === 'Tab' && hasCompletion) { | ||
event.preventDefault(); | ||
acceptSuggestion(); | ||
fetcher.pendingCompletion = null; | ||
acceptCompletion(); | ||
fetcher.currentCompletion = null; | ||
} | ||
else if (event.key === 'ArrowRight' && hasCompletion) { | ||
event.preventDefault(); | ||
acceptSuggestion(); | ||
fetcher.pendingCompletion = null; | ||
acceptCompletion(); | ||
fetcher.currentCompletion = null; | ||
} | ||
else if (event.key === 'ArrowLeft' && hasCompletion) { | ||
clearSuggestion(); | ||
fetcher.pendingCompletion = null; | ||
clearCompletion(); | ||
fetcher.currentCompletion = null; | ||
} | ||
else if ((event.key === 'ArrowDown' || event.key === 'ArrowUp') && hasCompletion) { | ||
clearSuggestion(); | ||
clearCompletion(); | ||
} | ||
else if (event.key === 'Backspace') { | ||
fetcher.pendingCompletion = null; | ||
clearSuggestion(); | ||
fetcher.currentCompletion = null; | ||
clearCompletion(); | ||
} | ||
@@ -141,3 +144,3 @@ else if (event.key === 'Enter' && !event.metaKey) { | ||
if (props.multiline) { | ||
clearSuggestion(); | ||
clearCompletion(); | ||
editor.insertText('\n'); | ||
@@ -147,9 +150,13 @@ } | ||
else if (event.key !== 'Shift') { | ||
if (completion && !event.metaKey && completion.startsWith(event.key) && event.key.length === 1) { | ||
updateCompletion(editor, completion.substring(1)); | ||
setCompletion(completion.substring(1)); | ||
if (completion && | ||
!event.metaKey && | ||
((_c = completion.completion) === null || _c === void 0 ? void 0 : _c.startsWith(event.key)) && | ||
event.key.length === 1) { | ||
var newCompletionText = completion.completion.substring(1); | ||
EditorHelper.updateCompletion(editor, newCompletionText); | ||
setCompletion(__assign(__assign({}, completion), { completion: newCompletionText })); | ||
} | ||
else { | ||
fetcher.pendingCompletion = null; | ||
clearSuggestion(); | ||
fetcher.currentCompletion = null; | ||
clearCompletion(); | ||
} | ||
@@ -162,59 +169,63 @@ } | ||
} | ||
function isCompletionActive(editor) { | ||
var completion = editor.children.find(function (n) { return n.type === 'completion'; }); | ||
return !!completion; | ||
} | ||
function isCursorAtEndOfDocument(editor) { | ||
var sel = editor.selection; | ||
if (!sel) { | ||
return false; | ||
} | ||
var node = sel.anchor.path[0]; | ||
var offset = sel.anchor.offset; | ||
if (node !== editor.children.length - 1) { | ||
return false; | ||
} | ||
return offset === Node.string(editor.children[node]).length; | ||
} | ||
function acceptCompletion(editor, completion) { | ||
var isActive = isCompletionActive(editor); | ||
if (isActive) { | ||
removeCompletion(editor); | ||
editor.insertText(completion); | ||
} | ||
} | ||
function addCompletion(editor, completion) { | ||
var isActive = isCompletionActive(editor); | ||
var isCursorEnd = isCursorAtEndOfDocument(editor); | ||
if (!isActive && isCursorEnd) { | ||
Transforms.insertNodes(editor, { | ||
type: 'completion', | ||
children: [{ text: completion }], | ||
}, { | ||
at: [editor.children.length], | ||
}); | ||
} | ||
} | ||
function removeCompletion(editor) { | ||
var isActive = isCompletionActive(editor); | ||
if (isActive) { | ||
Transforms.removeNodes(editor, { | ||
at: [editor.children.length - 1], | ||
}); | ||
} | ||
} | ||
function updateCompletion(editor, newCompletion) { | ||
var isActive = isCompletionActive(editor); | ||
if (isActive && newCompletion.length > 0) { | ||
Transforms.delete(editor, { | ||
at: { | ||
anchor: { path: [editor.children.length - 1, 0], offset: 0 }, | ||
focus: { path: [editor.children.length - 1, 0], offset: 1 }, | ||
}, | ||
}); | ||
} | ||
} | ||
var serialize = function (nodes) { | ||
return nodes.map(function (n) { return Node.string(n); }).join('\n'); | ||
var EditorHelper = { | ||
isCompletionActive: function (editor) { | ||
var completion = editor.children.find(function (n) { return n.type === 'completion'; }); | ||
return !!completion; | ||
}, | ||
isCursorAtEndOfDocument: function (editor) { | ||
var sel = editor.selection; | ||
if (!sel) { | ||
return false; | ||
} | ||
var node = sel.anchor.path[0]; | ||
var offset = sel.anchor.offset; | ||
if (node !== editor.children.length - 1) { | ||
return false; | ||
} | ||
return offset === Node.string(editor.children[node]).length; | ||
}, | ||
acceptCompletion: function (editor, fetcher, completion) { | ||
var isActive = EditorHelper.isCompletionActive(editor); | ||
if (isActive && (completion === null || completion === void 0 ? void 0 : completion.completion)) { | ||
EditorHelper.removeCompletion(editor); | ||
editor.insertText(completion.completion); | ||
fetcher.updateCompletion(completion.sid, { accepted: true }); | ||
} | ||
}, | ||
addCompletion: function (editor, fetcher, completion) { | ||
var isActive = EditorHelper.isCompletionActive(editor); | ||
var isCursorEnd = EditorHelper.isCursorAtEndOfDocument(editor); | ||
if (!isActive && isCursorEnd && (completion === null || completion === void 0 ? void 0 : completion.completion)) { | ||
Transforms.insertNodes(editor, { | ||
type: 'completion', | ||
children: [{ text: completion.completion }], | ||
}, { | ||
at: [editor.children.length], | ||
}); | ||
fetcher.updateCompletion(completion.sid, { seen: true }); | ||
} | ||
}, | ||
removeCompletion: function (editor) { | ||
var isActive = EditorHelper.isCompletionActive(editor); | ||
if (isActive) { | ||
Transforms.removeNodes(editor, { | ||
at: [editor.children.length - 1], | ||
}); | ||
} | ||
}, | ||
updateCompletion: function (editor, newCompletion) { | ||
var isActive = EditorHelper.isCompletionActive(editor); | ||
if (isActive && newCompletion.length > 0) { | ||
Transforms.delete(editor, { | ||
at: { | ||
anchor: { path: [editor.children.length - 1, 0], offset: 0 }, | ||
focus: { path: [editor.children.length - 1, 0], offset: 1 }, | ||
}, | ||
}); | ||
} | ||
}, | ||
serialize: function (nodes) { | ||
return nodes.map(function (n) { return Node.string(n); }).join('\n'); | ||
}, | ||
}; | ||
//# sourceMappingURL=SmartInput.js.map |
@@ -0,13 +1,24 @@ | ||
/// <reference types="lodash" /> | ||
import { ICompletionResponse } from './ICompletionResponse'; | ||
export declare class SmartInputFetcher { | ||
addSuggestion: (text: string, suggestion: string) => void; | ||
addCompletion: (text: string, completion: ICompletionResponse) => void; | ||
modelId?: string | undefined; | ||
mockSuggestion?: ((text: string) => any) | undefined; | ||
mockCompletion?: ((text: string) => string | null) | undefined; | ||
sequenceId: number; | ||
pendingCompletion: { | ||
sessionId: string; | ||
fetchCache: Record<string, ICompletionResponse | null>; | ||
alreadySeen: Set<string>; | ||
alreadyAccepted: Set<string>; | ||
currentCompletion: { | ||
sequenceId: number; | ||
text: string; | ||
suggestion?: string; | ||
completion?: string | null; | ||
} | null; | ||
constructor(addSuggestion: (text: string, suggestion: string) => void, modelId?: string | undefined, mockSuggestion?: ((text: string) => any) | undefined); | ||
fetch: (...args: any[]) => void; | ||
constructor(addCompletion: (text: string, completion: ICompletionResponse) => void, modelId?: string | undefined, mockCompletion?: ((text: string) => string | null) | undefined); | ||
fetchCompletion: import("lodash").DebouncedFunc<(text: string, context: any) => Promise<ICompletionResponse | null>>; | ||
updateCompletion(completionSid: string, arg: { | ||
seen?: boolean; | ||
accepted?: boolean; | ||
}): void; | ||
sendEvents: import("lodash").DebouncedFunc<(text: string, context: any) => void>; | ||
} |
@@ -0,36 +1,127 @@ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
import debounce from 'lodash.debounce'; | ||
import throttle from 'lodash.throttle'; | ||
import { ulid } from 'ulid'; | ||
var SmartInputFetcher = (function () { | ||
function SmartInputFetcher(addSuggestion, modelId, mockSuggestion) { | ||
function SmartInputFetcher(addCompletion, modelId, mockCompletion) { | ||
var _this = this; | ||
this.addSuggestion = addSuggestion; | ||
this.addCompletion = addCompletion; | ||
this.modelId = modelId; | ||
this.mockSuggestion = mockSuggestion; | ||
this.mockCompletion = mockCompletion; | ||
this.sequenceId = 0; | ||
this.pendingCompletion = null; | ||
this.fetch = debounce(function (text, context) { | ||
var _a; | ||
if (text.length === 0) { | ||
return; | ||
} | ||
var seqId = ++_this.sequenceId; | ||
if ((_a = _this.pendingCompletion) === null || _a === void 0 ? void 0 : _a.suggestion) { | ||
var currExpectedText = _this.pendingCompletion.text + _this.pendingCompletion.suggestion; | ||
if (currExpectedText.startsWith(text)) { | ||
return; | ||
} | ||
} | ||
_this.pendingCompletion = { text: text, sequenceId: seqId }; | ||
if (_this.mockSuggestion) { | ||
var suggestion_1 = _this.mockSuggestion(text); | ||
if (suggestion_1) { | ||
setTimeout(function () { | ||
var _a; | ||
if (((_a = _this.pendingCompletion) === null || _a === void 0 ? void 0 : _a.sequenceId) === seqId) { | ||
_this.addSuggestion(text, suggestion_1); | ||
_this.pendingCompletion.suggestion = suggestion_1; | ||
this.sessionId = ulid(); | ||
this.fetchCache = {}; | ||
this.alreadySeen = new Set(); | ||
this.alreadyAccepted = new Set(); | ||
this.currentCompletion = null; | ||
this.fetchCompletion = debounce(function (text, context) { return __awaiter(_this, void 0, void 0, function () { | ||
var seqId, currExpectedText, cachedVal, completion_1, res, data; | ||
var _this = this; | ||
var _a, _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
if (text.length === 0) { | ||
return [2, null]; | ||
} | ||
}, getRandomInt(200, 1000)); | ||
seqId = ++this.sequenceId; | ||
if ((_a = this.currentCompletion) === null || _a === void 0 ? void 0 : _a.completion) { | ||
currExpectedText = this.currentCompletion.text + this.currentCompletion.completion; | ||
if (currExpectedText.startsWith(text)) { | ||
return [2, null]; | ||
} | ||
} | ||
this.currentCompletion = { text: text, sequenceId: seqId }; | ||
cachedVal = this.fetchCache[text]; | ||
if (cachedVal) { | ||
this.addCompletion(text, cachedVal); | ||
this.currentCompletion.completion = cachedVal.completion; | ||
return [2, cachedVal]; | ||
} | ||
if (!this.mockCompletion) return [3, 3]; | ||
completion_1 = this.mockCompletion(text); | ||
if (!completion_1) return [3, 2]; | ||
return [4, new Promise(function (resolve) { | ||
setTimeout(function () { | ||
var _a; | ||
var c = { input: text, sid: ulid(), completion: completion_1 }; | ||
_this.fetchCache[text] = c; | ||
if (((_a = _this.currentCompletion) === null || _a === void 0 ? void 0 : _a.sequenceId) === seqId) { | ||
_this.addCompletion(text, c); | ||
_this.currentCompletion.completion = completion_1; | ||
} | ||
resolve(c); | ||
}, getRandomInt(200, 1000)); | ||
})]; | ||
case 1: return [2, _c.sent()]; | ||
case 2: return [2, { input: text, sid: ulid(), completion: null }]; | ||
case 3: return [4, fetch('https://api.foundation-ui.com/completions', { | ||
method: 'POST', | ||
mode: 'cors', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
Authorization: "Bearer ".concat(this.modelId), | ||
}, | ||
body: JSON.stringify({ | ||
model: this.modelId, | ||
input: text, | ||
session: this.sessionId, | ||
context: context, | ||
}), | ||
})]; | ||
case 4: | ||
res = _c.sent(); | ||
if (res.status !== 200) { | ||
console.error("Couldn't fetch completions"); | ||
return [2, null]; | ||
} | ||
return [4, res.json()]; | ||
case 5: | ||
data = (_c.sent()); | ||
this.fetchCache[text] = data; | ||
if (((_b = this.currentCompletion) === null || _b === void 0 ? void 0 : _b.sequenceId) === seqId) { | ||
this.addCompletion(text, data); | ||
this.currentCompletion.completion = data.completion; | ||
} | ||
return [2, data]; | ||
} | ||
return; | ||
} | ||
fetch('https://api.lydian.company/app/events', { | ||
}); | ||
}); }, 200); | ||
this.sendEvents = throttle(function (text, context) { | ||
fetch('https://api.foundation-ui.com/events', { | ||
method: 'POST', | ||
@@ -44,3 +135,3 @@ mode: 'cors', | ||
model: _this.modelId, | ||
session: '' + Date.now(), | ||
session: _this.sessionId, | ||
input: text, | ||
@@ -52,18 +143,43 @@ context: context, | ||
if (res.status !== 200) { | ||
console.error("Couldn't fetch suggestions"); | ||
return; | ||
console.error('Error sending events'); | ||
} | ||
return res.json(); | ||
}) | ||
.then(function (data) { | ||
var _a; | ||
var suggestion = (data === null || data === void 0 ? void 0 : data.suggestion) || ''; | ||
if (suggestion && ((_a = _this.pendingCompletion) === null || _a === void 0 ? void 0 : _a.sequenceId) === seqId) { | ||
_this.addSuggestion(text, suggestion); | ||
_this.pendingCompletion.suggestion = suggestion; | ||
} | ||
}) | ||
.catch(function (e) { return console.error(e); }); | ||
}, 200); | ||
}, 1000, { trailing: true }); | ||
} | ||
SmartInputFetcher.prototype.updateCompletion = function (completionSid, arg) { | ||
var _this = this; | ||
if (this.mockCompletion) { | ||
return; | ||
} | ||
var shouldUpdate = (arg.seen && !this.alreadySeen.has(completionSid)) || (arg.accepted && !this.alreadyAccepted.has(completionSid)); | ||
if (!shouldUpdate) { | ||
return; | ||
} | ||
fetch('https://api.foundation-ui.com/completions', { | ||
method: 'PUT', | ||
mode: 'cors', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
Authorization: "Bearer ".concat(this.modelId), | ||
}, | ||
body: JSON.stringify({ | ||
completionSid: completionSid, | ||
seen: arg.seen, | ||
accepted: arg.accepted, | ||
}), | ||
}) | ||
.then(function (res) { | ||
if (res.status !== 200) { | ||
console.error("Couldn't update completion"); | ||
} | ||
if (arg.seen) { | ||
_this.alreadySeen.add(completionSid); | ||
} | ||
if (arg.accepted) { | ||
_this.alreadyAccepted.add(completionSid); | ||
} | ||
}) | ||
.catch(function (e) { return console.error(e); }); | ||
}; | ||
return SmartInputFetcher; | ||
@@ -77,15 +193,2 @@ }()); | ||
} | ||
var debounce = function (callback, wait) { | ||
var timeoutId = null; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
window.clearTimeout(timeoutId); | ||
timeoutId = window.setTimeout(function () { | ||
callback.apply(null, args); | ||
}, wait); | ||
}; | ||
}; | ||
//# sourceMappingURL=SmartInputFetcher.js.map |
{ | ||
"name": "@foundationui/smart-input", | ||
"version": "1.0.9", | ||
"version": "1.0.10", | ||
"description": "Smart input/textarea component for React. Learns to provide inline, tab-completeable suggestions.", | ||
@@ -37,2 +37,4 @@ "main": "lib/cjs/index.js", | ||
"devDependencies": { | ||
"@types/lodash.debounce": "^4.0.7", | ||
"@types/lodash.throttle": "^4.1.7", | ||
"@types/react": "^18.0.26", | ||
@@ -46,5 +48,8 @@ "@types/react-dom": "^18.0.10", | ||
"dependencies": { | ||
"lodash.debounce": "^4.0.8", | ||
"lodash.throttle": "^4.1.1", | ||
"slate": "^0.87.0", | ||
"slate-history": "^0.86.0", | ||
"slate-react": "^0.88.0" | ||
"slate-react": "^0.88.0", | ||
"ulid": "^2.3.0" | ||
}, | ||
@@ -51,0 +56,0 @@ "prettier": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
80660
27
1022
8
8
6
+ Addedlodash.debounce@^4.0.8
+ Addedlodash.throttle@^4.1.1
+ Addedulid@^2.3.0
+ Addedlodash.debounce@4.0.8(transitive)
+ Addedlodash.throttle@4.1.1(transitive)
+ Addedulid@2.3.0(transitive)