From e0e8cf698adba41508da9354320b1ab31cd4b77c Mon Sep 17 00:00:00 2001 From: Andy Zhang Date: Mon, 12 Feb 2024 11:50:46 -0800 Subject: [PATCH 01/28] Show scrollbar --- src/components/CodeiumEditor/CodeiumEditor.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/CodeiumEditor/CodeiumEditor.tsx b/src/components/CodeiumEditor/CodeiumEditor.tsx index d532f17..f3e325d 100644 --- a/src/components/CodeiumEditor/CodeiumEditor.tsx +++ b/src/components/CodeiumEditor/CodeiumEditor.tsx @@ -174,7 +174,6 @@ export const CodeiumEditor: React.FC = ({ scrollBeyondLastColumn: 0, scrollbar: { alwaysConsumeMouseWheel: false, - vertical: "hidden", }, codeLens: false, // for resizing, but apparently might have "severe performance impact" From c25e67210d4c34a092f294b8de2098160d2c5061 Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Mon, 12 Feb 2024 17:20:57 -0800 Subject: [PATCH 02/28] Fix metadata --- .../CodeiumEditor/CompletionProvider.ts | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/components/CodeiumEditor/CompletionProvider.ts b/src/components/CodeiumEditor/CompletionProvider.ts index d79be15..faf426b 100644 --- a/src/components/CodeiumEditor/CompletionProvider.ts +++ b/src/components/CodeiumEditor/CompletionProvider.ts @@ -52,7 +52,6 @@ const EDITOR_API_KEY = "d49954eb-cfba-4992-980f-d8fb37f0e942"; * CompletionProvider class for Codeium. */ export class MonacoCompletionProvider { - authHeader: Record = {}; private client: PromiseClient; private sessionId: string; @@ -64,22 +63,26 @@ export class MonacoCompletionProvider { ) { this.sessionId = `react-editor-${uuid()}`; this.client = grpcClient; + } - const Authorization = `Basic ${this.getMetadata().apiKey}-${ - this.sessionId - }`; - this.authHeader = { Authorization }; + private getAuthHeader() { + const metadata = this.getMetadata(); + const headers = { + Authorization: `Basic ${metadata.apiKey}-${metadata.sessionId}`, + }; + return headers; } private getMetadata(): Metadata { - return new Metadata({ + const metadata = new Metadata({ ideName: "web", ideVersion: getCurrentURL() ?? "unknown", extensionName: "@codeium/react-code-editor", extensionVersion: getPackageVersion() ?? "unknown", apiKey: this.apiKey ?? EDITOR_API_KEY, - sessionId: `demo-${uuid()}`, + sessionId: this.sessionId, }); + return metadata; } /** @@ -130,7 +133,7 @@ export class MonacoCompletionProvider { }, { signal, - headers: this.authHeader, + headers: this.getAuthHeader(), } ); } catch (err) { @@ -185,7 +188,7 @@ export class MonacoCompletionProvider { completionId: completionId, }, { - headers: this.authHeader, + headers: this.getAuthHeader(), } ) .then(resolve) From af93615b3fd8f75c4b951b994ba25ff165f2efdc Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Mon, 12 Feb 2024 16:33:40 -0800 Subject: [PATCH 03/28] Language parsed for each request --- .../CodeiumEditor/CodeiumEditor.tsx | 5 +- .../CodeiumEditor/CompletionProvider.ts | 14 +- src/components/CodeiumEditor/types.ts | 18 +++ src/index.ts | 1 + src/models/index.ts | 1 + src/utils/language.ts | 141 ++++++++++++++++++ 6 files changed, 172 insertions(+), 8 deletions(-) create mode 100644 src/models/index.ts create mode 100644 src/utils/language.ts diff --git a/src/components/CodeiumEditor/CodeiumEditor.tsx b/src/components/CodeiumEditor/CodeiumEditor.tsx index d532f17..aabe97b 100644 --- a/src/components/CodeiumEditor/CodeiumEditor.tsx +++ b/src/components/CodeiumEditor/CodeiumEditor.tsx @@ -32,6 +32,7 @@ export interface CodeiumEditorProps extends EditorProps { * The layout by default is width = 100% and height = 300px. These values can be overridden by passing in a string value to the width and/or height props. */ export const CodeiumEditor: React.FC = ({ + language, languageServerAddress = "https://web-backend.codeium.com", ...props }) => { @@ -133,8 +134,8 @@ export const CodeiumEditor: React.FC = ({ }; let defaultLanguageProps: EditorProps = { - defaultLanguage: props.language, - defaultValue: getDefaultValue(props.language), + defaultLanguage: language, + defaultValue: getDefaultValue(language), }; const layout = { diff --git a/src/components/CodeiumEditor/CompletionProvider.ts b/src/components/CodeiumEditor/CompletionProvider.ts index faf426b..3750dc5 100644 --- a/src/components/CodeiumEditor/CompletionProvider.ts +++ b/src/components/CodeiumEditor/CompletionProvider.ts @@ -19,11 +19,8 @@ import { } from "../../api/proto/exa/codeium_common_pb/codeium_common_pb"; import { Status } from "./Status"; import { uuid } from "../../utils/uuid"; -import { - getBrowserVersion, - getCurrentURL, - getPackageVersion, -} from "../../utils/identity"; +import { getCurrentURL, getPackageVersion } from "../../utils/identity"; +import { languageIdToEnum } from "../../utils/language"; class MonacoInlineCompletion implements monaco.languages.InlineCompletion { readonly insertText: string; @@ -214,10 +211,15 @@ export class MonacoCompletionProvider { const numCodeUnits = document.offsetAt(position); const offset = numCodeUnitsToNumUtf8Bytes(text, numCodeUnits); + const language = languageIdToEnum(document.languageId); + if (language === Language.UNSPECIFIED) { + console.warn(`Unknown language: ${document.languageId}`); + } + const documentInfo = new DocumentInfo({ text: text, editorLanguage: document.languageId, - language: Language.PYTHON, + language, cursorOffset: BigInt(offset), lineEnding: "\n", }); diff --git a/src/components/CodeiumEditor/types.ts b/src/components/CodeiumEditor/types.ts index 24d695c..00c70fa 100644 --- a/src/components/CodeiumEditor/types.ts +++ b/src/components/CodeiumEditor/types.ts @@ -2,6 +2,7 @@ import { Completion, CompletionSource, } from "../../api/proto/exa/codeium_common_pb/codeium_common_pb"; +import { Language } from "../../models"; export type CompletionAndRange = { completion: Completion; @@ -23,3 +24,20 @@ export type CompletionsAndMetadata = { promptId: string; timestamp: number; }; + +export type Document = { + /** + * The absolute path of the document. + */ + absolutePath: string; + + /** + * The document content. + */ + text: string; + + /** + * Language of the document. + */ + language: Language; +}; diff --git a/src/index.ts b/src/index.ts index 40b494c..1c439a0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,2 @@ export * from "./components"; +export * from "./models"; diff --git a/src/models/index.ts b/src/models/index.ts new file mode 100644 index 0000000..4518cb0 --- /dev/null +++ b/src/models/index.ts @@ -0,0 +1 @@ +export { Language } from "../api/proto/exa/codeium_common_pb/codeium_common_pb"; diff --git a/src/utils/language.ts b/src/utils/language.ts new file mode 100644 index 0000000..0e38261 --- /dev/null +++ b/src/utils/language.ts @@ -0,0 +1,141 @@ +import { Language } from "../models"; + +/** + * Converts a language ID to a strongly-typed enum value. + */ +export const languageIdToEnum = (languageId: string): Language => { + switch (languageId.toLowerCase()) { + case "c": + return Language.C; + case "clojure": + return Language.CLOJURE; + case "coffeescript": + return Language.COFFEESCRIPT; + case "cpp": + return Language.CPP; + case "csharp": + return Language.CSHARP; + case "css": + return Language.CSS; + case "cudacpp": + return Language.CUDACPP; + case "dockerfile": + return Language.DOCKERFILE; + case "go": + return Language.GO; + case "groovy": + return Language.GROOVY; + case "handlebars": + return Language.HANDLEBARS; + case "haskell": + return Language.HASKELL; + case "hcl": + return Language.HCL; + case "html": + return Language.HTML; + case "ini": + return Language.INI; + case "java": + return Language.JAVA; + case "javascript": + return Language.JAVASCRIPT; + case "json": + return Language.JSON; + case "julia": + return Language.JULIA; + case "kotlin": + return Language.KOTLIN; + case "latex": + return Language.LATEX; + case "less": + return Language.LESS; + case "lua": + return Language.LUA; + case "makefile": + return Language.MAKEFILE; + case "markdown": + return Language.MARKDOWN; + case "objectivec": + return Language.OBJECTIVEC; + case "objectivecpp": + return Language.OBJECTIVECPP; + case "perl": + return Language.PERL; + case "php": + return Language.PHP; + case "plaintext": + return Language.PLAINTEXT; + case "protobuf": + return Language.PROTOBUF; + case "pbtxt": + return Language.PBTXT; + case "python": + return Language.PYTHON; + case "r": + return Language.R; + case "ruby": + return Language.RUBY; + case "rust": + return Language.RUST; + case "sass": + return Language.SASS; + case "scala": + return Language.SCALA; + case "scss": + return Language.SCSS; + case "shell": + return Language.SHELL; + case "sql": + return Language.SQL; + case "starlark": + return Language.STARLARK; + case "swift": + return Language.SWIFT; + case "tsx": + return Language.TSX; + case "typescript": + return Language.TYPESCRIPT; + case "visualbasic": + return Language.VISUALBASIC; + case "vue": + return Language.VUE; + case "xml": + return Language.XML; + case "xsl": + return Language.XSL; + case "yaml": + return Language.YAML; + case "svelte": + return Language.SVELTE; + case "toml": + return Language.TOML; + case "dart": + return Language.DART; + case "rst": + return Language.RST; + case "ocaml": + return Language.OCAML; + case "cmake": + return Language.CMAKE; + case "pascal": + return Language.PASCAL; + case "elixir": + return Language.ELIXIR; + case "fsharp": + return Language.FSHARP; + case "lisp": + return Language.LISP; + case "matlab": + return Language.MATLAB; + case "powershell": + return Language.POWERSHELL; + case "solidity": + return Language.SOLIDITY; + case "ada": + return Language.ADA; + case "ocaml_interface": + return Language.OCAML_INTERFACE; + default: + return Language.UNSPECIFIED; + } +}; From 6722c1ae16f2aefe2b213bff6945eeb2efc9b826 Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Mon, 12 Feb 2024 16:34:38 -0800 Subject: [PATCH 04/28] Revert unneeded changes --- src/components/CodeiumEditor/CodeiumEditor.tsx | 5 ++--- src/components/CodeiumEditor/types.ts | 18 ------------------ 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/components/CodeiumEditor/CodeiumEditor.tsx b/src/components/CodeiumEditor/CodeiumEditor.tsx index aabe97b..d532f17 100644 --- a/src/components/CodeiumEditor/CodeiumEditor.tsx +++ b/src/components/CodeiumEditor/CodeiumEditor.tsx @@ -32,7 +32,6 @@ export interface CodeiumEditorProps extends EditorProps { * The layout by default is width = 100% and height = 300px. These values can be overridden by passing in a string value to the width and/or height props. */ export const CodeiumEditor: React.FC = ({ - language, languageServerAddress = "https://web-backend.codeium.com", ...props }) => { @@ -134,8 +133,8 @@ export const CodeiumEditor: React.FC = ({ }; let defaultLanguageProps: EditorProps = { - defaultLanguage: language, - defaultValue: getDefaultValue(language), + defaultLanguage: props.language, + defaultValue: getDefaultValue(props.language), }; const layout = { diff --git a/src/components/CodeiumEditor/types.ts b/src/components/CodeiumEditor/types.ts index 00c70fa..24d695c 100644 --- a/src/components/CodeiumEditor/types.ts +++ b/src/components/CodeiumEditor/types.ts @@ -2,7 +2,6 @@ import { Completion, CompletionSource, } from "../../api/proto/exa/codeium_common_pb/codeium_common_pb"; -import { Language } from "../../models"; export type CompletionAndRange = { completion: Completion; @@ -24,20 +23,3 @@ export type CompletionsAndMetadata = { promptId: string; timestamp: number; }; - -export type Document = { - /** - * The absolute path of the document. - */ - absolutePath: string; - - /** - * The document content. - */ - text: string; - - /** - * Language of the document. - */ - language: Language; -}; From 90c1515a7eb8b5421e6b0217f8e7bec799550009 Mon Sep 17 00:00:00 2001 From: Andy Zhang Date: Mon, 12 Feb 2024 18:34:13 -0800 Subject: [PATCH 05/28] Readme to make it clear it's a component --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 1150cd7..4993ef4 100644 --- a/readme.md +++ b/readme.md @@ -4,7 +4,7 @@ [![NPM](https://nodei.co/npm/@codeium/react-code-editor.png?downloads=true)](https://www.npmjs.com/package/@codeium/react-code-editor) -Codeium React Editor is a free, open-source code editor with unlimited AI autocomplete. Brought to you by the team at [Codeium](https://www.codeium.com/). **Free with no account required.**. All you need to do is install our NPM package and you're good to go! +Codeium React Editor is a free, open-source code editor component with unlimited AI autocomplete. Add it to any React project in just a few lines of code. Brought to you by the team at [Codeium](https://www.codeium.com/). **Free with no account required.**. All you need to do is install our NPM package, add it to your website and you're good to go! ![codeium demo](docs/codeium_playground.gif) From f65c7b500670491462f16caed92b4f269da55efe Mon Sep 17 00:00:00 2001 From: Andy Zhang Date: Mon, 12 Feb 2024 18:35:33 -0800 Subject: [PATCH 06/28] Edit copy --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 4993ef4..6f2c368 100644 --- a/readme.md +++ b/readme.md @@ -4,7 +4,7 @@ [![NPM](https://nodei.co/npm/@codeium/react-code-editor.png?downloads=true)](https://www.npmjs.com/package/@codeium/react-code-editor) -Codeium React Editor is a free, open-source code editor component with unlimited AI autocomplete. Add it to any React project in just a few lines of code. Brought to you by the team at [Codeium](https://www.codeium.com/). **Free with no account required.**. All you need to do is install our NPM package, add it to your website and you're good to go! +Codeium React Code Editor is a free, open-source code editor as a React component with unlimited AI autocomplete. Brought to you by the team at [Codeium](https://www.codeium.com/). **Free with no account required.**. All you need to do is install our NPM package, add it to your website and you're good to go! ![codeium demo](docs/codeium_playground.gif) From 518b55cdf0093ad3fd9f980bc1bb5039ed707217 Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Mon, 12 Feb 2024 16:47:14 -0800 Subject: [PATCH 07/28] Enable passing in other documents as context --- src/components/CodeiumEditor/CodeiumEditor.tsx | 14 ++++++++++++++ src/components/CodeiumEditor/CompletionProvider.ts | 14 ++++++++++++++ .../CodeiumEditor/InlineCompletionProvider.ts | 6 ++++++ src/models/index.ts | 1 + 4 files changed, 35 insertions(+) diff --git a/src/components/CodeiumEditor/CodeiumEditor.tsx b/src/components/CodeiumEditor/CodeiumEditor.tsx index d532f17..8236670 100644 --- a/src/components/CodeiumEditor/CodeiumEditor.tsx +++ b/src/components/CodeiumEditor/CodeiumEditor.tsx @@ -11,6 +11,7 @@ import { getDefaultValue } from "./defaultValues"; import { LanguageServerService } from "../../api/proto/exa/language_server_pb/language_server_connect"; import { InlineCompletionProvider } from "./InlineCompletionProvider"; import { CodeiumLogo } from "../CodeiumLogo/CodeiumLogo"; +import { Document } from "../../models"; export interface CodeiumEditorProps extends EditorProps { language: string; @@ -25,6 +26,13 @@ export interface CodeiumEditorProps extends EditorProps { * to Codeium's language server. */ languageServerAddress?: string; + + /** + * Optional list of other documents in the workspace. This can be used to provide additional + * context to Codeium beyond simply the current document. There is a limit of 10 medium sized + * documents. + */ + otherDocuments?: Document[]; } /** @@ -33,6 +41,7 @@ export interface CodeiumEditorProps extends EditorProps { */ export const CodeiumEditor: React.FC = ({ languageServerAddress = "https://web-backend.codeium.com", + otherDocuments = [], ...props }) => { const editorRef = useRef(null); @@ -132,6 +141,11 @@ export const CodeiumEditor: React.FC = ({ } }; + // Keep other documents up to date. + useEffect(() => { + inlineCompletionsProviderRef.current?.updateOtherDocuments(otherDocuments); + }, [otherDocuments]); + let defaultLanguageProps: EditorProps = { defaultLanguage: props.language, defaultValue: getDefaultValue(props.language), diff --git a/src/components/CodeiumEditor/CompletionProvider.ts b/src/components/CodeiumEditor/CompletionProvider.ts index 3750dc5..d28bb52 100644 --- a/src/components/CodeiumEditor/CompletionProvider.ts +++ b/src/components/CodeiumEditor/CompletionProvider.ts @@ -52,6 +52,11 @@ export class MonacoCompletionProvider { private client: PromiseClient; private sessionId: string; + /** + * A list of other documents to include as context in the prompt. + */ + public otherDocuments: DocumentInfo[] = []; + constructor( grpcClient: PromiseClient, readonly setStatus: (status: Status) => void, @@ -119,6 +124,14 @@ export class MonacoCompletionProvider { insertSpaces: model.getOptions().insertSpaces, }; + let includedOtherDocs = this.otherDocuments; + if (includedOtherDocs.length > 10) { + console.warn( + `Too many other documents: ${includedOtherDocs.length} (max 10)` + ); + includedOtherDocs = includedOtherDocs.slice(0, 10); + } + // Get completions. let getCompletionsResponse: GetCompletionsResponse; try { @@ -127,6 +140,7 @@ export class MonacoCompletionProvider { metadata: this.getMetadata(), document: documentInfo, editorOptions: editorOptions, + otherDocuments: includedOtherDocs, }, { signal, diff --git a/src/components/CodeiumEditor/InlineCompletionProvider.ts b/src/components/CodeiumEditor/InlineCompletionProvider.ts index 445e3b9..7c87e87 100644 --- a/src/components/CodeiumEditor/InlineCompletionProvider.ts +++ b/src/components/CodeiumEditor/InlineCompletionProvider.ts @@ -1,4 +1,5 @@ import * as monaco from "monaco-editor/esm/vs/editor/editor.api"; +import { Document as DocumentInfo } from "../../api/proto/exa/language_server_pb/language_server_pb"; import { Dispatch, SetStateAction } from "react"; import { PromiseClient } from "@connectrpc/connect"; import { Status } from "./Status"; @@ -18,6 +19,7 @@ export class InlineCompletionProvider { private numCompletionsProvided: number; readonly completionProvider: MonacoCompletionProvider; + constructor( grpcClient: PromiseClient, readonly setCompletionCount: Dispatch>, @@ -63,4 +65,8 @@ export class InlineCompletionProvider public acceptedLastCompletion(completionId: string) { this.completionProvider.acceptedLastCompletion(completionId); } + + public updateOtherDocuments(otherDocuments: DocumentInfo[]) { + this.completionProvider.otherDocuments = otherDocuments; + } } diff --git a/src/models/index.ts b/src/models/index.ts index 4518cb0..586fc62 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -1 +1,2 @@ export { Language } from "../api/proto/exa/codeium_common_pb/codeium_common_pb"; +export { Document } from "../api/proto/exa/language_server_pb/language_server_pb"; From 5d8bb0b1b3d9455090d6158bda8b9c622d2b8ecb Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Mon, 12 Feb 2024 17:08:30 -0800 Subject: [PATCH 08/28] Updating the story --- ...r.stories.ts => CodeiumEditor.stories.tsx} | 89 ++++++++++++++++--- 1 file changed, 75 insertions(+), 14 deletions(-) rename src/stories/{CodeiumEditor.stories.ts => CodeiumEditor.stories.tsx} (62%) diff --git a/src/stories/CodeiumEditor.stories.ts b/src/stories/CodeiumEditor.stories.tsx similarity index 62% rename from src/stories/CodeiumEditor.stories.ts rename to src/stories/CodeiumEditor.stories.tsx index 3edbd02..7404227 100644 --- a/src/stories/CodeiumEditor.stories.ts +++ b/src/stories/CodeiumEditor.stories.tsx @@ -1,6 +1,8 @@ import type { Meta, StoryObj } from "@storybook/react"; +import React from "react"; import { CodeiumEditor } from "../components"; +import { Document, Language } from "../models"; // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export const meta: Meta = { @@ -20,9 +22,9 @@ export default meta; type Story = StoryObj; const baseParams = { - width: "700px", - height: "500px", -} + width: "700px", + height: "500px", +}; const PYTHON_SNIPPET = `# Need inspiration? Try adding extra constraints or context to this parse json function! # Or scratch everything and use your imagination. @@ -30,14 +32,14 @@ const PYTHON_SNIPPET = `# Need inspiration? Try adding extra constraints or cont def parse_json_lines(filename: str) -> List[Any]: output = [] with open(filename, "r", encoding="utf-8") as f: -` +`; // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args export const PythonEditor: Story = { args: { ...baseParams, language: "python", - value: PYTHON_SNIPPET + value: PYTHON_SNIPPET, }, }; @@ -47,13 +49,13 @@ const JAVASCRIPT_SNIPPET = ` // Convert HTML string to DOM object function parseStringAsHtml(content, selector) { -` +`; export const JavaScriptEditor: Story = { args: { ...baseParams, language: "javascript", - value: JAVASCRIPT_SNIPPET + value: JAVASCRIPT_SNIPPET, }, }; @@ -70,12 +72,12 @@ import ( func main() { // Configure log and create a new logger -` +`; export const GoEditor: Story = { args: { ...baseParams, language: "go", - value: GO_SNIPPET + value: GO_SNIPPET, }, }; @@ -88,17 +90,16 @@ const JAVA_SNIPPET = ` * @return ArrayList of all visible widgets */ public ArrayList getVisibleWidgets() { -` +`; export const JavaEditor: Story = { args: { ...baseParams, language: "java", - value: JAVA_SNIPPET + value: JAVA_SNIPPET, }, }; - const CPP_SNIPPET = ` // Need inspiration? Try finishing this Matrix class with constructors, // destructors, getter/setters, utilities like transpose, etc. @@ -109,13 +110,73 @@ template class Matrix() { public: Matrix(int rows, int cols) { -` +`; export const CppEditor: Story = { args: { ...baseParams, language: "cpp", - value: CPP_SNIPPET + value: CPP_SNIPPET, + }, +}; + +const HTML_SNIPPET = ` + + Contact Form + + +

Contact Form

+

I'm a simple contact form.

+ +
+ + + + + +
+ + +`; + +export const HTMLEditor: Story = { + args: { + ...baseParams, + language: "html", + value: HTML_SNIPPET, }, }; +export const MultiFileContext: Story = { + decorators: (Story) => ( +
+

Multi File Context

+

+ Neighboring file at index.html passed into the{" "} + otherDocuments property: +

+ +
{HTML_SNIPPET}
+
+
+

Context Aware Editor

+ +
+
+ ), + args: { + ...baseParams, + language: "javascript", + value: `// You have context over a sample HTML page. +// Codeium's generation will take this context into account when suggesting.`, + otherDocuments: [ + new Document({ + absolutePath: "/index.html", + relativePath: "/index.html", + text: HTML_SNIPPET, + editorLanguage: "html", + language: Language.HTML, + }), + ], + }, +}; From bac6de2fe0420acac62cb56d9fb3d90eafdd7db1 Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Mon, 12 Feb 2024 18:36:21 -0800 Subject: [PATCH 09/28] Minor tweaks --- src/components/CodeiumEditor/CompletionProvider.ts | 4 ++++ src/stories/CodeiumEditor.stories.tsx | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/CodeiumEditor/CompletionProvider.ts b/src/components/CodeiumEditor/CompletionProvider.ts index d28bb52..91e0ad9 100644 --- a/src/components/CodeiumEditor/CompletionProvider.ts +++ b/src/components/CodeiumEditor/CompletionProvider.ts @@ -131,6 +131,10 @@ export class MonacoCompletionProvider { ); includedOtherDocs = includedOtherDocs.slice(0, 10); } + console.log( + `Included other documents: ${includedOtherDocs.length}`, + includedOtherDocs.map((d) => d.toJson()) + ); // Get completions. let getCompletionsResponse: GetCompletionsResponse; diff --git a/src/stories/CodeiumEditor.stories.tsx b/src/stories/CodeiumEditor.stories.tsx index 7404227..11f97b2 100644 --- a/src/stories/CodeiumEditor.stories.tsx +++ b/src/stories/CodeiumEditor.stories.tsx @@ -168,11 +168,13 @@ export const MultiFileContext: Story = { ...baseParams, language: "javascript", value: `// You have context over a sample HTML page. -// Codeium's generation will take this context into account when suggesting.`, +// Codeium's generation will take this context into account when suggesting. + +// Get the contact form values by ID.`, otherDocuments: [ new Document({ absolutePath: "/index.html", - relativePath: "/index.html", + relativePath: "index.html", text: HTML_SNIPPET, editorLanguage: "html", language: Language.HTML, From 7f7dde477706dd800b4f15d17797e8cb79c102eb Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Mon, 12 Feb 2024 23:21:00 -0800 Subject: [PATCH 10/28] Update readme with usage example --- readme.md | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 1150cd7..5fd824e 100644 --- a/readme.md +++ b/readme.md @@ -47,6 +47,45 @@ export const IdeWithAutocomplete = () => { }; ``` +Here's an advanced example that uses multi-document context to provide more intelligent autocompletion: + +```tsx +import { CodeiumEditor, Document, Language } from "@codeium/react-code-editor"; + +export const JavascriptEditorWithContext = () => { + const html = ` + +

Contact Us

+
+ + + + +
+ +`; + + return ( +
+

This editor has context awareness of a neighboring HTML file and can provide better autocompletion suggestions.

+ +
+ ); +}; +``` + ### Examples Here are some examples of Codeium React Editor used in production: @@ -70,12 +109,13 @@ The core API of the editor is the same as that of the wrapped project. You can v ## FAQ #### How can I import the ESM version of this? + To import the ESM version of this, you can use `import { CodeiumEditor } from "@codeium/react-code-editor/dist/esm";`. If you're using TypeScript, your editor might warn that the types are missing. A current workaround is: + - Create a `codeiumeditor.d.ts` file, - Add `declare module '@codeium/react-code-editor/dist/esm';` to the file - Import the types file in the file using the `CodeiumEditor` component. - This is an open issue in terms of supporting both CommonJS and ESM. If you're interested in contributing and have a fix for this, pull requests are welcome. ## Acknowledgements From c85f47e7a37fd394eeeb7d2841907dad4b752887 Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Tue, 13 Feb 2024 10:30:54 -0800 Subject: [PATCH 11/28] Update readme --- readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 5fd824e..e765e37 100644 --- a/readme.md +++ b/readme.md @@ -52,7 +52,7 @@ Here's an advanced example that uses multi-document context to provide more inte ```tsx import { CodeiumEditor, Document, Language } from "@codeium/react-code-editor"; -export const JavascriptEditorWithContext = () => { +export const JavaScriptEditorWithContext = () => { const html = `

Contact Us

@@ -86,6 +86,8 @@ export const JavascriptEditorWithContext = () => { }; ``` +Note that the `otherDocuments` prop has a limit of 10 documents. Within those documents, Codeium will run a reranker behind the scenes to optimize what is included in the token limit. + ### Examples Here are some examples of Codeium React Editor used in production: From 84ac52cebd891c7f993421bad7c25c73cca98eaa Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Tue, 13 Feb 2024 10:34:33 -0800 Subject: [PATCH 12/28] Add prettier script --- .prettierrc | 6 ++++++ package.json | 2 ++ pnpm-lock.yaml | 9 +++++++++ 3 files changed, 17 insertions(+) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..7766217 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "semi": false, + "singleQuote": true, + "tabWidth": 2, + "printWidth": 80 +} \ No newline at end of file diff --git a/package.json b/package.json index 1847eed..5e907c5 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "test": "echo \"Error: no test specified\" && exit 1", "storybook": "storybook dev -p 6006 --no-open", "build-storybook": "storybook build", + "format": "prettier --write 'src/**/*.{ts,tsx}'", "prepare": "npm run rollup" }, "repository": { @@ -50,6 +51,7 @@ "@storybook/test": "^7.6.4", "@swc/core": "^1.3.104", "@types/react": "^18.2.42", + "prettier": "^3.2.5", "rollup": "^4.7.0", "rollup-plugin-banner2": "^1.2.2", "rollup-plugin-dts": "^6.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4193b4e..e66840d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -73,6 +73,9 @@ devDependencies: '@types/react': specifier: ^18.2.42 version: 18.2.42 + prettier: + specifier: ^3.2.5 + version: 3.2.5 rollup: specifier: ^4.7.0 version: 4.7.0 @@ -6603,6 +6606,12 @@ packages: hasBin: true dev: true + /prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + engines: {node: '>=14'} + hasBin: true + dev: true + /pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} From 93cc31d11513439415276756d537611e4af02d2c Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Tue, 13 Feb 2024 10:35:34 -0800 Subject: [PATCH 13/28] Run format --- .prettierrc | 2 +- .../CodeiumEditor/CodeiumEditor.tsx | 60 ++++---- .../CodeiumEditor/CompletionProvider.ts | 77 +++++----- src/components/CodeiumEditor/Document.ts | 14 +- .../CodeiumEditor/InlineCompletionProvider.ts | 24 ++-- src/components/CodeiumEditor/Line.ts | 2 +- src/components/CodeiumEditor/Location.ts | 4 +- src/components/CodeiumEditor/Status.ts | 10 +- src/components/CodeiumEditor/defaultValues.ts | 14 +- src/components/CodeiumEditor/types.ts | 2 +- src/components/CodeiumLogo/CodeiumLogo.tsx | 16 +-- src/components/index.ts | 2 +- src/index.ts | 4 +- src/models/index.ts | 4 +- src/stories/CodeiumEditor.stories.tsx | 40 +++--- src/utils/identity.ts | 2 +- src/utils/language.ts | 132 +++++++++--------- src/utils/utf.ts | 4 +- src/utils/uuid.ts | 4 +- 19 files changed, 210 insertions(+), 207 deletions(-) diff --git a/.prettierrc b/.prettierrc index 7766217..5a58802 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,5 @@ { - "semi": false, + "semi": true, "singleQuote": true, "tabWidth": 2, "printWidth": 80 diff --git a/src/components/CodeiumEditor/CodeiumEditor.tsx b/src/components/CodeiumEditor/CodeiumEditor.tsx index 8236670..a3928eb 100644 --- a/src/components/CodeiumEditor/CodeiumEditor.tsx +++ b/src/components/CodeiumEditor/CodeiumEditor.tsx @@ -1,17 +1,17 @@ -"use client"; +'use client'; -import React, { useEffect, useRef, useState, useMemo } from "react"; -import { createConnectTransport } from "@connectrpc/connect-web"; -import { createPromiseClient } from "@connectrpc/connect"; -import { Status } from "./Status"; -import Editor, { EditorProps, Monaco } from "@monaco-editor/react"; -import { editor } from "monaco-editor/esm/vs/editor/editor.api"; -import { getDefaultValue } from "./defaultValues"; +import React, { useEffect, useRef, useState, useMemo } from 'react'; +import { createConnectTransport } from '@connectrpc/connect-web'; +import { createPromiseClient } from '@connectrpc/connect'; +import { Status } from './Status'; +import Editor, { EditorProps, Monaco } from '@monaco-editor/react'; +import { editor } from 'monaco-editor/esm/vs/editor/editor.api'; +import { getDefaultValue } from './defaultValues'; -import { LanguageServerService } from "../../api/proto/exa/language_server_pb/language_server_connect"; -import { InlineCompletionProvider } from "./InlineCompletionProvider"; -import { CodeiumLogo } from "../CodeiumLogo/CodeiumLogo"; -import { Document } from "../../models"; +import { LanguageServerService } from '../../api/proto/exa/language_server_pb/language_server_connect'; +import { InlineCompletionProvider } from './InlineCompletionProvider'; +import { CodeiumLogo } from '../CodeiumLogo/CodeiumLogo'; +import { Document } from '../../models'; export interface CodeiumEditorProps extends EditorProps { language: string; @@ -40,19 +40,19 @@ export interface CodeiumEditorProps extends EditorProps { * The layout by default is width = 100% and height = 300px. These values can be overridden by passing in a string value to the width and/or height props. */ export const CodeiumEditor: React.FC = ({ - languageServerAddress = "https://web-backend.codeium.com", + languageServerAddress = 'https://web-backend.codeium.com', otherDocuments = [], ...props }) => { const editorRef = useRef(null); const monacoRef = useRef(null); const inlineCompletionsProviderRef = useRef( - null + null, ); const [acceptedCompletionCount, setAcceptedCompletionCount] = useState(-1); const [completionCount, setCompletionCount] = useState(0); const [codeiumStatus, setCodeiumStatus] = useState(Status.INACTIVE); - const [codeiumStatusMessage, setCodeiumStatusMessage] = useState(""); + const [codeiumStatusMessage, setCodeiumStatusMessage] = useState(''); const [mounted, setMounted] = useState(false); const transport = useMemo(() => { @@ -72,7 +72,7 @@ export const CodeiumEditor: React.FC = ({ setCompletionCount, setCodeiumStatus, setCodeiumStatusMessage, - props.apiKey + props.apiKey, ); }, []); @@ -88,11 +88,11 @@ export const CodeiumEditor: React.FC = ({ const providerDisposable = monaco.languages.registerInlineCompletionsProvider( - { pattern: "**" }, - inlineCompletionsProviderRef.current + { pattern: '**' }, + inlineCompletionsProviderRef.current, ); const completionDisposable = monaco.editor.registerCommand( - "codeium.acceptCompletion", + 'codeium.acceptCompletion', (_: unknown, completionId: string, insertText: string) => { try { if (props.onAutocomplete) { @@ -100,12 +100,12 @@ export const CodeiumEditor: React.FC = ({ } setAcceptedCompletionCount(acceptedCompletionCount + 1); inlineCompletionsProviderRef.current?.acceptedLastCompletion( - completionId + completionId, ); } catch (err) { - console.log("Err"); + console.log('Err'); } - } + }, ); return () => { @@ -122,7 +122,7 @@ export const CodeiumEditor: React.FC = ({ const handleEditorDidMount = async ( editor: editor.IStandaloneCodeEditor, - monaco: Monaco + monaco: Monaco, ) => { editorRef.current = editor; monacoRef.current = monaco; @@ -152,30 +152,30 @@ export const CodeiumEditor: React.FC = ({ }; const layout = { - width: props.width || "100%", + width: props.width || '100%', // The height is set to 300px by default. Otherwise, the editor when // rendered with the default value will not be visible. // The monaco editor's default height is 100% but it requires the user to // define a container with an explicit height. - height: props.height || "300px", + height: props.height || '300px', }; return (
= ({ scrollBeyondLastColumn: 0, scrollbar: { alwaysConsumeMouseWheel: false, - vertical: "hidden", + vertical: 'hidden', }, codeLens: false, // for resizing, but apparently might have "severe performance impact" @@ -202,7 +202,7 @@ export const CodeiumEditor: React.FC = ({ foldingImportsByDefault: false, links: false, fontSize: 14, - wordWrap: "on", + wordWrap: 'on', ...props.options, }} /> diff --git a/src/components/CodeiumEditor/CompletionProvider.ts b/src/components/CodeiumEditor/CompletionProvider.ts index 91e0ad9..b0df60e 100644 --- a/src/components/CodeiumEditor/CompletionProvider.ts +++ b/src/components/CodeiumEditor/CompletionProvider.ts @@ -1,26 +1,26 @@ -import { Code, ConnectError, PromiseClient } from "@connectrpc/connect"; -import { CancellationToken } from "./CancellationToken"; +import { Code, ConnectError, PromiseClient } from '@connectrpc/connect'; +import { CancellationToken } from './CancellationToken'; import { Document as DocumentInfo, GetCompletionsResponse, CompletionItem, -} from "../../api/proto/exa/language_server_pb/language_server_pb"; -import { Document } from "./Document"; -import { Position, Range } from "./Location"; +} from '../../api/proto/exa/language_server_pb/language_server_pb'; +import { Document } from './Document'; +import { Position, Range } from './Location'; import { numUtf8BytesToNumCodeUnits, numCodeUnitsToNumUtf8Bytes, -} from "../../utils/utf"; -import * as monaco from "monaco-editor/esm/vs/editor/editor.api"; -import { LanguageServerService } from "../../api/proto/exa/language_server_pb/language_server_connect"; +} from '../../utils/utf'; +import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; +import { LanguageServerService } from '../../api/proto/exa/language_server_pb/language_server_connect'; import { Language, Metadata, -} from "../../api/proto/exa/codeium_common_pb/codeium_common_pb"; -import { Status } from "./Status"; -import { uuid } from "../../utils/uuid"; -import { getCurrentURL, getPackageVersion } from "../../utils/identity"; -import { languageIdToEnum } from "../../utils/language"; +} from '../../api/proto/exa/codeium_common_pb/codeium_common_pb'; +import { Status } from './Status'; +import { uuid } from '../../utils/uuid'; +import { getCurrentURL, getPackageVersion } from '../../utils/identity'; +import { languageIdToEnum } from '../../utils/language'; class MonacoInlineCompletion implements monaco.languages.InlineCompletion { readonly insertText: string; @@ -38,13 +38,13 @@ class MonacoInlineCompletion implements monaco.languages.InlineCompletion { this.text = insertText; this.range = range; this.command = { - id: "codeium.acceptCompletion", - title: "Accept Completion", + id: 'codeium.acceptCompletion', + title: 'Accept Completion', arguments: [completionId, insertText], }; } } -const EDITOR_API_KEY = "d49954eb-cfba-4992-980f-d8fb37f0e942"; +const EDITOR_API_KEY = 'd49954eb-cfba-4992-980f-d8fb37f0e942'; /** * CompletionProvider class for Codeium. */ @@ -61,7 +61,7 @@ export class MonacoCompletionProvider { grpcClient: PromiseClient, readonly setStatus: (status: Status) => void, readonly setMessage: (message: string) => void, - readonly apiKey?: string | undefined + readonly apiKey?: string | undefined, ) { this.sessionId = `react-editor-${uuid()}`; this.client = grpcClient; @@ -77,10 +77,10 @@ export class MonacoCompletionProvider { private getMetadata(): Metadata { const metadata = new Metadata({ - ideName: "web", - ideVersion: getCurrentURL() ?? "unknown", - extensionName: "@codeium/react-code-editor", - extensionVersion: getPackageVersion() ?? "unknown", + ideName: 'web', + ideVersion: getCurrentURL() ?? 'unknown', + extensionName: '@codeium/react-code-editor', + extensionVersion: getPackageVersion() ?? 'unknown', apiKey: this.apiKey ?? EDITOR_API_KEY, sessionId: this.sessionId, }); @@ -97,7 +97,7 @@ export class MonacoCompletionProvider { public async provideInlineCompletions( model: monaco.editor.ITextModel, monacoPosition: monaco.Position, - token: CancellationToken + token: CancellationToken, ): Promise< | monaco.languages.InlineCompletions | undefined @@ -116,7 +116,7 @@ export class MonacoCompletionProvider { const signal = abortController.signal; this.setStatus(Status.PROCESSING); - this.setMessage("Generating completions..."); + this.setMessage('Generating completions...'); const documentInfo = this.getDocumentInfo(document, position); const editorOptions = { @@ -127,13 +127,13 @@ export class MonacoCompletionProvider { let includedOtherDocs = this.otherDocuments; if (includedOtherDocs.length > 10) { console.warn( - `Too many other documents: ${includedOtherDocs.length} (max 10)` + `Too many other documents: ${includedOtherDocs.length} (max 10)`, ); includedOtherDocs = includedOtherDocs.slice(0, 10); } console.log( `Included other documents: ${includedOtherDocs.length}`, - includedOtherDocs.map((d) => d.toJson()) + includedOtherDocs.map((d) => d.toJson()), ); // Get completions. @@ -149,7 +149,7 @@ export class MonacoCompletionProvider { { signal, headers: this.getAuthHeader(), - } + }, ); } catch (err) { // Handle cancellation. @@ -157,13 +157,13 @@ export class MonacoCompletionProvider { // cancelled } else { this.setStatus(Status.ERROR); - this.setMessage("Something went wrong; please try again."); + this.setMessage('Something went wrong; please try again.'); } return undefined; } if (!getCompletionsResponse.completionItems) { // TODO(nick): Distinguish warning / error states here. - const message = " No completions were generated"; + const message = ' No completions were generated'; this.setStatus(Status.SUCCESS); this.setMessage(message); return undefined; @@ -173,7 +173,7 @@ export class MonacoCompletionProvider { // Create inline completion items from completions. const inlineCompletionItems = completionItems .map((completionItem) => - this.createInlineCompletionItem(completionItem, document) + this.createInlineCompletionItem(completionItem, document), ) .filter((item) => !!item); @@ -204,11 +204,11 @@ export class MonacoCompletionProvider { }, { headers: this.getAuthHeader(), - } + }, ) .then(resolve) .catch((err) => { - console.log("Error: ", err); + console.log('Error: ', err); }); }); } @@ -222,7 +222,7 @@ export class MonacoCompletionProvider { */ private getDocumentInfo( document: Document, - position: Position + position: Position, ): DocumentInfo { // The offset is measured in bytes. const text = document.getText(); @@ -239,7 +239,7 @@ export class MonacoCompletionProvider { editorLanguage: document.languageId, language, cursorOffset: BigInt(offset), - lineEnding: "\n", + lineEnding: '\n', }); return documentInfo; @@ -254,7 +254,7 @@ export class MonacoCompletionProvider { */ private createInlineCompletionItem( completionItem: CompletionItem, - document: Document + document: Document, ): MonacoInlineCompletion | undefined { if (!completionItem.completion || !completionItem.range) { return undefined; @@ -263,17 +263,20 @@ export class MonacoCompletionProvider { // Create and return inlineCompletionItem. const text = document.getText(); const startPosition = document.positionAt( - numUtf8BytesToNumCodeUnits(text, Number(completionItem.range.startOffset)) + numUtf8BytesToNumCodeUnits( + text, + Number(completionItem.range.startOffset), + ), ); const endPosition = document.positionAt( - numUtf8BytesToNumCodeUnits(text, Number(completionItem.range.endOffset)) + numUtf8BytesToNumCodeUnits(text, Number(completionItem.range.endOffset)), ); const range = new Range(startPosition, endPosition); const inlineCompletionItem = new MonacoInlineCompletion( completionItem.completion.text, range, - completionItem.completion.completionId + completionItem.completion.completionId, ); return inlineCompletionItem; } diff --git a/src/components/CodeiumEditor/Document.ts b/src/components/CodeiumEditor/Document.ts index e384364..640d0a1 100644 --- a/src/components/CodeiumEditor/Document.ts +++ b/src/components/CodeiumEditor/Document.ts @@ -1,7 +1,7 @@ -import * as monaco from "monaco-editor/esm/vs/editor/editor.api"; +import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; -import { Position, Range } from "./Location"; -import { Line } from "./Line"; +import { Position, Range } from './Location'; +import { Line } from './Line'; export class Document { private model: monaco.editor.ITextModel; @@ -20,7 +20,7 @@ export class Document { } public lineAt(positionOrLine: Position | number): Line { - if (typeof positionOrLine !== "number") { + if (typeof positionOrLine !== 'number') { positionOrLine = positionOrLine.line; } return new Line( @@ -29,9 +29,9 @@ export class Document { new Position(positionOrLine, 0), new Position( positionOrLine, - this.model.getLineLength(positionOrLine + 1) - ) - ) + this.model.getLineLength(positionOrLine + 1), + ), + ), ); } diff --git a/src/components/CodeiumEditor/InlineCompletionProvider.ts b/src/components/CodeiumEditor/InlineCompletionProvider.ts index 7c87e87..c44b91d 100644 --- a/src/components/CodeiumEditor/InlineCompletionProvider.ts +++ b/src/components/CodeiumEditor/InlineCompletionProvider.ts @@ -1,12 +1,12 @@ -import * as monaco from "monaco-editor/esm/vs/editor/editor.api"; -import { Document as DocumentInfo } from "../../api/proto/exa/language_server_pb/language_server_pb"; -import { Dispatch, SetStateAction } from "react"; -import { PromiseClient } from "@connectrpc/connect"; -import { Status } from "./Status"; -import { MonacoCompletionProvider } from "./CompletionProvider"; -import { LanguageServerService } from "../../api/proto/exa/language_server_pb/language_server_connect"; +import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; +import { Document as DocumentInfo } from '../../api/proto/exa/language_server_pb/language_server_pb'; +import { Dispatch, SetStateAction } from 'react'; +import { PromiseClient } from '@connectrpc/connect'; +import { Status } from './Status'; +import { MonacoCompletionProvider } from './CompletionProvider'; +import { LanguageServerService } from '../../api/proto/exa/language_server_pb/language_server_connect'; -declare module "monaco-editor" { +declare module 'monaco-editor' { namespace editor { interface ICodeEditor { _commandService: { executeCommand(command: string): unknown }; @@ -25,14 +25,14 @@ export class InlineCompletionProvider readonly setCompletionCount: Dispatch>, setCodeiumStatus: Dispatch>, setCodeiumStatusMessage: Dispatch>, - apiKey?: string | undefined + apiKey?: string | undefined, ) { this.numCompletionsProvided = 0; this.completionProvider = new MonacoCompletionProvider( grpcClient, setCodeiumStatus, setCodeiumStatusMessage, - apiKey + apiKey, ); } @@ -44,12 +44,12 @@ export class InlineCompletionProvider model: monaco.editor.ITextModel, position: monaco.Position, context: monaco.languages.InlineCompletionContext, - token: monaco.CancellationToken + token: monaco.CancellationToken, ) { const completions = await this.completionProvider.provideInlineCompletions( model, position, - token + token, ); // Only count completions provided if non-empty (i.e. exclude cancelled // requests). diff --git a/src/components/CodeiumEditor/Line.ts b/src/components/CodeiumEditor/Line.ts index 68332f2..474e266 100644 --- a/src/components/CodeiumEditor/Line.ts +++ b/src/components/CodeiumEditor/Line.ts @@ -1,4 +1,4 @@ -import { Range } from "./Location"; +import { Range } from './Location'; export class Line { readonly text: string; diff --git a/src/components/CodeiumEditor/Location.ts b/src/components/CodeiumEditor/Location.ts index e6a4f59..0e9f3a5 100644 --- a/src/components/CodeiumEditor/Location.ts +++ b/src/components/CodeiumEditor/Location.ts @@ -1,4 +1,4 @@ -import * as monaco from "monaco-editor/esm/vs/editor/editor.api"; +import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; export class Position implements monaco.IPosition { readonly line: number; @@ -48,7 +48,7 @@ export class Range implements monaco.IRange { static fromMonaco(range: monaco.IRange): Range { return new Range( new Position(range.startLineNumber - 1, range.startColumn - 1), - new Position(range.endLineNumber - 1, range.endColumn - 1) + new Position(range.endLineNumber - 1, range.endColumn - 1), ); } diff --git a/src/components/CodeiumEditor/Status.ts b/src/components/CodeiumEditor/Status.ts index cc707b1..357f1f0 100644 --- a/src/components/CodeiumEditor/Status.ts +++ b/src/components/CodeiumEditor/Status.ts @@ -2,11 +2,11 @@ * Status of the Codeium AI completions generation. */ export enum Status { - INACTIVE = "inactive", - PROCESSING = "processing", - SUCCESS = "success", - WARNING = "warning", - ERROR = "error", + INACTIVE = 'inactive', + PROCESSING = 'processing', + SUCCESS = 'success', + WARNING = 'warning', + ERROR = 'error', } /** diff --git a/src/components/CodeiumEditor/defaultValues.ts b/src/components/CodeiumEditor/defaultValues.ts index 8e01b01..a931253 100644 --- a/src/components/CodeiumEditor/defaultValues.ts +++ b/src/components/CodeiumEditor/defaultValues.ts @@ -1,24 +1,24 @@ export const getDefaultValue = (language: string): string => { switch (language) { - case "typescript": - case "tsx": - case "javascript": - case "java": + case 'typescript': + case 'tsx': + case 'javascript': + case 'java': return `// Welcome to Codeium Editor! // Press Enter and use Tab to accept AI suggestions. Here's an example: // fib(n) function to calculate the n-th fibonacci number`; - case "python": + case 'python': return `# Welcome to Codeium Editor! # Press Enter and use Tab to accept AI suggestions. Here's an example: # fib(n) function to calculate the n-th fibonacci number`; - case "css": + case 'css': return `/* Welcome to Codeium Editor! Press Enter and use Tab to accept AI suggestions. Here's an example:*/ /* .action-button class with a hover effect. */`; default: - return ""; + return ''; } }; diff --git a/src/components/CodeiumEditor/types.ts b/src/components/CodeiumEditor/types.ts index 24d695c..7a17823 100644 --- a/src/components/CodeiumEditor/types.ts +++ b/src/components/CodeiumEditor/types.ts @@ -1,7 +1,7 @@ import { Completion, CompletionSource, -} from "../../api/proto/exa/codeium_common_pb/codeium_common_pb"; +} from '../../api/proto/exa/codeium_common_pb/codeium_common_pb'; export type CompletionAndRange = { completion: Completion; diff --git a/src/components/CodeiumLogo/CodeiumLogo.tsx b/src/components/CodeiumLogo/CodeiumLogo.tsx index 7252fef..02cff27 100644 --- a/src/components/CodeiumLogo/CodeiumLogo.tsx +++ b/src/components/CodeiumLogo/CodeiumLogo.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React from 'react'; type CodeiumLogoProps = { className?: string; @@ -30,7 +30,7 @@ export const CodeiumLogo: React.FC = ({ = ({ d="M75.196 77.1134C74.1902 77.1134 73.3102 76.7612 72.5559 76.0566C71.8375 75.3169 71.4783 74.4538 71.4783 73.4675C71.4783 72.4459 71.8375 71.5828 72.5559 70.8783C73.3102 70.1386 74.1902 69.7687 75.196 69.7687C76.2377 69.7687 77.1177 70.1386 77.8361 70.8783C78.5545 71.5828 78.9137 72.4459 78.9137 73.4675C78.9137 74.4538 78.5545 75.3169 77.8361 76.0566C77.1177 76.7612 76.2377 77.1134 75.196 77.1134Z" fill="white" aria-label="right-dot" - className={loading ? "animate-blink duration-1000" : ""} - style={{ animationDelay: "666ms" }} + className={loading ? 'animate-blink duration-1000' : ''} + style={{ animationDelay: '666ms' }} /> = { - title: "Example/Editor", + title: 'Example/Editor', component: CodeiumEditor, parameters: { // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout - layout: "centered", + layout: 'centered', }, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs - tags: ["autodocs"], + tags: ['autodocs'], // More on argTypes: https://storybook.js.org/docs/api/argtypes argTypes: {}, } satisfies Meta; @@ -22,8 +22,8 @@ export default meta; type Story = StoryObj; const baseParams = { - width: "700px", - height: "500px", + width: '700px', + height: '500px', }; const PYTHON_SNIPPET = `# Need inspiration? Try adding extra constraints or context to this parse json function! @@ -38,7 +38,7 @@ def parse_json_lines(filename: str) -> List[Any]: export const PythonEditor: Story = { args: { ...baseParams, - language: "python", + language: 'python', value: PYTHON_SNIPPET, }, }; @@ -54,7 +54,7 @@ function parseStringAsHtml(content, selector) { export const JavaScriptEditor: Story = { args: { ...baseParams, - language: "javascript", + language: 'javascript', value: JAVASCRIPT_SNIPPET, }, }; @@ -76,7 +76,7 @@ func main() { export const GoEditor: Story = { args: { ...baseParams, - language: "go", + language: 'go', value: GO_SNIPPET, }, }; @@ -95,7 +95,7 @@ public ArrayList getVisibleWidgets() { export const JavaEditor: Story = { args: { ...baseParams, - language: "java", + language: 'java', value: JAVA_SNIPPET, }, }; @@ -115,7 +115,7 @@ class Matrix() { export const CppEditor: Story = { args: { ...baseParams, - language: "cpp", + language: 'cpp', value: CPP_SNIPPET, }, }; @@ -142,7 +142,7 @@ const HTML_SNIPPET = ` export const HTMLEditor: Story = { args: { ...baseParams, - language: "html", + language: 'html', value: HTML_SNIPPET, }, }; @@ -152,7 +152,7 @@ export const MultiFileContext: Story = {

Multi File Context

- Neighboring file at index.html passed into the{" "} + Neighboring file at index.html passed into the{' '} otherDocuments property:

@@ -166,17 +166,17 @@ export const MultiFileContext: Story = { ), args: { ...baseParams, - language: "javascript", + language: 'javascript', value: `// You have context over a sample HTML page. // Codeium's generation will take this context into account when suggesting. // Get the contact form values by ID.`, otherDocuments: [ new Document({ - absolutePath: "/index.html", - relativePath: "index.html", + absolutePath: '/index.html', + relativePath: 'index.html', text: HTML_SNIPPET, - editorLanguage: "html", + editorLanguage: 'html', language: Language.HTML, }), ], diff --git a/src/utils/identity.ts b/src/utils/identity.ts index 1e5284c..9590ebc 100644 --- a/src/utils/identity.ts +++ b/src/utils/identity.ts @@ -23,7 +23,7 @@ export const getBrowserVersion = () => { */ export const getPackageVersion = () => { try { - return require("../../package.json").version; + return require('../../package.json').version; } catch (e) { return null; } diff --git a/src/utils/language.ts b/src/utils/language.ts index 0e38261..968bc67 100644 --- a/src/utils/language.ts +++ b/src/utils/language.ts @@ -1,139 +1,139 @@ -import { Language } from "../models"; +import { Language } from '../models'; /** * Converts a language ID to a strongly-typed enum value. */ export const languageIdToEnum = (languageId: string): Language => { switch (languageId.toLowerCase()) { - case "c": + case 'c': return Language.C; - case "clojure": + case 'clojure': return Language.CLOJURE; - case "coffeescript": + case 'coffeescript': return Language.COFFEESCRIPT; - case "cpp": + case 'cpp': return Language.CPP; - case "csharp": + case 'csharp': return Language.CSHARP; - case "css": + case 'css': return Language.CSS; - case "cudacpp": + case 'cudacpp': return Language.CUDACPP; - case "dockerfile": + case 'dockerfile': return Language.DOCKERFILE; - case "go": + case 'go': return Language.GO; - case "groovy": + case 'groovy': return Language.GROOVY; - case "handlebars": + case 'handlebars': return Language.HANDLEBARS; - case "haskell": + case 'haskell': return Language.HASKELL; - case "hcl": + case 'hcl': return Language.HCL; - case "html": + case 'html': return Language.HTML; - case "ini": + case 'ini': return Language.INI; - case "java": + case 'java': return Language.JAVA; - case "javascript": + case 'javascript': return Language.JAVASCRIPT; - case "json": + case 'json': return Language.JSON; - case "julia": + case 'julia': return Language.JULIA; - case "kotlin": + case 'kotlin': return Language.KOTLIN; - case "latex": + case 'latex': return Language.LATEX; - case "less": + case 'less': return Language.LESS; - case "lua": + case 'lua': return Language.LUA; - case "makefile": + case 'makefile': return Language.MAKEFILE; - case "markdown": + case 'markdown': return Language.MARKDOWN; - case "objectivec": + case 'objectivec': return Language.OBJECTIVEC; - case "objectivecpp": + case 'objectivecpp': return Language.OBJECTIVECPP; - case "perl": + case 'perl': return Language.PERL; - case "php": + case 'php': return Language.PHP; - case "plaintext": + case 'plaintext': return Language.PLAINTEXT; - case "protobuf": + case 'protobuf': return Language.PROTOBUF; - case "pbtxt": + case 'pbtxt': return Language.PBTXT; - case "python": + case 'python': return Language.PYTHON; - case "r": + case 'r': return Language.R; - case "ruby": + case 'ruby': return Language.RUBY; - case "rust": + case 'rust': return Language.RUST; - case "sass": + case 'sass': return Language.SASS; - case "scala": + case 'scala': return Language.SCALA; - case "scss": + case 'scss': return Language.SCSS; - case "shell": + case 'shell': return Language.SHELL; - case "sql": + case 'sql': return Language.SQL; - case "starlark": + case 'starlark': return Language.STARLARK; - case "swift": + case 'swift': return Language.SWIFT; - case "tsx": + case 'tsx': return Language.TSX; - case "typescript": + case 'typescript': return Language.TYPESCRIPT; - case "visualbasic": + case 'visualbasic': return Language.VISUALBASIC; - case "vue": + case 'vue': return Language.VUE; - case "xml": + case 'xml': return Language.XML; - case "xsl": + case 'xsl': return Language.XSL; - case "yaml": + case 'yaml': return Language.YAML; - case "svelte": + case 'svelte': return Language.SVELTE; - case "toml": + case 'toml': return Language.TOML; - case "dart": + case 'dart': return Language.DART; - case "rst": + case 'rst': return Language.RST; - case "ocaml": + case 'ocaml': return Language.OCAML; - case "cmake": + case 'cmake': return Language.CMAKE; - case "pascal": + case 'pascal': return Language.PASCAL; - case "elixir": + case 'elixir': return Language.ELIXIR; - case "fsharp": + case 'fsharp': return Language.FSHARP; - case "lisp": + case 'lisp': return Language.LISP; - case "matlab": + case 'matlab': return Language.MATLAB; - case "powershell": + case 'powershell': return Language.POWERSHELL; - case "solidity": + case 'solidity': return Language.SOLIDITY; - case "ada": + case 'ada': return Language.ADA; - case "ocaml_interface": + case 'ocaml_interface': return Language.OCAML_INTERFACE; default: return Language.UNSPECIFIED; diff --git a/src/utils/utf.ts b/src/utils/utf.ts index 692ddf4..3b6b171 100644 --- a/src/utils/utf.ts +++ b/src/utils/utf.ts @@ -27,7 +27,7 @@ function numUtf8BytesForCodePoint(codePointValue: number): number { */ export function numCodeUnitsToNumUtf8Bytes( text: string, - numCodeUnits?: number + numCodeUnits?: number, ): number { if (numCodeUnits === 0) { return 0; @@ -46,7 +46,7 @@ export function numCodeUnitsToNumUtf8Bytes( export function numUtf8BytesToNumCodeUnits( text: string, - numUtf8Bytes?: number + numUtf8Bytes?: number, ): number { if (numUtf8Bytes === 0) { return 0; diff --git a/src/utils/uuid.ts b/src/utils/uuid.ts index a2cd878..dfee32c 100644 --- a/src/utils/uuid.ts +++ b/src/utils/uuid.ts @@ -2,9 +2,9 @@ * Generates a random UUID. */ export const uuid = () => { - return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { const r = (Math.random() * 16) | 0; - const v = c === "x" ? r : (r & 0x3) | 0x8; + const v = c === 'x' ? r : (r & 0x3) | 0x8; return v.toString(16); }); }; From eec706ed6cff160840e5cb285274c32680c13095 Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Tue, 13 Feb 2024 10:36:37 -0800 Subject: [PATCH 14/28] Update rules --- .prettierrc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.prettierrc b/.prettierrc index 5a58802..e230f59 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,8 @@ { "semi": true, "singleQuote": true, + "useTabs": false, "tabWidth": 2, - "printWidth": 80 + "printWidth": 80, + "trailingComma": "all" } \ No newline at end of file From 16afcb199747eb21684c596dac8bc5cf1defb8e8 Mon Sep 17 00:00:00 2001 From: Andy Zhang Date: Tue, 13 Feb 2024 12:05:04 -0800 Subject: [PATCH 15/28] Add extension version --- rollup.config.js | 9 ++++++++- src/utils/identity.ts | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/rollup.config.js b/rollup.config.js index 344c7cf..f22f04e 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -5,6 +5,9 @@ import dts from "rollup-plugin-dts"; import banner2 from 'rollup-plugin-banner2' import packageJson from "./package.json" assert { type: "json" }; +const version = packageJson.version ?? null; + + export default [ { input: "src/index.ts", @@ -26,7 +29,11 @@ export default [ commonjs(), typescript({ tsconfig: "./tsconfig.json" }), banner2(() => ` - "use client"; +"use client"; + +if (typeof window !== "undefined") { + window.CODEIUM_REACT_CODE_VERSION = ${version ? `${JSON.stringify(version)}` : null}; +} `) ], }, diff --git a/src/utils/identity.ts b/src/utils/identity.ts index 9590ebc..7b1ff39 100644 --- a/src/utils/identity.ts +++ b/src/utils/identity.ts @@ -23,7 +23,8 @@ export const getBrowserVersion = () => { */ export const getPackageVersion = () => { try { - return require('../../package.json').version; + // @ts-ignore + return window.CODEIUM_REACT_CODE_VERSION ? window.CODEIUM_REACT_CODE_VERSION : null; } catch (e) { return null; } From 4967c9d435f631b70515caab58f3de025d6c404b Mon Sep 17 00:00:00 2001 From: Andy Zhang Date: Tue, 13 Feb 2024 12:12:31 -0800 Subject: [PATCH 16/28] Bump version to 1.0.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5e907c5..89a2b6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codeium/react-code-editor", - "version": "1.0.7", + "version": "1.0.8", "description": "AI-powered React component", "main": "dist/index.js", "type": "module", From 436c248eae17f82d70ee040d6d06acc4da40a694 Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Tue, 13 Feb 2024 13:54:10 -0800 Subject: [PATCH 17/28] Removing logging --- src/components/CodeiumEditor/CompletionProvider.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/CodeiumEditor/CompletionProvider.ts b/src/components/CodeiumEditor/CompletionProvider.ts index b0df60e..4c14c9a 100644 --- a/src/components/CodeiumEditor/CompletionProvider.ts +++ b/src/components/CodeiumEditor/CompletionProvider.ts @@ -131,10 +131,6 @@ export class MonacoCompletionProvider { ); includedOtherDocs = includedOtherDocs.slice(0, 10); } - console.log( - `Included other documents: ${includedOtherDocs.length}`, - includedOtherDocs.map((d) => d.toJson()), - ); // Get completions. let getCompletionsResponse: GetCompletionsResponse; From e8386e92318fe8b92239852b1494d66072350b65 Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Tue, 13 Feb 2024 13:57:12 -0800 Subject: [PATCH 18/28] Markdown example --- src/stories/CodeiumEditor.stories.tsx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/stories/CodeiumEditor.stories.tsx b/src/stories/CodeiumEditor.stories.tsx index 717f6e8..0454e40 100644 --- a/src/stories/CodeiumEditor.stories.tsx +++ b/src/stories/CodeiumEditor.stories.tsx @@ -120,6 +120,23 @@ export const CppEditor: Story = { }, }; +const MARKDOWN_SNIPPET = `# Readme Template +Author: [Your Name] + +This is a template for your README.md file. + +## Features + +List of features:`; + +export const MarkdownEditor: Story = { + args: { + ...baseParams, + language: 'markdown', + value: MARKDOWN_SNIPPET, + }, +}; + const HTML_SNIPPET = ` Contact Form From d3700a9d71984baeb09433382ca4cfd94b114909 Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Tue, 13 Feb 2024 14:13:21 -0800 Subject: [PATCH 19/28] Merge user settings with defaults --- .../CodeiumEditor/CodeiumEditor.tsx | 41 ++++++++++--------- src/utils/merge.ts | 31 ++++++++++++++ 2 files changed, 53 insertions(+), 19 deletions(-) create mode 100644 src/utils/merge.ts diff --git a/src/components/CodeiumEditor/CodeiumEditor.tsx b/src/components/CodeiumEditor/CodeiumEditor.tsx index 3266d3c..5aab388 100644 --- a/src/components/CodeiumEditor/CodeiumEditor.tsx +++ b/src/components/CodeiumEditor/CodeiumEditor.tsx @@ -12,6 +12,7 @@ import { LanguageServerService } from '../../api/proto/exa/language_server_pb/la import { InlineCompletionProvider } from './InlineCompletionProvider'; import { CodeiumLogo } from '../CodeiumLogo/CodeiumLogo'; import { Document } from '../../models'; +import { deepMerge } from '../../utils/merge'; export interface CodeiumEditorProps extends EditorProps { language: string; @@ -184,26 +185,28 @@ export const CodeiumEditor: React.FC = ({ width={layout.width} height={layout.height} onMount={handleEditorDidMount} - options={{ - scrollBeyondLastColumn: 0, - scrollbar: { - alwaysConsumeMouseWheel: false, + options={deepMerge( + props.options, + { + scrollBeyondLastColumn: 0, + scrollbar: { + alwaysConsumeMouseWheel: false, + }, + codeLens: false, + // for resizing, but apparently might have "severe performance impact" + // automaticLayout: true, + minimap: { + enabled: false, + }, + quickSuggestions: false, + folding: false, + foldingHighlight: false, + foldingImportsByDefault: false, + links: false, + fontSize: 14, + wordWrap: 'on', }, - codeLens: false, - // for resizing, but apparently might have "severe performance impact" - // automaticLayout: true, - minimap: { - enabled: false, - }, - quickSuggestions: false, - folding: false, - foldingHighlight: false, - foldingImportsByDefault: false, - links: false, - fontSize: 14, - wordWrap: 'on', - ...props.options, - }} + )} />
); diff --git a/src/utils/merge.ts b/src/utils/merge.ts new file mode 100644 index 0000000..df87541 --- /dev/null +++ b/src/utils/merge.ts @@ -0,0 +1,31 @@ +/** + * Merges a partial object with a fallback object, deeply combining the two. + * + * @param {Partial} partial - the partial object to merge (can be undefined) + * @param {T} fallback - the fallback object to merge with + * @return {T} the merged object + */ +export function deepMerge(partial: Partial | undefined, fallback: T): T { + const merged: any = { ...fallback }; + + for (const key in partial) { + if (typeof partial[key] === 'object' && !Array.isArray(partial[key])) { + if ( + fallback[key] && + typeof fallback[key] === 'object' && + !Array.isArray(fallback[key]) + ) { + merged[key] = deepMerge( + partial[key] as Partial | undefined, + fallback[key] as T, + ); + } else { + merged[key] = { ...partial[key] }; + } + } else { + merged[key] = partial[key]; + } + } + + return merged; +} From 64ad4b4d7ab779ea45dab2ce64aeb132ef0ea95d Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Tue, 13 Feb 2024 14:19:57 -0800 Subject: [PATCH 20/28] Working options merge --- src/stories/CodeiumEditor.stories.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/stories/CodeiumEditor.stories.tsx b/src/stories/CodeiumEditor.stories.tsx index 717f6e8..2d78b7d 100644 --- a/src/stories/CodeiumEditor.stories.tsx +++ b/src/stories/CodeiumEditor.stories.tsx @@ -167,6 +167,11 @@ export const MultiFileContext: Story = { args: { ...baseParams, language: 'javascript', + options: { + scrollbar: { + vertical: 'hidden', + }, + }, value: `// You have context over a sample HTML page. // Codeium's generation will take this context into account when suggesting. From 788bae38304e88c4f95bcaaa7ca21e94c029574a Mon Sep 17 00:00:00 2001 From: Andy Zhang Date: Tue, 13 Feb 2024 14:24:49 -0800 Subject: [PATCH 21/28] Update version to 1.0.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 89a2b6b..d5860a2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codeium/react-code-editor", - "version": "1.0.8", + "version": "1.0.9", "description": "AI-powered React component", "main": "dist/index.js", "type": "module", From 9aa1bec425d451d121513d6c51d3e311bbe0a9ef Mon Sep 17 00:00:00 2001 From: Andy Zhang Date: Tue, 13 Feb 2024 14:36:08 -0800 Subject: [PATCH 22/28] Update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d5860a2..dd765ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@codeium/react-code-editor", - "version": "1.0.9", + "version": "1.0.10", "description": "AI-powered React component", "main": "dist/index.js", "type": "module", From 95abf18947f13a0e85f2903adf5f75511d32fc96 Mon Sep 17 00:00:00 2001 From: Kevin Hou Date: Thu, 15 Feb 2024 16:52:52 -0800 Subject: [PATCH 23/28] Plain text editor --- .../CodeiumEditor/CodeiumEditor.tsx | 14 ++++ src/stories/CodeiumEditor.stories.tsx | 68 +++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/components/CodeiumEditor/CodeiumEditor.tsx b/src/components/CodeiumEditor/CodeiumEditor.tsx index 5aab388..2b78e7a 100644 --- a/src/components/CodeiumEditor/CodeiumEditor.tsx +++ b/src/components/CodeiumEditor/CodeiumEditor.tsx @@ -34,6 +34,16 @@ export interface CodeiumEditorProps extends EditorProps { * documents. */ otherDocuments?: Document[]; + + /** + * Optional classname for the container. + */ + containerClassName?: string; + + /** + * Optional styles for the container. + */ + containerStyle?: React.CSSProperties; } /** @@ -43,6 +53,8 @@ export interface CodeiumEditorProps extends EditorProps { export const CodeiumEditor: React.FC = ({ languageServerAddress = 'https://web-backend.codeium.com', otherDocuments = [], + containerClassName = '', + containerStyle = {}, ...props }) => { const editorRef = useRef(null); @@ -166,7 +178,9 @@ export const CodeiumEditor: React.FC = ({ style={{ ...layout, position: 'relative', + ...containerStyle, }} + className={containerClassName} > ( +
+

Plain Text

+