New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@foundationui/smart-input

Package Overview
Dependencies
Maintainers
1
Versions
100
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@foundationui/smart-input - npm Package Compare versions

Comparing version 1.0.9 to 1.0.10

lib/cjs/ICompletionResponse.d.ts

6

lib/cjs/SmartInput.d.ts

@@ -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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc