Better AI Fill inputs (#6984)

* Remove most yPadding={7}

* migrate DynamicInputHelpBox to Alert

* fix button heights

* Fix TemplateEditor padding and FakeMonacoPlaceholder

* SimpleEditor fix left padding

* Better AI Fill inputs

* update svelte

* Fix svelte bug, propertyType not updating

* Revert "update svelte"

This reverts commit 1c0f5ed15c.

* MONACO_Y_PADDING var

* Fixed Flow Loop AI gen

* nit button fixes
This commit is contained in:
Diego Imbert
2025-10-28 22:00:57 +00:00
committed by GitHub
parent 5161a1afc8
commit 3413a856dc
22 changed files with 349 additions and 357 deletions
+11 -2
View File
@@ -46,7 +46,11 @@
import { workspaceStore } from '$lib/stores'
import { getJsonSchemaFromResource } from './schema/jsonSchemaResource.svelte'
import AIProviderPicker from './AIProviderPicker.svelte'
import TextInput, { inputBaseClass, inputBorderClass } from './text_input/TextInput.svelte'
import TextInput, {
inputBaseClass,
inputBorderClass,
inputSizeClasses
} from './text_input/TextInput.svelte'
import FileInput from './common/fileInput/FileInput.svelte'
interface Props {
@@ -1401,7 +1405,12 @@
use:autosize
onkeydown={onKeyDown}
{disabled}
class={twMerge('w-full', inputBaseClass, inputBorderClass({ error: !!error }))}
class={twMerge(
'w-full',
inputBaseClass,
inputSizeClasses.md,
inputBorderClass({ error: !!error })
)}
placeholder={placeholder ?? defaultValue ?? ''}
bind:value
></textarea>
@@ -169,7 +169,7 @@
{/if}
{/each}
</div>
<div class="flex gap-2 py-4">
<div class="flex gap-2 py-4 whitespace-nowrap">
<input type="text" placeholder="client_id" bind:value={clientName} />
<Button
variant="accent"
+9 -3
View File
@@ -42,7 +42,11 @@
import { workspaceStore } from '$lib/stores'
import { type Preview, ResourceService, type ScriptLang, UserService } from '$lib/gen'
import type { Text } from 'yjs'
import { initializeVscode, keepModelAroundToAvoidDisposalOfWorkers } from '$lib/components/vscode'
import {
initializeVscode,
keepModelAroundToAvoidDisposalOfWorkers,
MONACO_Y_PADDING
} from '$lib/components/vscode'
import { initializeMode } from 'monaco-graphql/esm/initializeMode.js'
import type { MonacoGraphQLAPI } from 'monaco-graphql/esm/api.js'
@@ -1077,6 +1081,8 @@
let pathTimeout: number | undefined = undefined
let yPadding = MONACO_Y_PADDING
function getHostname() {
return BROWSER ? window.location.protocol + '//' + window.location.host : 'SSR'
}
@@ -1262,7 +1268,7 @@
// overflowWidgetsDomNode: widgets,
tabSize: lang == 'python' ? 4 : 2,
folding,
padding: { bottom: 7, top: 7 }
padding: { bottom: yPadding, top: yPadding }
})
if (key && editorPositionMap?.[key]) {
editor.setPosition(editorPositionMap[key])
@@ -1721,7 +1727,7 @@
<EditorTheme />
{#if !editor}
<div class="inset-0 absolute overflow-clip">
<FakeMonacoPlaceHolder {code} />
<FakeMonacoPlaceHolder {code} lineNumbersWidth={51} />
</div>
{/if}
<div bind:this={divEl} class="{clazz} editor {disabled ? 'disabled' : ''}"></div>
@@ -437,7 +437,7 @@
{:else}
<Button
disabled={emptyString(handlerExtraArgs['channel'])}
btnClasses="w-32 text-center"
btnClasses="w-32 text-center whitespace-nowrap"
variant="default"
on:click={() => sendSlackMessage(handlerExtraArgs['channel'])}
unifiedSize="md">Send test message</Button
@@ -545,7 +545,7 @@
{:else}
<Button
disabled={emptyString(handlerExtraArgs['channel'])}
btnClasses="w-32 text-center mt-2"
btnClasses="w-32 text-center mt-2 whitespace-nowrap"
variant="default"
on:click={() => sendTeamsMessage(handlerExtraArgs['channel'] ?? '')}
size="xs">Send test message</Button
@@ -2,6 +2,7 @@
<script lang="ts">
import { getOS } from '$lib/utils'
import { MONACO_Y_PADDING } from './vscode'
type Props = {
code?: string
@@ -16,13 +17,15 @@
let {
code,
autoheight = false,
lineNumbersWidth = 51,
lineNumbersWidth = 0,
lineNumbersOffset = 0,
class: className = '',
showNumbers = true,
fontSize = 14
}: Props = $props()
let yPadding = MONACO_Y_PADDING
// https://github.com/microsoft/vscode/blob/baa2dad3cdacd97ac02eff0604984faf1167ff1e/src/vs/editor/common/config/editorOptions.ts#L5421
const DEFAULT_WINDOWS_FONT_FAMILY = "Consolas, 'Courier New', monospace"
const DEFAULT_MAC_FONT_FAMILY = "Menlo, Monaco, 'Courier New', monospace"
@@ -51,7 +54,9 @@
let [editorWidth, editorHeight] = $derived([
clientWidth,
autoheight ? lines.length * lineHeight + (showHorizontalScrollbar ? 12 : 0) : clientHeight
autoheight
? lines.length * lineHeight + (showHorizontalScrollbar ? 12 : 0) + yPadding * 2
: clientHeight
])
</script>
@@ -60,7 +65,7 @@
<div
bind:clientWidth
bind:clientHeight
class="h-full w-full relative editor {className}"
class="h-full w-full relative editor bg-surface-input rounded-md {className}"
style="--vscode-editorCodeLens-lineHeight: 18px; --vscode-editorCodeLens-fontSize: 12px; --vscode-editorCodeLens-fontFeatureSettings: 'liga' off, 'calt' off; --code-editorInlayHintsFontFamily: {fontFamily};"
>
<div
@@ -83,7 +88,7 @@
: 'block'};"
>
{#each lines as _, i}
<div style="top:{lineHeight * i}px;height:{lineHeight}px;">
<div style="top:{lineHeight * i + yPadding}px;height:{lineHeight}px;">
<div class="line-numbers" style="left:{lineNumbersOffset}px;width:25px;">{i + 1}</div>
</div>
{/each}
@@ -99,11 +104,11 @@
>
<div
class="view-lines monaco-mouse-cursor-text text-primary/60"
style="line-height: {lineHeight}px; position: absolute; font-family: {fontFamily}; font-weight: normal; font-size: {fontSize}px; font-feature-settings: 'liga' 0, 'calt' 0; font-variation-settings: normal; line-height: {lineHeight}px; letter-spacing: 0px; width: 1143px; height: 789px;"
style="padding-top: {yPadding}px; line-height: {lineHeight}px; position: absolute; font-family: {fontFamily}; font-weight: normal; font-size: {fontSize}px; font-feature-settings: 'liga' 0, 'calt' 0; font-variation-settings: normal; line-height: {lineHeight}px; letter-spacing: 0px; width: 1143px; height: 789px;"
>
{#each lines as line, i}
<div
style="height: {lineHeight}px; top: {i * lineHeight}px;"
style="height: {lineHeight}px; top: {lineHeight * i}px;"
class="text-nowrap whitespace-pre"
>
{line}
@@ -39,6 +39,7 @@
import { deepEqual } from 'fast-equals'
import S3ArrayHelperButton from './S3ArrayHelperButton.svelte'
import { inputBorderClass } from './text_input/TextInput.svelte'
import FakeMonacoPlaceHolder from './FakeMonacoPlaceHolder.svelte'
// We add 'ai' for ai agent tools. 'ai' means the field will be filled by the AI agent dynamically.
type PropertyType = InputTransform['type'] | 'ai'
@@ -457,6 +458,17 @@
inputCat === 'list' &&
['s3object', 's3_object'].includes(schema?.properties?.[argName]?.items?.resourceType)
)
let suggestion: string | undefined = $state()
// Svelte bug ...
// Somehow the value is updated in the UI of the parent, but not in the children
// when passed as a prop. setTimeout is a workaround to force the update
let visiblePropertyType = $state(untrack(() => (suggestion ? 'javascript' : propertyType)))
$effect(() => {
let value = suggestion ? 'javascript' : propertyType
setTimeout(() => (visiblePropertyType = value), 1)
})
</script>
{#if arg != undefined && !hidden}
@@ -497,22 +509,9 @@
{focused}
{arg}
schemaProperty={schema?.properties?.[argName]}
showPopup={(isStaticTemplate(inputCat) && propertyType == 'static') ||
propertyType === undefined ||
propertyType === 'static' ||
arg?.expr?.length > 0}
on:showExpr={(e) => {
setTimeout(() => {
if (monaco && propertyType === 'javascript') {
monaco.setSuggestion(e.detail)
}
}, 0)
}}
on:showExpr={(e) => (suggestion = e.detail || undefined)}
on:setExpr={(e) => {
arg = {
type: 'javascript',
expr: e.detail
}
arg = { type: 'javascript', expr: e.detail }
propertyType = 'javascript'
monaco?.setCode('')
monaco?.insertAtCursor(e.detail)
@@ -555,10 +554,10 @@
<div class="{ButtonType.UnifiedHeightClasses.sm} relative">
<ToggleButtonGroup
selected={propertyType}
selected={visiblePropertyType}
class="h-full"
on:selected={(e) => {
if (e.detail == propertyType) return
if (e.detail == propertyType || suggestion) return
const staticTemplate = isStaticTemplate(inputCat)
if (e.detail === 'ai') {
@@ -691,172 +690,189 @@
{propertyType} -->
<div class="relative flex flex-row items-top gap-1 justify-between">
<div class="min-w-0 grow">
{#if propertyType === 'ai'}
{#if suggestion}
<div
class="text-sm text-tertiary italic p-3 bg-surface-secondary rounded-md border border-gray-200"
class={`bg-surface-input rounded-md pl-2 overflow-auto ${inputBorderClass({ forceFocus: true })}`}
>
<span class="flex items-center gap-2">
<InfoIcon size={16} />
This field will be filled by the AI agent dynamically
</span>
<FakeMonacoPlaceHolder autoheight code={suggestion} fontSize={12} />
</div>
{#if argName && schema?.properties?.[argName]?.description}
<div class="text-xs italic py-1 text-hint">
<pre class="font-main whitespace-normal"
>{schema.properties[argName].description}</pre
>
{/if}
<div
class={suggestion ? 'opacity-0 absolute' : ''}
onkeydowncapture={(e) => {
if (e.key === 'Tab' && suggestion) {
e.preventDefault()
}
}}
>
{@render innerInput()}
</div>
{#snippet innerInput()}
{#if propertyType === 'ai'}
<div
class="text-sm text-tertiary italic p-3 bg-surface-secondary rounded-md border border-gray-200"
>
<span class="flex items-center gap-2">
<InfoIcon size={16} />
This field will be filled by the AI agent dynamically
</span>
</div>
{/if}
{:else if isStaticTemplate(inputCat) && propertyType == 'static' && !noDynamicToggle}
<div class="flex flex-col gap-1">
{#if argName && schema?.properties?.[argName]?.description}
<div class="text-xs text-secondary">
<div class="text-xs italic py-1 text-hint">
<pre class="font-main whitespace-normal">
{schema.properties[argName].description}
</pre>
{schema.properties[argName].description}
</pre>
</div>
{/if}
{:else if isStaticTemplate(inputCat) && propertyType == 'static' && !noDynamicToggle}
<div class="flex flex-col gap-1">
{#if argName && schema?.properties?.[argName]?.description}
<div class="text-xs text-secondary">
<pre class="font-main whitespace-normal">
{schema.properties[argName].description}
</pre>
</div>
{/if}
{#if arg}
<TemplateEditor
yPadding={7}
bind:this={monacoTemplate}
{extraLib}
on:focus={onFocus}
on:blur={() => {
focused = false
}}
bind:code={arg.value}
fontSize={12}
on:change={() => {
dispatch('change', { argName, arg })
}}
loadAsync
class="bg-surface-input"
/>
{/if}
</div>
{:else if (propertyType === undefined || propertyType == 'static') && schema?.properties?.[argName]}
<ArgInput
{resourceTypes}
noMargin
compact
on:focus={onFocus}
on:blur={() => {
focused = false
}}
shouldDispatchChanges
on:change={() => {
dispatch('change', { argName, arg })
}}
label={argName}
bind:editor={monaco}
bind:description={schema.properties[argName].description}
bind:value={arg.value}
type={schema.properties[argName].type}
oneOf={schema.properties[argName].oneOf}
required={schema.required?.includes(argName)}
bind:pattern={schema.properties[argName].pattern}
bind:valid={inputCheck}
defaultValue={schema.properties[argName].default}
bind:enum_={schema.properties[argName].enum}
bind:format={schema.properties[argName].format}
contentEncoding={schema.properties[argName].contentEncoding}
bind:itemsType={schema.properties[argName].items}
properties={schema.properties[argName].properties}
nestedRequired={schema.properties[argName].required}
displayHeader={false}
extra={argExtra}
{variableEditor}
{itemPicker}
bind:pickForField
showSchemaExplorer
nullable={schema.properties[argName].nullable}
bind:title={schema.properties[argName].title}
bind:placeholder={schema.properties[argName].placeholder}
{helperScript}
otherArgs={Object.fromEntries(
Object.entries(otherArgs).map(([key, transform]) => [
key,
transform?.type === 'static' ? transform.value : transform?.expr
])
)}
>
{#snippet innerBottomSnippet()}
{#if shouldShowS3ArrayHelper}
<S3ArrayHelperButton
{connecting}
onClick={() =>
switchToJsAndConnect((path) => appendPathToArrayExpr(arg.expr, path))}
{#if arg}
<TemplateEditor
bind:this={monacoTemplate}
{extraLib}
on:focus={onFocus}
on:blur={() => {
focused = false
}}
bind:code={arg.value}
fontSize={12}
on:change={() => {
dispatch('change', { argName, arg })
}}
loadAsync
class="bg-surface-input"
/>
{/if}
{/snippet}
</ArgInput>
{:else if arg.expr != undefined}
<div
class={`bg-surface-input rounded-md flex flex-col pl-3 ${inputBorderClass({ forceFocus: focused })}`}
>
<SimpleEditor
small
bind:this={monaco}
bind:code={arg.expr}
yPadding={7}
{extraLib}
lang="javascript"
shouldBindKey={false}
renderLineHighlight="none"
hideLineNumbers
fakeMonacoPlaceholderClass="mt-2"
on:focus={() => (focused = true)}
on:blur={() => (focused = false)}
</div>
{:else if (propertyType === undefined || propertyType == 'static') && schema?.properties?.[argName]}
<ArgInput
{resourceTypes}
noMargin
compact
on:focus={onFocus}
on:blur={() => {
focused = false
}}
shouldDispatchChanges
on:change={() => {
dispatch('change', { argName, arg })
}}
autoHeight
loadAsync
/>
<!-- <input type="text" bind:value={arg.expr} /> -->
</div>
{#if shouldShowS3ArrayHelper}
<S3ArrayHelperButton
class="mt-2"
{connecting}
onClick={() =>
focusProp?.(argName, 'connect', (path) => {
appendPathToArrayExpr(arg.expr, path)
return true
})}
/>
{/if}
{#if argName && schema?.properties?.[argName]?.description}
<div class="text-xs italic py-1 text-secondary">
<pre class="font-main whitespace-normal"
>{schema.properties[argName].description}</pre
>
label={argName}
bind:editor={monaco}
bind:description={schema.properties[argName].description}
bind:value={arg.value}
type={schema.properties[argName].type}
oneOf={schema.properties[argName].oneOf}
required={schema.required?.includes(argName)}
bind:pattern={schema.properties[argName].pattern}
bind:valid={inputCheck}
defaultValue={schema.properties[argName].default}
bind:enum_={schema.properties[argName].enum}
bind:format={schema.properties[argName].format}
contentEncoding={schema.properties[argName].contentEncoding}
bind:itemsType={schema.properties[argName].items}
properties={schema.properties[argName].properties}
nestedRequired={schema.properties[argName].required}
displayHeader={false}
extra={argExtra}
{variableEditor}
{itemPicker}
bind:pickForField
showSchemaExplorer
nullable={schema.properties[argName].nullable}
bind:title={schema.properties[argName].title}
bind:placeholder={schema.properties[argName].placeholder}
{helperScript}
otherArgs={Object.fromEntries(
Object.entries(otherArgs).map(([key, transform]) => [
key,
transform?.type === 'static' ? transform.value : transform?.expr
])
)}
>
{#snippet innerBottomSnippet()}
{#if shouldShowS3ArrayHelper}
<S3ArrayHelperButton
{connecting}
onClick={() =>
switchToJsAndConnect((path) => appendPathToArrayExpr(arg.expr, path))}
/>
{/if}
{/snippet}
</ArgInput>
{:else if arg.expr != undefined}
<div
class={`bg-surface-input rounded-md flex flex-col pl-2 overflow-auto ${inputBorderClass({ forceFocus: focused })}`}
>
<SimpleEditor
small
bind:this={monaco}
bind:code={arg.expr}
{extraLib}
lang="javascript"
shouldBindKey={false}
renderLineHighlight="none"
hideLineNumbers
on:focus={() => (focused = true)}
on:blur={() => (focused = false)}
on:change={() => {
dispatch('change', { argName, arg })
}}
autoHeight
loadAsync
/>
<!-- <input type="text" bind:value={arg.expr} /> -->
</div>
{/if}
{#if !hideHelpButton}
<DynamicInputHelpBox />
{/if}
{#if shouldShowS3ArrayHelper}
<S3ArrayHelperButton
class="mt-2"
{connecting}
onClick={() =>
focusProp?.(argName, 'connect', (path) => {
appendPathToArrayExpr(arg.expr, path)
return true
})}
/>
{/if}
<div class="mb-2"></div>
{:else}
<span class="text-xs text-red-500">
Not recognized input type {argName} ({arg.expr}, {propertyType})
</span>
<div class="flex mt-2">
<Button
variant="default"
size="xs"
on:click={() => {
arg.expr = ''
}}>Set expr to empty string</Button
></div
>
{/if}
{#if argName && schema?.properties?.[argName]?.description}
<div class="text-xs italic py-1 text-secondary">
<pre class="font-main whitespace-normal"
>{schema.properties[argName].description}</pre
>
</div>
{/if}
{#if !hideHelpButton}
<DynamicInputHelpBox />
{/if}
<div class="mb-2"></div>
{:else}
<span class="text-xs text-red-500">
Not recognized input type {argName} ({arg.expr}, {propertyType})
</span>
<div class="flex mt-2">
<Button
variant="default"
size="xs"
on:click={() => {
arg.expr = ''
}}>Set expr to empty string</Button
></div
>
{/if}
{/snippet}
</div>
</div>
</div>
@@ -87,7 +87,6 @@
{disabled}
{fixedOverflowWidgets}
renderLineHighlight="none"
yPadding={7}
/>
</div>
{#if error != ''}
+23 -39
View File
@@ -31,7 +31,11 @@
import libStdContent from '$lib/es6.d.ts.txt?raw'
import domContent from '$lib/dom.d.ts.txt?raw'
import { initializeVscode, keepModelAroundToAvoidDisposalOfWorkers } from './vscode'
import {
initializeVscode,
keepModelAroundToAvoidDisposalOfWorkers,
MONACO_Y_PADDING
} from './vscode'
import EditorTheme from './EditorTheme.svelte'
import { vimMode, relativeLineNumbers } from '$lib/stores'
import { initVim } from './monaco_keybindings'
@@ -49,6 +53,7 @@
type IPosition
} from 'monaco-editor'
import { setMonacoJavascriptOptions, setMonacoJsonOptions } from './monacoLanguagesOptions'
import { twMerge } from 'tailwind-merge'
// import { createConfiguredEditor } from 'vscode/monaco'
// import type { IStandaloneCodeEditor } from 'vscode/vscode/vs/editor/standalone/browser/standaloneCodeEditor'
@@ -59,7 +64,6 @@
let statusDiv = $state<Element | null>(null)
let width = $state(0)
let initialized = $state(false)
let suggestion = $state('')
let placeholderVisible = $state(false)
let mounted = $state(false)
@@ -85,13 +89,12 @@
allowVim = false,
tailwindClasses = [],
class: className = '',
fakeMonacoPlaceholderClass = '',
loadAsync = false,
key,
disabled = false,
minHeight = 1000,
renderLineHighlight = 'none',
yPadding
suggestion
}: {
lang: string
code?: string
@@ -113,16 +116,17 @@
allowVim?: boolean
tailwindClasses?: string[]
class?: string
fakeMonacoPlaceholderClass?: string
loadAsync?: boolean
initialCursorPos?: IPosition
key?: string
disabled?: boolean
minHeight?: number
renderLineHighlight?: 'all' | 'line' | 'gutter' | 'none'
yPadding?: number
suggestion?: string
} = $props()
let yPadding = MONACO_Y_PADDING
const dispatch = createEventDispatcher()
const uri = `file:///${hash}.${langToExt(lang)}`
@@ -214,17 +218,6 @@
export function hide(): void {
divEl?.classList.add('hidden')
}
export function setSuggestion(value: string): void {
suggestion = value
}
let disableTabCond: meditor.IContextKey<boolean> | undefined
$effect(() => {
disableTabCond?.set(!code && !!suggestion)
})
let vimDisposable: IDisposable | undefined = undefined
$effect(() => {
@@ -340,7 +333,7 @@
model,
...(yPadding !== undefined ? { padding: { bottom: yPadding, top: yPadding } } : {}),
renderLineHighlight,
lineDecorationsWidth: 6,
lineDecorationsWidth: 0,
lineNumbersMinChars: 2,
fontSize: fontSize,
quickSuggestions: disableSuggestions
@@ -369,7 +362,6 @@
let timeoutModel: number | undefined = undefined
editor.onDidChangeModelContent((event) => {
suggestion = ''
timeoutModel && clearTimeout(timeoutModel)
timeoutModel = setTimeout(() => {
updateCode()
@@ -389,9 +381,6 @@
shouldBindKey && format && format()
})
disableTabCond = editor.createContextKey('disableTabCond', !code)
editor.addCommand(KeyCode.Tab, function () {}, 'disableTabCond')
editor.addCommand(KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Digit7, function () {
// CMD + slash (toggle comment) on some EU keyboards
editor?.trigger('keyboard', 'editor.action.commentLine', {})
@@ -597,38 +586,32 @@
</script>
<EditorTheme />
{#if editor && suggestion && code?.length === 0}
<div
class="absolute top-[0.05rem] left-[2.05rem] z-10 text-sm text-[#0007] italic font-mono dark:text-[#ffffff56] text-ellipsis overflow-hidden whitespace-nowrap"
style={`max-width: calc(${width}px - 2.05rem)`}
>
{suggestion}
</div>
{/if}
{#if !editor}
{#if !editor || suggestion}
<FakeMonacoPlaceHolder
{code}
code={suggestion || code}
autoheight
lineNumbersWidth={hideLineNumbers ? 0 : (23 * fontSize) / 14}
lineNumbersOffset={fontSize == 14 ? -8 : -11}
{fontSize}
showNumbers={!hideLineNumbers}
class={fakeMonacoPlaceholderClass}
/>
{/if}
<div
bind:this={divEl}
class="relative {className} {!editor ? 'hidden' : ''} editor {disabled
? 'disabled'
: ''} simple-editor {!allowVim ? 'nonmain-editor' : ''}"
class={twMerge(
'relative editor simple-editor',
className,
suggestion ? 'absolute opacity-0 pointer-events-none' : '',
!editor ? 'hidden' : '',
disabled ? 'disabled' : '',
!allowVim ? 'nonmain-editor' : ''
)}
bind:clientWidth={width}
>
{#if placeholder}
<div
id="placeholder"
class="absolute left-[24px] text-gray-500 text-sm pointer-events-none font-mono z-10 {placeholderVisible
class="absolute text-gray-500 text-sm pointer-events-none font-mono z-10 {placeholderVisible
? ''
: 'hidden'}"
>
@@ -636,6 +619,7 @@
</div>
{/if}
</div>
{#if allowVim && vimMode}
<div class="fixed bottom-0 z-30" bind:this={statusDiv}></div>
{/if}
@@ -22,11 +22,12 @@
// import '@codingame/monaco-vscode-standalone-typescript-language-features'
import { initializeVscode } from './vscode'
import { initializeVscode, MONACO_Y_PADDING } from './vscode'
import EditorTheme from './EditorTheme.svelte'
import FakeMonacoPlaceHolder from './FakeMonacoPlaceHolder.svelte'
import { setMonacoJsonOptions } from './monacoLanguagesOptions'
import { inputBorderClass } from './text_input/TextInput.svelte'
import { twMerge } from 'tailwind-merge'
export const conf = {
wordPattern:
@@ -381,9 +382,10 @@
export let autoHeight = true
export let fixedOverflowWidgets = true
export let fontSize = 12
export let yPadding: number | undefined = undefined
export let loadAsync = false
let yPadding = MONACO_Y_PADDING
if (typeof code != 'string') {
code = ''
}
@@ -448,7 +450,7 @@
model,
// overflowWidgetsDomNode: widgets,
// lineNumbers: 'on',
lineDecorationsWidth: 6,
lineDecorationsWidth: 0,
lineNumbersMinChars: 2,
fontSize,
suggestOnTriggerCharacters: true,
@@ -656,24 +658,23 @@
<EditorTheme />
{#if !editor}
<FakeMonacoPlaceHolder
autoheight
showNumbers={false}
{code}
lineNumbersWidth={14}
lineNumbersOffset={-20}
{fontSize}
class="template nonmain-editor bg-surface-input rounded-md !py-[8px] overflow-clip"
/>
{/if}
<div
bind:this={divEl}
style="height: 18px; padding-left: 6px;"
class="{inputBorderClass({ forceFocus: isFocus })} {$$props.class ??
''} template nonmain-editor rounded-md overflow-clip {!editor ? 'hidden' : ''}"
bind:clientWidth={width}
></div>
class={twMerge(
inputBorderClass({ forceFocus: isFocus }),
'rounded-md overflow-auto pl-2',
$$props.class
)}
>
{#if !editor}
<FakeMonacoPlaceHolder autoheight showNumbers={false} {code} {fontSize} />
{/if}
<div
bind:this={divEl}
style="height: 18px;"
class="template nonmain-editor rounded-md overflow-clip {!editor ? 'hidden' : ''}"
bind:clientWidth={width}
></div>
</div>
<style>
:global(.template .mtk20) {
@@ -296,15 +296,12 @@
bind:componentInput={item.data.componentInput}
/>
{:else if item.data?.componentInput?.type === 'template' || item.data?.componentInput?.type === 'templatev2'}
<div class="py-1 min-h-[28px] rounded border border-1 border-gray-500">
<TemplateEditor
yPadding={7}
fontSize={12}
bind:code={item.data.componentInput.eval}
{extraLib}
on:change={onTemplateChange}
/>
</div>
<TemplateEditor
fontSize={12}
bind:code={item.data.componentInput.eval}
{extraLib}
on:change={onTemplateChange}
/>
{#if item.data?.componentInput?.type === 'templatev2'}
{#if item.data?.componentInput.connections?.length > 0}
<div class="flex flex-wrap gap-2 items-center">
@@ -6,7 +6,6 @@
import { getNonStreamingCompletion } from './lib'
import { sendUserToast } from '$lib/toast'
import type { Flow, InputTransform } from '$lib/gen'
import ManualPopover from '../ManualPopover.svelte'
import { createEventDispatcher, getContext, untrack } from 'svelte'
import type { FlowEditorContext } from '../flows/types'
import type { PickableProperties } from '../flows/previousResults'
@@ -30,7 +29,6 @@
schemaProperty: SchemaProperty
pickableProperties?: PickableProperties | undefined
argName: string
showPopup: boolean
btnClass?: string
}
@@ -40,7 +38,6 @@
schemaProperty,
pickableProperties = undefined,
argName,
showPopup,
btnClass = ''
}: Props = $props()
@@ -231,65 +228,54 @@ Only return the expression without any wrapper.`
bind:open={openInputsModal}
inputs={[newFlowInput]}
/>
<ManualPopover
showTooltip={showPopup && (generatedContent.length > 0 || !!$generatedExprs?.[argName])}
placement="bottom"
class="p-2"
<Button
size="xs"
variant="default"
btnClasses={twMerge(
flowAIBtnClasses(!loading && generatedContent.length > 0 ? 'green' : 'default'),
btnClass
)}
on:click={() => {
if (!loading && generatedContent.length > 0) {
dispatch('setExpr', generatedContent)
if (newFlowInput) {
openInputsModal = true
}
generatedContent = ''
}
}}
on:mouseenter={(ev) => {
if (out) {
out = false
generateStepInput()
}
}}
on:mouseleave={() => {
out = true
cancel()
}}
endIcon={{
icon:
loading || ($stepInputsLoading && empty)
? Loader2
: generatedContent.length > 0
? Check
: Wand2,
classes: loading || ($stepInputsLoading && empty) ? 'animate-spin' : ''
}}
on:focus={() => {
btnFocused = true
}}
on:blur={() => {
btnFocused = false
}}
>
<Button
size="xs"
variant="default"
btnClasses={twMerge(
flowAIBtnClasses(!loading && generatedContent.length > 0 ? 'green' : 'default'),
btnClass
)}
on:click={() => {
if (!loading && generatedContent.length > 0) {
dispatch('setExpr', generatedContent)
if (newFlowInput) {
openInputsModal = true
}
generatedContent = ''
}
}}
on:mouseenter={(ev) => {
if (out) {
out = false
generateStepInput()
}
}}
on:mouseleave={() => {
out = true
cancel()
}}
endIcon={{
icon:
loading || ($stepInputsLoading && empty)
? Loader2
: generatedContent.length > 0
? Check
: Wand2,
classes: loading || ($stepInputsLoading && empty) ? 'animate-spin' : ''
}}
on:focus={() => {
btnFocused = true
}}
on:blur={() => {
btnFocused = false
}}
>
{#if focused}
{#if loading}
ESC
{:else if generatedContent.length > 0}
TAB
{/if}
{#if focused}
{#if loading}
ESC
{:else if generatedContent.length > 0}
TAB
{/if}
</Button>
{#snippet content()}
<div class="text-sm text-primary">
{generatedContent || $generatedExprs?.[argName]}
</div>
{/snippet}
</ManualPopover>
{/if}
</Button>
{/if}
@@ -72,7 +72,6 @@
onClick={onPress}
startIcon={{ icon: WandSparkles }}
iconOnly
wrapperClasses="h-7"
btnClasses={flowAIBtnClasses(selected ? 'selected' : 'default')}
>
AI Panel
@@ -1,4 +1,5 @@
<script lang="ts">
import Alert from '$lib/components/common/alert/Alert.svelte'
import Button from '$lib/components/common/button/Button.svelte'
import { ChevronDown } from 'lucide-svelte'
@@ -21,12 +22,8 @@
</div>
{#if opened}
<div
class="bg-surface-secondary border-x border-r-0 border-l-4 text-sm text-secondary p-4 mt-2"
role="alert"
id="dynamic-input-help-box"
>
Single JavaScript expression. The following functions and objects are available:
<Alert title="Single JavaScript expression" class="mt-2">
The following functions and objects are available:
<ul class="ml-4 list-disc">
<li
><b>{'results.<id>'}</b>: the result of step at id 'id' (use optional chaining if id may not
@@ -44,5 +41,5 @@
</li>
</ul>
If using multiple statements, the last statement shall finish with a return. e.g: `return x`
</div>
</Alert>
{/if}
@@ -123,6 +123,8 @@
$effect(() => {
editor && currentEditor.set({ type: 'iterator', editor, stepId: mod.id })
})
let suggestion: string | undefined = $state(undefined)
</script>
<Drawer bind:open={previewOpen} alwaysOpen size="75%">
@@ -314,7 +316,6 @@
}
}
class="h-full"
yPadding={7}
shouldBindKey={false}
extraLib={stepPropPicker.extraLib}
/>
@@ -355,9 +356,7 @@
bind:this={iteratorGen}
focused={iteratorFieldFocused}
arg={mod.value.iterator}
on:showExpr={(e) => {
editor?.setSuggestion(e.detail)
}}
on:showExpr={(e) => (suggestion = e.detail || undefined)}
on:setExpr={(e) => {
setExpr(e.detail)
}}
@@ -387,22 +386,25 @@
}}
noPadding
>
<SimpleEditor
bind:this={editor}
on:focus={() => {
iteratorFieldFocused = true
}}
on:blur={() => {
iteratorFieldFocused = false
}}
autofocus
lang="javascript"
bind:code={mod.value.iterator.expr}
class="h-full"
yPadding={7}
shouldBindKey={false}
extraLib={stepPropPicker.extraLib}
/>
<div class="relative w-full h-full overflow-clip">
<SimpleEditor
small
bind:this={editor}
on:focus={() => {
iteratorFieldFocused = true
}}
on:blur={() => {
iteratorFieldFocused = false
}}
autofocus
lang="javascript"
bind:code={mod.value.iterator.expr}
class="h-full"
shouldBindKey={false}
extraLib={stepPropPicker.extraLib}
{suggestion}
/>
</div>
</PropPickerWrapper>
</div>
{:else}
@@ -177,7 +177,6 @@
>
<SimpleEditor
bind:this={editor}
yPadding={7}
lang="javascript"
bind:code={flowModule.stop_after_if.expr}
class="h-full"
@@ -317,7 +316,6 @@
lang="javascript"
bind:code={flowModule.stop_after_all_iters_if.expr}
class="h-full"
yPadding={7}
extraLib={`declare const result = ${JSON.stringify(result)};` +
`\ndeclare const flow_input = ${JSON.stringify(stepPropPicker.pickableProperties.flow_input)};`}
/>
@@ -82,7 +82,6 @@
bind:this={editor}
lang="javascript"
bind:code={flowModule.skip_if.expr}
yPadding={7}
class="h-full"
extraLib={stepPropPicker.extraLib}
/>
@@ -185,7 +185,6 @@
bind:this={editor}
lang="javascript"
bind:code={flowModuleRetry.retry_if.expr}
yPadding={7}
class="h-full"
extraLib={`declare const result = ${JSON.stringify(result)};` +
`\ndeclare const flow_input = ${JSON.stringify(stepPropPicker.pickableProperties.flow_input || {})};`}
@@ -262,7 +262,6 @@
<SimpleEditor
lang="javascript"
small
yPadding={7}
bind:code={flowStore.val.value.skip_expr}
class="small-editor"
extraLib={`declare const flow_input = ${JSON.stringify(
@@ -63,7 +63,7 @@
<Button
variant="default"
unifiedSize="sm"
wrapperClasses={twMerge('min-w-36 h-7', small ? 'max-w-52' : 'max-w-64')}
wrapperClasses={twMerge('min-w-36', small ? 'max-w-52' : 'max-w-64')}
btnClasses={twMerge(
aiModuleActionToBgColor(action),
aiModuleActionToBorderColor(action),
@@ -118,7 +118,7 @@
{#snippet trigger({ toggleOpen })}
<Button
unifiedSize="sm"
wrapperClasses="min-w-36 h-7"
wrapperClasses="min-w-36"
title={`Add failure module`}
variant="default"
id={`flow-editor-add-step-error-handler-button`}
@@ -452,7 +452,6 @@
<div class="mt-2 bg-surface-tertiary rounded-md pl-3">
<SimpleEditor
small
yPadding={7}
extraLib={`declare const fields: Record<${propsNames
?.filter((x) => x != name)
.map((x) => `"${x}"`)
@@ -24,17 +24,12 @@
export const inputSizeClasses = {
sm: twMerge(
`${ButtonType.UnifiedSizingClasses.sm} ${ButtonType.UnifiedMinHeightClasses.sm} !py-0.5`,
'px-2'
ButtonType.UnifiedSizingClasses.sm,
ButtonType.UnifiedMinHeightClasses.sm,
'px-2 !py-0.5'
),
md: twMerge(
`${ButtonType.UnifiedSizingClasses.md} ${ButtonType.UnifiedMinHeightClasses.md}`,
'px-2'
),
lg: twMerge(
`${ButtonType.UnifiedSizingClasses.lg} ${ButtonType.UnifiedMinHeightClasses.lg}`,
'px-2'
)
md: twMerge(ButtonType.UnifiedSizingClasses.md, ButtonType.UnifiedMinHeightClasses.md, 'px-2'),
lg: twMerge(ButtonType.UnifiedSizingClasses.lg, ButtonType.UnifiedMinHeightClasses.lg, 'px-2')
}
</script>
+2
View File
@@ -290,3 +290,5 @@ export function keepModelAroundToAvoidDisposalOfWorkers() {
meditor.createModel('', 'typescript', keepEditorUri)
}
}
export let MONACO_Y_PADDING = 7