diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 7fc0be1bd..dedb883f2 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -85,6 +85,7 @@ "@codemirror/language": "^6.10.3", "@codemirror/state": "^6.4.1", "@codemirror/view": "^6.34.1", + "@floating-ui/dom": "^1.6.12", "@formkit/auto-animate": "^0.8.2", "@internationalized/date": "^3.5.6", "@svelte-put/clickoutside": "^3.0.2", diff --git a/apps/frontend/src/lib/components/formula/formula-editor.svelte b/apps/frontend/src/lib/components/formula/formula-editor.svelte index abbba8165..8f3a2c943 100644 --- a/apps/frontend/src/lib/components/formula/formula-editor.svelte +++ b/apps/frontend/src/lib/components/formula/formula-editor.svelte @@ -16,6 +16,8 @@ import { derived } from "svelte/store" import FieldIcon from "../blocks/field-icon/field-icon.svelte" import { type Field } from "@undb/table" + import { computePosition, flip, shift, offset } from "@floating-ui/dom" + import { globalFormulaRegistry } from "@undb/formula/src/formula/formula.registry" const functions = FORMULA_FUNCTIONS @@ -31,8 +33,15 @@ export let value: string = "" let editor: EditorView - let suggestions: string[] = [...functions, ...$fields] + let formulaSuggestions: string[] = [...functions] + let fieldSuggestions: string[] = [...$fields] + + $: suggestions = [...formulaSuggestions, ...fieldSuggestions] + let selectedSuggestion: string = "" + let hoverSuggestion: string = "" + + $: hoverFormula = hoverSuggestion ? globalFormulaRegistry.get(hoverSuggestion as FormulaFunction) : undefined const highlightStyle = HighlightStyle.define([ { tag: tags.keyword, color: "#5c6bc0" }, @@ -281,8 +290,8 @@ if (!isInsideParens) { const functionNode = visitor.getNearestFunctionNode() if (functionNode) { - const functionStart = functionNode.start.startIndex - const functionNameLength = functionNode.IDENTIFIER().text.length + const functionStart = functionNode.start.tokenIndex + const functionNameLength = functionNode.IDENTIFIER().getText().length const transaction = editor.state.update({ changes: { from: functionStart, @@ -383,9 +392,30 @@ errorMessage = (error as Error).message } } + + let hoverSuggestionContainer: HTMLElement + let editorContainerWrapper: HTMLElement + + function update() { + if (hoverSuggestionContainer && editorContainerWrapper && hoverFormula) { + computePosition(editorContainerWrapper, hoverSuggestionContainer, { + placement: "left-start", + middleware: [flip(), shift({ padding: 5 }), offset(10)], + }).then(({ x, y }) => { + Object.assign(hoverSuggestionContainer.style, { + left: `${x}px`, + top: `${y}px`, + }) + }) + } + } + + onMount(() => { + update() + }) -
+
{#if errorMessage}

@@ -395,32 +425,94 @@ {/if}

+ +
+ {#if hoverFormula} +
+
+ + {hoverSuggestion}() +
+
+ +
+

{hoverFormula.description}

+
+

Syntax

+ {#each hoverFormula.syntax as syntax} +
+ {syntax} +
+ {/each} +
+ {#if hoverFormula.examples && hoverFormula.examples.length > 0} +

Examples

+
+ {#each hoverFormula.examples as example} +
+ {example[0]} + {#if example[1]} + + => {example[1]} + + {/if} +
+ {/each} +
+ {/if} +
+ {/if} +