Compare commits

...

2 Commits

Author SHA1 Message Date
Diego Imbert
9e2a182252 fix monaco height 2025-11-20 15:21:34 +01:00
Diego Imbert
6e03377d97 Fix alignment issues and TextArea min-height taller 2025-11-20 13:12:10 +01:00
6 changed files with 102 additions and 101 deletions

View File

@@ -28,7 +28,6 @@
import DateTimeInput from './DateTimeInput.svelte'
import DateInput from './DateInput.svelte'
import CurrencyInput from './apps/components/inputs/currency/CurrencyInput.svelte'
import autosize from '$lib/autosize'
import PasswordArgInput from './PasswordArgInput.svelte'
import Password from './Password.svelte'
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
@@ -46,11 +45,7 @@
import { workspaceStore } from '$lib/stores'
import { getJsonSchemaFromResource } from './schema/jsonSchemaResource.svelte'
import AIProviderPicker from './AIProviderPicker.svelte'
import TextInput, {
inputBaseClass,
inputBorderClass,
inputSizeClasses
} from './text_input/TextInput.svelte'
import TextInput from './text_input/TextInput.svelte'
import FileInput from './common/fileInput/FileInput.svelte'
interface Props {
@@ -1412,45 +1407,39 @@
{/if}
{:else}
{#key extra?.['minRows']}
<textarea
{autofocus}
rows={extra?.['minRows'] ? extra['minRows']?.toString() : '1'}
bind:this={el}
onfocus={(e) => {
dispatch('focus')
<TextInput
inputProps={{
autofocus,
onfocus: () => dispatch('focus'),
onblur: () => dispatch('blur'),
disabled,
onkeydown: onKeyDown,
placeholder: placeholder ?? defaultValue ?? '',
rows: extra?.['minRows'] ? extra['minRows']?.toString() : '1'
}}
onblur={(e) => {
dispatch('blur')
}}
use:autosize
onkeydown={onKeyDown}
{disabled}
class={twMerge(
'w-full',
inputBaseClass,
inputSizeClasses.md,
inputBorderClass({ error: !!error })
)}
placeholder={placeholder ?? defaultValue ?? ''}
bind:value
></textarea>
{error}
unifiedHeight={false}
underlyingInputEl="textarea"
/>
{/key}
{/if}
{#if !disabled && itemPicker && extra?.['disableVariablePicker'] != true}
<!-- svelte-ignore a11y_click_events_have_key_events -->
<button
class={twMerge(
'absolute opacity-0 group-hover:opacity-100 duration-200 py-1 min-w-min !px-2 items-center text-gray-800 bg-surface-secondary border rounded center-center hover:bg-gray-300 transition-all cursor-pointer',
password || extra?.['password'] == true ? 'right-16' : 'right-1'
)}
onclick={() => {
<Button
iconOnly
startIcon={{ icon: DollarSign }}
unifiedSize="sm"
onClick={() => {
pickForField = label
itemPicker?.openDrawer?.()
}}
wrapperClasses={twMerge(
'opacity-0 group-hover:opacity-100 transition-opacity absolute bg-surface-input',
password || extra?.['password'] == true ? 'right-8 ' : 'right-2'
)}
variant="subtle"
title="Insert a Variable"
>
<DollarSign class="!text-primary" size={14} />
</button>
/>
{/if}
</div>
{@render variableInput()}

View File

@@ -1,5 +1,8 @@
<script lang="ts">
import { createBubbler } from 'svelte/legacy'
import Button from './common/button/Button.svelte'
import TextInput from './text_input/TextInput.svelte'
import { Eye, EyeClosed } from 'lucide-svelte'
const bubble = createBubbler()
interface Props {
@@ -25,45 +28,35 @@
let red = $derived(required && (password == '' || password == undefined))
let hideValue = $state(true)
let randomId = (Math.random() * 10e15).toString(16)
</script>
<div class="relative w-full {small ? 'max-w-lg' : ''}">
<div class="absolute inset-y-0 right-0 flex items-center px-2">
<input bind:checked={hideValue} class="!hidden" id={randomId} type="checkbox" />
<label
class="bg-surface-secondary hover:bg-gray-400 rounded px-2 py-1 text-sm text-primary font-mono cursor-pointer"
for={randomId}>{hideValue ? 'show' : 'hide'}</label
>
<div class="absolute inset-y-0 right-1 flex items-center">
<Button
unifiedSize="sm"
onClick={() => (hideValue = !hideValue)}
iconOnly
startIcon={{ icon: hideValue ? Eye : EyeClosed }}
variant="subtle"
wrapperClasses="bg-surface-input"
/>
</div>
{#if hideValue}
<input
class="block {small ? '!text-2xs' : 'w-full'} px-2 py-1 {red
? '!border-red-500'
: ''} text-sm h-9"
type="password"
bind:value={password}
onkeydown={onKeyDown}
onblur={onBlur}
autocomplete="new-password"
{placeholder}
{disabled}
/>
{:else}
<input
class="block {small ? '!text-2xs' : 'w-full'} px-2 py-1 {red
? '!border-red-500'
: ''} text-sm h-9"
type="text"
bind:value={password}
onkeydown={bubble('keydown')}
onblur={onBlur}
autocomplete="new-password"
{placeholder}
{disabled}
/>
{/if}
<TextInput
size="md"
error={red}
bind:value={password}
inputProps={{
disabled,
placeholder,
autocomplete: 'new-password',
onblur: (e) => onBlur?.(e),
onkeydown: (e) => {
onKeyDown?.(e)
bubble('keydown')(e)
},
type: hideValue ? 'password' : 'text'
}}
/>
</div>
{#if red}
<div class="text-red-600 text-2xs grow">This field is required</div>

View File

@@ -415,7 +415,7 @@
{#snippet actions()}
{@render actions_render?.({ item })}
{#if linkedSecretCandidates?.includes(argName)}
<div>
<div class="relative">
<ToggleButtonGroup
selected={linkedSecret == argName ? 'secret' : 'inlined'}
on:selected={(e) => {
@@ -429,14 +429,12 @@
{#snippet children({ item })}
<ToggleButton
value="inlined"
small
label="Inlined"
tooltip="The value is inlined in the resource and thus has no special treatment."
{item}
/>
<ToggleButton
value="secret"
small
label="Secret"
tooltip="The value will be stored in a newly created linked secret variable at the same path. That variable can be permissioned differently, will be treated as a secret the UI, operators will not be able to load it and every access will generate a corresponding audit log."
{item}

View File

@@ -494,7 +494,7 @@
const updateHeight = () => {
const contentHeight = Math.min(1000, editor.getContentHeight())
if (divEl) {
divEl.style.height = `${contentHeight + 2}px`
divEl.style.height = `${contentHeight}px`
}
try {
editor.layout({ width, height: contentHeight })

View File

@@ -20,6 +20,7 @@
export const inputBaseClass =
'rounded-md focus:ring-0 no-default-style text-xs text-primary font-normal !bg-surface-input disabled:!bg-surface-disabled disabled:!border-transparent disabled:!text-disabled disabled:cursor-not-allowed shadow-none !placeholder-hint'
import autosize from '$lib/autosize'
import { ButtonType } from '$lib/components/common/button/model'
export const inputSizeClasses = {
@@ -38,49 +39,69 @@
}
</script>
<script lang="ts">
import type { HTMLInputAttributes } from 'svelte/elements'
<script lang="ts" generics="UnderlyingInputElT extends 'input' | 'textarea' = 'input'">
import type { HTMLInputAttributes, HTMLTextareaAttributes } from 'svelte/elements'
import { twMerge } from 'tailwind-merge'
type Props = {
inputProps?: HTMLInputAttributes
type Props<UnderlyingInputElT extends 'input' | 'textarea'> = {
inputProps?: UnderlyingInputElT extends 'input' ? HTMLInputAttributes : HTMLTextareaAttributes
value?: string
class?: string
error?: string | boolean
size?: ButtonType.UnifiedSize
unifiedHeight?: boolean
underlyingInputEl?: UnderlyingInputElT
}
export function focus() {
inputEl?.focus()
}
let inputEl: HTMLInputElement | undefined = $state()
let inputEl: HTMLInputElement | HTMLTextAreaElement | undefined = $state()
let {
inputProps,
inputProps: _inputProps,
value = $bindable(),
class: className = '',
error,
size = 'md',
unifiedHeight = true
}: Props = $props()
unifiedHeight = true,
underlyingInputEl: _underlyingInputEl
}: Props<UnderlyingInputElT> = $props()
let underlyingInputEl = $derived(_underlyingInputEl ?? ('input' as const))
let inputProps = $derived(_inputProps as any)
let fullClassName = $derived(
twMerge(
inputBaseClass,
inputSizeClasses[size],
'[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',
inputBorderClass({ error: !!error }),
unifiedHeight ? ButtonType.UnifiedHeightClasses[size] : '',
'w-full',
className
)
)
</script>
<input
{...inputProps}
class={twMerge(
inputBaseClass,
inputSizeClasses[size],
'w-full',
'[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',
inputBorderClass({ error: !!error }),
unifiedHeight ? ButtonType.UnifiedHeightClasses[size] : '',
className
)}
onpointerdown={(e) => {
e.stopImmediatePropagation()
}}
bind:this={inputEl}
bind:value
/>
{#if underlyingInputEl === 'textarea'}
<!-- We hardcode the py value because since textareas can be multiline, we can't rely on
the fact that it auto-centers -->
<textarea
class={twMerge('py-[0.45rem]', fullClassName)}
{...inputProps}
onpointerdown={(e) => e.stopImmediatePropagation()}
bind:this={inputEl}
bind:value
use:autosize
></textarea>
{:else if underlyingInputEl === 'input'}
<input
{...inputProps}
class={fullClassName}
onpointerdown={(e) => e.stopImmediatePropagation()}
bind:this={inputEl}
bind:value
/>
{/if}

View File

@@ -291,4 +291,4 @@ export function keepModelAroundToAvoidDisposalOfWorkers() {
}
}
export let MONACO_Y_PADDING = 7
export let MONACO_Y_PADDING = 6.5